Skip to content

Model fallback chains

Give each model a list of backups so Empryo switches to another model when a provider is overloaded, rate-limited, or timing out, and your session keeps going.

Recipes3 minutes to read
Copy & share
On this page7 sections

When a provider is overloaded, rate-limits you, or returns server errors, Empryo can switch to a backup model and keep working. You set the backups per model: each model you use can have its own ordered list.

Set it up in the appLink to this section

In the terminal app, open the router:

/router

Scroll to Model Fallback. Each model you use, your default model plus every model in the task router, has its own row. Press <kbd>Enter</kbd> to add a backup, or <kbd>d</kbd> to clear the list.

In the desktop app, the backup lists are in Settings → Agent behavior. Changes save immediately.

Or edit the configLink to this section

json
{
  "defaultModel": "anthropic/claude-sonnet-4-5",
  "modelFallback": {
    "anthropic/claude-sonnet-4-5": [
      "openrouter/anthropic/claude-sonnet-4.5",
      "openai/gpt-5"
    ],
    "anthropic/claude-haiku-4-5": [
      "google/gemini-2.5-flash"
    ]
  }
}

Each key is a model id. Its value is the list of backups, tried in order.

What happens when a model failsLink to this section

  1. Retry first. Empryo retries the same model a few times (3 by default), waiting a little longer each time.
  2. Switch. If it still fails, Empryo moves to the next model in the list. A message in the chat says Switched to fallback model: …, and the header shows the new model.
  3. Start over. If every backup fails, Empryo goes back to the first model and tries the whole list again, up to 3 rounds. After that it shows the original error.
  4. You can always stop it. Ctrl+X stops immediately, wherever it is in the list.

Models that have failed recently are tried later, so a provider that is down does not slow down every request.

Which errors trigger a switchLink to this section

Temporary errors trigger a retry and then a switch:

  • HTTP 408, 429, and any 5xx, including overload errors such as 529.
  • Quota messages that come without a status code, such as "credit balance is exhausted".
  • Network problems: timeouts, refused or reset connections, DNS failures, and streams that close early.

Permanent errors are shown right away, with no retry:

  • 401, and 403 unless the message is about rate limits or overload. These mean the key or account is wrong.
  • Other 4xx errors, such as 400 (bad request), 404 (unknown model), or 422. These mean the request itself is wrong, so another model would not help.

Tune the retriesLink to this section

json
{
  "retry": {
    "maxTransientRetries": 3,
    "maxStallRetries": 3,
    "baseDelayMs": 1000
  }
}
  • maxTransientRetries: retries on the same model before switching. 1 to 10.
  • maxStallRetries: retries when a response stops arriving. Only used when the stall watchdog is on (/timeouts). 1 to 10.
  • baseDelayMs: how long to wait before the first retry. The wait doubles each time, with some randomness. 250 to 60000 ms.

The older maxAttempts field still works as a default for both retry counts. You can also change these with /retry.

Good usesLink to this section

  • Overloaded provider. When Claude returns 529 overloaded, fall back to the same model through a gateway such as openrouter/… or llmgateway/….
  • Separate quotas. Pair a direct Anthropic key with a gateway account, so hitting one limit does not stop you.
  • Outages. Mix providers (anthropic/…, openai/…, google/…) so one provider's outage does not end your session.

What it does not doLink to this section

  • Switch to save money. Fallback reacts to failures, not cost. Use the task router to send work to cheaper models.
  • Handle stalls. If a response just stops without an error, the stall watchdog retries on the same model. Fallback only reacts to errors.
  • Retry permanent errors. A bad key, a malformed request, or an unknown model is shown right away.