Skip to content

feat: quota-aware subagent model fallback chain (#374)#391

Merged
Wibias merged 12 commits into
lidge-jun:devfrom
Wibias:codex/issue-374-subagent-model-fallback
Jul 25, 2026
Merged

feat: quota-aware subagent model fallback chain (#374)#391
Wibias merged 12 commits into
lidge-jun:devfrom
Wibias:codex/issue-374-subagent-model-fallback

Conversation

@Wibias

@Wibias Wibias commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements quota-aware subagent model fallback for thread_spawn child turns (issue #374).

  • Adds subagentModelFallback and subagentModelFallbackPollMs config
  • Rewrites child spawn requests at the proxy choke point before routing
  • Skips quota-exhausted native models and recently failed routed models
  • Supports per-agent TOML model_fallback merge
  • Primes Codex pool quotas before spawn selection
  • Records quota-like subagent failures for short TTL health blocking
  • Adds /api/subagent-model-fallback management route
  • Injects fallback-chain guidance into v2 multi-agent guidance

Verification

  • bun run typecheck
  • bun test tests/subagent-model-fallback.test.ts tests/multi-agent-compat.test.ts

Closes #374

Summary by CodeRabbit

  • New Features
    • Added quota- and health-aware subagent model fallback that can automatically rewrite spawned targets and inject fallback guidance into multi-agent instructions.
    • Added a management endpoint to view/update the fallback priority chain and polling interval.
    • Added support for the {{fallback}} placeholder in multi-agent guidance.
  • Bug Fixes
    • Improved thread-spawn rate-limit/quota failure detection and attribution, with more accurate rerouting and underlying request model updates.
    • Added dynamic Codex home resolution so environment changes are reflected after import.
  • Tests
    • Added end-to-end tests for chain building/deduping, fallback selection, guidance rendering, and spawn reroute behavior.

@github-actions github-actions Bot added the enhancement New feature or request label Jul 24, 2026
@coderabbitai

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requested fallback behavior is valuable, but the current implementation can repeatedly select an exhausted model or select against the wrong account. The unresolved findings are substantive: 429/402 are not classified, routed failures are cached under a different key than the configured slug, selection runs before pool account resolution and uses the main plan for pool accounts, native health is not account-scoped, the normal SSE path does not record failures, and combo/encrypted child paths can be rewritten incorrectly. Please rebuild the selection at the resolved routing/account boundary, validate configuration atomically, make the tests independent, resolve the current dev conflict, and re-request review.

@Wibias
Wibias marked this pull request as draft July 24, 2026 07:23
@Wibias
Wibias force-pushed the codex/issue-374-subagent-model-fallback branch from 4fc8a1d to d4d5b1a Compare July 24, 2026 11:06
@Wibias
Wibias marked this pull request as ready for review July 24, 2026 18:25
chatgpt-codex-connector[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

Wibias added a commit to Wibias/opencodex that referenced this pull request Jul 24, 2026
Wibias added a commit to Wibias/opencodex that referenced this pull request Jul 24, 2026
@Wibias

This comment was marked as outdated.

Wibias added a commit to Wibias/opencodex that referenced this pull request Jul 25, 2026
Ensure fallback selection skips stale provider-prefixed entries while still allowing valid raw vendor/model slugs, and cache native slug lookups so selection no longer times out under test load.
@Wibias
Wibias requested a review from Ingwannu July 25, 2026 03:45
coderabbitai[bot]

This comment was marked as outdated.

@lidge-jun

Copy link
Copy Markdown
Owner

🔒 Under maintainer review — detailed feedback incoming

@lidge-jun (maintainer) has this PR in an active review pass. Please do not merge or close
it
until the detailed review lands; a full comment with specific file:line findings,
failure modes, and suggested fixes is being prepared.

This PR is not part of the current integration batch. It is held back deliberately —
either because it touches a security boundary that MAINTAINERS.md requires an explicit
security review for, because it needs to be split into reviewable units, or because it needs
a rebase onto changes landing in dev right now.

Heads-up on rebasing: dev is receiving a coordinated integration batch today. If this PR
touches the same files, expect to rebase after that batch lands. The upcoming review comment
will name the exact overlapping paths so you only have to do it once.

No action needed from you until then. Thanks for the contribution and for your patience.

Review tracker: devlog/_plan/260725_pr_issue_rework · marker posted by the maintainer review pass

@lidge-jun

Copy link
Copy Markdown
Owner

Thank you for the substantial quota-aware subagent fallback work. I found three correctness blockers that need to be resolved before merge.

  1. src/codex/subagent-model-fallback.ts:275-281 starts quota refresh work with void and returns no promise. The caller at src/server/responses/core.ts:700-703 uses await maybePrimeSubagentQuota(...), but that await resolves immediately, so model selection can run on stale quota state. Return the actual refresh promise (with errors handled at the owning boundary) and add a deferred-promise regression proving selection waits for the refresh result.

  2. src/server/management/agent-settings-routes.ts:328-331 silently removes invalid entries with filter() instead of rejecting the request. That violates the management API's atomic validation contract: a typo can persist a partially truncated fallback chain while returning success. Validate every item first, return 400 with the offending index/value, and mutate config only after the whole payload is valid. Add a regression proving one invalid entry leaves the previous config unchanged.

  3. src/codex/subagent-model-fallback.ts:173-184 does not record ordinary rate-limit wording as a health block. Providers that report rate limiting without the currently recognized quota phrases remain eligible and are selected repeatedly. Normalize the existing rate-limit classifier into this health path and test representative generic 429/rate-limit messages without treating unrelated errors as quota exhaustion.

I appreciate the scope of this feature. The refresh must be truly awaited, settings updates must be atomic, and generic rate limits must participate in the same health block before the fallback chain is reliable.

Please also rebase onto current dev, which now includes #439's context-pressure fields in src/types.ts; preserve that public type contract.


Reviewed as part of a maintainer integration pass. dev moved to ebc62d1f today (7 PRs integrated); Cross-platform CI is green on ubuntu, macOS, and Windows.

Wibias added 7 commits July 25, 2026 20:42
Ensure fallback selection skips stale provider-prefixed entries while still allowing valid raw vendor/model slugs, and cache native slug lookups so selection no longer times out under test load.
…imit health

Make maybePrimeSubagentQuota return an awaitable refresh promise, reject invalid fallback-chain entries without truncating config, and route health blocks through the shared rate-limit/quota classifier.
@Wibias
Wibias force-pushed the codex/issue-374-subagent-model-fallback branch from ed1ee20 to 8f467d2 Compare July 25, 2026 18:47
coderabbitai[bot]

This comment was marked as resolved.

Repository owner deleted a comment from coderabbitai Bot Jul 25, 2026
Release abandoned Codex probe leases on pre-upstream fallback reroutes, run virtual-model/effort/service-tier normalization only against the final route, allow encrypted children to reach native fallbacks, and coalesce concurrent quota primes with success-only TTL.
coderabbitai[bot]

This comment was marked as outdated.

Wibias added 4 commits July 25, 2026 21:37
…verage

Avoid gpt-5.5 in native-only encrypted spawn tests: with an isolated CODEX_HOME, nativeOpenAiSlugs() can resolve to DOCUMENTED_NATIVE_OPENAI_ADDITIONS only, which omits gpt-5.5 and made CI reject before native fallback.
Avoid leasing primary Codex auth before routed fallback selection, clamp effort from the final native route, and always invoke passthrough terminal callbacks for non-quota stream failures.
Use routeModel and canonical/pool route metadata for encrypted eligibility and Codex quota checks instead of slug-only nativeSlugSet matching.
Drop the global explicit-pool config probe. Pool candidates now require a usable preview account based on each candidate routeModel result, including default openai pool mode.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Subagent model fallback chain with quota-aware auto-switching

3 participants