
起因:Token 焦虑症
跑 AI Agent 最大的开销是什么?Token。
我的 OpenClaw 实例每天定时执行 4 个 Cron 任务:Gmail 摘要、垃圾评论清理、爬虫数据分析、服务器安全巡检。每个任务都需要调用大模型,带 tool use 能力。主会话用的是 Claude Opus 级别的模型,Cron 任务本来也在跟着跑——一个早上 9 点的 Gmail digest 就干掉了当天一半的用量。
这让我动了歪脑筋:能不能用免费的中转站来跑这些非关键任务?
答案是可以,但我选错了路。
第一个坑:cliproxy 大一统中转方案
思路
cliproxy 是一个本地 API 代理,跑在 127.0.0.1:8317。它的核心功能是 round-robin——你给它配一堆后端,它轮流转发请求。
我的如意算盘:
OpenClaw → cliproxy (本地代理)
├── 后端 A (公益站 1)
├── 后端 B (公益站 2)
├── 后端 C (公益站 3)
└── 后端 D (付费站兜底)
只需要在 OpenClaw 里配一个 provider(cliproxy),cliproxy 自己搞定多后端轮换。简洁、优雅。
配置
cliproxy 的配置很简单。在 /opt/homebrew/etc/cliproxyapi.conf 里加后端,OpenClaw 这边只需要一个 provider:
{
"cliproxy": {
"baseUrl": "http://127.0.0.1:8317/v1",
"apiKey": "sk-free-xxxx",
"api": "openai-completions",
"models": [
{ "id": "claude-sonnet-4-5-20250929" },
{ "id": "deepseek-v3.2" },
{ "id": "gpt-5.3-codex" }
]
}
}

看起来没毛病。上线。
翻车
第一天,deepseek-v3.2 通过 cliproxy 发了 17 个请求,全部失败。后端返回 500 和 520。
问题出在哪?cliproxy 的 round-robin 没有熔断机制。
它就像一个不长记性的挂号员:明知道某个医生今天没来,还是把你的号挂给他。你说"这个医生不在",他说"好的下一位",然后下一轮又把别人挂给这个不在的医生。
具体来说:
- 无状态轮换:cliproxy 不记录后端健康状态。A 挂了,下一轮还是会轮到 A
- 错误不透明:OpenClaw 只看到 cliproxy 返回的错误,不知道背后是哪个后端出的问题
- 冷却失效:OpenClaw 把 cliproxy 整个 provider 标记为冷却,但问题可能只是某一个后端
- 无法精准恢复:某个后端恢复了,OpenClaw 不知道;整个 cliproxy 还在冷却期
这是架构上的根本缺陷:在 OpenClaw 和实际后端之间加了一层不透明的代理,破坏了 OpenClaw 原生故障感知的精度。
数据说话
跑了一天的结果:
指标
cliproxy 方案
直连方案
deepseek-v3.2 成功率
0/17 (0%)
N/A(后端本身不稳定)
错误定位时间
无法定位
即时(per-provider)
冷却精度
provider 级(误伤)
provider 级(精确)
恢复速度
等整个冷却期结束
单个 provider 独立恢复

第二个坑:OpenRouter 免费模型
cliproxy 方案挂了之后,我想到另一条路:OpenRouter。
OpenRouter 是一个模型聚合平台,上面有不少标记为 "free" 的模型。OpenClaw 有个内置命令 openclaw models scan,可以扫描 OpenRouter 上可用的免费模型。
openclaw models scan
注册了 OpenRouter 的 API key(sk-or-v1-xxxx...),开扫。
结果很快出来了:能找到好几个免费模型,看起来挺美好。
但全部不支持 tool use。
这就要命了。OpenClaw Agent 的核心能力依赖 tool use——读文件、执行命令、调 API、发消息。一个不支持 tool use 的模型对 Agent 来说就是个废物,只能做纯文本 Q&A。
免费模型不支持 tool use 不是巧合,是经济规律:tool use 需要模型理解复杂的函数签名、生成结构化的调用参数、处理多轮工具交互。这些能力需要更大的模型、更多的推理计算,免费额度覆盖不了这个成本。
这条路也死了。
正确的路:OpenClaw 原生 Failover

