[Feature Request] Add a resource-scoped admission gate for provider quota exhaustion
What variant of Codex are you using?
Codex CLI 0.147.0 on Windows 11, using MultiAgentV2 children inside an active Goal. Source analysis below is against main at 3b45c29062ff0e76e71c91b6753290400e7fa8da.
What feature would you like to see?
Add a resource-scoped admission gate for confirmed provider quota or usage exhaustion.
When one model request returns a machine-readable terminal exhaustion condition, Codex should stop admitting later model requests that are known to depend on the same exhausted provider resource. It should not require each parent or subagent to rediscover the same terminal condition through another provider request.
This request is downstream of #16891, which covers preserving structured child errors. It does not ask Codex to classify every HTTP 403 or 429 as shared quota exhaustion, and it does not ask Codex to cancel unrelated sibling work.
Evidence and current ownership
The rollout evidence on #16891 recorded 13 terminal child failures reduced to error strings. After receiving those strings, the parent made 11 explicit followup_task calls targeting 7 of the failed child paths. These were parent/model redispatches, not automatic transport retries. The trace demonstrates that later dispatch remains possible after a terminal provider failure, while the parent has no typed class or resource scope on which to base admission policy.
Current main already contains suitable lifecycle pieces:
AgentControlis shared by one root thread and its subagents, and owns the agent registry, execution limiter, and shared rollout budget.- Native quota and usage-limit errors are non-retryable and map to
CodexErrorInfo::UsageLimitExceeded(classification). - Goals already have a resumable
UsageLimitedstate and an existing transition into it. - The shared
RolloutBudgetaccounts a configured local token budget. Provider availability is a separate resource condition and should not be folded into that counter.
The missing contract is an admission decision between typed provider failure classification and later same-resource dispatch.
Requested contract
- Trip the gate only from a machine-readable terminal exhaustion class plus the finest authoritative resource scope Codex can establish. An HTTP status or provider error string alone is insufficient.
- Scope the resource identity to the relevant provider boundary, such as provider and endpoint/deployment plus an available account, credential slot, model, or quota-bucket identity. If Codex cannot establish that two requests share an exhausted resource, fail only the current request rather than opening a shared breaker.
- Close admission for the affected resource before returning the terminal failure to orchestration. A concurrent
followup_taskor new turn that needs the same resource should receive a typed unavailable/usage-limited result without sending another provider request. - Move affected active Goals to the existing
UsageLimitedstate. Requests using a demonstrably different resource, and local or MCP work that does not consume the exhausted provider resource, should remain eligible to run. - Preserve reset metadata when available. Recovery should use an explicit resume or a bounded half-open probe after
Retry-After/resets_at, with an epoch or generation so pre-trip admissions cannot race with reopened work.
Cancellation does not need to be part of the first implementation. If it is added later, it should target only cancellation-safe in-flight model operations that share the same resource key. It should not broadcast a process-wide cancellation token to arbitrary siblings, shell commands, or MCP calls.
Acceptance scenarios
- Children A and B use the same confirmed quota resource, child C uses a different provider resource, and child D is running a local tool. A receives typed terminal exhaustion: B is fenced before its next provider request, while C and D continue.
- A custom OpenAI-compatible provider returns an ambiguous HTTP 403 with no authoritative quota classification: no shared breaker is opened.
- A transient HTTP 429 includes
Retry-After: same-resource admission observes a bounded cooldown and one half-open probe rather than becoming permanently terminal. - A
followup_taskraces with breaker activation: the admission generation prevents a same-resource request from escaping after the trip decision. - Resume or reset creates a fresh generation and does not inherit stale cancellation state.
- Exhausting the existing local rollout token budget remains distinct from exhausting an external provider quota.
Additional information
Related but separate issues:
- #16891: preserve a structured quota/provider failure across the child-to-parent boundary.
- #23479: expose subagent thread-capacity and lifecycle preflight before
spawn_agent. - #30471: clarify or configure transport-level HTTP 429 retry behavior.
- #32453: fall back to the selected model when previous-model compaction is rate-limited.
Non-goals for this request are a general progress watchdog, automatic model fallback, treating all 403/429 responses as fatal, and globally cancelling sibling agents.
The requested maintainer decision is whether this resource-scoped admission contract fits the existing AgentControl ownership boundary after #16891 preserves the required typed error and scope information.