← 返回博客

我那套 AI 自动化系统出过的 3 次事故,和每次之后改了什么

2026-09-14 · 8 分钟阅读
AI 自动化工程实践定时任务Claude Code独立开发

这是「一个人的 AI 营销部门」系列第 5 篇。前四篇讲了这套系统 长什么样一条流水线怎么跑看板规则怎么定发布权怎么交出去

四篇都在讲它跑通的样子。这一篇讲它坏掉的样子。

因为如果你打算把一部分活真的交给 AI 去自动跑,你会遇到的麻烦不是"它写得不好", 而是"它看起来在跑,其实已经停了三天"。我三次都栽在这上面,而且三次都不是靠告警 发现的——是我自己偶然翻日志才看到。

下面是三次事故的原样记录。

事故一:一把锁,饿死了整条评论监听

我这套系统有两条定时线:

  • comment-watch.sh:每分钟跑一次,检查看板上有没有人写了新评论,有才唤起 AI 去处理
  • daily-agent.sh:每半小时跑一次,扫描整个看板找活干

两条线最初共用一把锁 /tmp/daily-agent.lock。当时的理由听起来很正当: 它们都会去改同一个状态文件,加锁防止写坏。

后果是:看板扫描一旦跑起长任务,整段时间里的人工评论一条都得不到响应。

扫描跑 15 分钟,这 15 分钟里 comment-watch 被唤起 15 次, 15 次全部撞在锁上、打一行"上一次仍在进行中"然后退出。我在卡片上写的评论, 要等到扫描结束后的下一分钟才有人看。最糟的一次是扫描跑了 40 多分钟。

改法:把锁拆成两把——/tmp/comment-watch.lock/tmp/daily-agent.lock。 每条线只和"上一轮的自己"互斥,两条线之间完全并行。

但拆锁的前提是职责不重叠,所以同时定了一条硬规矩:

  • 评论收件箱(读未处理评论、推进已处理水位线)comment-watch 独占, 看板扫描那条线一行都不许碰。两边都处理评论的后果是重复回复, 或者一边把另一边还没处理完的评论标记成已处理。
  • 但两边确实都要写同一个状态文件。所以所有读改写强制走一个带 flock 的封装 (agent_state.pylocked_state()),裸的读改写在并发下会丢更新。

最后这一条不是洁癖。丢掉的如果是"AI 自己写过哪些评论"这个 id 列表, 那么下一分钟系统就会把 AI 自己上一轮的分析当成人的新反馈,再回一遍—— 然后它又记下自己的回复、又丢、又回。每分钟自问自答一次,直到有人发现为止。

这一条通用:并发的两个东西共用一把锁,往往不是"更安全",而是把其中一个饿死。 真正该问的问题不是"要不要加锁",而是"这两件事为什么会碰同一份数据,能不能不碰"。

事故二:没有超时,一次卡死就永久占住了锁

拆完锁,问题换了个形状回来。

两条线都是这个结构:拿锁 → 唤起 claude -p 跑任务 → 放锁。 如果 claude -p 因为任何原因卡住不退出(网络挂起、等一个永远不来的响应), 那么这个进程会一直活着,锁一直被它持有。

之后的每一轮都会撞在锁上,打一行日志:

上一次仍在进行中,跳过

然后正常退出,退出码 0。

这就是它最阴险的地方:这行日志属于正常路径。它和"上一轮还没跑完,这轮跳过" 这种完全健康的情况长得一模一样。没有任何监控会对退出码 0 报警。 系统在我眼里一切正常,实际上已经死了。

改法:两条线的 claude -p 全部套上 timeout

timeout --signal=TERM --kill-after=60 "$TIMEOUT" claude -p ...
CODE=$?
if [ $CODE -eq 124 ] || [ $CODE -eq 137 ]; then
  # 超时,走企业微信告警
fi

评论线 30 分钟,扫描线 45 分钟,都能用环境变量覆盖。 超时按 124 退出(被 KILL 兜底的话是 137),这两个码单独判断,直接推一条企业微信告警给我。