两条捷径都走不通,我老老实实回来看 OpenClaw 自己的故障转移机制。
架构
OpenClaw 的 failover 分两级:
请求失败
│
├─ 第一级:Auth Profile 轮换(同一 provider 内)
│ 同一 provider 有多个 API key → 逐个尝试
│
└─ 第二级:Model Fallback(跨 provider)
当前 provider 所有 key 都失败 → 跳到 fallbacks 列表下一个
关键区别在于:每个 provider 是独立管理的。OpenClaw 精确知道哪个 provider 挂了、挂了多久、什么时候该重试。
配置方案
我把之前塞在 cliproxy 后面的公益站拆出来,每个作为独立 provider 注册:
{
"models": {
"providers": {
"linuxdo": {
"baseUrl": "https://free-api-1.example.com",
"apiKey": "sk-free-xxxx",
"api": "anthropic-messages",
"models": [{
"id": "claude-sonnet-4-5-20250929",
"name": "Claude Sonnet 4.5 (站点A)"
}]
},
"huan": {
"baseUrl": "https://free-api-2.example.com",
"apiKey": "sk-free-yyyy",
"api": "anthropic-messages",
"models": [{
"id": "claude-sonnet-4-5-20250929",
"name": "Claude Sonnet 4.5 (站点B)"
}]
},
"runanytime": {
"baseUrl": "https://free-api-3.example.com",
"apiKey": "sk-free-zzzz",
"api": "anthropic-messages",
"models": [{
"id": "claude-sonnet-4-5-20250929",
"name": "Claude Sonnet 4.5 (站点C)"
}]
},
"hotaru": {
"baseUrl": "https://paid-api.example.com",
"apiKey": "sk-paid-xxxx",
"api": "anthropic-messages",
"models": [{
"id": "claude-sonnet-4-5-20250929",
"cost": { "input": 0.003, "output": 0.015 }
}]
}
}
},
"agents": {
"defaults": {
"model": {
"primary": "anyrouter/claude-opus-4-6",
"fallbacks": [
"foxcode/claude-sonnet-4-5-thinking",
"linuxdo/claude-sonnet-4-5-20250929",
"huan/claude-sonnet-4-5-20250929",
"runanytime/claude-sonnet-4-5-20250929",
"hotaru/claude-sonnet-4-5-20250929",
"zai/glm-4.7",
"openai-codex/gpt-5.3-codex"
]
}
}
}
}
注意:模型名称必须用 provider/model-id 完整格式,不能用别名。这也是踩过的坑。
探测过程
配之前得先确认这些公益站真的能用。不能假设"支持 OpenAI 格式的站也支持 Anthropic Messages 格式"。我用 curl 逐个探测:
# 探测某个公益站是否支持 anthropic-messages 格式
curl -s -w "\nHTTP %{http_code} in %{time_total}s\n" \
https://free-api-1.example.com/v1/messages \
-H "x-api-key: sk-free-xxxx" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-5-20250929",
"max_tokens": 64,
"messages": [{"role":"user","content":"hi"}]
}'
一共测了 7 个站,3 个通过。有的站超时,有的站返回 401,有的站只支持 OpenAI Chat Completions 格式。实测是唯一可靠的验证方式。
深入 OpenClaw Failover 机制

