feat(config): support multiple API keys for failover#1707
Merged
yinwm merged 2 commits intosipeed:mainfrom Mar 18, 2026
Merged
Conversation
23f8c0e to
e8058ae
Compare
Add api_keys field to ModelConfig to support multiple API keys with
automatic failover. When multiple keys are configured, they are expanded
into separate model entries with fallbacks set up for key-level failover.
Example config:
{
"model_name": "glm-4.7",
"model": "zhipu/glm-4.7",
"api_keys": ["key1", "key2", "key3"]
}
Expands internally to:
- glm-4.7 (key1) -> fallbacks: [glm-4.7__key_1, glm-4.7__key_2]
- glm-4.7__key_1 (key2)
- glm-4.7__key_2 (key3)
Backward compatible: single api_key still works as before.
e8058ae to
ca153d5
Compare
This enables proper key-switching when multiple API keys share the same provider. Previously, when one key failed, all keys were blocked because cooldown was tracked per-provider. Now each (provider, model) combination has independent cooldown, allowing fallback to alternate keys when one is rate limited. Includes TestMultiKeyWithModelFallback and related failover tests.
ca153d5 to
38e144d
Compare
yinwm
approved these changes
Mar 18, 2026
Collaborator
yinwm
left a comment
There was a problem hiding this comment.
Pre-Landing Review: Approved ✅
Scope Check: CLEAN
- Intent: Support multiple API keys with automatic failover + fix cooldown tracking granularity
- Delivered: Complete implementation of
api_keysfield,ExpandMultiKeyModelsexpansion, cooldown changed from provider-level to (provider, model)-level
Backward Compatibility: 100%
- Old configs with single
api_keywork unchanged - New fields (
api_keys,fallbacks) are optional withomitempty - Cooldown granularity change is a positive improvement
Pass 1 (CRITICAL):
- ✅ SQL & Data Safety - Not applicable
- ✅ Race Conditions - Cooldown tracking correctly uses
ModelKey(provider, model) - ✅ LLM Output Trust Boundary - Not applicable
- ✅ Enum & Value Completeness - No new enum values
Pass 2 (INFORMATIONAL):
- ✅ Conditional Side Effects - Fallback chain logic is clear
- ✅ Magic Numbers -
__key_suffix is a reasonable naming convention - ✅ Dead Code - Clean code, comprehensive test coverage
- ✅ Test Gaps - Tests cover: single key, multi key, mixed key scenarios, fallback chain, cooldown skip, format error non-retry, cross-model fallback combination
Code Quality Highlights:
ExpandMultiKeyModelscorrectly copies all necessary fields (RPM, Timeout, ThinkingLevel, etc.)resolveAPIKeyshandles bothAPIKeyandAPIKeysarray decryption- Backward compatible: single
api_keycontinues to work normally
Optional suggestion (non-blocking):
- Consider extracting a
cloneModelConfighelper function if more fields are added in the future
Conclusion: High-quality PR with clear implementation, comprehensive tests, and full backward compatibility. Ready to merge.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add
api_keysfield toModelConfigto support multiple API keys with automatic failover. When multiple keys are configured, they are expanded into separate model entries with fallbacks set up for key-level failover.Also fixed cooldown tracking granularity from provider-level to
(provider, model)-level, enabling proper key-switching when multiple keys share the same provider.Failover Flow
Cooldown Fix
Before: Cooldown tracked per-provider → all keys blocked when one fails
After: Cooldown tracked per
(provider, model)→ each key has independent cooldownUsage
{ "model_name": "glm-4.7", "model": "zhipu/glm-4.7", "api_keys": ["key1", "key2", "key3"] }Expands internally to:
glm-4.7(uses key1) → fallbacks: [glm-4.7__key_1,glm-4.7__key_2]glm-4.7__key_1(uses key2)glm-4.7__key_2(uses key3)Backward Compatibility
Single
api_keystill works as before:{"model_name": "gpt-4", "model": "openai/gpt-4o", "api_key": "single-key"}Test Plan
Config expansion tests:
TestExpandMultiKeyModels_SingleKey- single key unchangedTestExpandMultiKeyModels_APIKeysOnly- array only configTestExpandMultiKeyModels_APIKeyAndAPIKeys- both fields mergedTestExpandMultiKeyModels_WithExistingFallbacks- prepends to existing fallbacksTestExpandMultiKeyModels_EmptyAPIKeys- empty array handledTestExpandMultiKeyModels_Deduplication- duplicate keys removedTestExpandMultiKeyModels_PreservesOtherFields- other config preservedTestMergeAPIKeys- key merging logicFailover behavior tests:
TestMultiKeyFailover- key1 429 → key2 successTestMultiKeyFailoverAllFail- all keys fail → FallbackExhaustedErrorTestMultiKeyFailoverCooldown- key1 in cooldown → skippedTestMultiKeyFailoverWithFormatError- non-retriable error → no fallbackTestMultiKeyWithModelFallback- keys exhausted → model fallback