---
read_when:
    - Діагностика ротації профілів автентифікації, періодів очікування або поведінки резервного перемикання моделі
    - Оновлення правил аварійного перемикання для профілів автентифікації або моделей
    - Розуміння того, як перевизначення моделі сеансу взаємодіють із повторними спробами резервного варіанта
sidebarTitle: Model failover
summary: Як OpenClaw чергує профілі автентифікації та переходить до резервних моделей
title: Аварійне перемикання моделі
x-i18n:
    generated_at: "2026-04-28T11:09:05Z"
    model: gpt-5.5
    provider: openai
    source_hash: af8c343186105256cb2e1a65cdfc3e0042ce8d3d14d21cd007d90174e35b98e7
    source_path: concepts/model-failover.md
    workflow: 16
---

OpenClaw обробляє збої у два етапи:

1. **Ротація профілів автентифікації** в межах поточного провайдера.
2. **Перехід на резервну модель** до наступної моделі в `agents.defaults.model.fallbacks`.

Цей документ пояснює правила виконання та дані, на яких вони базуються.

## Потік виконання

Для звичайного текстового запуску OpenClaw оцінює кандидатів у такому порядку:

<Steps>
  <Step title="Визначення стану сесії">
    Визначає активну модель сесії та налаштування профілю автентифікації.
  </Step>
  <Step title="Побудова ланцюжка кандидатів">
    Будує ланцюжок кандидатів моделей із поточного вибору моделі та політики резервних варіантів для джерела цього вибору. Налаштовані типові значення, основні моделі Cron-завдань і автоматично вибрані резервні моделі можуть використовувати налаштовані резервні варіанти; явні вибори користувача в сесії є строгими.
  </Step>
  <Step title="Спроба з поточним провайдером">
    Пробує поточного провайдера з правилами ротації/охолодження профілів автентифікації.
  </Step>
  <Step title="Перехід далі за помилок, придатних для аварійного перемикання">
    Якщо цей провайдер вичерпано з помилкою, придатною для аварійного перемикання, переходить до наступного кандидата моделі.
  </Step>
  <Step title="Збереження резервного перевизначення">
    Зберігає вибране резервне перевизначення до початку повторної спроби, щоб інші читачі сесії бачили того самого провайдера/модель, які runner збирається використати. Збережене перевизначення моделі позначається як `modelOverrideSource: "auto"`.
  </Step>
  <Step title="Вузький відкат у разі збою">
    Якщо резервний кандидат зазнає збою, відкочує лише поля перевизначення сесії, що належать резервному механізму, коли вони все ще відповідають цьому невдалому кандидату.
  </Step>
  <Step title="Викидання FallbackSummaryError, якщо все вичерпано">
    Якщо кожен кандидат зазнає збою, викидає `FallbackSummaryError` з деталями кожної спроби та найранішим завершенням охолодження, коли воно відоме.
  </Step>
</Steps>

Це навмисно вужче, ніж «зберегти й відновити всю сесію». Runner відповіді зберігає лише ті поля вибору моделі, якими він володіє для резервного переходу:

- `providerOverride`
- `modelOverride`
- `modelOverrideSource`
- `authProfileOverride`
- `authProfileOverrideSource`
- `authProfileOverrideCompactionCount`

Це запобігає тому, щоб невдала резервна повторна спроба перезаписала новіші непов’язані зміни сесії, як-от ручні зміни `/model` або оновлення ротації сесії, що сталися під час виконання спроби.

## Політика джерела вибору

OpenClaw відокремлює вибраного провайдера/модель від причини їх вибору. Це джерело визначає, чи дозволено ланцюжок резервних варіантів:

