Model Failover
How OpenClaw rotates authentication profiles and falls back across models.
OpenClaw handles failures in two phases:
1. Authentication profile rotation within the current provider.
2. ''Model fallback'' to the next model in ''agents.defaults.model.fallbacks''.
This document explains the runtime rules and the data that supports them.
Authentication Storage (Keys + OAuth)
OpenClaw uses authentication profiles for API keys and OAuth tokens.
- Secrets live in ''~/.openclaw/agents/<agentId>/agent/auth-profiles.json'' (legacy: ''~/.openclaw/agent/auth-profiles.json'').
- Configuration ''auth.profiles'' / ''auth.order'' is ''metadata + routing'' (no secrets).
- Legacy OAuth-only import: ''~/.openclaw/credentials/oauth.json'' (imported into ''auth-profiles.json'' on first use).
More details: ''/concepts/oauth''
Credential types:
- ''type: "api_key"'' β ''{ provider, key }''
- ''type: "oauth"'' β ''{ provider, access, refresh, expires, email? }'' (for some providers, + ''projectId''/''enterpriseUrl'')
Profile IDs
OAuth logins create distinct profiles so multiple accounts can coexist.
- Default: ''provider:default'' (when no email is available).
- OAuth with email: ''provider:<email>'' (e.g., ''google-antigravity:[email protected]'').
Profiles live under ''profiles'' in ''~/.openclaw/agents/<agentId>/agent/auth-profiles.json''.
Rotation Order
When a provider has multiple profiles, OpenClaw selects in this order:
1. ''Explicit configuration'': ''auth.order[provider]'' (if set).
2. ''Configured profiles'': ''auth.profiles'' filtered by provider.
3. ''Stored profiles'': entries in the provider's ''auth-profiles.json''.
If no explicit order is configured, OpenClaw uses a round-robin order:
- Primary key: profile type (OAuth before API key).
- ''Secondary key:'' ''usageStats.lastUsed'' (oldest first within each type).
- Cooldown/disabled profiles move to the end, sorted by earliest expiration.
#
Session Stickiness (Cache-Friendly)
OpenClaw pins the selected authentication profile per session to keep provider caches warm.
It does not rotate per-request. The pinned profile is reused until:
- Session reset (''/new'' / ''/reset'')
- Compaction completes (compaction count increments)
- Profile is in cooldown/disabled state
Manual selection via ''/model β¦@<profileId>'' sets a ''user override'' for that session
and does not auto-rotate until a new session starts.
Auto-pinned profiles (chosen by the session router) are treated as preferences:
They are tried first, but OpenClaw may rotate to another profile on rate limit/timeout.
User-pinned profiles stay locked to that profile; if it fails and model fallback
completes, OpenClaw moves to the next model instead of switching profiles.
Why OAuth Appears "Lost"
If you have both OAuth and API key profiles for the same provider, rotation can switch between them across messages unless pinned. To force a single profile:
- Pin with ''auth.order[provider] = ["provider:profileId"]'', or
- Use per-session override and profile override via ''/model β¦'' (when your UI/chat interface supports it).
Cooldown Times
When a profile fails due to auth/rate limit errors (or looks like a timeout
like rate limits), OpenClaw marks it for cooldown and moves to the next profile.
Format/invalid request errors (e.g., Cloud Code Assist tool call ID
validation failures) are treated as worthy of failover and use the same cooldown.
Cooldowns use exponential backoff:
- 1 minute
- 5 minutes
- 25 minutes
- 1 hour (capped)
{
"usageStats": {
"provider:profile": {
"lastUsed": 1736160000000,
"cooldownUntil": 1736160600000,
"errorCount": 2
}
}
}Billing Disable
Billing/credit failures (e.g., "insufficient credit"/"credit balance too low") are treated as worthy of failover, but they're usually not transient. Instead of a short cooldown, OpenClaw marks the profile as disabled (with a longer backoff) and rotates to the next profile/provider.
Status is stored in ''auth-profiles.json'':
{
"usageStats": {
"provider:profile": {
"disabledUntil": 1736178000000,
"disabledReason": "billing"
}
}
}Defaults:
- Billing backoff starts at 5 hours, doubles on each billing failure, capped at 24 hours.
- If a profile doesn't fail within 24 hours, the backoff counter resets (configurable).
Model Fallback
If all profiles for a provider fail, OpenClaw moves to the next model in
''agents.defaults.model.fallbacks''. This applies to auth failures, rate limits, and
timeouts that exhaust profile rotation (other errors don't advance fallbacks).
When a run starts with a model override (hook or CLI), fallbacks still try
''agents.defaults.model.primary'' after any configured fallbacks.
Related Configuration
See ''Gateway Configuration'' for:
- ''auth.profiles'' / ''auth.order''
- ''auth.cooldowns.billingBackoffHours'' / ''auth.cooldowns.billingBackoffHoursByProvider''
- ''auth.cooldowns.billingMaxHours'' / ''auth.cooldowns.failureWindowHours''
- ''agents.defaults.model.primary'' / ''agents.defaults.model.fallbacks''
- ''agents.defaults.imageModel'' routing
For a broader overview of model selection and fallbacks, see ''Models''.