'Configure automatic model fallbacks for high availability on OpenRouter.
Install to Claude Code
npx -y skills add jeremylongshore/tons-of-skills-marketplace --skill openrouter-fallback-config --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Openrouter Fallback Config?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jeremylongshore-openrouter-fallback-config-14b1c6a6)More formats (shields.io, HTML) on the badges page.
---
name: openrouter-fallback-config
description: 'Configure automatic model fallbacks for high availability on OpenRouter.
Use when building resilient systems that need to survive provider outages. Triggers:
''openrouter fallback'', ''model fallback'', ''openrouter failover'', ''openrouter
backup model''.
'
allowed-tools: Read, Write, Edit, Grep, Bash(python3:*), Bash(curl:*), Bash(jq:*)
version: 1.20.0
license: MIT
author: Jeremy Longshore <jeremy@intentsolutions.io>
tags:
- saas
- openrouter
- reliability
- fallback
- high-availability
compatibility: Designed for Claude Code
---
# OpenRouter Fallback Config
## Overview
OpenRouter supports native model fallbacks: pass multiple model IDs and OpenRouter tries each in order until one succeeds. You can also use `provider.order` to control which provider serves a specific model. This skill covers native fallbacks, provider routing, client-side fallback chains, and timeout configuration.
## Prerequisites
- An OpenRouter API key (`sk-or-v1-...`) exported as `OPENROUTER_API_KEY` — see the `openrouter-install-auth` skill for setup
- Python 3.8+ with the OpenAI SDK (`pip install openai`) for the fallback patterns; `curl` and `jq` for the Testing Fallbacks step
- A ranked list of acceptable models for your workload, matched by capability (tool calling, vision, context length) so a fallback never silently drops a feature you depend on
## Instructions
1. Start with Native Model Fallback (Server-Side): pass a `models` array plus `route: "fallback"` in `extra_body` and let OpenRouter try each model in order.
2. Log `response.model` after every call — it tells you which model actually served the request, which is how you detect that a fallback fired.
3. If you need the *same* model from specific vendors (e.g., Claude via Anthropic direct vs AWS Bedrock), use Provider Fallback with `provider.order` and `allow_fallbacks`.
4. For per-model timeouts and custom error handling, implement the Client-Side Fallback Chain: `resilient_completion()` walks `FALLBACK_CHAIN` (primary → secondary → budget-fallback → last-resort) and raises once every entry fails.
5. Pick chains per feature with Fallback with Capability Matching — `CAPABILITY_CHAINS` keeps tool-calling, vision, long-context, and budget workloads on models that actually support them.
6. Verify the behavior with Testing Fallbacks: send the curl request with an invalid primary model and confirm the response comes back from `openai/gpt-4o-mini`.
## Native Model Fallback (Server-Side)
```python
import os
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
default_headers={"HTTP-Referer": "https://my-app.com", "X-Title": "my-app"},
)
# Pass multiple models -- OpenRouter tries each in order
response = client.chat.completions.create(
model="anthropic/claude-3.5-sonnet", # Primary (used for param validation)
messages=[{"role": "user", "content": "Explain recursion"}],
max_tokens=500,
extra_body={
"models": [
"anthropic/claude-3.5-sonnet",
"openai/gpt-4o",
"google/gemini-2.0-flash-001",
],
"route": "fallback", # Try in order until one succeeds
},
)
# Check which model actually served the request
print(f"Served by: {response.model}")
```
## Provider Fallback (Same Model, Different Providers)
```python
# Route to specific providers in priority order
response = client.chat.completions.create(
model="anthropic/claude-3.5-sonnet",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=200,
extra_body={
"provider": {
"order": ["Anthropic", "AWS Bedrock", "GCP Vertex"],
"allow_fallbacks": True, # Fall to next provider if first fails
},
},
)
```
## Client-Side Fallback Chain
```python
import logging
from openai import OpenAI, APIError, APITimeoutError
log = logging.getLogger("openrouter.fallback")
FALLBACK_CHAIN = [
{"model": "anthropic/claude-3.5-sonnet", "timeout": 30.0, "label": "primary"},
{"model": "openai/gpt-4o", "timeout": 25.0, "label": "secondary"},
{"model": "openai/gpt-4o-mini", "timeout": 15.0, "label": "budget-fallback"},
{"model": "google/gemini-2.0-flash-001", "timeout": 15.0, "label": "last-resort"},
]
def resilient_completion(messages: list[dict], max_tokens: int = 1024, **kwargs):
"""Try each model in the fallback chain until one succeeds."""
last_error = None
for config in FALLBACK_CHAIN:
try:
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
timeout=config["timeout"],
default_headers={"HTTP-Referer": "https://my-app.com", "X-Title": "my-app"},
)
response = client.chat.completions.create(
model=config["model"],
messages=messages,
max_tokens=max_tokens,
**kwargs,
)
log.info(f"Served by {config['label']}: {response.model}")
return response
except (APIError, APITimeoutError) as e:
last_error = e
log.warning(f"{config['label']} failed ({config['model']}): {e}")
continue
raise RuntimeError(f"All fallbacks exhausted. Last error: {last_error}")
```
## Fallback with Capability Matching
```python
# Different models support different features. Match capabilities.
CAPABILITY_CHAINS = {
"tool_calling": [
"anthropic/claude-3.5-sonnet",
"openai/gpt-4o",
"openai/gpt-4o-mini",
],
"vision": [
"openai/gpt-4o",
"anthropic/claude-3.5-sonnet",
"google/gemini-2.0-flash-001",
],
"long_context": [
"google/gemini-2.0-flash-001", # 1M context
"anthropic/claude-3.5-sonnet", # 200K context
"openai/gpt-4o", # 128K context
],
"budget": [
"openai/gpt-4o-mini",
"meta-llama/llama-3.1-8b-instruct",
"google/gemma-2-9b-it:free",
],
}
def capability_fallback(messages, capability="tool_calling", **kwargs):
"""Select fallback chain based on required capability."""
chain = CAPABILITY_CHAINS.get(capability, CAPABILITY_CHAINS["tool_calling"])
return resilient_completion(messages, **kwargs) # Uses FALLBACK_CHAIN
```
## Testing Fallbacks
```bash
# Test with an invalid model to trigger fallback
curl -s https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "invalid/model-name",
"messages": [{"role": "user", "content": "test"}],
"max_tokens": 10,
"models": ["invalid/model-name", "openai/gpt-4o-mini"],
"route": "fallback"
}' | jq '{model: .model, content: .choices[0].message.content}'
# Should succeed with openai/gpt-4o-mini
```
## Output
A configured fallback setup produces:
- Chat completions whose `response.model` field reveals the model that actually served each request — the primary when healthy, a chain entry when a fallback fired
- Log lines from `resilient_completion()`: `Served by primary: anthropic/claude-3.5-sonnet` on success, `primary failed (anthropic/claude-3.5-sonnet): ...` warnings per failed hop
- A `RuntimeError("All fallbacks exhausted. Last error: ...")` when every model in `FALLBACK_CHAIN` fails — the signal to alert on
- From the Testing Fallbacks curl: a `{model, content}` JSON showing the request survived an invalid primary model
## Examples
Force a fallback by putting an invalid model first in the `models` array:
```bash
curl -s https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "invalid/model-name", "messages": [{"role": "user", "content": "test"}],
"max_tokens": 10, "models": ["invalid/model-name", "openai/gpt-4o-mini"], "route": "fallback"}' \
| jq '{model: .model, content: .choices[0].message.content}'
```
```json
{"model": "openai/gpt-4o-mini", "content": "Test received!"}
```
The `model` field proves the fallback chain worked. More worked examples: `references/examples.md`.
## Error Handling
| Error | Cause | Fix |
|-------|-------|-----|
| All fallbacks exhausted | Every model in chain failed | Add more diverse providers; alert on full chain failure |
| Slow cascade | Each model timing out sequentially | Reduce per-model timeout to 10-15s |
| Inconsistent responses | Different models have different capabilities | Ensure all fallback models support features your prompt uses |
| Wrong model served | Fallback triggered unexpectedly | Log which model served each request; check primary model health |
## Enterprise Considerations
- Use server-side fallback (`models` + `route: "fallback"`) for simplicity; client-side for fine-grained control
- Set per-model timeouts -- expensive models get longer timeouts, budget fallbacks get shorter
- Log which model served each request to track fallback frequency (indicates primary model issues)
- Test fallback chains regularly by intentionally failing the primary model
- Match fallback models by capability (tool calling, vision, context length) to avoid silent feature degradation
- Use `provider.order` when you need the same model from a different provider (e.g., Claude via Anthropic direct vs AWS Bedrock)
## References
- Examples | Errors
- [Model Routing](https://openrouter.ai/docs/features/model-routing) | [Provider Routing](https://openrouter.ai/docs/features/provider-routing)
Scanned 9/2/2026
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!