- **Налаштоване типове значення**: `agents.defaults.model.primary` використовує `agents.defaults.model.fallbacks`.
- **Основна модель агента**: `agents.list[].model` є строгою, якщо об’єкт моделі цього агента не містить власних `fallbacks`. Використовуйте `fallbacks: []`, щоб явно задати строгу поведінку, або надайте непорожній список, щоб увімкнути для цього агента резервний перехід між моделями.
- **Автоматичне резервне перевизначення**: резервний перехід під час виконання записує `providerOverride`, `modelOverride` і `modelOverrideSource: "auto"` перед повторною спробою. Це автоматичне перевизначення може й далі проходити налаштований ланцюжок резервних варіантів і очищається командами `/new`, `/reset` і `sessions.reset`.
- **Користувацьке перевизначення сесії**: `/model`, вибір моделі, `session_status(model=...)` і `sessions.patch` записують `modelOverrideSource: "user"`. Це точний вибір у межах сесії. Якщо вибраний провайдер/модель зазнає збою до створення відповіді, OpenClaw повідомляє про збій замість відповіді від непов’язаного налаштованого резервного варіанта.
- **Застаріле перевизначення сесії**: старіші записи сесій можуть мати `modelOverride` без `modelOverrideSource`. OpenClaw трактує їх як користувацькі перевизначення, щоб явний старий вибір не було непомітно перетворено на резервну поведінку.
- **Модель у payload Cron**: `payload.model` / `--model` Cron-завдання є основною моделлю завдання, а не користувацьким перевизначенням сесії. Вона використовує налаштовані резервні варіанти, якщо завдання не надає `payload.fallbacks`; `payload.fallbacks: []` робить запуск Cron строгим.

## Сховище автентифікації (ключі + OAuth)

OpenClaw використовує **профілі автентифікації** і для API-ключів, і для OAuth-токенів.

- Секрети зберігаються в `~/.openclaw/agents/<agentId>/agent/auth-profiles.json` (застаріле: `~/.openclaw/agent/auth-profiles.json`).
- Стан маршрутизації автентифікації під час виконання зберігається в `~/.openclaw/agents/<agentId>/agent/auth-state.json`.
- Конфігурація `auth.profiles` / `auth.order` — це **лише метадані + маршрутизація** (без секретів).
- Застарілий файл OAuth лише для імпорту: `~/.openclaw/credentials/oauth.json` (імпортується в `auth-profiles.json` під час першого використання).

Докладніше: [OAuth](/uk/concepts/oauth)

Типи облікових даних:

- `type: "api_key"` → `{ provider, key }`
- `type: "oauth"` → `{ provider, access, refresh, expires, email? }` (+ `projectId`/`enterpriseUrl` для деяких провайдерів)

## Ідентифікатори профілів

Входи OAuth створюють окремі профілі, щоб кілька облікових записів могли співіснувати.

- Типово: `provider:default`, коли email недоступний.
- OAuth з email: `provider:<email>` (наприклад, `google-antigravity:user@gmail.com`).

Профілі зберігаються в `~/.openclaw/agents/<agentId>/agent/auth-profiles.json` у `profiles`.

## Порядок ротації

Коли провайдер має кілька профілів, OpenClaw вибирає порядок так:

<Steps>
  <Step title="Явна конфігурація">
    `auth.order[provider]` (якщо задано).
  </Step>
  <Step title="Налаштовані профілі">
    `auth.profiles`, відфільтровані за провайдером.
  </Step>
  <Step title="Збережені профілі">
    Записи в `auth-profiles.json` для провайдера.
  </Step>
</Steps>

Якщо явний порядок не налаштовано, OpenClaw використовує циклічний порядок:

- **Первинний ключ:** тип профілю (**OAuth перед API-ключами**).
- **Вторинний ключ:** `usageStats.lastUsed` (спочатку найстаріші, у межах кожного типу).
- **Профілі в охолодженні/вимкнені профілі** переміщуються в кінець, упорядковані за найранішим завершенням.

### Прив’язка до сесії (зручно для кешу)

OpenClaw **закріплює вибраний профіль автентифікації за сесією**, щоб кеші провайдера залишалися прогрітими. Він **не** виконує ротацію на кожен запит. Закріплений профіль повторно використовується, доки:

- сесію не скинуто (`/new` / `/reset`)
- не завершиться Compaction (лічильник Compaction збільшується)
- профіль не перебуває в охолодженні/не вимкнений

Ручний вибір через `/model …@<profileId>` задає **користувацьке перевизначення** для цієї сесії й не ротуватиметься автоматично, доки не почнеться нова сесія.

<Note>
Автоматично закріплені профілі (вибрані маршрутизатором сесії) трактуються як **перевага**: їх пробують першими, але OpenClaw може перейти до іншого профілю за лімітів швидкості/тайм-аутів. Закріплені користувачем профілі залишаються прив’язаними до цього профілю; якщо він зазнає збою і налаштовано резервні моделі, OpenClaw переходить до наступної моделі замість перемикання профілів.
</Note>

