Skip to content

OpenClaw 处理模型故障时先轮换当前 provider 的 Auth Profile(按 OAuth → API Key 顺序),耗尽后再切换 agents.defaults.model.fallbacks 中的下一个模型。配置 auth.order 控制 profile 轮换顺序,agents.defaults.model.fallbacks 决定备用模型链;冷却使用指数退避(最长 1 小时),账单禁用最长 24 小时。通过 /model 手动选中的模型不触发 fallback,直接报告失败。

模型故障转移(Model Failover):Auth Profile 轮换与 Fallback 链配置

OpenClaw 的故障处理分两个阶段:

  1. 在当前 provider 内轮换 Auth Profile(交换 API Key 或 OAuth token)
  2. 切换到 agents.defaults.model.fallbacks 中的下一个模型

运行时流程

普通文本请求时,OpenClaw 按以下顺序评估候选:

解析会话状态

获取当前会话选中的模型和 Auth Profile 偏好。

构建候选链

从当前模型选择及对应的 fallback 策略(配置默认、cron job 主模型、自动 fallback override 可使用配置的 fallbacks;用户手工选择的模型为严格模式)构建模型候选列表。

尝试当前 provider

在当前 provider 内应用 Auth Profile 轮换与冷却规则。

遇到可 failover 的错误时前进

该 provider 因可 failover 的错误耗尽后,切换到下一个模型候选。

持久化 fallback override

重试开始前将选中的 fallback override 写入 session,使其他会话读取器看到同一 provider/model。写入的 override 标记 `modelOverrideSource: "auto"`。

失败时窄回滚

如果 fallback 候选失败,只回滚该候选对应的 session override 字段(`providerOverride`、`modelOverride`、`modelOverrideSource`、`authProfileOverride`、`authProfileOverrideSource`、`authProfileOverrideCompactionCount`),前提是这些字段仍匹配该失败候选。

全部失败时抛出 FallbackSummaryError

所有候选均失败时抛出 `FallbackSummaryError`,包含每次尝试的详情和最早的冷却到期时间(如已知)。

这个回滚策略比“保存并恢复整个 session”更窄,防止失败的 fallback 重试覆盖其他并发的 session 变更(如手工 /model 切换或 session 旋转更新)。

选择来源策略(Selection Source Policy)

OpenClaw 区分“选择了哪个 provider/model”与“为什么这样选”。来源控制是否允许 fallback 链:

  • Configured defaultagents.defaults.model.primary 使用 agents.defaults.model.fallbacks
  • Agent primaryagents.list[].model 默认严格(除非该 agent model 对象自带了 fallbacks)。设置 fallbacks: [] 显式声明严格,或提供非空列表去启用 fallback。
  • Auto fallback override:运行时 fallback 写入 providerOverridemodelOverridemodelOverrideSource: "auto" 及选中 origin model。auto override 会继续走配置的 fallback 链,而不在每次消息时探测主模型。OpenClaw 每 5 分钟(不可配置)探测一次 origin,恢复后清除 auto override。/new/resetsessions.reset 也立即清除 auto override。没有 heartbeat.model 的心跳运行会清除不再匹配当前默认的 auto override。
  • User session override/model、模型选择器、session_status(model=...)sessions.patch 写入 modelOverrideSource: "user"。这是精确的 session 选择,如果该 provider/model 失败,直接报告失败,不会应答无关的 fallback。
  • Legacy session override:较早的 session 可能只有 modelOverride 而无 modelOverrideSource,OpenClaw 视为 user override,防止老选择被悄悄当作 fallback。
  • Cron payload model:cron job 的 payload.model--model 是 job 主模型,除非提供了 payload.fallbacks,否则使用配置的 fallbacks。payload.fallbacks: [] 使 cron 严格。

用户可见的 Fallback 通知

当 session 进入自动 fallback 时,OpenClaw 在回复中发送状态通知:

text
↪️ Model Fallback: <fallback> (selected <primary>; <reason>)

当后续探测成功后恢复主模型时:

text
↪️ Model Fallback cleared: <primary> (was <fallback>)

这些通知仅状态变化时发送一次(含 effect-only turn),粘性 fallback 不重复。通知绕过 source-reply 抑制、不计为 thread 的首条 assistant 回复、不进入 TTS 和 commitment 提取。

Auth 存储(API Key + OAuth)

