改个模型名,两个定时任务静默死了:一次定义与引用的分离事故

1 阅读4分钟

排障实录 02:改个模型名,把两个定时任务搞死了

2026-10-20 | 真实故障复盘 | 一个改名引发的连锁反应


一句话结论

改配置的时候,你改的是"定义";但系统里还有一堆地方存的是"引用"。定义改了,引用全断。

我改了一个模型名,一周内两个自动化任务静默失败,直到我截图排查才发现。


一、事故现场

一张控制台截图,顶部一条红色警告:

部分模型无法刷新。请打开"模型"重试。

任务列表里两条红色:

任务计划上次运行状态
RSI素材日收集每天 23:0015 小时前❌
behavior_loop周检每周一 09:0027 小时前❌

它们已经连续失败了,但没有任何人收到通知——因为这两个任务都设了 delivery: none(静默模式)。


二、捞错误日志

# 列出所有自动化任务及其状态
openclaw automations list

关键字段出来了:

{
  "name": "RSI素材日收集",
  "lastRunStatus": "error",
  "lastRunError": "automation model override 'deepseek-direct/deepseek-v4-flash' \
    rejected by agents.defaults.modelPolicy.allow: \
    deepseek-direct/deepseek-v4-flash is not in [api88/..., blockrun/..., \
    deepseek-direct/deepseek-flash, deepseek-direct/deepseek-v4-pro, ...]"
}

翻译成人话:

  • 任务里写死了模型 deepseek-direct/deepseek-v4-flash
  • 但允许清单里只有 deepseek-direct/deepseek-flash
  • 名字差一截,直接被拒绝执行

三、根因:三天前的一次改名

三天前我把模型名对齐到官方新命名:

- "deepseek-v4-flash"   (旧名)
+ "deepseek-flash"      (新名,指向同一个后端)

改的时候我只做了两件事:

  1. 改了 provider 的模型表
  2. 改了全局默认模型

漏了第三件事:检查有哪些任务/会话在硬编码引用旧名。

结果:

  • 2 个自动化任务 → 失败
  • 若干旧会话 → 界面上还显示旧名(但不影响运行,因为旧名 API 仍可调用)

四、修复

不需要重建任务,只需要改任务里的模型覆盖字段:

# 方式一:通过工具更新
automations update <jobId> '{"payload":{"model":"deepseek-direct/deepseek-flash"}}'

修复后:

任务旧模型新模型下次运行
RSI素材日收集deepseek-v4-flash ❌deepseek-flash ✅今晚 23:00
behavior_loop周检deepseek-v4-flash ❌deepseek-flash ✅下周一 09:00

注意:lastRunStatus 不会自动刷新,要等下次实际运行成功才会变绿。这期间界面上还是红叉,属于正常现象。


五、顺手发现的第二个坑

改任务的时候注意到,behavior_loop周检 的 message 字段是:

峰哥行为层RSI闭环:每周自动扫描 corrections.md → 归集 → 标晋升...

结尾是个省略号——指令被截断了。

任务即使能跑,也会因为指令不完整而跑偏。

这说明:任务的 prompt 本身也会被截断,长指令要检查完整性。


六、第三个坑:白名单失真

排查时顺便看了模型白名单:

# 白名单原本 59 条

其中:

  • api88/* 和 blockrun/* 占 55 条
  • 但 api88 的 token 报 401 Invalid token,blockrun 早就在冷却期

一个白名单里 93% 是死条目,等于形同虚设。

更严重的:安全审计报过一条 CRITICAL——

Small models (<=300B params) detected: api88/qwen3.5-35b-a3b
  @ agents.defaults.model.fallbacks (unsafe; sandbox=off; web=[web_search, web_fetch, browser])

一个 35B 小模型,带联网工具,没有沙箱——它如果被 fallback 选中,就是个风险。

修复:白名单从 59 条砍到 4 条,全是实际在用的:

deepseek-direct/deepseek-flash      text+image
deepseek-direct/deepseek-v4-pro     text
deepseek-direct/deepseek-chat       text
deepseek-direct/deepseek-reasoner   text

七、四条可以抄走的经验

  1. 改任何一个"名字",都要全局搜一遍引用。 模型名、插件名、agent 名都一样。
  2. 静默任务失败了不会有人告诉你。 关键任务至少配一个失败告警通道。
  3. 任务 prompt 也会被截断。 长指令要检查结尾完整性。
  4. 白名单不是越多越安全。 一堆失效条目反而掩盖真正的风险。

八、一个更普适的教训

这次故障不是"改错了",而是"改完之后没有验证引用完整性"。

配置系统里,定义(definition)和引用(reference)是分开存储的。改定义的时候,引用不会自动跟着变,也不会报错——它只会在被使用的那一刻失败。

而如果那个"使用"发生在半夜、发生在静默任务里、发生在没有告警的地方,你就永远不知道它坏了。


所有日志和命令都是真实的,可复现。