### Чому OAuth може «виглядати втраченим»

Якщо для одного провайдера у вас є і OAuth-профіль, і профіль API-ключа, циклічна ротація може перемикатися між ними в різних повідомленнях, якщо профіль не закріплено. Щоб примусово використовувати один профіль:

- Закріпіть через `auth.order[provider] = ["provider:profileId"]`, або
- Використайте перевизначення для сесії через `/model …` з перевизначенням профілю (коли це підтримує ваш UI/чат-поверхня).

## Охолодження

Коли профіль зазнає збою через помилки автентифікації/ліміту швидкості (або тайм-аут, схожий на ліміт швидкості), OpenClaw позначає його як такий, що перебуває в охолодженні, і переходить до наступного профілю.

<AccordionGroup>
  <Accordion title="Що потрапляє в кошик ліміту швидкості / тайм-ауту">
    Цей кошик ліміту швидкості ширший за звичайний `429`: він також охоплює повідомлення провайдерів, як-от `Too many concurrent requests`, `ThrottlingException`, `concurrency limit reached`, `workers_ai ... quota limit exceeded`, `throttled`, `resource exhausted`, і періодичні ліміти вікна використання, як-от `weekly/monthly limit reached`.

    Помилки формату/некоректного запиту (наприклад, помилки перевірки ID виклику інструмента Cloud Code Assist) трактуються як придатні для аварійного перемикання і використовують ті самі охолодження. OpenAI-сумісні помилки причини зупинки, як-от `Unhandled stop reason: error`, `stop reason: error` і `reason: error`, класифікуються як сигнали тайм-ауту/аварійного перемикання.

    Загальний серверний текст також може потрапити в цей кошик тайм-ауту, коли джерело відповідає відомому тимчасовому шаблону. Наприклад, просте повідомлення stream-wrapper pi-ai `An unknown error occurred` трактується як придатне для аварійного перемикання для кожного провайдера, бо pi-ai видає його, коли потоки провайдера завершуються з `stopReason: "aborted"` або `stopReason: "error"` без конкретних деталей. JSON-повідомлення `api_error` з тимчасовим серверним текстом, як-от `internal server error`, `unknown error, 520`, `upstream error` або `backend error`, також трактуються як тайм-аути, придатні для аварійного перемикання.

    Специфічний для OpenRouter загальний текст upstream, як-от просте `Provider returned error`, трактується як тайм-аут лише тоді, коли контекст провайдера справді OpenRouter. Загальний внутрішній текст резервного механізму, як-от `LLM request failed with an unknown error.`, залишається консервативним і сам по собі не запускає аварійне перемикання.

  </Accordion>
  <Accordion title="Обмеження retry-after в SDK">
    Деякі SDK провайдерів інакше можуть чекати довге вікно `Retry-After`, перш ніж повернути керування OpenClaw. Для SDK на базі Stainless, як-от Anthropic і OpenAI, OpenClaw типово обмежує внутрішні очікування SDK `retry-after-ms` / `retry-after` до 60 секунд і негайно показує довші повторювані відповіді, щоб цей шлях аварійного перемикання міг виконатися. Налаштуйте або вимкніть обмеження за допомогою `OPENCLAW_SDK_RETRY_MAX_WAIT_SECONDS`; див. [Поведінка повторних спроб](/uk/concepts/retry).
  </Accordion>
  <Accordion title="Охолодження з прив’язкою до моделі">
    Охолодження ліміту швидкості також можуть бути прив’язані до моделі:

    - OpenClaw записує `cooldownModel` для збоїв ліміту швидкості, коли відомий ID моделі, що зазнала збою.
    - Споріднену модель у того самого провайдера все ще можна спробувати, коли охолодження прив’язане до іншої моделі.
    - Вікна білінгу/вимкнення все одно блокують увесь профіль для всіх моделей.

  </Accordion>
</AccordionGroup>

Охолодження використовують експоненційний backoff:

- 1 хвилина
- 5 хвилин
- 25 хвилин
- 1 година (обмеження)

Стан зберігається в `auth-state.json` у `usageStats`:

