{"slug": "the-idle-parent-trap-on-llm-agents", "title": "The idle-parent trap on LLM Agents", "summary": "A developer's analysis of LLM agent orchestration found that idle parent agents on Codex burn tokens polling for worker completion because the runtime lacks event-driven wake-ups, with one run issuing 89 waits that consumed 10.28 million tokens, 6.5% of the run and 12.7% of its list-price cost. The writeup contrasts this with Claude Code, where background workers notify the parent once on completion, and argues the fix for Codex must be structural rather than a declarative \"do not poll\" rule.", "body_md": "Companion to [Two agents, one night, 158 million tokens](//2026-09-16_article_two-agents-one-night-158-million-tokens_Claude-Naruto.md). About four minutes to read.\n\nA parent model delegates a job to a worker and then has nothing else to do. It wants to know when the worker is finished. It has one tool for that: *wait up to N seconds for the worker, then tell me what happened.* The default N is sixty.\n\n```\nBUSY parent (rule holds)                IDLE parent (rule fails)\n\ndispatch worker                         dispatch worker\nwork on own task ─┐                     wait 60 s ─── \"not yet\"   115k tokens\nwork on own task  │ worker finishes     wait 60 s ─── \"not yet\"   115k tokens\nwork on own task  │ notification lands  wait 60 s ─── \"not yet\"   115k tokens\nread result ◄─────┘                     wait 60 s ─── \"not yet\"   115k tokens\n                                          ... × 66 ...\n1 wake-up, paid once                    wait 60 s ─── \"done\"      115k tokens\n```\n\nEach \"not yet\" is a full activation. The parent re-reads its entire conversation to learn that a minute has passed. The rule that says *do not poll* is obeyed as long as the parent is busy, because a busy parent is woken by the worker's completion in the normal course of its next step. The moment the parent is idle, the only way it knows how to wait is the sixty-second wait, and the rule has nothing to grip.\n\n| Measure | Value | \n|---|---|\n| Waits issued by the parent | 89 | \n| At sixty seconds | 88 | \n| Timed out without a result | 66 | \n| Returned a completion | 23 | \n| Tokens in activations that ended in a wait | 10,281,999 | \n| Of which cached re-reads | 10,153,856 | \n| Mean tokens per waiting activation | 115,528 | \n| Share of the whole run | 6.5% | \n| Share of the run's list-price cost | 12.7% | \n\nThe largest single turn issued 62 waits, 50 of which timed out. An earlier, smaller build showed the same pattern at five waits. This is a mechanism, not a one-off.\n\nUpper bound, labelled as a counterfactual: if every timed-out wait had been replaced by a silent notification, the 66 activations at the mean size would not have happened, about 7.6 million tokens. The 23 completions would still have cost a wake-up each. That is the most an event-driven design could remove here, not what it would save.\n\nOn **Claude Code**, a background worker or a background shell command notifies the parent when it finishes. The harness wakes the parent once, on the event. There is nothing to poll, and the guardrail simply says: dispatch, then continue or end the turn.\n\nOn **Codex**, in the runtime we measured, a worker's completion message does not trigger a parent turn. A finished worker cannot wake an idle parent. The parent's only options are a bounded wait or a scheduled check, so a declarative \"do not poll\" rule cannot be followed by an idle parent. The fix has to be structural.\n\nTwo telemetry-only tests decide whether the fix worked, over three consecutive qualifying sessions per agent:\n\nNeither field exists in the telemetry yet. Adding them is fix number four in the article.", "url": "https://wpnews.pro/news/the-idle-parent-trap-on-llm-agents", "canonical_source": "https://dev.to/maxstravion/the-idle-parent-trap-on-llm-agents-1ma5", "published_at": "2026-09-17 04:51:38+00:00", "updated_at": "2026-09-17 05:23:22.903492+00:00", "lang": "en", "topics": ["ai-agents", "large-language-models", "ai-infrastructure", "mlops", "developer-tools"], "entities": ["Claude Code", "Codex", "Claude"], "alternates": {"html": "https://wpnews.pro/news/the-idle-parent-trap-on-llm-agents", "markdown": "https://wpnews.pro/news/the-idle-parent-trap-on-llm-agents.md", "text": "https://wpnews.pro/news/the-idle-parent-trap-on-llm-agents.txt", "jsonld": "https://wpnews.pro/news/the-idle-parent-trap-on-llm-agents.jsonld"}}