Concepts and configuration

模型故障轉移

OpenClaw 會分兩個階段處理失敗:

  1. 在目前提供者內進行驗證設定檔輪替
  2. 模型後援agents.defaults.model.fallbacks 中的下一個模型。

本文件說明執行階段規則及其背後的資料。

執行階段流程

對一般文字執行而言,OpenClaw 會依照下列順序評估候選項目:

  • 解析工作階段狀態

    解析作用中的工作階段模型與驗證設定檔偏好。

  • 建立候選鏈

    從目前的模型選取項目,以及該選取來源的後援政策,建立模型候選鏈。已設定的預設值、Cron 工作主要模型,以及自動選取的後援模型,可以使用已設定的後援;明確的使用者工作階段選取則是嚴格模式。

  • 嘗試目前提供者

    依照驗證設定檔輪替/冷卻規則嘗試目前提供者。

  • 在值得故障轉移的錯誤時前進

    如果該提供者因值得故障轉移的錯誤而耗盡,移至下一個模型候選項目。

  • 保存後援覆寫

    在重試開始前保存選取的後援覆寫,讓其他工作階段讀取者看到執行器即將使用的相同提供者/模型。保存的模型覆寫會標記為 modelOverrideSource: "auto"

  • 失敗時狹義回復

    如果後援候選項目失敗,只有在後援擁有的工作階段覆寫欄位仍符合該失敗候選項目時,才回復那些欄位。

  • 耗盡時拋出 FallbackSummaryError

    如果每個候選項目都失敗,拋出包含每次嘗試詳細資料,以及已知最早冷卻到期時間的 FallbackSummaryError

  • 這有意比「儲存並還原整個工作階段」更窄。回覆執行器只會保存它為後援所擁有的模型選取欄位:

    • providerOverride
    • modelOverride
    • modelOverrideSource
    • authProfileOverride
    • authProfileOverrideSource
    • authProfileOverrideCompactionCount

    這可防止失敗的後援重試覆寫較新的無關工作階段變更,例如嘗試執行期間發生的手動 /model 變更或工作階段輪替更新。

    選取來源政策

    OpenClaw 會區分選取的提供者/模型,以及它為何被選取。該來源會控制是否允許後援鏈:

    • 已設定的預設值agents.defaults.model.primary 會使用 agents.defaults.model.fallbacks
    • Agent 主要模型agents.list[].model 是嚴格模式,除非該 agent 模型物件包含自己的 fallbacks。使用 fallbacks: [] 可明確指定嚴格行為,或提供非空清單來讓該 agent 啟用模型後援。
    • 自動後援覆寫:執行階段後援會在重試前寫入 providerOverridemodelOverridemodelOverrideSource: "auto"。該自動覆寫可以繼續走已設定的後援鏈,並會由 /new/resetsessions.reset 清除。
    • 使用者工作階段覆寫/model、模型選擇器、session_status(model=...)sessions.patch 會寫入 modelOverrideSource: "user"。這是精確的工作階段選取。如果選取的提供者/模型在產生回覆前失敗,OpenClaw 會回報失敗,而不是從無關的已設定後援回答。
    • 舊版工作階段覆寫:較舊的工作階段項目可能有 modelOverride 但沒有 modelOverrideSource。OpenClaw 會將它們視為使用者覆寫,因此明確的舊選取不會被靜默轉換成後援行為。
    • Cron 承載模型:Cron 工作的 payload.model / --model 是工作主要模型,不是使用者工作階段覆寫。它會使用已設定的後援,除非該工作提供 payload.fallbackspayload.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
    • 含電子郵件的 OAuth:provider:<email>(例如 google-antigravity:[email protected])。

    設定檔位於 ~/.openclaw/agents/<agentId>/agent/auth-profiles.jsonprofiles 底下。

    輪替順序

    當提供者有多個設定檔時,OpenClaw 會以下列方式選擇順序:

  • 明確設定

    auth.order[provider](如果已設定)。

  • 已設定的設定檔

    依提供者篩選的 auth.profiles

  • 已儲存的設定檔

    auth-profiles.json 中該提供者的項目。

  • 如果未設定明確順序,OpenClaw 會使用循環順序:

    • **主要鍵:**設定檔類型(OAuth 優先於 API 金鑰)。
    • 次要鍵:usageStats.lastUsed(每種類型內最舊的優先)。
    • 冷卻/停用的設定檔會移到最後,依最早到期時間排序。

    工作階段黏著性(快取友善)

    OpenClaw 會將選定的驗證設定檔固定到每個工作階段,以保持提供者快取溫熱。它不會在每次請求時輪替。固定的設定檔會重複使用,直到:

    • 工作階段被重設(/new / /reset
    • Compaction 完成(Compaction 計數增加)
    • 設定檔處於冷卻/停用狀態

    透過 /model …@<profileId> 手動選取會為該工作階段設定使用者覆寫,且在新工作階段開始前不會自動輪替。

    為什麼 OAuth 可能「看起來遺失」

    如果同一個提供者同時有 OAuth 設定檔和 API 金鑰設定檔,除非已固定,否則循環可能會在訊息之間切換它們。若要強制使用單一設定檔:

    • 使用 auth.order[provider] = ["provider:profileId"] 固定,或
    • 透過 /model … 搭配設定檔覆寫使用每工作階段覆寫(當你的 UI/聊天介面支援時)。

    冷卻

    當設定檔因驗證/速率限制錯誤(或看起來像速率限制的逾時)失敗時,OpenClaw 會將它標記為冷卻,並移至下一個設定檔。

    會進入速率限制 / 逾時類別的內容

    該速率限制類別比單純的 429 更廣:它也包含提供者訊息,例如 Too many concurrent requestsThrottlingExceptionconcurrency limit reachedworkers_ai ... quota limit exceededthrottledresource exhausted,以及週期性使用量視窗限制,例如 weekly/monthly limit reached

    格式/無效請求錯誤(例如 Cloud Code Assist 工具呼叫 ID 驗證失敗)會被視為值得故障轉移,並使用相同的冷卻。OpenAI 相容的停止原因錯誤,例如 Unhandled stop reason: errorstop reason: errorreason: error,會被分類為逾時/故障轉移訊號。

    當來源符合已知暫時性模式時,一般伺服器文字也可能進入該逾時類別。例如,裸露的 pi-ai 串流包裝器訊息 An unknown error occurred 會被視為所有提供者都值得故障轉移,因為 pi-ai 會在提供者串流以 stopReason: "aborted"stopReason: "error" 結束且沒有具體詳細資訊時發出它。含暫時性伺服器文字的 JSON api_error 承載,例如 internal server errorunknown error, 520upstream errorbackend error,也會被視為值得故障轉移的逾時。

    OpenRouter 特定的一般上游文字,例如裸露的 Provider returned error,只有在提供者內容實際上是 OpenRouter 時才會被視為逾時。一般內部後援文字,例如 LLM request failed with an unknown error.,會保持保守,本身不會觸發故障轉移。

    SDK Retry-After 上限

    某些提供者 SDK 可能會在將控制權傳回 OpenClaw 前,因較長的 Retry-After 視窗而休眠。對於 Anthropic 和 OpenAI 等以 Stainless 為基礎的 SDK,OpenClaw 預設會將 SDK 內部的 retry-after-ms / retry-after 等待限制在 60 秒,並立即浮現更長的可重試回應,讓這條故障轉移路徑可以執行。使用 OPENCLAW_SDK_RETRY_MAX_WAIT_SECONDS 調整或停用該上限;請參閱重試行為

    模型範圍冷卻

    速率限制冷卻也可以限定於模型範圍:

    • 當失敗模型 ID 已知時,OpenClaw 會為速率限制失敗記錄 cooldownModel
    • 當冷卻限定於不同模型時,同一提供者上的同級模型仍可被嘗試。
    • 帳單/停用視窗仍會跨模型封鎖整個設定檔。

    冷卻使用指數退避:

    • 1 分鐘
    • 5 分鐘
    • 25 分鐘
    • 1 小時(上限)

    狀態會儲存在 auth-state.jsonusageStats 底下:

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

    帳單停用

    帳單/額度失敗(例如 "insufficient credits" / "credit balance too low")會被視為值得故障轉移,但它們通常不是暫時性的。OpenClaw 不會使用短冷卻,而是將設定檔標記為停用(搭配較長退避),並輪替到下一個設定檔/提供者。

    狀態會儲存在 auth-state.json

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

    預設值:

    • 帳單退避從 5 小時開始,每次帳單失敗後加倍,並以 24 小時為上限。
    • 如果設定檔已 24 小時未失敗,退避計數器會重設(可設定)。
    • 過載重試允許在模型後援前進行 1 次同提供者設定檔輪替
    • 過載重試預設使用 0 毫秒退避

    模型後援

    如果提供者的所有設定檔都失敗,OpenClaw 會移至 agents.defaults.model.fallbacks 中的下一個模型。這適用於已耗盡設定檔輪替的驗證失敗、速率限制和逾時(其他錯誤不會推進後援)。沒有暴露足夠詳細資訊的提供者錯誤仍會在後援狀態中精確標記:empty_response 表示提供者沒有回傳可用訊息或狀態,no_error_details 表示提供者明確回傳 Unknown error (no error details in response),而 unclassified 表示 OpenClaw 保留了原始預覽,但尚未有分類器符合它。

    過載和速率限制錯誤會比計費冷卻更積極地處理。預設情況下,OpenClaw 允許同一提供者的驗證設定檔重試一次,接著不等待就切換到下一個已設定的模型備援。像 ModelNotReadyException 這類提供者忙碌訊號會歸入該過載類別。可用 auth.cooldowns.overloadedProfileRotationsauth.cooldowns.overloadedBackoffMsauth.cooldowns.rateLimitedProfileRotations 進行調整。

    當一次執行從已設定的預設主要模型、cron 工作主要模型、具有明確備援的代理主要模型,或自動選取的備援覆寫開始時,OpenClaw 可以依序走過相符的已設定備援鏈。沒有明確備援的代理主要模型,以及明確的使用者選擇(例如 /model ollama/qwen3.5:27b、模型選擇器、sessions.patch,或一次性的 CLI 提供者/模型覆寫)都是嚴格模式:如果該提供者/模型無法連線,或在產生回覆前失敗,OpenClaw 會回報失敗,而不是從不相關的備援回答。

    候選鏈規則

    OpenClaw 會根據目前請求的 provider/model 加上已設定的備援來建立候選清單。

    規則
    • 請求的模型一律排在第一個。
    • 明確設定的備援會去重,但不會依模型允許清單過濾。它們會被視為明確的操作員意圖。
    • 如果目前執行已位於同一提供者家族中的已設定備援上,OpenClaw 會繼續使用完整的已設定鏈。
    • 如果目前執行所在的提供者不同於設定,且目前模型尚未屬於已設定的備援鏈,OpenClaw 不會附加來自其他提供者的不相關已設定備援。
    • 當沒有向備援執行器提供明確的備援覆寫時,已設定的主要模型會附加在最後,讓鏈在前面的候選都耗盡後,可以回到正常預設。
    • 當呼叫端提供 fallbacksOverride 時,執行器只會使用請求的模型加上該覆寫清單。空清單會停用模型備援,並防止已設定的主要模型被附加為隱藏重試目標。

    哪些錯誤會推進備援

    會繼續於

    • 驗證失敗
    • 速率限制和冷卻耗盡
    • 過載/提供者忙碌錯誤
    • 類似逾時的容錯移轉錯誤
    • 計費停用
    • LiveSessionModelSwitchError,它會被正規化為容錯移轉路徑,讓過期的持久化模型不會建立外層重試迴圈
    • 當仍有剩餘候選時的其他無法辨識錯誤

    不會繼續於

    • 非逾時/容錯移轉形態的明確中止
    • 應留在 Compaction/重試邏輯內的上下文溢位錯誤(例如 request_too_largeINVALID_ARGUMENT: input exceeds the maximum number of tokensinput token count exceeds the maximum number of input tokensThe input is too long for the model,或 ollama error: context length exceeded
    • 沒有剩餘候選時的最終未知錯誤

    冷卻略過與探測行為

    當某個提供者的每個驗證設定檔都已在冷卻中時,OpenClaw 不會自動永遠略過該提供者。它會針對每個候選做出決策:

    逐候選決策
    • 持續性驗證失敗會立即略過整個提供者。
    • 計費停用通常會略過,但主要候選仍可在節流下被探測,讓恢復可在不重新啟動的情況下發生。
    • 主要候選可在接近冷卻到期時被探測,並套用逐提供者節流。
    • 當失敗看起來是暫時性的(rate_limitoverloaded 或未知)時,同一提供者的備援同層模型仍可在冷卻期間嘗試。這在速率限制是模型範圍,而同層模型可能仍能立即恢復時特別相關。
    • 暫時性冷卻探測在每次備援執行中,每個提供者最多一次,避免單一提供者阻塞跨提供者備援。

    工作階段覆寫和即時模型切換

    工作階段模型變更是共享狀態。作用中的執行器、/model 命令、Compaction/工作階段更新,以及即時工作階段協調,都會讀取或寫入同一個工作階段項目的部分內容。

    這表示備援重試必須與即時模型切換協調:

    • 只有明確由使用者驅動的模型變更會標記待處理的即時切換。這包括 /modelsession_status(model=...)sessions.patch
    • 系統驅動的模型變更,例如備援輪換、Heartbeat 覆寫或 Compaction,本身永遠不會標記待處理的即時切換。
    • 使用者驅動的模型覆寫會被視為備援策略的精確選擇,因此無法連線的已選提供者會呈現為失敗,而不是被 agents.defaults.model.fallbacks 遮蔽。
    • 在備援重試開始前,回覆執行器會將所選備援覆寫欄位持久化到工作階段項目。
    • 自動備援覆寫會在後續回合保持選取狀態,因此 OpenClaw 不會在每則訊息上探測已知故障的主要模型。/new/resetsessions.reset 會清除自動來源的覆寫,並讓工作階段回到已設定的預設值。
    • /status 會顯示所選模型;當備援狀態不同時,也會顯示作用中的備援模型和原因。
    • 即時工作階段協調會優先使用持久化的工作階段覆寫,而不是過期的執行階段模型欄位。
    • 如果即時切換錯誤指向作用中備援鏈中較後面的候選,OpenClaw 會直接跳到該選取的模型,而不是先走過不相關的候選。
    • 如果備援嘗試失敗,執行器只會回復它寫入的覆寫欄位,而且只有在它們仍與該失敗候選相符時才會回復。

    這可防止典型競態:

  • 主要模型失敗

    所選的主要模型失敗。

  • 在記憶體中選擇備援

    在記憶體中選擇備援候選。

  • 工作階段儲存仍顯示舊主要模型

    工作階段儲存仍反映舊的主要模型。

  • 即時協調讀取過期狀態

    即時工作階段協調讀取過期的工作階段狀態。

  • 重試被拉回

    在備援嘗試開始前,重試被拉回舊模型。

  • 持久化的備援覆寫會關閉這個時間窗,而狹窄的回復會保留較新的手動或執行階段工作階段變更。

    可觀測性和失敗摘要

    runWithModelFallback(...) 會記錄每次嘗試的詳細資料,用於日誌和面向使用者的冷卻訊息:

    • 嘗試的提供者/模型
    • 原因(rate_limitoverloadedbillingauthmodel_not_found,以及類似的容錯移轉原因)
    • 選用狀態/代碼
    • 人類可讀的錯誤摘要

    結構化的 model_fallback_decision 日誌也會在候選失敗、被略過,或較後面的備援成功時包含扁平的 fallbackStep* 欄位。這些欄位會明確呈現嘗試的轉換(fallbackStepFromModelfallbackStepToModelfallbackStepFromFailureReasonfallbackStepFromFailureDetailfallbackStepFinalOutcome),讓日誌和診斷匯出器即使在最終備援也失敗時,仍能重建主要失敗。

    當每個候選都失敗時,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 路由

    請參閱 模型 了解更廣泛的模型選擇和備援概觀。