`collab_tool_call` "spawn_agent" item missing from `exec --experimental-json` stream; "wait" item's `receiver_thread_ids` stays empty despite a real, successful delegation underneath
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- rust, typescript
- Domain
- api, cli, distributed-systems
Research direction
Start with node_modules/@openai/codex-sdk/src/exec.ts and reproduce the delegation through Codex.startThread().runStreamed() using codex exec --experimental-json. Compare the emitted stream with the full session rollout JSONL and the thread_spawn_edges records in state_5.sqlite. Done means the public stream includes the spawn_agent item and the wait item contains the actual receiver thread IDs.
Written by the indexing model from the issue text.
Description
What version of Codex CLI is running?
0.144.5 (installed via @openai/codex-sdk / @openai/codex npm packages)
Which model were you using?
gpt-5.6-sol
What platform is your computer?
Linux (Ubuntu 20.04 focal), invoked via @openai/codex-sdk's Codex.startThread().runStreamed(), which shells out to codex exec --experimental-json (see node_modules/@openai/codex-sdk/src/exec.ts).
What happened?
Using native subagent support ([features] multi_agent = true, a custom
agent defined at <CODEX_HOME>/agents/<name>.toml), I asked the root agent
to spawn a named custom agent and relay its exact reply. The
--experimental-json event stream only ever shows:
{"type":"item.started","item":{"id":"item_1","type":"collab_tool_call","tool":"wait","sender_thread_id":"...","receiver_thread_ids":[],"prompt":null,"agents_states":{},"status":"in_progress"}}
{"type":"item.completed","item":{"id":"item_1","type":"collab_tool_call","tool":"wait","sender_thread_id":"...","receiver_thread_ids":[],"prompt":null,"agents_states":{},"status":"completed"}}
{"type":"item.completed","item":{"id":"item_2","type":"agent_message","text":"SPECIALIST SAID: PONG"}}
Note: no collab_tool_call with tool: "spawn_agent" (or similar) ever
appears in this stream, and the wait item's receiver_thread_ids is
always [], even though the final agent_message content is correct.
This reproduced identically across 6 separate runs, with and without
[features.multi_agent_v2].
Reading the FULL session rollout (~/.codex/sessions/**/*.jsonl) for the
same turn tells a different, complete story — it contains the actual
function_call/function_call_output pair for the spawn, a
sub_agent_activity event ("kind": "started"), the child thread's own
rollout file (session_meta subagent.thread_spawn with the correct
agent_path/agent_nickname), and the real agent_message reply routed
back from the child. state_5.sqlite's thread_spawn_edges table also
correctly records the parent→child edge for every one of the 6 runs.
So: delegation genuinely works end-to-end. The bug is that the
--experimental-json stream — the one @openai/codex-sdk consumes and
exposes to SDK users — is missing the spawn_agent collab_tool_call event
entirely, and the wait item it does emit never reflects the real
receiver thread. This is different from #28318 (missing TypeScript type for
collab_tool_call — that reporter's runtime JSON did include a populated
spawn_agent item with real receiver_thread_ids); here the data itself
is missing from this event source, not just its type.
Expected behavior
exec --experimental-json (and therefore @openai/codex-sdk's public
event stream) should include the spawn_agent collab_tool_call item, and
wait's receiver_thread_ids should reflect the actual spawned child
thread(s) — matching what the full session rollout already records
correctly.
Why this matters
Any SDK consumer trying to observe or verify subagent delegation
(logging, tracing, debugging, deciding whether to trust a delegated
result) via the public event stream currently gets a false negative —
delegation looks like a silent no-op even when it succeeded. We only
caught this by cross-referencing the full rollout JSONL and
state_5.sqlite directly, which isn't part of the SDK's public surface.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- Avg merge
- 1m
- Merged PRs (30d)
- 1k
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from openai/codex
-
enhancement remote
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
bug CLI windows-os
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
macOS sandbox blocks hw.optional.arm64 sysctl, causing Flutter to misdetect Apple Silicon as x64 Openbug CLI sandbox
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
bug CLI TUI
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
CLI config enhancement skills
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kwakseongjae/auto-hwp#319 ·
-
area:cli bug filter-quality good first issue priority:medium
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 1/5 Under an hour Newbie friendliness 72/100
bevyengine/bevy#25861 ·
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
A-linter
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
oxc-project/oxc#26863 ·