- 当前提供方内的认证配置文件轮换。
- 模型回退到
agents.defaults.model.fallbacks中的下一个模型。
运行流程
1
解析会话状态
解析当前会话模型和认证配置文件偏好。
2
构建候选链
根据当前模型选择以及该选择来源的回退策略构建模型候选链。已配置的默认值、cron 任务主模型以及自动选择的回退模型可以使用已配置的回退;显式的用户会话选择是严格的。
3
尝试当前提供方
使用认证配置文件轮换/冷却规则尝试当前提供方。
4
在可故障转移错误时推进
如果该提供方因可故障转移错误而用尽,移动到下一个模型候选项。
5
当前轮次使用回退
在不更改会话中所选提供方/模型的情况下,使用获胜的回退候选项运行。
6
重试安全的纯超载耗尽
如果每个候选都仅因提供方过载而失败,则在尚未开始任何工具执行或助手输出时,以指数退避方式对整个轮次本地链重试最多 10 次。30 秒后,发送一条状态通知,这样用户就不会一直无声等待。
7
耗尽时抛出 FailoverError
如果每个候选都失败,则抛出一个
FailoverError,其中包含每次尝试的结构化详细信息,以及在已知时最早的冷却期结束时间。选择来源策略
选择来源决定是否允许回退链:- 已配置默认值:
agents.defaults.model.primary使用agents.defaults.model.fallbacks。 - Agent 主模型:
agents.entries.*.model默认是严格模式,除非该 agent 的 model 对象包含自己的fallbacks。使用fallbacks: []可显式启用严格行为,或提供一个非空列表让该 agent 使用模型回退。 - 运行时回退: 回退候选项仅适用于当前轮次。下一轮会再次从所选主模型开始。OpenClaw 仍会识别之前保存的
modelOverrideSource: "auto"条目,每 5 分钟探测其配置来源一次,并在来源恢复后将其清除。/new、/reset和sessions.reset也会清除这些条目。 - 用户会话覆盖:
/model、模型选择器、session_status(model=...)和sessions.patch会写入modelOverrideSource: "user"。这是一个精确的会话选择。如果所选 provider/model 在生成回复前失败,OpenClaw 会报告该失败,而不是从无关的已配置回退项中回答。 - 旧版会话覆盖: 较旧的会话条目可能只有
modelOverride而没有modelOverrideSource。OpenClaw 会将这些条目视为用户覆盖,因此显式的旧选择不会被悄然转换为回退行为。 - Cron 负载模型: cron 作业的
payload.model/--model是作业主模型,不是用户会话覆盖。除非作业提供payload.fallbacks,否则它会使用已配置的回退;payload.fallbacks: []会使 cron 运行保持严格模式。
认证失败跳过缓存
默认情况下,每个新的轮次都会保持现有的回退重试行为:OpenClaw 会再次重试每个已配置的回退候选项,包括最近因auth 或 auth_permanent 失败的非主候选项。
可通过以下方式启用跳过重复认证失败:
0 或未设置会禁用该缓存。正值会被限制在 1 秒到 10 分钟之间。
面向用户的回退通知
当会话切换到自动选择的回退时,OpenClaw 会在同一回复界面发送状态通知:认证存储(密钥 + OAuth)
OpenClaw 对 API 密钥和 OAuth 令牌都使用认证配置文件。- 密钥和运行时认证路由状态存储在
~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite中。 - 配置中的
auth.profiles/auth.order仅用于元数据和路由(不包含密钥)。 - 旧版的
credentials/oauth.json、auth-profiles.json、auth-state.json以及每个代理的auth.json文件,仅会由openclaw doctor --fix导入。 在包含凭据的旧版文件完成迁移之前,受影响的代理将无法通过运行时认证;系统绝不会静默导入或回退到这些文件。
type: "api_key"→{ provider, key }type: "oauth"→{ provider, access, refresh, expires, email? }(某些提供商还适用projectId/enterpriseUrl)type: "token"→ 静态 bearer 风格令牌,可选择设置过期时间;OpenClaw 不会刷新它(用于aws-sdk和其他凭据链认证模式)。
配置文件 ID
OAuth 登录会创建不同的配置文件,以便多个账户可以共存。- 默认:
provider:default(无可用电子邮件地址时)。 - 带电子邮件地址的 OAuth:
provider:<email>(例如openai:[email protected])。
openclaw-agent.sqlite 身份验证配置文件存储中。
轮换顺序
当一个提供方有多个配置文件时,OpenClaw 会按如下顺序选择:1
显式配置
auth.order[provider](如果已设置)。2
已配置的配置文件
按 provider 过滤后的
auth.profiles。3
已存储的配置文件
每个 agent 的 SQLite 认证配置文件条目。
- 主键: 配置文件类型(OAuth,然后是静态 token,最后是 API key)。
- OAuth 的次键: 当前可用访问令牌的配置文件优先于 访问令牌已过期的配置文件。已过期的 OAuth 配置文件仍保留资格, 这样当没有可用的同类配置文件时,运行时可以刷新它们。
- 下一个键:
usageStats.lastUsed(在每个类型/状态层级内按最久未使用优先)。 - 冷却/已禁用配置文件 会被移动到末尾,并按最早过期时间排序。
会话粘性(缓存友好)
OpenClaw 会为每个会话固定自动选择的认证配置文件,以保持提供方缓存处于预热状态。它不会在每次请求时轮换。自动固定的配置文件可能会在以下情况下轮换或清除:- 会话被重置(
/new/reset) - 完成一次压缩(压缩计数递增)
- 该配置文件处于冷却/禁用状态
/model …@<profileId> -s 手动选择会设置一个用户覆盖。有效的用户固定配置文件会在 /new、/reset、会话轮换、压缩和冷却窗口期间保留。只要该配置文件符合条件,它就仍是首选;当该确切配置文件处于冷却或禁用状态时,OpenClaw 会尝试下一个符合条件的同提供商配置文件,而不会替换已存储的固定配置。配置文件消失、不再匹配所选提供方,或用户选择了其他显式配置文件时,OpenClaw 会清除该固定配置。/model default -s 会清除模型覆盖,同时保留兼容的认证固定配置,并清除不兼容的固定配置。
自动固定和用户固定的认证配置文件都是重试首选项:只要所选配置文件符合条件,OpenClaw 就会先尝试它,然后可能因认证失败、速率限制、计费限制或超时而轮换到另一个同提供商配置文件。用户固定配置会在临时轮换期间保持持久化,因此冷却期结束后新的运行会再次优先使用它,而不会更改所选模型或运行时。此认证轮换不会放宽模型选择:显式的用户提供方/模型选择在其同提供商认证配置文件耗尽后仍会严格报告失败。
OpenAI Codex 订阅加 API 密钥备用
对于 OpenAI agent 模型,认证和运行时是分开的。openai/gpt-* 会继续使用 Codex harness,而认证可以在 Codex 订阅配置文件和 OpenAI API key 备用配置文件之间轮换。
对于面向用户的顺序,使用 auth.order.openai:
openai:*。当订阅达到 Codex 使用上限时,OpenClaw 会记录 Codex 提供的确切重置时间,尝试下一个按顺序排列的认证配置文件,并保持运行在 Codex harness 中。一旦重置时间过去,订阅配置文件就会再次具备资格,下一次自动选择可以重新返回它。
使用用户固定的配置文件,可以让某个账户/密钥成为该会话中持久的首选。如果它变得不可用,OpenClaw 会暂时轮换遍历其余符合条件的 auth.order.openai 配置文件,并在恢复后返回固定的配置文件。
冷却
当一个配置文件由于认证/速率限制错误(或看起来像速率限制的超时)而失败时,OpenClaw 会将其标记为冷却并移动到下一个配置文件。 CLI 支持的运行时只有在其恢复、分叉和新会话恢复尝试完成后,才会确定配置文件的健康状态。终端凭据失败会在模型回退前冷却确切选中的配置文件;成功运行会清除过期的失败状态。转录、格式、上下文、提供方调用前超时,以及没有选中配置文件的 CLI 环境失败,都不会更改共享的配置文件健康状态。什么会进入速率限制 / 超时桶
什么会进入速率限制 / 超时桶
这个速率限制桶比普通的
429 更宽泛:它还包括提供方消息,例如 Too many concurrent requests、ThrottlingException、concurrency limit reached、workers_ai ... quota limit exceeded、throttled、resource exhausted,以及周期性使用窗口限制,例如 weekly limit reached 或 monthly limit exhausted。格式/无效请求错误通常是终止性的,因为重试相同的负载会以相同方式失败,因此 OpenClaw 会直接报告这些错误,而不是轮换认证配置文件。已知的重试修复路径可以显式选择加入:例如,Cloud Code Assist 工具调用 ID 验证失败会经过清理,并通过 allowFormatRetry 策略重试一次。OpenAI 兼容的由提供方完成的停止/完成原因,例如 Unhandled stop reason: error、stop reason: error、reason: error 和 Provider finish_reason: error,会被分类为 server_error(类似 HTTP 的状态码 500),而不是超时。它们仍符合故障转移条件,可用于模型/配置文件轮换,但诊断信息会保留提供方的完成原因文本,而不会将面向用户的文案改写为“LLM 请求超时”。传输层形式的完成原因,例如 Provider finish_reason: abort、network_error 和 malformed_response,仍会归入超时/故障转移桶(状态码 408)。当来源匹配已知的暂时性模式时,通用服务器文本也可能进入那个超时桶。例如,裸的模型运行时流包装器消息 An unknown error occurred 会被视为每个提供方都值得故障转移,因为共享模型运行时在提供方流以 stopReason: "aborted" 或 stopReason: "error" 结束且没有具体细节时会发出该消息。带有暂时性服务器文本的 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. 这样的通用内部回退文本会保持保守,不会自行触发故障转移。SDK 重试后等待上限
SDK 重试后等待上限
某些提供方 SDK 可能会在把控制权交还给 OpenClaw 之前,先长时间休眠一个
Retry-After 窗口。对于基于 Stainless 的 SDK,例如 Anthropic 和 OpenAI,OpenClaw 默认会将 SDK 内部的 retry-after-ms / retry-after 等待上限设为 60 秒,并立即呈现更长的可重试响应,以便该故障转移路径可以运行。可使用 OPENCLAW_SDK_RETRY_MAX_WAIT_SECONDS 调整或禁用该上限;参见重试行为。按模型范围的冷却
按模型范围的冷却
速率限制冷却也可以按模型范围生效:
- 当已知失败的模型 ID 时,OpenClaw 会为速率限制失败记录
cooldownModel。 - 当冷却范围限定在不同模型上时,同一提供方上的兄弟模型仍可尝试。
- 计费/禁用窗口仍会阻止整个配置文件在所有模型上的使用。
- 第 1 次失败:30 秒
- 第 2 次失败:1 分钟
- 第 3 次及以后失败:5 分钟(上限)
usageStats 下:
计费禁用
计费/信用失败(例如“积分不足”/“信用余额过低”)会被视为值得故障转移的情况,但它们通常不是瞬时性的。OpenClaw 不会使用短暂冷却,而是将该配置文件标记为 disabled(采用更长的退避时间),然后轮换到下一个配置文件/提供商。并非所有看起来像计费问题的响应都是
402,也并非所有 HTTP 402 都会进入这里。即使提供商返回的是 401 或 403,OpenClaw 也会将明确的计费文本保留在计费通道中,但提供商特定的匹配器仍然只作用于其所属的提供商(例如 OpenRouter 403 Key limit exceeded)。与此同时,临时性的 402 使用窗口和组织/工作区支出上限错误,如果消息看起来可重试,则会被归类为 rate_limit(例如 weekly usage limit exhausted、daily limit reached, resets tomorrow,或 organization spending limit exceeded)。这些情况会走短冷却/故障转移路径,而不是长计费禁用路径。模型回退
如果某个提供方的所有配置文件都失败了,OpenClaw 会切换到agents.defaults.model.fallbacks 中的下一个模型。这适用于认证失败、速率限制以及耗尽配置文件轮换后的超时(其他错误不会推进回退)。没有暴露足够细节的提供商错误在回退状态中仍会被精确标记:empty_response 表示提供商没有返回可用消息或状态,no_error_details 表示提供商明确返回了 Unknown error (no error details in response),而 unclassified 表示 OpenClaw 保留了原始预览,但当前还没有分类器匹配到它。
提供商繁忙信号,例如 ModelNotReadyException,会落入过载桶,并遵循与速率限制相同的“轮换一次后再回退”策略(参见上面的默认表)。
如果整个候选链只因过载失败而耗尽,回复运行器会在同一轮次中最多重试该链 10 次。只有在工具执行或助手输出开始之前才允许整轮重试,以避免在过载出现在可观察工作之后时产生重复的修改或消息。退避从 2.5 秒开始,并指数翻倍,最高封顶 30 秒。一旦该轮次已经等待了 30 秒,OpenClaw 会发送一条一次性的临时状态通知:AI 服务暂时过载。我仍在重试;这可能需要几分钟。 重试以及任何回退胜出项都只对当前轮次生效;普通的瞬时服务器错误仍保留其单次重试策略。
当一次运行从已配置的默认主项、cron 作业主项、带有显式回退的代理主项,或自动选择的回退覆盖开始时,OpenClaw 可以沿着匹配的已配置回退链向下遍历。没有显式回退的代理主项以及显式的用户选择(例如 /model ollama/qwen3.5:27b、模型选择器、sessions.patch,或一次性的 CLI 提供方/模型覆盖)是严格的:如果该提供方/模型不可达,或者在生成回复之前失败,OpenClaw 会报告失败,而不是从无关的回退中回答。
候选链规则
OpenClaw 会根据当前请求的provider/model 以及已配置的回退构建候选列表。
规则
规则
- 请求的模型始终排在第一位。
- 显式配置的回退会去重,但不会按模型允许列表过滤。它们被视为明确的操作员意图。
- 如果当前运行已经在同一提供商家族中的某个已配置回退上,OpenClaw 会继续使用完整的已配置链。
- 当未提供显式回退覆盖时,即使请求的模型使用的是不同提供商,已配置的回退也会在已配置主项之前尝试。
- 当回退运行器未收到显式回退覆盖时,已配置主项会被追加到末尾,这样在更早的候选项耗尽后,链可以回到正常默认项。
- 当调用方提供
fallbacksOverride时,运行器会精确使用请求的模型加上该覆盖列表。空列表会禁用模型回退,并阻止将已配置主项作为隐藏重试目标追加。
哪些错误会推进回退
- 继续执行
- 不继续执行
- 认证失败
- 速率限制和冷却耗尽
- 过载/提供商繁忙错误
- 超时形态的故障转移错误
- 计费禁用
LiveSessionModelSwitchError,它会被规范化为故障转移路径,这样过时的持久化模型就不会创建外层重试循环- 当仍有剩余候选项时,其他无法识别的错误
冷却跳过 vs 探测行为
当某个提供方的所有认证配置文件都已经处于冷却中时,OpenClaw 不会自动永远跳过该提供方。它会按每个候选项做决策:逐候选项决策
逐候选项决策
- 持久性认证失败会立即跳过整个提供商。
- 计费禁用通常会跳过,但主候选项仍可能在节流条件下被探测,以便无需重启也能恢复。
- 主候选项可能会在接近冷却到期时被探测,并带有按提供商节流。
- 即使处于冷却中,只要失败看起来是瞬时性的(
rate_limit、overloaded或未知),仍可尝试同提供商的回退兄弟项。这在速率限制是模型范围、而兄弟模型可能仍可立即恢复时尤其相关。 - 瞬时冷却探测在每次回退运行中每个提供商最多一次,以免单个提供商拖慢跨提供商回退。
会话覆盖与实时模型切换
会话模型变更属于共享状态。活动运行器、/model 命令、压缩/会话更新,以及实时会话协调都会读取或写入同一会话条目的部分内容。回退执行不会写入模型选择字段,因此在重试时无法替换更新的手动选择。
实时模型切换遵循以下规则:
- 只有用户显式驱动的模型变更才会标记待处理的实时切换。其中包括
/model、session_status(model=...)和sessions.patch。 - 由系统驱动的模型变更,例如回退轮换、心跳覆盖或压缩,绝不会自行标记待处理的实时切换。
- 用户驱动的模型覆盖会被视为回退策略的精确选择,因此不可达的已选提供方会直接表现为失败,而不会被
agents.defaults.model.fallbacks掩盖。 - 运行时回退候选仍然局限于当前轮次。下一轮会从当前所选模型开始,包括上一轮运行期间到达的手动选择。
- 先前存储的自动回退覆盖仍受支持:OpenClaw 会定期探测其配置的来源,并在恢复后清除该覆盖;
/new、/reset和sessions.reset会立即清除自动来源的覆盖。 - 用户回复会在每次状态变更时通报回退转换和回退清除后的恢复。同一已选/活动配对的重复轮次不会重复该通知。
/status会显示所选模型,以及在回退状态不同时,显示活动的回退模型和原因。- 实时会话协调优先使用持久化的会话覆盖,而不是过时的运行时模型字段。
- 如果实时切换错误指向当前回退链中的更后一个候选,OpenClaw 会直接跳转到该所选模型,而不是先遍历无关候选。
可观测性与失败摘要
runWithModelFallback(...) 会记录每次尝试的详细信息,这些信息会显示在日志和面向用户的冷却提示中:
- 正在尝试的提供商/模型
- 原因(
rate_limit、overloaded、billing、auth、model_not_found以及类似的回退原因) - 可选的状态码/代码
- 人类可读的错误摘要
model_fallback_decision 日志还会在候选项失败、被跳过或后续回退成功时包含扁平化的 fallbackStep* 字段。这些字段会明确记录尝试过的转换(fallbackStepFromModel、fallbackStepToModel、fallbackStepFromFailureReason、fallbackStepFromFailureDetail、fallbackStepFinalOutcome),因此即使最终回退也失败,日志和诊断导出器仍然可以重建主要失败信息。
当每个候选项都失败时,OpenClaw 会抛出带有结构化尝试记录的 FailoverError。外层回复运行器可以使用这些记录来构建更具体的消息,例如“所有模型暂时都受到速率限制”,并在已知最早冷却到期时间时将其包含在内。
此冷却摘要会感知模型:
- 与尝试中的提供商/模型链无关的模型范围速率限制会被忽略
- 如果剩余阻止因素是匹配的模型范围速率限制,OpenClaw 会报告仍在阻止该模型的最后一个匹配到期时间。
相关配置
有关以下内容,请参见网关配置:auth.profiles/auth.orderagents.defaults.model.primary/agents.defaults.model.fallbacksagents.defaults.imageModel路由