モデルフェイルオーバー
OpenClawは失敗を2段階で処理します。- 現在のプロバイダー内での認証プロファイルのローテーション。
agents.defaults.model.fallbacks内の次のモデルへのモデルフォールバック。
ランタイムフロー
通常のテキスト実行では、OpenClawは候補を次の順序で評価します。- 現在選択されているセッションモデル。
- 設定された
agents.defaults.model.fallbacksを順番に。 - 実行がオーバーライドから開始された場合は、最後に設定済みのプライマリモデル。
- アクティブなセッションモデルと認証プロファイルの優先設定を解決する。
- モデル候補チェーンを構築する。
- 現在のプロバイダーを、認証プロファイルのローテーション/クールダウンルールとともに試す。
- そのプロバイダーがフェイルオーバー対象のエラーで尽きた場合、次のモデル候補へ移る。
- 再試行が始まる前に、選択されたフォールバックオーバーライドを永続化し、他のセッションリーダーがランナーがこれから使うのと同じプロバイダー/モデルを見られるようにする。
- フォールバック候補が失敗した場合、その失敗した候補とまだ一致しているときに限り、フォールバック所有のセッションオーバーライドフィールドだけをロールバックする。
- すべての候補が失敗した場合、各試行の詳細と、わかっている場合は最も早いクールダウン満了時刻を含む
FallbackSummaryErrorを投げる。
providerOverridemodelOverrideauthProfileOverrideauthProfileOverrideSourceauthProfileOverrideCompactionCount
/model変更やセッションローテーション更新など、新しい無関係のセッション変更を上書きするのを防ぎます。
認証ストレージ(キー + 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へインポートされます)。
type: "api_key"→{ provider, key }type: "oauth"→{ provider, access, refresh, expires, email? }(一部のプロバイダーではprojectId/enterpriseUrlを追加)
プロファイルID
OAuthログインは、複数アカウントが共存できるように個別のプロファイルを作成します。- デフォルト: メールアドレスが利用できない場合は
provider:default - メールアドレス付きOAuth:
provider:<email>(例:google-antigravity:user@gmail.com)
~/.openclaw/agents/<agentId>/agent/auth-profiles.jsonのprofiles配下に保存されます。
ローテーション順序
プロバイダーに複数のプロファイルがある場合、OpenClawは次のような順序を選びます。- 明示的な設定:
auth.order[provider](設定されている場合)。 - 設定済みプロファイル: プロバイダーでフィルタした
auth.profiles。 - 保存済みプロファイル: そのプロバイダー向けの
auth-profiles.json内エントリ。
- 主キー: プロファイル種別(APIキーよりOAuthを優先)
- 副キー:
usageStats.lastUsed(各種別内で最も古いものが先) - クールダウン中/無効化されたプロファイルは末尾へ移動し、最も早く期限切れになる順に並べられます。
セッションのスティッキネス(キャッシュにやさしい)
OpenClawは、プロバイダーキャッシュを温かい状態に保つため、選択した認証プロファイルをセッションごとに固定します。 毎リクエストごとにローテーションするわけではありません。固定されたプロファイルは次の場合まで再利用されます。- セッションがリセットされたとき(
/new//reset) - compactionが完了したとき(compaction countが増加)
- プロファイルがクールダウン中/無効化されているとき
/model …@<profileId>による手動選択は、そのセッションに対するユーザーオーバーライドを設定し、
新しいセッションが始まるまで自動ローテーションされません。
自動固定されたプロファイル(セッションルーターが選択したもの)は、優先設定として扱われます。
最初に試されますが、レート制限やタイムアウト時にはOpenClawが別のプロファイルへローテーションする場合があります。
ユーザー固定のプロファイルはそのプロファイルにロックされたままです。そのプロファイルが失敗し、モデルフォールバックが設定されている場合、
OpenClawはプロファイルを切り替える代わりに次のモデルへ移動します。
OAuthが「消えたように見える」理由
同じプロバイダーにOAuthプロファイルとAPIキープロファイルの両方がある場合、固定されていなければ、ラウンドロビンによってメッセージ間でそれらが切り替わることがあります。単一プロファイルを強制するには:auth.order[provider] = ["provider:profileId"]で固定する、または/model …でプロファイルオーバーライド付きのセッション単位オーバーライドを使う(UI/チャット面が対応している場合)。
クールダウン
プロファイルが認証/レート制限エラー(またはレート制限のように見えるタイムアウト)で失敗すると、 OpenClawはそのプロファイルをクールダウン状態にし、次のプロファイルへ移動します。 このレート制限バケットは単純な429より広く、Too many concurrent requests、ThrottlingException、
concurrency limit reached、workers_ai ... quota limit exceeded、
throttled、resource exhausted、weekly/monthly limit reachedのような
定期的な使用量ウィンドウ制限などのプロバイダーメッセージも含みます。
フォーマット/無効リクエストエラー(たとえばCloud Code AssistのツールコールID
検証失敗)はフェイルオーバー対象として扱われ、同じクールダウンを使用します。
Unhandled stop reason: error、
stop reason: error、reason: errorのようなOpenAI互換のstop-reasonエラーは、タイムアウト/フェイルオーバー
シグナルとして分類されます。
ソースが既知の一時的パターンに一致する場合、プロバイダースコープの汎用サーバーテキストもこのタイムアウトバケットに入ることがあります。たとえば、Anthropicの単体の
An unknown error occurredや、internal server error、unknown error, 520、upstream error、
backend errorといった一時的サーバーテキストを含むJSON api_errorペイロードは、フェイルオーバー対象のタイムアウトとして扱われます。OpenRouter固有の
単体のProvider returned errorのような汎用upstreamテキストも、プロバイダーコンテキストが実際にOpenRouterである場合に限って
タイムアウトとして扱われます。LLM request failed with an unknown error.のような汎用の内部
フォールバックテキストは保守的に扱われ、それ単体ではフェイルオーバーをトリガーしません。
レート制限クールダウンはモデルスコープになることもあります。
- 失敗したモデルIDがわかっている場合、OpenClawはレート制限失敗に対して
cooldownModelを記録します。 - 同じプロバイダー上の兄弟モデルは、クールダウンが別モデルにスコープされていれば引き続き試行できます。
- 請求/無効化ウィンドウは、モデルをまたいでプロファイル全体を引き続きブロックします。
- 1分
- 5分
- 25分
- 1時間(上限)
auth-state.jsonのusageStats配下に保存されます。
請求による無効化
請求/クレジット失敗(たとえば「insufficient credits」や「credit balance too low」)はフェイルオーバー対象として扱われますが、通常は一時的ではありません。短いクールダウンの代わりに、OpenClawはそのプロファイルを無効化済みとしてマークし(より長いバックオフ付き)、次のプロファイル/プロバイダーへローテーションします。 すべての請求っぽいレスポンスが402というわけではなく、すべてのHTTP 402が
ここに入るわけでもありません。OpenClawは、プロバイダーが代わりに401や403を返した場合でも、
明示的な請求テキストを請求レーンに保持しますが、プロバイダー固有のマッチャーはそれを所有するプロバイダーにスコープされたままです(例: OpenRouterの403 Key limit exceeded)。一方、一時的な402の使用量ウィンドウや
organization/workspaceのspend-limitエラーは、メッセージが再試行可能に見える場合、rate_limitとして分類されます
(例: weekly usage limit exhausted、daily limit reached, resets tomorrow、organization spending limit exceeded)。
これらは長い
請求無効化パスではなく、短いクールダウン/フェイルオーバーパスに留まります。
状態はauth-state.jsonに保存されます。
- 請求バックオフは5時間から始まり、請求失敗ごとに倍増し、24時間で上限になります。
- バックオフカウンターは、そのプロファイルが24時間失敗しなければリセットされます(設定可能)。
- 過負荷時の再試行では、モデルフォールバックの前に同一プロバイダー内で1回の認証プロファイルローテーションを許可します。
- 過負荷時の再試行はデフォルトで0 msバックオフを使用します。
モデルフォールバック
あるプロバイダーのすべてのプロファイルが失敗した場合、OpenClawはagents.defaults.model.fallbacks内の次のモデルへ移動します。これは認証失敗、レート制限、および
プロファイルローテーションを使い切ったタイムアウトに適用されます(それ以外のエラーではフォールバックは進みません)。
過負荷エラーとレート制限エラーは、請求クールダウンよりも積極的に処理されます。デフォルトでは、OpenClawは同一プロバイダー内で1回の認証プロファイル再試行を許可し、その後待機せずに次に設定されたモデルフォールバックへ切り替えます。
ModelNotReadyExceptionのようなプロバイダー多忙シグナルはその過負荷バケットに入ります。
これはauth.cooldowns.overloadedProfileRotations、
auth.cooldowns.overloadedBackoffMs、および
auth.cooldowns.rateLimitedProfileRotationsで調整できます。
実行がモデルオーバーライド(フックまたはCLI)で始まった場合でも、フォールバックは設定されたフォールバックを試したあと、
最後はagents.defaults.model.primaryに到達します。
候補チェーンのルール
OpenClawは、現在要求されているprovider/modelと設定済みフォールバックから候補リストを構築します。
ルール:
- 要求されたモデルは常に最初です。
- 明示的に設定されたフォールバックは重複排除されますが、モデル allowlistではフィルタされません。これらは明示的なオペレーター意図として扱われます。
- 現在の実行が同じプロバイダーファミリー内の設定済みフォールバック上にすでにある場合、OpenClawは設定済みチェーン全体を使い続けます。
- 現在の実行が設定とは異なるプロバイダー上にあり、その現在の モデルが設定済みフォールバックチェーンの一部でない場合、OpenClawは別プロバイダーの無関係な設定済みフォールバックを追加しません。
- 実行がオーバーライドから始まった場合、設定済みプライマリが 最後に追加されるため、先行する候補が尽きたあとにチェーンを通常のデフォルトへ戻せます。
どのエラーでフォールバックが進むか
モデルフォールバックは次の場合に継続します。- 認証失敗
- レート制限とクールダウン枯渇
- 過負荷/プロバイダー多忙エラー
- タイムアウト系のフェイルオーバーエラー
- 請求による無効化
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) - 候補が残っていないときの最終的な未知のエラー
クールダウンのスキップとプローブ動作
あるプロバイダーのすべての認証プロファイルがすでにクールダウン中の場合でも、OpenClawは そのプロバイダーを永続的に自動スキップするわけではありません。候補ごとに判断します。- 永続的な認証失敗では、プロバイダー全体を即座にスキップします。
- 請求による無効化は通常スキップしますが、再起動なしで回復できるよう、 プライマリ候補はスロットル付きで引き続きプローブされることがあります。
- プライマリ候補は、クールダウン満了が近い場合に、プロバイダーごとの スロットル付きでプローブされることがあります。
- 同一プロバイダー内のフォールバック兄弟は、失敗が一時的に見える場合(
rate_limit、overloaded、またはunknown)、 クールダウン中でも試行されることがあります。これは特に、レート制限がモデルスコープであり、兄弟モデルが すぐ回復する可能性がある場合に重要です。 - 一時的クールダウンのプローブは、1回のフォールバック実行につきプロバイダーごとに1回に制限されるため、 単一のプロバイダーがクロスプロバイダーのフォールバックを停滞させることはありません。
セッションオーバーライドとライブモデル切り替え
セッションモデルの変更は共有状態です。アクティブなランナー、/modelコマンド、
compaction/セッション更新、およびライブセッション再調整はすべて、同じセッションエントリの
一部を読み書きします。
つまり、フォールバック再試行はライブモデル切り替えと協調する必要があります。
- 保留中のライブ切り替えをマークするのは、明示的なユーザー主導のモデル変更だけです。これには
/model、session_status(model=...)、およびsessions.patchが含まれます。 - フォールバックローテーション、heartbeatオーバーライド、 compactionのようなシステム主導のモデル変更は、それ自体では保留中のライブ切り替えをマークしません。
- フォールバック再試行が始まる前に、返信ランナーは選択された フォールバックオーバーライドフィールドをセッションエントリへ永続化します。
- ライブセッション再調整は、古いランタイムモデルフィールドよりも永続化されたセッションオーバーライドを優先します。
- フォールバック試行が失敗した場合、ランナーは自分が書き込んだオーバーライドフィールドだけを、 それらがまだその失敗した候補と一致している場合に限ってロールバックします。
- プライマリが失敗する。
- フォールバック候補がメモリ上で選択される。
- セッションストアはまだ古いプライマリを示している。
- ライブセッション再調整がその古いセッション状態を読み取る。
- フォールバック試行が始まる前に、再試行が古いモデルへ戻されてしまう。
可観測性と失敗サマリー
runWithModelFallback(...)は、ログと
ユーザー向けクールダウンメッセージに使われる試行ごとの詳細を記録します。
- 試行したprovider/model
- reason(
rate_limit、overloaded、billing、auth、model_not_found、および 類似のフェイルオーバー理由) - 任意のstatus/code
- 人が読めるエラーサマリー
FallbackSummaryErrorを投げます。外側の
返信ランナーはそれを使って、「すべてのモデルが一時的にレート制限されている」のような、より具体的なメッセージを構築し、
わかっている場合は最も早いクールダウン満了時刻を含めることができます。
そのクールダウンサマリーはモデルを考慮します。
- 試行された provider/modelチェーンに無関係なモデルスコープのレート制限は無視されます
- 残っているブロックがそのモデルに一致するモデルスコープのレート制限である場合、OpenClawは そのモデルを引き続きブロックしている最後の一致満了時刻を報告します
関連する設定
以下についてはGateway configurationを参照してください。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.fallbacksagents.defaults.imageModelのルーティング