这一条通用:任何"持有锁 → 调用外部服务 → 释放锁"的结构, 外部调用必须有超时。没有超时的话,一次卡死就是永久故障, 而且是那种日志干净、监控绿灯的永久故障。

顺便说一句:--kill-after 那个参数不是可选的。timeout 默认只发 TERM, 一个真卡死的进程可能连 TERM 都不处理。

事故三:一条 git clean,抹掉了整个监听脚本

2026 年 9 月 6 日,评论监听整整一天在刷 not found

原因是定时跑的 AI 为了"清理工作区",执行了 git checkout / git clean 一类的命令。 而 comment-watch.shtrello-inbox.py--check 参数当时还没有提交进 git—— 它们是我临时写出来验证思路的,一直处于未跟踪状态。

一条清理命令,两个文件一起没了。定时任务还在每分钟准点跑, 跑的内容变成了"找不到这个文件"。

改法两条

  1. 定时 agent 绝对禁止执行 git checkout / restore / clean / stash / 切分支。 这条直接写死在给 AI 的规则文件里,和"不许部署上线"放在同一级。 它没有任何理由需要这些命令——一个只往前写代码的角色, 不需要任何一个会让工作区倒退的动作。
  2. 脚本一律提交进 git,别留未跟踪状态。 这一条是给我自己的。 "临时写的,先跑跑看"是最容易出事的状态:它已经在生产里承担职责了, 但在版本管理眼里它还不存在。

这一条通用:给 AI 的权限清单里,危险的不只是"对外"的动作。 删文件、回滚工作区、切分支这些纯本地操作,破坏力一点不比"发布上线"小, 而且没有任何外部系统会拦住它。

三次事故的共同点

回头看,这三次不是三个独立的 bug,是同一个问题的三种长相:

自动化系统的失败是静默的。

  • 事故一:日志在滚,锁在等,每一行都"正常"
  • 事故二:退出码 0,日志写着"跳过",监控全绿
  • 事故三:定时任务准点执行,只是执行的内容变成了报错

人工流程坏掉你会立刻知道,因为有人在等结果,等不到就会来问你。 自动化流程坏掉没人等,它就那么静静地停着,直到你某天偶然想起来去看一眼。

所以现在我给这套系统定的规矩里,有一条优先级很高: 每一条自动线都必须有一个"我还活着"的正向信号,而不只是出错时报警。 每天 9 点的日报就是这个信号——它按时到了,说明整条链路是通的; 它没到,比它报错更值得我警惕。

如果你也打算把一部分工作交给 AI 自动跑,我的建议是: 在你开心地看它跑通第一轮之后,立刻花半天想清楚它坏掉的时候你怎么知道。 这半天的回报率,比你再给它加三个功能都高。

想给自己的团队搭一套?

这套系统是我给自己 12 个产品用的。现在我把同一套东西搭进别人的公司:

  • 一块属于你自己的看板:AI 在里面领任务、写稿、配图、发布、汇报,进度你随时能看
  • 一套它不会闯祸的规则:谁能发、发之前过几道闸、出问题多久告警,全部写死在规则文件里
  • 每周 30 分钟的你:审方向、点发布。剩下的活它自己干
  • 按月交付内容和数据:不是「给你一个会写字的 AI」,是内容条数、搜索展现、转化数据一起交

上面这三次事故,以及从里面抠出来的锁、超时、权限边界,都是交付内容的一部分—— 你不用再自己踩一遍。

价格:启动包 ¥3,000 起(搭板 + 规则 + 跑通第一轮),月度方案 ¥5,000 起(持续产出 + 数据复盘)。 首批 3 个创始客户 8 折,我会按你的行业把规则调到能用为止。

下一步:微信聊 20 分钟,看看你那边哪些活能自动化掉。 聊完你至少能带走一张「你的内容流水线该长什么样」的一页纸,不合适也不亏。 (微信号我正在这几篇文末统一补上,这两天就位。急的话先在 不墨 AI 里给我留言也行。)

想先自己动手也完全可以。这套流水线调用的模型能力全部来自 不墨 AI——一个订阅同时用 GPT / Claude / Gemini / DeepSeek / Kimi, 写稿、起标题、做摘要这些活它都能接。