← Back to PRs

#13188: fix: add cross-provider fallback when primary provider is rate-limited

by 1bcMax open 2026-02-10 06:07 View on GitHub →
agents stale
## Summary When all models from the primary provider are exhausted or rate-limited, the fallback chain now includes models from OTHER configured providers. This addresses issue #13082 where users with Anthropic-only fallbacks couldn't escape to OpenRouter when Anthropic returned 429. ## Changes - `resolveFallbackCandidates()` now appends one model from each configured provider (in `models.providers`) that isn't already in the fallback chain - Added test case verifying cross-provider escape on rate limit ## Before ``` Primary: anthropic/claude-sonnet-4 Fallbacks: [anthropic/claude-opus-4] When Anthropic returns 429: 1. Try claude-sonnet-4 → 429 2. Try claude-opus-4 → 429 3. Error: All models failed ``` ## After ``` Primary: anthropic/claude-sonnet-4 Fallbacks: [anthropic/claude-opus-4] Configured providers: { openrouter: { models: [...] } } When Anthropic returns 429: 1. Try claude-sonnet-4 → 429 2. Try claude-opus-4 → 429 3. Try openrouter/first-model → Success! (cross-provider escape) ``` ## Test Plan - [x] All existing tests pass (19/19) - [x] New test case for cross-provider fallback passes - [ ] Manual testing with real rate-limited scenario Fixes #13082 <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR extends `resolveFallbackCandidates()` so that when the primary provider (and its configured fallbacks) are exhausted/rate-limited, the fallback chain can “escape” to at least one model from other configured providers in `cfg.models.providers`. A new Vitest test exercises the Anthropic->OpenRouter cross-provider fallback path on 429s. Main integration point is `src/agents/model-fallback.ts`, which constructs the ordered candidate list consumed by `runWithModelFallback()`. The added logic appends at most one model per extra provider after the existing primary/fallbacks/configured-primary candidates. <h3>Confidence Score: 3/5</h3> - This PR is close, but has a couple of correctness gaps in provider normalization and test realism that should be fixed before merging. - The functional intent is clear and the change is localized, but (1) using raw `models.providers` keys as provider IDs can break allowlist/cooldown matching when keys aren’t normalized, and (2) the new test uses an invalid `ModelProviderConfig.models` shape that may not reflect real validated configs. - src/agents/model-fallback.ts, src/agents/model-fallback.test.ts <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs