Резервне переключення моделей
OpenClaw обробляє збої у два етапи:- Ротація профілю автентифікації в межах поточного провайдера.
- Резервний перехід моделі до наступної моделі в
agents.defaults.model.fallbacks.
Потік виконання
Для звичайного текстового запуску OpenClaw оцінює кандидатів у такому порядку:- Поточна вибрана модель сесії.
- Налаштовані
agents.defaults.model.fallbacksу заданому порядку. - Налаштована основна модель наприкінці, якщо запуск почався з перевизначення.
- Визначити активну модель сесії та перевагу профілю автентифікації.
- Побудувати ланцюжок моделей-кандидатів.
- Спробувати поточного провайдера з правилами ротації/cooldown профілів автентифікації.
- Якщо можливості цього провайдера вичерпано через помилку, що допускає резервний перехід, перейти до наступного кандидата моделі.
- Зберегти вибране перевизначення резервної моделі до початку повторної спроби, щоб інші читачі сесії бачили того самого провайдера/модель, яких виконавець ось-ось використає.
- Якщо кандидат резервної моделі не спрацює, відкотити лише поля перевизначення сесії, що належать резервному переходу, коли вони все ще відповідають цьому невдалому кандидату.
- Якщо всі кандидати не спрацюють, згенерувати
FallbackSummaryErrorіз деталями по кожній спробі та найближчим часом завершення cooldown, якщо він відомий.
providerOverridemodelOverrideauthProfileOverrideauthProfileOverrideSourceauthProfileOverrideCompactionCount
/model або оновлення ротації сесії, що
сталися під час виконання спроби.
Зберігання автентифікації (ключі + OAuth)
OpenClaw використовує профілі автентифікації як для ключів API, так і для OAuth-токенів.- Секрети зберігаються в
~/.openclaw/agents/<agentId>/agent/auth-profiles.json(застаріле:~/.openclaw/agent/auth-profiles.json). - Конфігурація
auth.profiles/auth.order— це лише метадані + маршрутизація (без секретів). - Застарілий файл OAuth лише для імпорту:
~/.openclaw/credentials/oauth.json(імпортується вauth-profiles.jsonпід час першого використання).
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 вибирає порядок так:- Явна конфігурація:
auth.order[provider](якщо задано). - Налаштовані профілі:
auth.profiles, відфільтровані за провайдером. - Збережені профілі: записи в
auth-profiles.jsonдля цього провайдера.
- Основний ключ: тип профілю (OAuth перед ключами API).
- Другорядний ключ:
usageStats.lastUsed(найдавніші спочатку, у межах кожного типу). - Профілі в cooldown/вимкнені переміщуються в кінець, упорядковані за найближчим завершенням блокування.
Прикріплення до сесії (дружнє до кешу)
OpenClaw закріплює вибраний профіль автентифікації за сесією, щоб підтримувати кеші провайдера «теплими». Він не виконує ротацію на кожний запит. Закріплений профіль використовується повторно, доки не станеться:- скидання сесії (
/new//reset) - завершення compaction (лічильник compaction збільшується)
- профіль потрапляє в cooldown/вимикається
/model …@<profileId> задає перевизначення користувача для цієї сесії
і не ротуватиметься автоматично, доки не почнеться нова сесія.
Автоматично закріплені профілі (вибрані маршрутизатором сесії) вважаються перевагою:
вони перевіряються першими, але OpenClaw може перейти на інший профіль при rate limit/тайм-аутах.
Профілі, закріплені користувачем, залишаються прив’язаними до цього профілю; якщо він не спрацьовує і налаштовано резервні моделі,
OpenClaw переходить до наступної моделі, а не перемикає профілі.
Чому OAuth може «здаватися втраченим»
Якщо у вас є і OAuth-профіль, і профіль із ключем API для одного провайдера, round-robin може перемикатися між ними між повідомленнями, якщо профілі не закріплено. Щоб примусово використовувати один профіль:- Закріпіть через
auth.order[provider] = ["provider:profileId"], або - Використайте перевизначення для конкретної сесії через
/model …із перевизначенням профілю (коли це підтримується вашим UI/поверхнею чату).
Cooldown
Коли профіль не спрацьовує через помилки автентифікації/rate limit (або тайм-аут, що схожий на rate limiting), OpenClaw позначає його як такий, що перебуває в cooldown, і переходить до наступного профілю. Цей кошик 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) вважаються такими, що допускають резервний перехід, і використовують ті самі cooldown.
Помилки OpenAI-compatible stop reason, такі як Unhandled stop reason: error,
stop reason: error і reason: error, класифікуються як сигнали
тайм-ауту/резервного переходу.
Загальний текст серверних помилок у межах провайдера також може потрапляти в цей кошик тайм-аутів, якщо
джерело відповідає відомому шаблону тимчасової помилки. Наприклад, для Anthropic просте
An unknown error occurred і JSON-пейлоади api_error із тимчасовим текстом серверної помилки, таким як
internal server error, unknown error, 520, upstream error
або backend error, вважаються такими, що допускають резервний перехід через тайм-аут. Загальний висхідний текст OpenRouter,
наприклад простий Provider returned error, також розглядається як
тайм-аут лише тоді, коли контекст провайдера справді є OpenRouter. Загальний внутрішній
резервний текст, такий як LLM request failed with an unknown error., залишається
консервативним і сам по собі не запускає резервний перехід.
Cooldown через rate limit також можуть бути прив’язані до моделі:
- OpenClaw записує
cooldownModelдля помилок rate limit, коли відомий ідентифікатор моделі, що не спрацювала. - Сусідню модель у того самого провайдера все ще можна спробувати, коли cooldown прив’язано до іншої моделі.
- Billing/вікна вимкнення все одно блокують весь профіль у всіх моделях.
- 1 хвилина
- 5 хвилин
- 25 хвилин
- 1 година (максимум)
auth-profiles.json у usageStats:
Billing-вимкнення
Помилки billing/кредитів (наприклад, «insufficient credits» / «credit balance too low») вважаються такими, що допускають резервний перехід, але зазвичай вони не є тимчасовими. Замість короткого cooldown OpenClaw позначає профіль як вимкнений (з довшим backoff) і переходить до наступного профілю/провайдера. Не кожна відповідь, схожа на billing, є402, і не кожен HTTP 402 потрапляє
сюди. OpenClaw зберігає явний текст billing у гілці billing, навіть коли
провайдер повертає 401 або 403, але matchers, специфічні для провайдера, залишаються
обмеженими тим провайдером, якому вони належать (наприклад, OpenRouter 403 Key limit exceeded). Тим часом тимчасові 402 для вікон використання та
лімітів витрат організації/workspace класифікуються як rate_limit, коли
повідомлення виглядає придатним для повторної спроби (наприклад, weekly usage limit exhausted, daily limit reached, resets tomorrow або organization spending limit exceeded).
Такі випадки залишаються на шляху короткого cooldown/резервного переходу замість довгого
шляху вимкнення через billing.
Стан зберігається в auth-profiles.json:
- Backoff для billing починається з 5 годин, подвоюється з кожною помилкою billing і обмежується 24 годинами.
- Лічильники backoff скидаються, якщо профіль не помилявся протягом 24 годин (можна налаштувати).
- Для перевантажених повторних спроб дозволяється 1 ротація профілю того самого провайдера перед переходом до резервної моделі.
- Для перевантажених повторних спроб типово використовується backoff 0 мс.
Резервний перехід моделі
Якщо всі профілі провайдера не спрацювали, OpenClaw переходить до наступної моделі вagents.defaults.model.fallbacks. Це стосується помилок автентифікації, rate limit і
тайм-аутів, які вичерпали ротацію профілів (інші помилки не просувають резервний перехід).
Перевантаження і помилки rate limit обробляються агресивніше, ніж cooldown billing.
Типово OpenClaw дозволяє одну повторну спробу з іншим профілем того самого провайдера,
а потім без очікування переходить до наступної налаштованої резервної моделі.
Сигнали зайнятості провайдера, такі як ModelNotReadyException, потрапляють у цей кошик перевантаження.
Налаштовуйте це через auth.cooldowns.overloadedProfileRotations,
auth.cooldowns.overloadedBackoffMs і
auth.cooldowns.rateLimitedProfileRotations.
Коли запуск починається з перевизначення моделі (hooks або CLI), резервні переходи все одно завершуються на
agents.defaults.model.primary після спроби всіх налаштованих резервних варіантів.
Правила ланцюжка кандидатів
OpenClaw будує список кандидатів із поточного запитаногоprovider/model
та налаштованих резервних варіантів.
Правила:
- Запитана модель завжди перша.
- Явно налаштовані резервні варіанти дедуплікуються, але не фільтруються за списком дозволу моделей. Вони вважаються явним наміром оператора.
- Якщо поточний запуск уже працює на налаштованому резервному варіанті в тій самій родині провайдера, OpenClaw продовжує використовувати весь налаштований ланцюжок.
- Якщо поточний запуск працює на іншому провайдері, ніж у конфігурації, і ця поточна модель ще не є частиною налаштованого ланцюжка резервного переходу, OpenClaw не додає непов’язані резервні варіанти з іншого провайдера.
- Коли запуск почався з перевизначення, налаштована основна модель додається в кінці, щоб ланцюжок міг повернутися до звичайного типового значення після вичерпання попередніх кандидатів.
Які помилки просувають резервний перехід
Резервний перехід моделі продовжується у випадках:- збої автентифікації
- rate limit і вичерпання cooldown
- помилки перевантаження/зайнятості провайдера
- помилки резервного переходу, схожі на тайм-аут
- вимкнення через billing
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) - фінальна невідома помилка, коли кандидатів більше немає
Поведінка пропуску cooldown проти probe
Коли всі профілі автентифікації провайдера вже перебувають у cooldown, OpenClaw не пропускає цього провайдера автоматично назавжди. Він ухвалює рішення для кожного кандидата окремо:- Стійкі збої автентифікації негайно пропускають увесь провайдер.
- Вимкнення через billing зазвичай пропускаються, але основного кандидата все ще можна probe з throttling, щоб відновлення було можливе без перезапуску.
- Основного кандидата можна probe ближче до завершення cooldown із throttling для кожного провайдера.
- Сусідні резервні моделі того самого провайдера можна спробувати попри cooldown, якщо
збій виглядає тимчасовим (
rate_limit,overloadedабо unknown). Це особливо важливо, коли rate limit прив’язано до моделі і сусідня модель може одразу відновитися. - Тимчасові cooldown probe обмежуються однією спробою на провайдера в межах одного резервного запуску, щоб один провайдер не затримував міжпровайдерний резервний перехід.
Перевизначення сесії та живе перемикання моделі
Зміни моделі сесії — це спільний стан. Активний виконавець, команда/model,
оновлення compaction/сесії та узгодження живої сесії читають або записують
частини того самого запису сесії.
Це означає, що повторні спроби резервного переходу мають координуватися з живим перемиканням моделі:
- Лише явні зміни моделі, ініційовані користувачем, позначають очікуване живе перемикання. Це
включає
/model,session_status(model=...)іsessions.patch. - Зміни моделі, ініційовані системою, такі як ротація резервного переходу, перевизначення heartbeat або compaction, самі по собі ніколи не позначають очікуване живе перемикання.
- Перед початком повторної спроби резервного переходу виконавець відповіді зберігає вибрані поля перевизначення резервного переходу в запис сесії.
- Узгодження живої сесії надає перевагу збереженим перевизначенням сесії над застарілими полями моделі під час виконання.
- Якщо спроба резервного переходу не спрацює, виконавець відкочує лише ті поля перевизначення, які він записав, і лише якщо вони все ще відповідають невдалому кандидату.
- Основна модель не спрацьовує.
- Кандидат резервної моделі вибирається в пам’яті.
- У сховищі сесії все ще вказано стару основну модель.
- Узгодження живої сесії читає застарілий стан сесії.
- Повторну спробу відкидає назад на стару модель до початку спроби резервного переходу.
Спостережуваність і підсумки збоїв
runWithModelFallback(...) записує деталі кожної спроби, які потрапляють у журнали та
повідомлення користувача про cooldown:
- спроба provider/model
- причина (
rate_limit,overloaded,billing,auth,model_not_foundта подібні причини резервного переходу) - необов’язковий status/code
- зрозумілий для людини підсумок помилки
FallbackSummaryError. Зовнішній
виконавець відповіді може використати це, щоб побудувати точніше повідомлення на кшталт «усі моделі
тимчасово обмежені через rate limit» і додати найближчий час завершення cooldown, якщо він відомий.
Цей підсумок cooldown враховує модель:
- непов’язані rate limit, прив’язані до інших моделей, ігноруються для ланцюжка спроб provider/model
- якщо блокування, що залишилося, є відповідним rate limit, прив’язаним до моделі, OpenClaw повідомляє останній відповідний час завершення, який все ще блокує цю модель
Пов’язана конфігурація
Див. Конфігурація шлюзу, щоб дізнатися про:auth.profiles/auth.orderauth.cooldowns.billingBackoffHours/auth.cooldowns.billingBackoffHoursByProviderauth.cooldowns.billingMaxHours/auth.cooldowns.failureWindowHoursauth.cooldowns.overloadedProfileRotations/auth.cooldowns.overloadedBackoffMsauth.cooldowns.rateLimitedProfileRotationsagents.defaults.model.primary/agents.defaults.model.fallbacks- маршрутизацію
agents.defaults.imageModel