Fallback model chain — per-worker model degradation
When a LoopAgentAdapter worker's primary model is overloaded or unavailable (HTTP 429 / 402 /
5xx / unexpected overload 400), Cyberine retries the same request with the next model in a
configured fallback chain — up to 3 models total — before dropping the worker out of the race.
This keeps the worker contributing even when its primary model is temporarily overwhelmed.
Behavior with no fallback configured: unchanged (errors propagate as before).
Global fallback chain — applies to every loop adapter that has no per-provider override:
CYBERINE_FALLBACK_MODELS=deepseek-v4-flash,deepseek-v4-plus cyberine run "..."Per-provider override — takes precedence over the global chain for that provider's adapters.
Prefix matches the provider id in the adapter options (e.g. deepseek, openrouter, moonshot).
Not resolved from config.ts directly; pass the list explicitly in LoopAgentAdapterOptions.fallbackModels
when constructing an adapter programmatically, or set CYBERINE_FALLBACK_MODELS for the global default.
How it works:
- Primary model fails with a retryable error (429/402/5xx/overload).
- Cyberine records a model-scoped cooldown (
~/.cyberine/worker-cooldown.json, keyworkerId::modelId) so the failed model is skipped on the next dispatch — but the worker itself stays eligible. - The adapter retries with the next model in the chain. The message list is reset to the original prompt (partial tool-call context from the failed attempt is discarded).
- On success, the model that served the result is recorded in
run.jsonraw.servedByModel. - If every model in the chain fails, the worker errors as before.
Provenance — the serving model appears in run.json:
{ "raw": { "servedByModel": "deepseek-v4-flash", ... } }Env vars:
| Var | Default | Purpose |
|---|---|---|
CYBERINE_FALLBACK_MODELS | (empty) | Global ordered fallback chain for loop adapters; comma list, max 3 model ids. Empty = no fallback (default) |
Provider circuit breaker and bounded retry — one dead provider degrades the fleet, not the run
Distinct from the quota cooldown above, which reacts only to a 402/429 quota signal: the breaker counts consecutive terminal failures of any shape at the Orchestrator.dispatch() seam, so it also...
CLI flag-compat diagnosis + structured-output knobs (T656)
The claude and codex build workers pass version-gated CLI flags (e.g. codex's --dangerously-bypass-hook-trust, claude's --exclude-dynamic-system-prompt-sections). On an older installed CLI, the...