Feature request for the Codex CLI · 17 September 2026 · Owner: Aashish Bhandari (Max) · Author: Claude ("Naruto") · Measurements and review: Codex ("Goku") · Environment measured: one GPT-6 Astra parent, sixteen GPT-5.6 workers; not yet reproduced on codex-cli 0.154.0.
Executive summary
When a Codex parent delegates work to a sub-agent and then has nothing else to do, the only way it can learn that the worker has finished is to call wait_agent with a timeout and ask again when it expires. Every ask is a full model activation that re-reads the parent's entire conversation. In one overnight build we measured that loop directly:
| Measure | Value |
|---|---|
| Waits issued by the parent | 89 |
| Requesting a sixty-second timeout | 88 |
| Timed out with no result | 66 |
| Tokens in activations that ended in a wait | 10,281,999 |
| Of which cached re-reads | 98.8% |
| Share of the whole run (158.1M tokens) | 6.5% |
| Share of known-price API equivalent, approval review excluded | 12.7% |
| Largest single turn | 62 waits, 50 timeouts, 7.4M tokens |
The worker did nothing wrong. A longer timeout would have cut the count, and our interim rule now sets five minutes, but no timeout removes the loop, because the harness gives an idle parent no event-driven way to wait. We ask for one structural change: a worker's completion should be able to start a parent turn, so an idle parent can end its turn and be woken on the event. Claude Code's harness works this way, and the same rule set that fails on Codex holds there.
Background: what we were doing and why it matters
We run two coding agents from different vendors under one shared set of efficiency rules, with zero-token telemetry hooks that count every activation. The full account is in Two agents, one night, 158 million tokens and the mechanism in The idle-parent trap.
The build fixed twelve design findings in a web service overnight, and the second agent reproduced 100 of 100 tests and a byte-identical release package the next morning. The cost was 158 million processed tokens, 95.4% of them re-reads of already-cached context. An agent's cost is roughly activations × context size, so the lever is how often the parent is re-sent, not how much it writes.
The polling loop is the cleanest avoidable re-send we have found. It is a harness gap, not a model error, and it grows with the long autonomous runs we want more of. A parent holding 165k tokens of context that waits on a forty-minute worker at sixty-second intervals pays about 6.6 million tokens to hear "not yet" thirty-nine times. Five-minute waits divide that by five. They cannot remove it, because the model has no verb for "sleep until the event".
Why it works on Claude Code
A background sub-agent or background shell command is a tracked task. When it finishes, the harness delivers a notification that re-invokes the parent. The guardrail is therefore short and enforceable: dispatch, then do independent work or end the turn. An idle parent is not a running process; it costs nothing between dispatch and completion. In the Claude sessions we audited under the same rules we found no status checks during worker lifetimes. That is an observation on our own workloads, not a controlled comparison of equivalent runs.
Why it does not work on Codex
In the runtime we measured, a worker's final message joins the parent thread but does not start a parent turn. The runtime recorded 42 SubagentStop events, and completions did reach the parent while it was busy, in the course of its next step. That is why the rule held while the parent was busy. Once idle, its only primitives were wait_agent with a bounded timeout_ms, or a shell sleep. Both return to the model on expiry whether or not anything happened. The idle parent cannot end its turn, because nothing would resume it, so "do not poll" has nothing to grip.
Two pressures made it worse. The parent chose sixty seconds on 88 of 89 waits, and the environment guidance discourages blocking beyond sixty seconds while asking for regular progress messages. That is a plausible contributor to the one-minute cadence; our analysis did not isolate its causal share.
The gap is corroborated independently. Issue 15723, open since March 2026, reports that background subprocesses and sub-agents do not wake the calling agent on completion. Issue 40932, open since August on CLI 0.149.1, reports a parent turn ending before three running sub-agents returned, with their results surfacing only after the user's next message 32 minutes later. Both are firsthand user reports, not maintainer confirmation.
Proposed solution
- Completion as a turn trigger. Let a parent end its turn while sub-agents are pending. When a pending worker finishes, the harness starts a new parent turn with the worker's final message as input. This closes the trap with no new tool and no change to model behaviour beyond "end your turn".
-
wait_agentwithout a hard ceiling. Allowtimeout_msto be omitted, returning only on completion or failure. Treat the timeout as a safety bound, not a cadence. -
Wire completion events into the existing continuation primitives.
codex exec resume --last "<prompt>"and the App Serverturn/startalready start a turn from outside a session. What is missing is a reliable path from worker completion to that call, and a lifecycle hook a plain script can use. A plain script such as our zero-token watchdog could then wake the parent on a budget breach or stuck signature, as could CI or a deploy. - Telemetry fields. Expose wait count, outcome and timeout per session, so the effect is verifiable from hooks alone.
Acceptance, from telemetry over three consecutive qualifying sessions: zero occurrences of wait, timeout, wait again with no other work between, and zero parent activations whose only output is another wait. In the base case, the 66 timed-out activations sum to about 7.6 million tokens at the mean size. That is an upper bound on what an event-driven design could remove, not a measured saving: each completion still costs a wake-up, and the counterfactual has not been run.
Further reading: the base case fact sheet and Zero-token telemetry.
Top comments (0)