Skip to content

Align wait_agent default timeout with prompt-cache TTL (30 min on GPT-5.6+) to cut parent-agent polling cost #41875

Open

Description

@johnlanni

What variant of Codex are you using?

CLI (multi-agent / collab mode, GPT-5.6 family)

What feature would you like to see?

Summary: Raise the wait_agent default timeout so the parent-agent polling cadence aligns with the model's prompt-cache TTL (30 min on GPT-5.6+), or make the harness TTL-aware. Today's 30 s default burns parent-agent tokens at ~40 no-op model turns per 20 minutes of waiting, all of which are avoidable.

Background (evidence from existing reports)

wait_agent is already event-driven internally (status watch channels; it returns early on completion), but each timeout expiry returns a timed_out result that re-enters the parent model with the full conversation context. With the 30 s default, a long-running subagent produces a steady stream of no-op parent turns. This is well documented:

What is missing from the discussion so far: the cache-TTL dimension

All quantified reports observe polling cadences of 10–60 s. That is far below any cache TTL, so existing measurements only capture the regime where the prefix never falls out of cache. The interaction between wait interval and cache lifetime has not been analyzed.

GPT-5.6-and-later models guarantee a minimum 30-minute prompt cache lifetime (prompt_cache_options.ttl, only supported value 30m, also the default; per the OpenAI prompt-caching docs). Once wait intervals approach or exceed that TTL, each parent turn pays full uncached input price to rebuild the prefix.

A simple per-hour cost model for a parent holding context C while waiting (cached input ≈ 0.1× uncached price):

  • 30 s interval (current default): 120 turns/h × 0.1·pC = 12 pC/h
  • 20 min interval (keep-alive, every turn cache-hit): 3 × 0.1·pC = 0.3 pC/h
  • ~28 min interval (just under TTL with safety margin): ≈ 0.21 pC/h — the cost optimum
  • 60 min interval (every turn a cache miss, full-price refill): 1 × 1.0·pC = 1.0 pC/h

Two useful invariants from this model:

  1. Even in the worst case (the TTL assumption is wrong and every 20-min turn misses), a 20-min interval costs 3 × 1.0 = 3 pC/h — still 4× cheaper than the best case of the current 30 s default (12 pC/h, all hits). The 30 s default is dominated regardless of TTL behavior.
  2. Within the 1 h hard cap on timeout_ms, a keep-alive interval below TTL is structurally cheaper than any miss interval: at a 0.1 cached discount, a miss interval only wins if it exceeds 10× TTL (10 h) — unreachable.