```json
{
  "usageStats": {
    "provider:profile": {
      "lastUsed": 1736160000000,
      "cooldownUntil": 1736160600000,
      "errorCount": 2
    }
  }
}
```

## Вимкнення через білінг

Збої білінгу/кредитів (наприклад, "insufficient credits" / "credit balance too low") трактуються як придатні для аварійного перемикання, але зазвичай вони не є тимчасовими. Замість короткого охолодження OpenClaw позначає профіль як **вимкнений** (з довшим backoff) і переходить до наступного профілю/провайдера.

<Note>
Не кожна відповідь, схожа на білінг, є `402`, і не кожен HTTP `402` потрапляє сюди. OpenClaw залишає явний білінговий текст у білінговому напрямку навіть тоді, коли провайдер натомість повертає `401` або `403`, але специфічні для провайдера зіставлення залишаються в межах провайдера, якому вони належать (наприклад, OpenRouter `403 Key limit exceeded`).

Водночас тимчасові помилки `402` вікна використання та лімітів витрат організації/робочого простору класифікуються як `rate_limit`, коли повідомлення виглядає придатним для повторної спроби (наприклад, `weekly usage limit exhausted`, `daily limit reached, resets tomorrow` або `organization spending limit exceeded`). Вони залишаються на короткому шляху охолодження/аварійного перемикання замість довгого шляху вимкнення через білінг.
</Note>

Стан зберігається в `auth-state.json`:

```json
{
  "usageStats": {
    "provider:profile": {
      "disabledUntil": 1736178000000,
      "disabledReason": "billing"
    }
  }
}
```

Типові значення:

- Backoff білінгу починається з **5 годин**, подвоюється після кожного білінгового збою та обмежується **24 годинами**.
- Лічильники backoff скидаються, якщо профіль не зазнавав збою протягом **24 годин** (налаштовується).
- Повторні спроби за перевантаження дозволяють **1 ротацію профілю того самого провайдера** перед переходом на резервну модель.
- Повторні спроби за перевантаження типово використовують **0 мс backoff**.

## Резервний перехід між моделями

Якщо всі профілі для провайдера зазнають збою, OpenClaw переходить до наступної моделі в `agents.defaults.model.fallbacks`. Це застосовується до збоїв автентифікації, лімітів швидкості й тайм-аутів, що вичерпали ротацію профілів (інші помилки не просувають резервний перехід). Помилки провайдера, які не надають достатньо деталей, усе одно точно позначаються в стані резервного переходу: `empty_response` означає, що провайдер не повернув придатного повідомлення або статусу, `no_error_details` означає, що провайдер явно повернув `Unknown error (no error details in response)`, а `unclassified` означає, що OpenClaw зберіг сирий попередній перегляд, але жоден класифікатор ще не зіставив його.

Перевантаження та помилки лімітів частоти обробляються агресивніше, ніж паузи через білінг. За замовчуванням OpenClaw дозволяє одну повторну спробу з тим самим профілем автентифікації того самого провайдера, а потім без очікування перемикається на наступну налаштовану резервну модель. Сигнали зайнятості провайдера, як-от `ModelNotReadyException`, потрапляють у цю категорію перевантаження. Налаштуйте це за допомогою `auth.cooldowns.overloadedProfileRotations`, `auth.cooldowns.overloadedBackoffMs` і `auth.cooldowns.rateLimitedProfileRotations`.

Коли запуск починається з налаштованої основної моделі за замовчуванням, основної моделі cron-завдання, основної моделі агента з явними резервними варіантами або автоматично вибраного перевизначення резервного варіанта, OpenClaw може пройти відповідним налаштованим резервним ланцюжком. Основні моделі агентів без явних резервних варіантів і явні вибори користувача (наприклад, `/model ollama/qwen3.5:27b`, вибір моделі, `sessions.patch` або одноразові перевизначення провайдера/моделі в CLI) є строгими: якщо цей провайдер/модель недоступні або зазнають збою до створення відповіді, OpenClaw повідомляє про збій замість відповіді з непов’язаного резервного варіанта.

### Правила ланцюжка кандидатів

OpenClaw формує список кандидатів із поточно запитаного `provider/model` та налаштованих резервних варіантів.

