多账号、多模型是 OpenClaw 生产部署的常态,但很多人不清楚当一个 Auth Profile 出问题时,系统内部到底是怎么决定切换到哪一个的。本文基于官方文档详解 Model Failover 机制的两级处理逻辑:Auth Profile 轮换和 Model 降级。
两级故障处理
OpenClaw 处理故障分两个阶段:
1. Auth Profile 轮换 —— 在当前 Provider 内部切换账号/密钥
2. Model 降级 —— 切换到 agents.defaults.model.fallbacks
中配置的下一个模型
先在同一个 Provider 内部尝试换账号,实在不行才降级到配置的备用模型——这个先后顺序本身就值得记住,遇到故障排查问题时可以按这个顺序去想"现在系统卡在哪一步"。
Auth Profile 存储位置
密钥存放在:
~/.openclaw/agents/<agentId>/agent/auth-profiles.json
(旧版路径:~/.openclaw/agent/auth-profiles.json)
config 里的 auth.profiles / auth.order 只是元数据+路由信息,
本身不含任何密钥
旧版 OAuth 导入专用文件:
~/.openclaw/credentials/oauth.json
(首次使用时会被导入进 auth-profiles.json)
Profile ID 命名规则——OAuth 登录会创建独立的 Profile,让多个账号可以共存:没有邮箱信息时默认为 provider:default;有邮箱的 OAuth 登录则是 provider:<email>(例如 google-antigravity:user@gmail.com)。
轮换顺序:怎么决定先用哪个账号
当一个 Provider 配置了多个 Profile 时,OpenClaw 按以下
优先级决定顺序:
1. 显式配置:auth.order[provider](如果设置了)
2. 已配置的 Profile:按 Provider 过滤的 auth.profiles
3. 已存储的 Profile:auth-profiles.json 中该 Provider 下的条目
如果没有显式配置顺序,采用轮询(round-robin):
主排序键:Profile 类型(OAuth 优先于 API Key)
次排序键:usageStats.lastUsed(同类型内,最久未用的排前面)
处于冷却/禁用状态的 Profile 会被移到队尾,
按最快到期时间排序
会话粘性(Session Stickiness):为什么不是每次都换
这是理解"为什么我的账号感觉是固定用某一个,而不是均匀轮询"的关键机制:
OpenClaw 会为每个会话"钉住"(pin)选定的 Auth Profile,
以保持 Provider 缓存的"热"状态
它不会每次请求都轮换。被钉住的 Profile 会一直复用,
直到:
- 会话被重置(/new 或 /reset)
- 一次压缩(compaction)完成(compaction 计数递增)
- 该 Profile 进入冷却/被禁用状态
通过 /model …@<profileId> 手动选择的 Profile,会为该会话
设置一个"用户覆盖"(user override),
在新会话开始之前不会被自动轮换
自动钉住的 Profile(由会话路由器选定)被当作"偏好"处理:
会优先尝试,但如果遇到限流/超时,OpenClaw 仍可能
轮换到其他 Profile
用户手动钉住的 Profile 则是锁死状态——如果它失败了,
且配置了 Model 降级,OpenClaw 会切换到下一个模型,
而不是切换到其他 Profile
为什么 OAuth"看起来像丢了"
如果同一个 Provider 下你既配置了 OAuth Profile,
又配置了 API Key Profile,轮询机制可能会在不同消息之间
在两者间切换(除非被钉住)
如果想强制固定用某一个 Profile:
1. 用 auth.order[provider] = ["provider:profileId"] 显式钉住
2. 或在支持的 UI/聊天界面里通过 /model … 带 Profile 覆盖
做会话级手动选择
很多人遇到"明明配了 OAuth 却时不时又在用 API Key"这类困惑,根源往往就是没有显式钉住顺序,让轮询机制在两者间自然切换了。
冷却机制:认证/限流错误如何触发
当一个 Profile 因为认证/限流错误(或者看起来像限流的超时)
失败时,OpenClaw 会把它标记为冷却状态并切到下一个 Profile
格式/无效请求类错误(例如 Cloud Code Assist 工具调用ID
校验失败)同样被视为"值得触发故障切换",使用相同的冷却逻辑
OpenAI 兼容的停止原因错误,比如
Unhandled stop reason: error / stop reason: error /
reason: error,会被归类为超时/故障切换信号
冷却时长采用指数退避:
第1次冷却:1 分钟
第2次冷却:5 分钟
第3次冷却:25 分钟
第4次及以后:1 小时(封顶)
状态记录在 auth-profiles.json 的 usageStats 字段下,包含 lastUsed、cooldownUntil、errorCount 等信息。
实战建议
1. 多账号并存但希望固定用某一个时,务必显式配置
auth.order[provider],不要依赖默认轮询行为
2. 排查"账号突然被切走"类问题时,先检查
auth-profiles.json 的 usageStats 字段,
看是否处于冷却或禁用状态
3. 理解 Session Stickiness 的存在——正常情况下账号是
按会话粘住的,频繁切换往往意味着确实遇到了
限流/超时/认证错误,而不是系统"随机换着玩"
4. 用户手动通过 /model @profileId 选择后,该会话内
不会自动轮换,出问题时会直接走 Model 降级而非换账号,
这点和自动钉住的行为不同,需要区分理解
总结
Model Failover 机制的核心设计思路是**"先在同一 Provider 内换账号,实在不行再换模型"**,同时通过 Session Stickiness 尽量保持缓存热度,避免不必要的频繁切换。理解轮换顺序、粘性规则和冷却退避这三个要点,能帮你更准确地判断线上遇到的账号/模型切换行为到底是预期设计还是真的出了问题。
来源:Model Failover — OpenClaw 官方文档