Codex Desktop repeatedly re-enters the model during wait/status polling, consuming substantial credits
Summary
During intentional Ultra and multi-agent work, Codex Desktop repeatedly re-entered the model merely to wait for agents or poll terminal status. In a corrected reset-to-49%-usage window, model turns whose only tool action was wait/status polling accounted for 19.8% of raw local token volume.
Ultra and multi-agent use were intentional. The suspected defect is not normal agent fan-out; it is repeated model inference during quiet coordination and process-wait intervals, often at 30- or 60-second cadence.
Related reports exist, but this report adds current-build evidence, replay-safe accounting, a full usage-cycle window, tool-level decomposition, a representative long-running trace, and a public-rate-card estimate.
Environment
- ChatGPT Pro
- macOS on Apple silicon
- Codex Desktop 26.721.31836 (build 5828)
- Incident runtime: codex-cli 0.146.0-alpha.3.1
- Mostly GPT-5.6 Sol
What issue are you seeing?
Long-running multi-agent tasks can generate hundreds of distinct model turns that do no substantive work beyond calling one of these tools:
wait_agentlist_agentswrite_stdin- generic
wait
Each polling interval appears to re-enter the model, ingest a large cached conversation prefix, and then make another wait/status call. This can continue for hours while delegated work or a terminal process is still running.
Corrected local evidence
I analyzed local rollout telemetry from one complete weekly reset window, from the reset through the first observed 49% usage state.
The parser:
- excludes copied parent-history prefixes in child rollouts;
- starts each child at its live
task_startedboundary; - ignores unchanged cumulative token snapshots; and
- counts only genuine per-turn token deltas.
Corrected window:
- 10,586 genuine model turns
- 1,382,757,012 raw local tokens
- 43,668,351 uncached input tokens
- 1,335,723,264 cached input tokens
- 3,365,397 output tokens
- 96.83% cached-input share
- 94,241 copied-prefix token records excluded
- 404 duplicate token snapshots excluded
Tool-only wait/status turns:
| Tool group | Turns | Raw local tokens | Uncached input | Cached input | Output | Share of all raw |
|---|---:|---:|---:|---:|---:|---:|
| wait_agent / list_agents only | 985 | 142,137,652 | 2,654,345 | 139,365,376 | 117,931 | 10.3% |
| write_stdin / wait only | 983 | 131,423,068 | 1,319,437 | 130,028,544 | 75,087 | 9.5% |
| Combined | 1,968 | 273,560,720 | 3,973,782 | 269,393,920 | 193,018 | 19.8% |
Using the current public GPT-5.6 Sol rate card, the combined wait/status subset corresponds to an estimated 3,948 credits. This is a rate-card estimate from local telemetry, not a claim about the private subscription billing ledger.
Representative long-running trace
One child task ran for about 10 hours 55 minutes and contained:
- 1,417 genuine model turns
- 254
wait_agentcalls - 31
list_agentscalls - 316
write_stdincalls - 12 generic
waitcalls - 613 combined wait/status-only turns
- about 93.17 million raw local tokens attributable to those wait/status turns
The wait/status subset was about 45% of that child task's genuine raw token volume. Most agent waits requested only 30 or 60 seconds before another model-mediated poll.
Steps to reproduce
- Start an Ultra task that delegates a genuinely long-running child task.
- Let the child run for at least 30-60 minutes while the parent or another child coordinates it.
- Observe repeated
wait_agent,list_agents,write_stdin, or genericwaitcalls during otherwise quiet intervals. - Inspect per-turn local token deltas, excluding copied child-history prefixes and unchanged cumulative snapshots.
- Note that status-only polling repeatedly creates distinct model turns and reprocesses a large cached context.
Expected behavior
Waiting for an agent or terminal process should be event-driven, or handled by the harness without repeatedly invoking the model. The model should wake when:
- the child or process produces meaningful new output;
- the child completes or requires attention;
- the user sends new input; or
- a deliberately bounded, low-frequency checkpoint is required.
Actual behavior
Quiet wait intervals repeatedly invoke the model so it can issue another polling tool call. Large cached prefixes are charged through the public credit model even though the turns produce almost no substantive user-facing work.
Why this is not ordinary Ultra fan-out
Ultra and explicit multi-agent delegation were intentional, and their extra cost is expected. The anomalous subset here is narrower: nearly one-fifth of corrected raw token volume came from turns whose only action was waiting or checking status.
The same corrected window attributed 68.1% of raw volume to Ultra and 58.7% to subagents. Those figures describe the chosen workload. This issue concerns the avoidable model-mediated polling inside that workload.
Evidence boundary
- These figures come from local rollout telemetry, not OpenAI's internal billing ledger.
- Raw local token volume is not the same as subscription usage.
- The credit figure is an estimate using the published model rate card.
- Copied historical token records were explicitly excluded and are not claimed as billing events.
- I found no evidence here of a silent quota reduction.
- No private prompts, task identifiers, repository names, local paths, account details, or transcript content are included.
Related reports
- #34468 — parent chat polls child agents every minute
- #33276 — wait-for-agents loop drained quota
- #35108 — nested wait-agent polling
- #13733 — terminal polling
- #18394 — default wait timeout
- #34361 — replay attribution work
Suggested fix direction
- Make agent and terminal waits event-driven inside the harness.
- Avoid a fresh model call when no meaningful state has changed.
- Coalesce repeated status checks and apply backoff for long-running work.
- Surface wait/polling usage separately in diagnostics.
- Add regression coverage asserting that unchanged wait state does not create repeated billable model turns.
19 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Addendum: ten-day baseline comparison (July 15–24, 2026)
I extended the replay-corrected audit to compare the July 23–24 incident period with the preceding eight-calendar-day baseline. Copied child-history prefixes and unchanged cumulative token snapshots remain excluded.
| Metric | Jul 15–22 baseline | Jul 23–24 incident | Change |
|---|---:|---:|---:|
| Raw local model tokens/hour | 27.02M | 69.68M | 2.58× |
| Genuine model turns/hour | 214.43 | 546.80 | 2.55× |
| Raw tokens/genuine turn | 125.99K | 127.43K | +1.14% |
| Wait/status-only raw-token share | 9.54% | 17.80% | +8.26 percentage points |
| Subagent raw-token share | 28.46% | 51.58% | +23.12 percentage points |
The spike is therefore primarily a much higher frequency of genuine full-context model turns, not materially larger individual turns. The increased wait/status share strengthens the narrower harness concern in this issue: quiet coordination intervals are repeatedly re-entering the model.
I also compared two consecutive weekly-meter cycles. The current cycle produced 25.50M replay-safe raw local tokens per observed meter percentage point versus 26.28M in the previous cycle, a difference of about 3%. This does not support a newly smaller Pro allowance or changed meter denominator. It is consistent with the meter depleting faster because substantially more model turns were executed per hour.
There was substantial update activity during the window: six local Desktop install-start events were observed between July 21 and July 23, and the public
openai/codexrepository published 28 releases from July 15 through July 24 UTC. However, the activity spike began before the transition to Desktop build 5828, so build 5828 cannot be identified as the sole cause. A public ChatGPT/Codex service incident also overlapped part of July 23. These timings warrant investigation but do not establish causation.Evidence boundary: these remain privacy-safe aggregates from local rollout telemetry, not OpenAI billing records. Ultra and multi-agent usage were intentional; the suspected defect remains repeated model-mediated polling during unchanged wait/status intervals.
Analysis (community)
Residual analysis for #35259 (Desktop re-enters the model during wait/status polling and burns credits) under docs/contributing.md — invitation-only. No unsolicited PR.
Root-cause hypothesis
wait_agentis a local timeout over an activity watch channel; on timeout the turn layer setsneeds_follow_upand issues a fresh sampling request that re-ingests the full prefix, so long delegated work becomesN ≈ ceil(W/t)billable model turns. This is client-side re-entry, not a silent server quota cut.@dimasyankauskas — this is an exceptional piece of forensic work; the 10-day baseline comparison (2.58x tokens/hr, +8.26pp wait/status share, +23.12pp subagent share) and the meter-cycle parity check are exactly the kind of evidence that isolates "more turns per hour" from "smaller allowance." Your "no evidence of a silent quota reduction" conclusion is, I think, the right read.
I want to add the missing piece you and the cluster (#32640, #35108, #34468, #32309) describe behaviorally but don't trace in code: the unified OSS root cause. At HEAD
4c43465133,wait_agent(codex-rs/core/src/tools/handlers/multi_agents_v2/wait.rs:178-196) blocks on a purely localtokio::time::timeout_atover awatch::Receiversourced fromInputQueue::subscribe_activity(input_queue.rs:49-54) — no server round-trip, no long-poll. On timeout it returnsWaitAgentResult{timed_out:true}as aFunctionCallOutput. The turn layer then unconditionally setsneeds_follow_up=true(turn.rs:2199, plusend_turn=falseon any tool call atturn.rs:2369-2370),continues the loop, and issues a freshrun_sampling_requestthat re-ingests the full prefix viasess.clone_history().for_prompt(...)(turn.rs:295-308,history.rs:143-146).prompt_cache_key/previous_response_idare billing/transport discounts only — they do not skip the model turn. SoN = ceil(W/t)polling inferences, each billing the prefix. That is your 2.58x.Two corrections to the cluster, for the record: (1) the OSS
wait_agentdefault is 30s, max 1h (config/mod.rs:209-211), not 50s — #32640's ~50s is the model's chosentimeout_mson the code_modewaittool path, a different handler; (2) out-of-rangetimeout_msis rejected, not clamped (wait.rs:54-63). Neither changes the mechanism.Ranked fix outline (all OSS): (a) re-arm
wait_for_activityonTimedOutwhile the child is still running, instead of returning to the model (wait.rs:96-117) — collapses N polling turns into ≤1; (d) coalesce unchanged-status polls with backpressure; (b) raise/documentdefault_wait_timeout_ms(defense-in-depth only; doesn't cover code_modewaitor explicit short choices); (c) suppress prefix re-billing for pure status polls (partially server-side).Fail-first tests I'd want before any merge: a 10-min delegated child produces
≤1model turn for the whole wait (today: ~20); a pure-status timeout does not issue a newrun_sampling_request(today: does); steer/mailbox wake still fires immediately (regression guard for #18968/#28341). Happy to draft the test patch if a maintainer wants it.Happy to refine measurements or a fail-first test patch if maintainers want one. No unsolicited PR from me.
@bbingz Thank you—this source trace is highly relevant and broadly consistent with the telemetry.
Two evidence boundaries are worth preserving:
clone_history().for_prompt()establishes the logical model-visible context, while the WebSocket path may transmit an incremental delta usingprevious_response_id. OpenAI's API documentation says previous chain input remains billed as input tokens, but my ChatGPT Pro credit ledger is not directly observable. I am therefore keeping the conclusion at: repeated sampling requests are consistent with faster credit depletion, rather than proof of private subscription-billing semantics.The fail-first tests are excellent. I would also add equivalent coverage for
write_stdin/ code-mode waiting, since terminal polling accounted for another 9.5% of raw volume. Given the repository's contribution policy, waiting for maintainer direction before drafting a patch makes sense.Additional recurrence data: fixed 12-hour window
I ran the same replay-safe analysis on a separate fixed window (2026-07-25 05:08–17:08 UTC). The same model-mediated wait/status symptom persisted, but at lower intensity than the Jul 23–24 incident window.
Corrected aggregate totals:
wait_agent/list_agents): 202 turns, 28,298,127 raw tokenswrite_stdin/ genericwait): 127 turns, 18,048,878 raw tokensRepeated-polling evidence:
wait_agentcalls at 30 seconds, 9 at 60 seconds, and 33 generic waits at 30 secondsComparison using the same definitions:
| Window | Raw tokens/hour | Turns/hour | Wait/status raw share | Subagent raw share |
|---|---:|---:|---:|---:|
| Jul 15–22 baseline | 27.02M | 214.43 | 9.54% | 28.46% |
| Jul 23–24 incident | 69.68M | 546.80 | 17.80% | 51.58% |
| New 12-hour window | 30.27M | 260.17 | 12.76% | 34.59% |
This places the new window 3.22 percentage points above the earlier wait/status baseline, but 5.04 points below the incident. It supports recurrence of the same mechanism without suggesting that the current intensity equals the incident peak.
Method and privacy boundary:
task_startedboundaryI encountered the same issue on Codex TUI / CLI 0.145.0 on Windows with gpt-5.6-sol, Ultra, and multi-agent v2. A
parent turn ran for 16 hours 29 minutes without further user input or completion, recorded 255 wait_agent calls and 11
context compactions, and ended with another unmatched wait_agent call. The final five-minute polling cycles each re-
entered the model and processed about 213,000 tokens, overwhelmingly cached input.
Independent corroboration from a different account, plus one methodological note that may help others reproduce your numbers.
I only report what I could verify. Where my own accounting is still unreliable I say so rather than post a figure.
1. The wait/status polling, in an 11-day session
Same mechanism you describe, on ChatGPT Pro with gpt-5.6-sol. One session stayed open for 11 days and produced a single 475 MB rollout.
I counted the blocking wait calls directly from their arguments:
The empty returns escalate over the life of the session:
The session recorded 8 errors in 11 days. Nothing failed and nothing retried, which is why it ran that long unnoticed. On the last day my client logged 379
usage_limit_exceedederrors.This supports @bbingz's root-cause reading: the empty return is the local timeout firing, and each one costs a fresh full-prefix turn.
2. A clean account exhausted a full weekly allowance in 407 model turns
After exhaustion I moved to a brand-new account on a different tier — no history, no prior usage. It was active for four hours (13:12–17:15 UTC) and reached 100% of its weekly cap.
Counted with your criteria (anchor on
turn_context, exclude inherited prefixes, ignore unchanged cumulative snapshots, count genuine deltas only):Four hundred turns for a week's allowance. This is the part I find hardest to explain as normal accounting, because there is no accumulated history to blame.
3. Methodological note: ~90 telemetry events per genuine turn
This is why I think several reports in these threads produce figures that cannot be reconciled with each other.
Counting
token_countevents overstates model turns by roughly two orders of magnitude. On one day I measured:turn_contextis the anchor that gives turn counts matching plausible activity. I had this wrong myself for several passes, and every derived figure was inflated until I fixed it. Your parser already handles this; it may be worth stating the anchor explicitly, since it is the single correction that reconciles the numbers.What I am not reporting
My per-window token totals for the older account are still wrong — my delta accounting mishandles the gap left when an inherited prefix is skipped, which inflates the sum. I would rather leave that out than add a number to this thread that has to be withdrawn later. The wait counts and turn counts above do not depend on that calculation.
Follow-up to my comment above: the empty-return rate correlates with the CLI version, and it looks like something between 0.144.6 and 0.146.0 fixed it.
I grouped every rollout in July by the version recorded in its
session_meta, then counted blocking wait calls and how many returned with the payload field empty. These are counts of calls and of return values — they do not depend on any token accounting.| CLI version | wait calls | empty returns | % empty | days seen (July) |
|---|---:|---:|---:|---|
| 0.144.6 | 10,828 | 1,824 | 16.8% | 19–27 |
| 0.143.0 | 653 | 62 | 9.5% | 09–11 |
| 0.144.5 | 2,672 | 201 | 7.5% | 16–19 |
| 0.145.0 | 7,390 | 460 | 6.2% | 22–30 |
| 0.144.1 | 1,567 | 55 | 3.5% | 11–13 |
| 0.144.3 | 2,980 | 69 | 2.3% | 13–19 |
| 0.142.4 | 116 | 2 | 1.7% | 03–09 |
| 0.146.0 | 617 | 4 | 0.6% | 30–31 |
Two things stand out.
0.144.6 is roughly 3x worse than any other version I ran, and it is the version that was active during the 11-day session I described above — it covered nine of those eleven days.
0.146.0 is effectively clean at 0.6%. That also resolved something that had confused me: when I measured the wait calls made by a separate, brand-new account, I got 0.6% empty and read it as "no busy-waiting happened there". It was not a different behaviour — that account simply ran on 0.146.0.
If this holds on other accounts, there is a change between 0.144.6 and 0.146.0 that addresses it, which gives a concrete range to bisect rather than a symptom description.
Caveats, stated plainly: this is one account's data; the samples are uneven (0.146.0 has only 617 wait calls against 10,828 for 0.144.6); and version attribution comes from each rollout's own
session_meta, so a session spanning an upgrade is attributed to the version it opened with. I would not read the ordering of the middle rows as meaningful — the gap between 0.144.6 and 0.146.0 is what I would test.Worth someone with 0.146.0 and heavy multi-agent use confirming whether the empty returns really did stop, or whether they are simply rarer in their workload.
Follow-up on the version correlation I posted above: I think the fix is #34852, "Wake sleeping threads for queued agent mail", merged 2026-07-23.
It touches
codex-rs/core/src/tasks/mod.rs(+16/-4). From its own description:That matches the empty returns exactly. Before it, the sub-agent's message landed in the mailbox but did not wake the sleeping supervisor. The supervisor stayed asleep until its own timeout fired, woke on its own, and found the message already sitting there — and that timeout wake is the billed turn that re-ingests the full prefix. The work was already done; what was missing was the notification.
This lines up with the dates in my table. The fix merged Jul 23. I was still running 0.144.6 from Jul 19 to Jul 27 at 16.8% empty returns, i.e. several days after the fix existed. 0.146.0, which includes it, gives 0.6%.
It also matches @bbingz's reading of the source further up this thread.
Two adjacent commits in the same range suggest this was a recognised problem rather than an incidental change: #34887 "Allow disabling the multi-agent wait tool" and #34969 "Keep the sleep tool outside code mode".
Caveat: I identified this by diffing the two tags and matching commit messages against the observed behaviour — I have not built both versions to confirm the causal link. Someone on the team can verify that far faster than I can.
I still experience heavy preference for polling in 1.46.0. Made a full post here:
https://github.com/openai/codex/issues/32309#issuecomment-5160186183
I built and tested a V2-only root-cause patch for the model re-entry mechanism traced in this thread.
Current
main(5157493c23, 2026-08-02) still wraps the parentInputQueueActivitywatch receiver intimeout_at. When that local deadline expires,wait_agentreturns a function result and the turn loop samples the model again even though agent state has not changed. #34852 improves delivery of queued agent mail, but it does not remove this residual timer-driven re-entry path.Patch: https://github.com/seattled23/codex/commit/74b2624e2d33edb07e3c2ad0d56f191f725b8c2d
The patch:
timeout_msand the deadline from MultiAgentV2 only;timed_outresult field for wire compatibility (alwaysfalse);wait_agent_enabledconfiguration gate on currentmain.Validation against current
main: 11 matched tests passed, including remaining pending without activity, waking on queued/new mailbox activity, preserving the enable/disable gate, the event-only tool schema, and the end-to-end steering interruption test. I also ran the repository formatter and clippy gate on the release-tag version of the same patch.This deliberately does not claim to solve missing child-death notifications: if a terminal path fails to enqueue mailbox activity, that lifecycle defect still needs its own fix. It does eliminate periodic inference turns while the mailbox is genuinely quiet.
I have not opened a PR because the contribution guide says code changes are invitation-only. Happy to rebase or submit one if a maintainer wants this direction.
中文:Windows Codex Desktop 独立排查结果
我在 Windows 11 的 Codex Desktop 上遇到了相同问题。以下结论是我针对自己机器上的 Codex rollout 日志独立排查、逐条统计后得到的,不是根据本 Issue 的数据推测,也不是直接复述现有报告。排查完成后,我才发现这里已有相同机制的反馈。
环境
本地日志统计结果
按本地日期统计,一个工作日的 rollout telemetry 为:
其中一个主要会话产生了 145,083,309 Token,约占当天总量的 80%。
我继续把该会话中的工具调用和紧随其后的 token delta 关联统计,发现:
wait调用共 702 次yield_time_ms=1000:552 次yield_time_ms=10000:139 次yield_time_ms=30000:11 次这说明异常消耗并不是 High/xHigh reasoning 或 Fast 模式造成的。该会话明确使用 Low reasoning 和 Default service tier,而 reasoning token 只有 39,202。主要原因是:后台命令未结束时,每次短间隔
wait都重新进入模型,并重新携带当时约 15 万以上 Token 的长上下文。即使终端没有产生有意义的新输出,也会形成新的完整模型回合。期望行为
说明:以上均为本机 rollout telemetry 的脱敏汇总,不代表 OpenAI 内部计费账本,也不包含任务 ID、文件路径、仓库名称、账号信息、业务内容或原始日志。
---
English: Independently diagnosed on Windows Codex Desktop
I reproduced the same behavior on Codex Desktop for Windows 11. The findings below were independently derived by analyzing and correlating my own local Codex rollout logs. They were not inferred from or copied from this issue. I found this existing report only after completing the investigation.
Environment
Sanitized local telemetry
For one local calendar day:
One main session contributed 145,083,309 tokens, about 80% of the daily total.
I then correlated tool calls with the immediately following per-turn token deltas:
waitcallsyield_time_ms=1000yield_time_ms=10000yield_time_ms=30000This rules out High/xHigh reasoning or Fast mode as the primary cause in this case. The session was consistently configured for Low reasoning and Default service tier, and reasoning usage was only 39,202 tokens. The dominant mechanism was repeated model re-entry while waiting for a terminal process: every short
waitturn carried a context of more than roughly 150k tokens even when the process produced no meaningful new output.Expected behavior
These figures are sanitized summaries from local rollout telemetry, not claims about OpenAI's internal billing ledger. No task IDs, local paths, repository names, account details, business content, or raw logs are included.
Windows Pro 20x addendum: wait polling and rate-bucket mismatch
Environment:
Observed in a long-running Reborn-related task (sanitized local rollout aggregates; no prompts, paths, account identifiers, or checkout data included):
waitcalls and 1list_agentscall.waitcalls, 16 requested a 10-second wait, 9 requested 1 second, and 1 requested 30 seconds.gpt-5.6-solwithreasoning_effort=max; there is no evidence that these children were configured as a fast model.plan_type=probutlimit_id=codex_bengalfox,limit_name=GPT-5.3-Codex-Spark, andprimary.used_percent=0, despite the turn context identifying Sol/max. This makes model/usage attribution ambiguous.Expected behavior:
waitfor unchanged agent/process state should be handled event-driven or with bounded backoff, without repeatedly re-entering the model and reprocessing a large cached context.Requested investigation:
This is a sanitized addendum to the existing wait/status polling report; raw rollout files can be provided privately if maintainers need them.
Environment:
Windows
Codex Desktop
Prolite
weekly window: 2026-08-13 08:13:35 → 2026-08-20 08:13:35
Observed:
6,829 genuine local model turns
554 redundant wait_agent re-entries
Waste:
73,709,145 raw input tokens
73,169,792 cached input
539,353 uncached input
19,553 output
7,973,650 input-equivalent tokens
995.314 estimated credits
Impact:
7.50% of locally observed usage
~6.00 percentage points of the entire weekly rate-limit window
Models:
551 / 554 redundant wakeups were GPT-5.6 Sol
Independent Linux reproduction on Codex CLI 0.149.0 with a ChatGPT Pro 20x
account. I analyzed the complete local rollout corpus from a weekly reset at 0%
used through the first observed 33% state.
Methodology:
last_token_usage, actual model,and reported quota-bucket signature.
or credentials.
Corrected ordinary-pool window:
Wait/status-only subset:
| Class | Turns | Input | Cached input | Estimated credits |
| --- | ---: | ---: | ---: | ---: |
| Terminal/process wait only | 570 | 128.5M | 127.7M | 1,334 |
| Shell sleep + status poll only | 263 | 59.2M | 58.7M | 598 |
| Agent wait/list only | 106 | 40.0M | 39.5M | 347 |
| Total | 939 | 227.7M | 225.9M | 2,278 |
The wait/status subset is 17.4% of reconstructed ordinary credits, equivalent
to roughly 5.7 percentage points of the inferred weekly allowance. The largest
single root had 450 wait/status-only turns and about 947 estimated credits in
that subset.
Repeated patterns include identical
write_stdincalls, 25–50 second shellsleeps followed by unchanged CI/pipeline status checks, and repeated
wait_agent/list_agentscalls. Each interval re-entered the model andreprocessed a large cached prefix.
This supports the requested fix direction in this issue: waits should be
event-driven in the harness, unchanged state should not create a new model
turn, and wait/polling usage should be exposed separately.
I can provide maintainers with sanitized per-turn and per-session metadata
privately if requested. These are local rate-card estimates, not claims about
OpenAI's private server billing ledger. No chat content is included in this
report.
Fresh, narrow follow-up for the direct V2 wait path on Codex CLI 0.149.0. This sample does not use the nested V1
functions.execwrapper described in #35108.Environment:
During a fixed 24-hour window, the root made 91 direct
wait_agentcalls:The 50 timeout-only returns caused 50 model re-entries with:
Completed waits caused another 5.001M processed tokens, but this comment isolates the timeout-only subset because those 50 re-entries occurred without a terminal agent event.
The analysis used each changed cumulative token snapshot once and excluded copied child-history prefixes. The sample therefore does not count fork replay as fresh model activity.
This confirms that the timer-driven re-entry mechanism remains present in 0.149.0. Increasing the timeout reduces poll frequency, but it does not fix the lifecycle: every expired wait still returns unchanged state to the model and reprocesses a large cached context.
The runtime should keep the parent suspended and re-arm waits internally. It should wake the model only for agent completion, failure, actionable output, user input, or an explicitly requested checkpoint.
No prompts, task identifiers, repository names, local paths, account data, or credentials are included.
Fresh sanitized reproduction of model-mediated wait re-entry on the current 0.149.x line.
During one parent turn, the parent delegated work to an existing task and then issued at least 10 consecutive
wait_threadscalls withtimeoutMs=60000. Each timeout returned control to the model, which immediately submitted another 60-second wait. There was no intervening user message and no terminal task event that justified substantive parent work. The sequence consumed roughly 10 minutes, after which the parent also performed manual rollout-status polling.This is a task-level wait API occurrence rather than the nested V1 wrapper path. I am not attaching a token estimate for this sample; the narrow evidence is the repeated timeout -> model re-entry -> identical wait cycle within one parent turn.
Project names, prompts, local paths, hostnames, account data, and task IDs are omitted.
Fresh narrow reproduction on the current 0.149.x line using Codex Desktop and a local orchestrator waiting on an existing Remote SSH task.
The target's observable task state did not change: repeated
wait_threads(timeoutMs=0)snapshots kept the same revision, reported the aggregate thread asactive, and reported the latest terminal turn ascompletedwith a final response.Despite that unchanged state, within 5 minutes 11 seconds the parent issued five completed
wait_threads(timeoutMs=60000)calls and started a sixth. Over the same interval, six model token snapshots increased the cumulative localtotal_tokenscounter by 725,168.Per re-entry:
There was no intervening user input and no target revision or terminal event. The parent was therefore repeatedly sampled to wait on a target that had no new work to report. The aggregate
activebit appears to have kept the polling loop alive even though the latest terminal turn was already completed.This is local rollout telemetry, not a claim about private billing or subscription accounting. No prompts, task IDs, project or repository names, paths, hostnames, addresses, account data, or credentials are included.
Cross-linking this implementation-level consumption amplifier to #41220, the meta tracker for abnormal Codex usage/quota depletion and usage-accounting inconsistencies. Your corrected telemetry showing 19.8% of raw local token volume in wait/status-only turns is especially useful because it demonstrates one mechanism that can reduce effective usable subscription capacity even if the quota arithmetic itself is correct. The tracker explicitly distinguishes this class from entitlement/metering defects.