<AccordionGroup>
  <Accordion title="Rules">
    - Запитана модель завжди перша.
    - Явно налаштовані резервні варіанти дедуплікуються, але не фільтруються за allowlist моделей. Вони розглядаються як явний намір оператора.
    - Якщо поточний запуск уже перебуває на налаштованому резервному варіанті в тій самій родині провайдерів, OpenClaw продовжує використовувати повний налаштований ланцюжок.
    - Якщо поточний запуск використовує іншого провайдера, ніж у конфігурації, і ця поточна модель ще не є частиною налаштованого резервного ланцюжка, OpenClaw не додає непов’язані налаштовані резервні варіанти від іншого провайдера.
    - Коли до runner резервних варіантів не передано явне перевизначення резервного варіанта, налаштована основна модель додається в кінець, щоб ланцюжок міг повернутися до звичайного значення за замовчуванням після вичерпання попередніх кандидатів.
    - Коли викликач передає `fallbacksOverride`, runner використовує рівно запитану модель плюс цей список перевизначень. Порожній список вимикає резервну модель і запобігає додаванню налаштованої основної моделі як прихованої цілі повторної спроби.

  </Accordion>
</AccordionGroup>

### Які помилки просувають резервний варіант

<Tabs>
  <Tab title="Continues on">
    - збої автентифікації
    - ліміти частоти та вичерпання пауз
    - помилки перевантаження/зайнятості провайдера
    - помилки failover, схожі на таймаут
    - вимкнення через білінг
    - `LiveSessionModelSwitchError`, яка нормалізується в шлях failover, щоб застаріла збережена модель не створювала зовнішній цикл повторних спроб
    - інші нерозпізнані помилки, коли ще залишаються кандидати

  </Tab>
  <Tab title="Does not continue on">
    - явні переривання, які не схожі на таймаут/failover
    - помилки переповнення контексту, які мають залишатися всередині логіки compaction/повторної спроби (наприклад, `request_too_large`, `INVALID_ARGUMENT: input exceeds the maximum number of tokens`, `input token count exceeds the maximum number of input tokens`, `The input is too long for the model` або `ollama error: context length exceeded`)
    - фінальна невідома помилка, коли кандидатів не залишилося

  </Tab>
</Tabs>

### Пропуск через паузу проти поведінки проби

Коли кожен профіль автентифікації для провайдера вже перебуває в паузі, OpenClaw не пропускає цього провайдера автоматично назавжди. Він ухвалює рішення для кожного кандидата:

<AccordionGroup>
  <Accordion title="Per-candidate decisions">
    - Постійні збої автентифікації негайно пропускають усього провайдера.
    - Вимкнення через білінг зазвичай пропускаються, але основного кандидата все ще можна пробувати з обмеженням частоти, щоб відновлення було можливим без перезапуску.
    - Основного кандидата можна пробувати ближче до завершення паузи, з обмеженням частоти для кожного провайдера.
    - Споріднені резервні варіанти того самого провайдера можна пробувати попри паузу, коли збій виглядає тимчасовим (`rate_limit`, `overloaded` або невідомий). Це особливо актуально, коли ліміт частоти прив’язаний до моделі, а споріднена модель усе ще може відновитися негайно.
    - Тимчасові проби під час пауз обмежені однією на провайдера для кожного резервного запуску, щоб один провайдер не затримував резервне перемикання між провайдерами.

  </Accordion>
</AccordionGroup>

## Перевизначення сеансу та живе перемикання моделі

Зміни моделі сеансу є спільним станом. Активний runner, команда `/model`, оновлення compaction/сеансу та узгодження живого сеансу читають або записують частини одного й того самого запису сеансу.

Це означає, що повторні спроби резервних варіантів мають координуватися з живим перемиканням моделі:

- Лише явні зміни моделі, ініційовані користувачем, позначають очікуване живе перемикання. Це включає `/model`, `session_status(model=...)` і `sessions.patch`.
- Системні зміни моделі, як-от ротація резервних варіантів, перевизначення heartbeat або compaction, самі по собі ніколи не позначають очікуване живе перемикання.
- Перевизначення моделі, ініційовані користувачем, трактуються як точні вибори для політики резервного перемикання, тому недоступний вибраний провайдер показується як збій, а не маскується `agents.defaults.model.fallbacks`.
- Перед початком повторної спроби з резервним варіантом runner відповіді зберігає поля вибраного перевизначення резервного варіанта в записі сеансу.
- Автоматичні перевизначення резервних варіантів залишаються вибраними в наступних ходах, щоб OpenClaw не пробував відомо несправну основну модель у кожному повідомленні. `/new`, `/reset` і `sessions.reset` очищають автоматично створені перевизначення та повертають сеанс до налаштованого значення за замовчуванням.
- `/status` показує вибрану модель і, коли резервний стан відрізняється, активну резервну модель та причину.
- Узгодження живого сеансу віддає перевагу збереженим перевизначенням сеансу над застарілими runtime-полями моделі.
- Якщо помилка живого перемикання вказує на пізнішого кандидата в активному резервному ланцюжку, OpenClaw переходить прямо до цієї вибраної моделі замість того, щоб спершу проходити непов’язаних кандидатів.
- Якщо резервна спроба зазнає збою, runner відкочує лише ті поля перевизначення, які він записав, і лише якщо вони все ще відповідають цьому невдалому кандидату.

Це запобігає класичній гонці:

<Steps>
  <Step title="Primary fails">
    Вибрана основна модель зазнає збою.
  </Step>
  <Step title="Fallback chosen in memory">
    Резервний кандидат вибирається в пам’яті.
  </Step>
  <Step title="Session store still says old primary">
    Сховище сеансу все ще відображає стару основну модель.
  </Step>
  <Step title="Live reconciliation reads stale state">
    Узгодження живого сеансу читає застарілий стан сеансу.
  </Step>
  <Step title="Retry snapped back">
    Повторну спробу повертає до старої моделі до початку спроби з резервним варіантом.
  </Step>
</Steps>

Збережене перевизначення резервного варіанта закриває це вікно, а вузький відкат залишає новіші ручні або runtime-зміни сеансу неушкодженими.

## Спостережуваність і підсумки збоїв

`runWithModelFallback(...)` записує деталі кожної спроби, які потрапляють у журнали та повідомлення про паузи для користувача:

- спробуваний провайдер/модель
- причина (`rate_limit`, `overloaded`, `billing`, `auth`, `model_not_found` і подібні причини failover)
- необов’язковий статус/код
- читабельний для людини підсумок помилки

Структуровані журнали `model_fallback_decision` також містять плоскі поля `fallbackStep*`, коли кандидат зазнає збою, пропускається або пізніший резервний варіант успішний. Ці поля роблять спробу переходу явною (`fallbackStepFromModel`, `fallbackStepToModel`, `fallbackStepFromFailureReason`, `fallbackStepFromFailureDetail`, `fallbackStepFinalOutcome`), щоб експортери журналів і діагностики могли відновити початковий збій навіть тоді, коли кінцевий резервний варіант також зазнає збою.

Коли кожен кандидат зазнає збою, OpenClaw викидає `FallbackSummaryError`. Зовнішній runner відповіді може використати це для створення конкретнішого повідомлення, наприклад "усі моделі тимчасово обмежені лімітами частоти", і додати найближчий час завершення паузи, якщо він відомий.

Цей підсумок паузи враховує модель:

- непов’язані ліміти частоти, прив’язані до моделі, ігноруються для випробуваного ланцюжка провайдер/модель
- якщо залишкове блокування є відповідним лімітом частоти, прив’язаним до моделі, OpenClaw повідомляє останній відповідний час завершення, який усе ще блокує цю модель

## Пов’язана конфігурація

Див. [Конфігурація Gateway](/uk/gateway/configuration) для:

- `auth.profiles` / `auth.order`
- `auth.cooldowns.billingBackoffHours` / `auth.cooldowns.billingBackoffHoursByProvider`
- `auth.cooldowns.billingMaxHours` / `auth.cooldowns.failureWindowHours`
- `auth.cooldowns.overloadedProfileRotations` / `auth.cooldowns.overloadedBackoffMs`
- `auth.cooldowns.rateLimitedProfileRotations`
- `agents.defaults.model.primary` / `agents.defaults.model.fallbacks`
- маршрутизації `agents.defaults.imageModel`

Див. [Моделі](/uk/concepts/models) для ширшого огляду вибору моделей і резервного перемикання.