OpenClaw 对 API Key 和 OAuth token 统一使用 Auth Profile 管理:

  • 密钥存储:~/.openclaw/agents/<agentId>/agent/auth-profiles.json
  • Runtime auth 路由状态:~/.openclaw/agents/<agentId>/agent/auth-state.json
  • 配置 auth.profiles / auth.order 仅含元数据和路由,不含密钥
  • 旧版 OAuth 导入文件:~/.openclaw/credentials/oauth.json(首次使用导入到 auth-profiles.json

Credential 类型:

  • type: "api_key"{ provider, key }
  • type: "oauth"{ provider, access, refresh, expires, email? }(部分 provider 加 projectId/enterpriseUrl

Profile ID 规则

  • 默认无 email:provider:default
  • OAuth 有 email:provider:&lt;email&gt;(例如 google-antigravity:user@gmail.com

轮换顺序

provider 有多个 profile 时按以下优先级排序:

显式配置

检查 `auth.order[provider]`(若已设置)。

配置的 profiles

`auth.profiles` 中该 provider 的条目。

存储的 profiles

`auth-profiles.json` 中该 provider 的条目。

无显式顺序时使用轮转(round-robin):

  • 主键:profile 类型(OAuth 优先于 API Key
  • 次键usageStats.lastUsed(同类型内最久未用的优先)
  • 冷却/禁用的 profile 移到末尾,按最快到期排序

会话粘性(Session Stickiness)

OpenClaw 每个 session 锁定一个 Auth Profile 以保持 provider 缓存温热,不在每次请求时轮换。已锁定的 profile 持续使用直到:

  • 会话重置(/new / /reset
  • compaction 完成(compaction count 递增)
  • 该 profile 进入冷却/禁用状态

手工 /model …@<profileId> 设置为 user override,新 session 开始前不会自动轮换。

INFO

自动锁定(session 路由器选择)的 profile 被视为偏好:优先尝试,但 OpenClaw 在限流/超时时可能切换到其他 profile。原 profile 可用后,新运行可再次优先使用它,无需改变模型或 runtime。用户锁定的 profile 严格锁定;如果它失败且配置了模型 fallback,OpenClaw 会切换到下一个模型而不是切换 profile。

OpenAI Codex 订阅 + API Key 备份

OpenAI 智能体模型的 Auth 与 Runtime 分离。openai/gpt-* 始终在 Codex harness 上,而 Auth 可在 Codex 订阅 profile 和 OpenAI API Key 备份之间轮换。

使用 auth.order.openai 控制用户侧顺序:

json5
{
  auth: {
    order: {
      openai: ["openai-codex:user@example.com", "openai:api-key-backup"],
    },
  },
}

订阅达到 Codex 使用限制时,OpenClaw 记录精确的重置时间(如 Codex 提供),尝试下一个 ordered auth profile,并在 Codex harness 内继续运行。重置时间过后订阅 profile 恢复可用。

只有需要强制固定账号时才使用 user-pinned profile,因为它不会自动跳转。

冷却机制(Cooldowns)

profile 因 Auth/限流错误(或看起来像限流的超时)失败时,标记为冷却状态并切换到下一个 profile。

被归类为限流/超时的错误

包括但不限于:HTTP 429、`Too many concurrent requests`、`ThrottlingException`、`concurrency limit reached`、`workers_ai ... quota limit exceeded`、`throttled`、`resource exhausted`、`weekly/monthly limit reached`。

格式/参数错误通常为终态,OpenClaw 直接暴露而不轮换 auth profile。已知可修复重试的路径可选纳入(如 Cloud Code Assist 的 tool call ID 校验失败通过 `allowFormatRetry` 策略重试一次)。OpenAI 兼容的 stop-reason 错误(如 `Unhandled stop reason: error`、`stop reason: error`)归类为超时/故障转移信号。

pi-ai 流包装器消息 `An unknown error occurred`(由 provider 流以 `stopReason: "aborted"` 或 `stopReason: "error"` 结束时产生)视为可 failover。JSON `api_error` 中包含 transient 文本(如 `internal server error`、`unknown error, 520`、`upstream error`、`backend error`)也视为超时。

OpenRouter 特定文本 `Provider returned error` 仅在 provider 上下文为 OpenRouter 时视为超时。通用内部 fallback 文本 `LLM request failed with an unknown error.` 保守处理,不触发 failover。

SDK Retry-After 上限

某些 provider SDK(如基于 Stainless 的 Anthropic、OpenAI)可能会在较长的 `Retry-After` 窗口内休眠。OpenClaw 默认将 SDK 内部 `retry-after-ms` 等待上限设为 60 秒,超出时将长等待响应立刻返回给 failover 路径。通过环境变量 `OPENCLAW_SDK_RETRY_MAX_WAIT_SECONDS` 调整或禁用此上限(参见 [Retry behavior](/ai/ai-tools/openclaw/concepts/retry))。

模型级冷却

限流冷却可限定到特定模型:
- OpenClaw 记录 `cooldownModel`(当知道失败模型 ID 时)
- 同一 provider 的不同模型仍可尝试
- 账单/禁用状态仍跨模型阻塞整个 profile

冷却使用指数退避:

  • 1 分钟
  • 5 分钟
  • 25 分钟
  • 1 小时(上限)

状态存储在 auth-state.jsonusageStats 中:

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

账单禁用(Billing Disables)

账单/信用不足错误(如 insufficient creditscredit balance too low)视为可 failover,但通常非临时性。OpenClaw 将 profile 标记为禁用(更长退避)而不是短期冷却,并切换到下一个 profile/provider。

INFO

不每个账单错误都是 HTTP 402,也不是每 402 都进入此路径。OpenClaw 通过明确账单文本归类(即使 provider 返回 401/403)。但临时 402 使用窗口、组织/工作区支出限制错误(如 weekly usage limit exhausteddaily limit reached, resets tomorroworganization spending limit exceeded)归类为限流,走短冷却路径而非长账单禁用。

状态存储在 auth-state.json

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

默认值:

  • 账单退避从 5 小时开始,每次账单失败翻倍,上限 24 小时
  • 退避计数器在 profile 连续 24 小时无失败后重置(可配置)。
  • 过载重试允许 1 次同 provider profile 轮换后再进行模型 fallback。
  • 过载重试默认使用 0 ms 退避

模型 Fallback

所有 provider 的 profile 都失败后,OpenClaw 切换到 agents.defaults.model.fallbacks 中的下一个模型。这适用于耗尽了 profile 轮换的 Auth 失败、限流、超时。不能暴露足够详情的 provider 错误也在 fallback 状态中精确标记:empty_response(无可用消息或状态)、no_error_details(显式返回 Unknown error (no error details in response))、unclassified(保留原始预览但无匹配分类)。

过载和限流错误比账单禁用更激进。默认允许 1 次同 provider auth-profile 重试,然后立即切换到下一个配置的模型 fallback(不等待)。Provider-busy 信号如 ModelNotReadyException 落入过载桶。通过以下参数调整:auth.cooldowns.overloadedProfileRotationsauth.cooldowns.overloadedBackoffMsauth.cooldowns.rateLimitedProfileRotations

从配置默认主模型、cron job 主模型、带显式 fallbacks 的 agent 主模型、或自动 fallback override 开始的运行可以走匹配的 fallback 链。无显式 fallbacks 的 agent 主模型和显式用户选择(如 /model ollama/qwen3.5:27b、模型选择器、sessions.patch、一次性 CLI provider/model 覆盖)为严格模式:若该 provider/model 不可达或失败前无法产生回复,直接报告失败。

候选链规则

OpenClaw 从当前请求的 provider/model 加上配置的 fallbacks 构建候选列表。

规则

- 请求的模型始终排在首位。
- 显式配置的 fallbacks 去重,但不被模型允许列表过滤(视为操作者显式意图)。
- 如果当前运行已在同一 provider 家族的配置 fallback 上,OpenClaw 继续使用完整配置链。
- 未提供 fallback override 时,配置的 fallbacks 在主模型之前尝试(即使请求的模型使用不同 provider)。
- 未提供 fallback override 时,配置的主模型追加到末尾,以便链在早期候选耗尽后回到正常默认。
- 当调用方提供 `fallbacksOverride` 时,运行器仅使用请求的模型加上该 override 列表。空列表禁用模型 fallback 并阻止主模型被追加为隐藏重试目标。

哪些错误推进 Fallback

推进 fallback

- Auth 失败
- 限流和冷却耗尽
- 过载/provider-busy 错误
- 超时形状的 failover 错误
- 账单禁用
- `LiveSessionModelSwitchError`(规范化为 failover 路径,防止陈旧持久化模型创建外部重试循环)
- 其他未识别错误(当仍有候选剩余时)

不推进 fallback

- 非超时/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`
- 无候选剩余时的最终未知错误

冷却跳过 vs 探测行为

当 provider 的所有 auth profile 都在冷却中时,OpenClaw 不会自动永久跳过该 provider,而是做出每个候选的决定:

每候选决定

- 持久性 Auth 失败立即跳过整个 provider。
- 账单禁用通常跳过,但主候选可以受节流限制探测以允许恢复。
- 主候选可在冷却到期前探测(每个 provider 有节流)。
- 同 provider 的 fallback 兄弟模型仍可尝试(即使有冷却),当失败看起来是瞬时(`rate_limit`、`overloaded` 或未知)时。尤其当限流是模型级时,兄弟模型可能立即恢复。
- 瞬时冷却探测限制为每个 provider 每次 fallback 运行最多一次,防止单个 provider 阻塞跨 provider fallback。

Session Overrides 与实时模型切换

Session 模型变更是共享状态。活跃 runner、/model 命令、compaction/session 更新、实时 session 协调都会读写同一 session 条目。因此 fallback 重试必须与实时模型切换协调:

  • 只有显式用户驱动的模型变更(/modelsession_status(model=...)sessions.patch)标记待命实时切换。
  • 系统驱动的模型变更(fallback 旋转、心跳 override、compaction)从不自行标记实时切换。
  • 用户驱动的模型 override 视为精确选择,不可达时直接报告失败。
  • Fallback 重试开始前,回复 runner 将选中的 fallback override 字段持久化到 session 条目。
  • Auto fallback override 在后续轮次中保持选中,避免每次消息探测已知故障的 primary。OpenClaw 每 5 分钟探测 origin 一次,恢复后清除 auto override;/new/resetsessions.reset 立即清除。
  • 用户回复在状态变更时通知 fallback 过渡和恢复,粘性 fallback 不重复通知。
  • /status 显示当前选定模型,当 fallback 状态不同时显示活跃 fallback 模型和原因。
  • 实时 session 协调优先使用持久化的 session override 而非过时的 runtime 模型字段。
  • 如果实时切换错误指向活跃 fallback 链中的某一候选,OpenClaw 直接跳跃到该模型,而不是先遍历无关候选。
  • 如果 fallback 尝试失败,runner 只回滚它写入的 override 字段,且仅当它们仍匹配该失败候选。

这防止典型的竞争:

Primary 失败

选定的 primary 模型失败。

内存中选中 fallback

在内存中选定 fallback 候选。

Session 存储仍显示旧 primary

Session 存储仍反映旧的 primary。

实时协调读取过期状态

实时 session 协调读到过期 session 状态。

重试被拉回

重试在 fallback 尝试开始前被拉回到旧模型。

持久化 fallback override 关闭了这个窗口,而窄回滚保持了更新的手工或运行时 session 变更完好。

可观测性与失败摘要

runWithModelFallback(...) 记录每次尝试的详情(provider/model、原因 rate_limit/overloaded/billing/auth/model_not_found 等、可选状态码、人类可读错误摘要)。结构化的 model_fallback_decision 日志还包括平铺的 fallbackStep* 字段(fallbackStepFromModelfallbackStepToModelfallbackStepFromFailureReasonfallbackStepFromFailureDetailfallbackStepFinalOutcome),使日志和诊断导出器能重构 primary 失败,即使终端 fallback 也失败。

所有候选均失败时抛出 FallbackSummaryError。外部回复 runner 可据此构建更具体消息如“所有模型暂时被限流”,并包含最早的冷却到期时间(如已知)。该冷却总结是模型感知的:忽略与当前尝试 provider/model 链无关的模型级限流;如果剩余阻塞是匹配的模型级限流,则报告最后一个仍阻塞该模型的到期时间。

相关配置

参见 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 路由

更多模型选择和 fallback 概览见 Models

常见问题

怎么配置 fallback 模型列表?

openclaw.ymlagents.defaults.model.fallbacks 中添加模型 ID 数组,例如 ["openai/gpt-4", "anthropic/claude-3-opus"]。agent 主模型也可自带 fallbacks 列表。

限流冷却时间能缩短或禁用吗?

可以。调整 auth.cooldowns.overloadedProfileRotationsauth.cooldowns.overloadedBackoffMsauth.cooldowns.rateLimitedProfileRotations。但冷却保护账号不被封禁,不建议设得太短。

怎么强制某 session 一直使用指定 Auth Profile?

在 session 中输入 /model ...@<profileId>(如 /model openai/gpt-4@openai-codex:user@example.com)设置 user override,该 session 后续请求锁定该 profile 直到重置或新 session。