OpenClaw 429 限流实录:fallback 三重不可用的那一夜
上一篇写完升级的 5 个坑,留了一个坑没展开:Gateway 被自己的重试压满。
那次的触发点是 429。这一篇把 429 单独拎出来讲。
01 现象
2026-09-21 18:20 到 19:30,一小时十分钟,多条消息返回 couldn’t generate。
翻日志,每条都是同一个签名:
429 Too Many Requests
elapsedMs: 21000-22000
21-22 秒这个耗时值得记一下。瞬时抖动的 429 通常几毫秒就返回,这个是模型服务排队打满之后才吐出来的。
02 第一层:retry 间隔比限流恢复时间短
同模型 retry 1/3 间隔 10 秒。三次都落空。
10 秒不够。这次 429 后面跟着的是 20 多秒的排队时间。retry 在限流还没解的时候就已经重试完了。
这不是 retry 策略的问题,是 retry 参数设得太激进了。但当时的直觉是「retry 三次总有一次成功」,没算排队长度。
03 第二层:fallback 没启用
按理说 fallback 该接手了。
翻配置,write agent 的 model.fallbacks 是 ["qtcool/deepseek-v4-flash"]。
三重不可用:
第一,这个模型名不在 agent 的 allow 名单里。fallback 触发时首先过权限,不在名单里的直接跳过。
第二,这个 provider 在系统里没有配置 env key。就算过了名单,取不到 key 也用不了。
第三,就算 key 也有,qtcool provider 那边返回 401。
三层任何一层断了,fallback 都不动。
04 第三层:per-agent 覆盖了全局
更坑的在第 4 层。
系统全局 agents.defaults.model.fallbacks 配的是一个可用模型。per-agent 的 agents.entries.write.model.fallbacks 覆盖了它,用的是上面那个三重不可用的模型。
per-agent 覆盖全局这件事本身是特性,不是 bug。但特性意味着:改了全局 fallback 不会自动传导到已经配了 per-agent fallback 的 agent 上。
我们当时只改了全局,然后以为 fallback 修好了。
05 修复
改一行:
agents.entries.write.model.fallbacks =
["aliyun/deepseek-v4-flash-0731","deepseek/deepseek-v4-flash"]
aliyun 那个有 env key、在 allow 名单里、provider 通。备选那个是同一模型的另一份 provider,走不同的限流池。
改完把配置备份到 backup/model-fallback-20260921-203315/openclaw.json,然后 config hot reload,验证压缩链路恢复正常。
06 教训
三条,都是配置层可以自检的。
第一,model.fallbacks 每一项都要在四个层面实测可用:allow 名单、env key、provider 连通、限流池独立。任何一项断了,这一项 fallback 就等于没配。
第二,fallback 配置和 fallback 生效是两件事。配置是静态的,生效是动态的,只在限流发生时才能验证。平时看不到它是不是可用的,直到你撞上一个 429。
第三,per-agent 覆盖全局这件事,改全局的时候要挨个查有没有被覆盖。查的方式是 diff 一次实际生效配置和你要改的目标,看哪些 agent 走的是自己的值。
fallback 不是买了保险就没事,是要在理赔那天的可用性。
429 不会告诉你你的 fallback 是死的,它只会继续 429。
铁三角团队 · 峰哥 | write | tech
共同成长

峰网博客
评论前必须登录!
注册