既然决定依赖 OpenClaw 原生能力,就有必要彻底搞懂它的运作逻辑。
冷却机制(Cooldown)
当一个 provider 的请求失败(auth 错误、429 限流、超时),OpenClaw 用指数退避标记冷却:
连续失败次数
冷却时长
1
1 分钟
2
5 分钟
3
25 分钟
4+
1 小时(上限)
冷却状态存在 ~/.openclaw/agents/<agentId>/agent/auth-profiles.json:
{
"usageStats": {
"linuxdo:default": {
"lastUsed": 1739577600000,
"cooldownUntil": 1739577660000,
"errorCount": 1
}
}
}
如果错误原因是账单/额度不足(insufficient credits),退避策略更激进:5 小时起步,翻倍递增,上限 24 小时。因为余额不足不是重试能解决的。
会话粘性(Session Stickiness)
OpenClaw 不会每次请求都重新选 provider。它为每个会话锁定一个 auth profile,保持不变直到:
- 会话重置(
/new或/reset) - Compaction 完成(上下文压缩)
- 当前 profile 进入冷却
为什么要锁定?缓存。很多 API provider 对同一个 session 有 prompt caching,频繁换 provider 会丢失缓存,导致每次请求都重新计算整个上下文。这在长会话里是巨大的浪费。
错误分类与触发
不是所有错误都会触发 failover:
错误类型
HTTP 状态码
触发 Failover?
处理方式
认证失败
401/403
✅
冷却 + 轮换
速率限制
429
✅
冷却 + 轮换
格式/参数错误
400
✅
冷却 + 轮换
账单不足
402/payment
✅
长禁用 + 轮换
超时
timeout
✅
冷却 + 轮换
服务器内部错误
500
❌
不推进(可能是临时抖动)
模型不支持
404
❌
报错给用户
这里有个细节值得注意:HTTP 400 在最近的版本中被纳入了 failover 触发范围。以前 400 被认为是"你的请求格式有问题",不该换 provider。但实际上很多中转站对特定请求格式的兼容性不同,同一个请求在 A 站 400 在 B 站可能正常。这个改动让跨 provider 兼容性好了很多。
Fallback 链的执行逻辑
用户消息到达
│
├─ 取 primary model (anyrouter/claude-opus-4-6)
│ ├─ 取该 provider 的 auth profiles
│ │ ├─ profile 1 → 成功 → 返回
│ │ ├─ profile 1 → 失败 → 标记冷却
│ │ ├─ profile 2 → 成功 → 返回
│ │ └─ 所有 profiles 失败 → 进入第二级
│ │
│ └─ 第二级:取 fallbacks[0] (foxcode/...)
│ ├─ 同样尝试所有 profiles
│ ├─ 失败 → 取 fallbacks[1] (linuxdo/...)
│ └─ ... 直到 fallbacks 耗尽
│
└─ 所有 fallback 耗尽 → 报错给用户
对 Cron 任务,我给每个任务单独指定了 provider,避免和主会话抢资源:
任务
指定模型
为什么
Gmail digest (09:00)
linuxdo/claude-sonnet-4-5
免费,能力足够
垃圾评论清理 (11:00)
huan/claude-sonnet-4-5
免费,分散负载
爬虫分析 (11:10)
runanytime/claude-sonnet-4-5
免费,分散负载
服务器巡检 (11:40)
linuxdo/claude-sonnet-4-5
复用,间隔够长
cliproxy vs OpenClaw 原生:本质区别
回头看,cliproxy 方案和 OpenClaw 原生 failover 的本质区别在于信息对称性。
cliproxy 是个黑盒。OpenClaw 往里扔请求,cliproxy 内部怎么轮、轮到谁、谁挂了——OpenClaw 一无所知。这导致:
- 冷却粒度太粗:一个后端挂了,整个 cliproxy provider 被冷却
- 恢复不及时:某个后端恢复了,OpenClaw 还在等冷却结束
- 调试困难:出了问题去看 OpenClaw 日志,只能看到 cliproxy 返回的错误,不知道原始后端是谁
OpenClaw 原生方案,每个后端都是独立 provider,故障信息完全透明:
- 冷却粒度精确:哪个站挂了冷却哪个,不影响其他
- 恢复即时:冷却到期自动重试,不依赖外部状态
- 日志清晰:
linuxdo 429 → cooldown 1min → fallback to huan一目了然
用一句话总结:不要在 Agent 框架和模型 API 之间插入不透明的代理层。除非这个代理层本身有完善的健康检查和熔断机制。
公益站使用心得
最后说几句关于公益站的实践经验。
不稳定是常态。 公益站靠社区维护,没有 SLA,随时可能跑路或者限流。"随时跑路公益站"——人家自己名字都写得很诚实。
分散比集中好。 配 3-5 个公益站,每个独立 provider,让 OpenClaw failover 自动切换。比把所有鸡蛋放在一个 cliproxy 篮子里强。
API 格式不能假设。 有的站支持 OpenAI Chat Completions,有的支持 Anthropic Messages,有的两个都支持但模型名前缀不同。必须 curl 实测。
付费站兜底。 免费的东西总有代价,关键时刻需要一个稳定的付费站保底。我的 hotaru 就是这个角色——输入 $0.003/1K tokens,输出 $0.015/1K tokens,便宜但稳。
成本对比。 切换到多 provider 直连方案后,Cron 任务的主力消耗从主 account 的高端模型转移到了免费公益站。每天 4 个任务的 token 开销从"半天用量"降到了几乎为零。偶尔公益站不稳定时 failover 到付费站,一天也就几分钱。
结论
这次折腾的核心教训:
- 中间代理层破坏信息对称——OpenClaw 的 failover 依赖对每个 provider 精确的健康状态感知,cliproxy 把这些信息全挡了
- 免费模型不支持 tool use——OpenRouter 的免费模型对 Agent 场景没用
- 分散风险比集中管理好——多个独立 provider 各自冷却,比一个代理统一管理更可靠
- 实测是唯一验证方式——API 兼容性不能靠文档推断
省钱没有捷径。但正确的架构选择可以在保持可靠性的前提下把成本压到最低。OpenClaw 原生 failover + 多公益站独立注册,就是目前最优解。