Providers, routing, and fallbacks
How the Gateway routes requests across providers, handles fallbacks, and supports per-request routing controls.
The Gateway can route chat completion requests to four production providers and supports a hierarchical fallback chain when the primary provider is unavailable.
Supported providers
| Provider ID | Common name | Environment variable |
|---|---|---|
openai | OpenAI | OPENAI_API_KEY |
anthropic | Anthropic | ANTHROPIC_API_KEY |
deepseek | DeepSeek | DEEPSEEK_API_KEY |
openai-compatible | Any OpenAI-compatible endpoint | ETHEN_OPENAI_COMPATIBLE_BASE_URL, ETHEN_OPENAI_COMPATIBLE_API_KEY |
A mock provider is available for local development when MOCK_MODE=true is set. The mock provider returns a pre-determined response without calling any upstream API.
Route profiles
A route profile defines a capability category and maps it to default models across providers:
| Route ID | Capability | Purpose |
|---|---|---|
text-general | generic | General-purpose text responses (default route). |
text-quality | quality | Editing, rewriting, and precision-oriented text work. |
text-creative | creative | Drafting, ideation, and open-ended creative text. |
text-reasoning | reasoning | Research, analysis, and problem-solving. |
When a request does not specify a route, the Gateway uses text-general.
Provider ordering
The Gateway determines which provider to call first using the following priority:
- Request-level
providerOptions.gateway.order— if set, this list takes
highest priority.
- Cortex router selection — when the request includes a provider selected
by the router, that provider is tried first.
- Environment default — set the
ETHEN_DEFAULT_PROVIDERenvironment
variable to openai, anthropic, deepseek, or openai-compatible.
- Auto-detected order — all available providers are tried in the order
openai → anthropic → deepseek → openai-compatible.
Providers that are not configured (no API key set), have an open circuit breaker, or are blocked by a project's provider allowlist are skipped.
Fallback behavior
When the primary provider fails, the Gateway falls back to the next available provider in the chain:
- Same-provider retries — the Gateway retries the primary provider up to the
configured limit if the failure is classified as retryable (transient network error, timeout, rate-limit, or server error).
- Cross-provider fallback — after exhausting retries on the primary provider,
the Gateway moves to the next provider in the ordered chain.
- Cortex fallback policy — when Cortex is active, its fallback policy can
override both retry counts and cross-provider fallback behavior.
Each provider attempt is logged with status, latency, and error details, visible in the request logs.
Circuit breaker
The Gateway tracks per-provider failures using a circuit breaker. When a provider fails repeatedly, the circuit opens and the provider is temporarily excluded from routing. A successful request closes the circuit and restores the provider to the eligible pool.
Per-request routing controls
The Gateway supports OpenAI-style providerOptions.gateway in the chat completions request body for fine-grained routing:
| Field | Type | Description |
|---|---|---|
order | string[] | Preferred provider execution order (highest priority first). |
only | string[] | Restrict eligible providers to this allow-list. |
models | Record<string, string> | Per-provider model alias overrides. |
providerTimeouts | Record<string, number> | Per-provider timeout in milliseconds. |
Example:
{
"model": "openai/gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello"}],
"providerOptions": {
"gateway": {
"order": ["anthropic", "openai"],
"only": ["anthropic", "openai"],
"models": {
"anthropic": "claude-sonnet-4-20250514"
},
"providerTimeouts": {
"anthropic": 30000
}
}
}
}Unknown or invalid provider IDs in the routing controls are silently dropped — they never cause a 400 error.
Provider allowlist
Projects can configure a provider allowlist to restrict which providers are eligible for use. When a project has any allowlist entries:
- Only explicitly allowed providers are considered for routing.
- Providers with no matching entry are denied by default.
When no allowlist is configured (the default), all available providers are eligible. Allowlist enforcement requires a configured Supabase storage backing. If storage is unavailable the check fails closed: provider access is denied unless GATEWAY_BYPASS_ALLOWLIST_CHECK=true is set (local development only).
Listing providers
GET /api/gateway/v1/providers
Authorization: Bearer ***Returns metadata about all known providers including configuration status and runnable model counts:
{
"data": [
{
"providerId": "openai",
"providerName": "OpenAI",
"providerKnown": true,
"health": {
"configured": true,
"setupRequired": false
},
"runnableModelCount": 42
}
],
"meta": {
"providerCount": 5,
"knownProviderCount": 5,
"runnableProviderCount": 2
}
}