Concepts and configuration

Аварійне перемикання моделі

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

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

У цьому документі пояснено правила виконання та дані, на яких вони ґрунтуються.

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

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

  • Визначення стану сеансу

    Визначає активну модель сеансу та бажаний профіль автентифікації.

  • Побудова ланцюжка кандидатів

    Будує ланцюжок моделей-кандидатів із поточного вибору моделі та політики резервного переходу для джерела цього вибору. Налаштовані значення за замовчуванням, основні моделі завдань cron і автоматично вибрані резервні моделі можуть використовувати налаштовані резервні варіанти; явні вибори користувацького сеансу є строгими.

  • Спроба з поточним провайдером

    Пробує поточного провайдера з правилами ротації/затримки профілів автентифікації.

  • Перехід після помилок, придатних для failover

    Якщо цей провайдер вичерпано через помилку, придатну для failover, переходить до наступної моделі-кандидата.

  • Збереження резервного перевизначення

    Зберігає вибране резервне перевизначення до початку повторної спроби, щоб інші читачі сеансу бачили того самого провайдера/модель, яку runner от-от використає. Збережене перевизначення моделі позначається як modelOverrideSource: "auto".

  • Вузький відкат у разі збою

    Якщо резервний кандидат зазнає збою, відкочує лише поля перевизначення сеансу, що належать резервному переходу, коли вони все ще відповідають цьому невдалому кандидату.

  • Викидання FallbackSummaryError, якщо все вичерпано

    Якщо всі кандидати зазнають збою, викидає FallbackSummaryError з деталями кожної спроби та найближчим завершенням затримки, коли воно відоме.

  • Це навмисно вужче, ніж "зберегти й відновити весь сеанс". 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

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

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

    ID профілів

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

    • За замовчуванням: provider:default, коли email недоступний.
    • OAuth з email: provider:<email> (наприклад, google-antigravity:[email protected]).

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

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

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

  • Явна конфігурація

    auth.order[provider] (якщо встановлено).

  • Налаштовані профілі

    auth.profiles, відфільтровані за провайдером.

  • Збережені профілі

    Записи в auth-profiles.json для провайдера.

  • Якщо явний порядок не налаштовано, OpenClaw використовує round-robin порядок:

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

    Прив’язка сеансу (дружня до кешу)

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

    • сеанс не скинуто (/new / /reset)
    • Compaction не завершиться (лічильник compaction збільшується)
    • профіль не перебуває в затримці/не вимкнений

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

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

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

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

    Затримки

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

    Що потрапляє до кошика rate-limit / timeout

    Цей кошик rate-limit ширший за простий 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) трактуються як придатні для failover і використовують ті самі затримки. Помилки причини зупинки, сумісні з OpenAI, як-от Unhandled stop reason: error, stop reason: error і reason: error, класифікуються як сигнали timeout/failover.

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

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

    Обмеження retry-after в SDK

    Деякі SDK провайдерів інакше могли б очікувати довге вікно Retry-After перед поверненням керування OpenClaw. Для SDK на основі Stainless, як-от Anthropic і OpenAI, OpenClaw за замовчуванням обмежує внутрішні для SDK очікування retry-after-ms / retry-after до 60 секунд і негайно показує довші повторювані відповіді, щоб цей шлях failover міг виконатися. Налаштуйте або вимкніть обмеження через OPENCLAW_SDK_RETRY_MAX_WAIT_SECONDS; див. Поведінка повторних спроб.

    Затримки в межах моделі

    Затримки rate-limit також можуть бути обмежені моделлю:

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

    Затримки використовують експоненційний backoff:

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

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

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

    Вимкнення через billing

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

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

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

    Значення за замовчуванням:

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

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

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

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

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

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

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

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

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

    Продовжується за

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

    Не продовжується за

    • явних переривань, які не мають форми тайм-ауту/перемикання
    • помилок переповнення контексту, які мають залишатися всередині логіки 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)
    • фінальної невідомої помилки, коли кандидатів більше немає

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

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

    Рішення для кожного кандидата
    • Стійкі помилки автентифікації негайно пропускають усього провайдера.
    • Вимкнення через білінг зазвичай пропускаються, але основного кандидата все ще можна пробувати з обмеженням частоти, щоб відновлення було можливим без перезапуску.
    • Основного кандидата можна пробувати ближче до завершення паузи, з обмеженням частоти для кожного провайдера.
    • Суміжні резервні варіанти того самого провайдера можна пробувати попри паузу, коли збій виглядає тимчасовим (rate_limit, overloaded або невідомий). Це особливо актуально, коли обмеження частоти діє на рівні моделі, а суміжна модель може відновитися негайно.
    • Тимчасові проби під час паузи обмежені однією на провайдера для кожного запуску резервних варіантів, щоб один провайдер не затримував перемикання між провайдерами.

    Перевизначення сеансів і live-перемикання моделей

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

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

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

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

  • Основна модель зазнає збою

    Вибрана основна модель зазнає збою.

  • Резервний варіант вибрано в пам’яті

    Кандидат резервного варіанта вибирається в пам’яті.

  • Сховище сеансу все ще вказує стару основну модель

    Сховище сеансу все ще відображає стару основну модель.

  • Live-узгодження читає застарілий стан

    Узгодження live-сеансу читає застарілий стан сеансу.

  • Повторну спробу повернуто назад

    Повторну спробу повертає до старої моделі до початку спроби резервного варіанта.

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

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

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

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

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

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

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

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

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

    Див. Конфігурацію Gateway для:

    • 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

    Див. Моделі для ширшого огляду вибору моделей і резервних варіантів.