Caveat, stated separately from the evidence: under the official credit rate card, cached input is metered at ~10% of the input rate, so staying cache-hot is a ~10x difference under quota metering too; what remains officially unspecified is how cached context is weighted inside the included 5-hour/weekly subscription limits (asked in #37299, unanswered; the rate card covers credit-based usage). Regardless of that weighting, turn-count reduction dominates under every metering regime, and for intervals ≤ ~25 min both goals align (fewer turns AND cache-hot).

Request

  1. Raise the default wait_agent timeout for models with a known cache TTL (30 min on GPT-5.6+) from 30 s to a TTL-aligned value (~20–25 min), or surface the cache-TTL consideration in the tool description so the model scales timeout_ms accordingly (the collab prompt already says the value "should be wisely scaled" — the default undercuts that guidance).
  2. Alternatively/additionally, adopt the stronger fix already proposed in Desktop wait/status orchestration re-meters full cached context every 10-30s; stale 'running' subagents keep it looping (90% of weekly Pro in 15.5h) #37299 / Codex Desktop repeatedly re-enters the model during wait/status polling, consuming substantial credits #35259: don't re-enter the model at all when a wait_agent timeout produced no state change — the harness already knows nothing happened.
  3. Align the v1 multi-agent namespace with the v2 config knobs — DEFAULT_WAIT_TIMEOUT_MS = 30_000 in multi_agents_common.rs is hardcoded and ignores [features.multi_agent_v2] settings, so users on the v1 toolset cannot tune this without patching source (noted in Make wait_agent default timeout configurable #18394).
  4. When documenting the knobs, mention the quota-vs-cost trade-off above so users can pick min_wait_timeout_ms / default_wait_timeout_ms deliberately (quota-constrained: larger; cost-constrained: just under TTL).

Additional information

Activity

  1. added
    enhancementNew feature or request
    CLIIssues related to the Codex CLI
    subagentIssues involving subagents or multi-agent features
    rate-limitsIssues related to rate limits, quotas, and token usage reporting
    on Aug 31, 2026
  2. johnlanni commented on Aug 31, 2026

    @johnlanni
    Author

    Follow-up: a case where a short wait interval is optimal — and a debounce idea it motivates

    The cost model in this issue assumed the parent's wake cadence is set by timeout_ms. That holds for quiet waits, but there is a second regime worth spelling out, because it inverts the conclusion.

    In MultiAgentV2, wait_agent returns early on any mailbox update from a live agent. So when the subagent is active, the parent's actual wake interval is g = min(e, T), where e is the subagent's inter-update interval and T is the requested timeout — the timeout only caps, not paces, the wake-ups.

    Worked example with a provider whose cache TTL is 5 min (e.g. Alibaba Model Studio explicit cache, or Anthropic's default 5-min TTL):

    • Subagent produces an update every e = 6 min and finishes at 30 min.
    • e > TTL, so every parent re-entry finds the cache expired: 5 turns × full-price context rebuild.
    • 30 s of polling would actually have been the correct keep-alive cadence here; a 20-min default that is optimal at TTL = 30 min makes this case worse (fewer refresh pings, same 5 misses).

    Two consequences:

    1. The right default is a function of two things the harness can observe: the model family's cache TTL and the subagent's activity pattern. A single static default (30 s or 20 min) cannot be right in both regimes — which strengthens the case for making the harness TTL-aware rather than just bumping the constant.
    2. When e < TTL the parent is woken for every subagent turn even though nothing actionable happened; when e > TTL it is woken exactly often enough to always miss. Both are wasteful in different directions.

    Suggested addition to the fix space: debounce/coalesce parent wake-ups to the TTL boundary.

    When the parent is idle in wait_agent and a non-final mailbox update arrives, don't wake it immediately. Hold pending updates and wake the parent at most once per cache-TTL window (or when updates accumulate past a threshold), and always wake immediately on:

    • a final agent status (completion must not be delayed),
    • steered user input (already wakes immediately in V2).

    This bounds the parent's no-op turn rate regardless of subagent chattiness, keeps wake intervals inside the cache window by construction (the harness doesn't need to know the exact TTL — a conservative internal cap such as 5 min achieves the bounded-turn property on its own), and eliminates the e > TTL always-miss regime. It composes with the existing suggestion of not re-entering the model when a timeout produced no state change: one rule covers timeout-expiry no-ops, the other covers event-driven no-ops.

    For tracing/diagnostics, the wait/status turn attribution work in #35259 would make the effect of such a debounce directly measurable (parent wait-turns per child completion before/after).

  3. razdgann commented on Sep 3, 2026

    @razdgann

    I like the TTL-aware approach because this looks like a case where the optimization shouldn’t only be “make the LLM call cheaper.”

    The first question should be whether another model invocation is necessary just to check if the agent finished.

    Ideally the runtime could wait deterministically for state changes and only wake the model when there is actually new information to reason about.

    We’re exploring this distinction in ModelGate: finding repetitive and expensive LLM traffic that may not need to stay an LLM call.

    Agent polling is probably one of the clearest examples of that problem.

  4. tagorr commented on Sep 8, 2026

    @tagorr

    I have a clean Codex CLI reproduction that strongly supports the failure mode described here.

    Environment: Codex CLI 0.153.1, Plus, Windows; parent gpt-6-astra / low, with 2 × gpt-5.6-luna / xhigh workers.

    During one ~33-minute orchestration run:

    • Astra issued 47 × wait_agent
    • all 47/47 used timeout_ms = 30000
    • all 47/47 returned only timed_out: true
    • those waits account for 23m 30s of the run
    • every timeout re-entered the parent model with roughly 150k input tokens
    • the timeout-only polls consumed 7,130,181 parent input tokens, of which 7,114,112 were cached
    • polling alone represented about 68% of the Astra parent's total raw input volume

    During the same interval, server-reported 5h usage went from 53% to the 100% cap.

    The session guidance explicitly said:

    When calling wait_agent, prefer longer waits (minutes) to avoid busy polling.

    but the parent nevertheless continued using 30-second waits.

    For additional scale, I measured an active Luna Max control session from the same account earlier the same day: 9.54M input tokens over 127 minutes increased the 5h metric by only 8 percentage points.

    So in this reproduction, 7.13M input tokens were spent solely on timeout polls that returned no new worker state.

    Full telemetry, worker accounting, and the uploaded diagnostic thread are here:

    #35259 (comment)

    This seems to support both fixes proposed here: substantially increasing the wait interval, and preferably avoiding parent-model re-entry entirely when a wait_agent timeout contains no state change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIenhancementNew feature or requestperformancerate-limitsIssues related to rate limits, quotas, and token usage reportingsubagentIssues involving subagents or multi-agent features

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions