Agent 调用没报错,不等于这件事办成了
先说结论,因为这条判断是我这一年带 Agent 干活踩出来的最贵的一条:你让 Agent 去做一件会改变外部状态的事,验收标准必须是「回头查一下那个状态真的变了吗」,不能是「调用过程中没报错」。
这话听着像废话。谁不知道要验证呢。但我是在三条互不相干的线上、各自翻过一次车之后才真正把它变成规矩的。三次的表面症状完全不同,形状却一模一样。
三次翻车,长得不像,其实是一件事
第一次在部署上。 我有一套脚本,把构建好的站点打包传到服务器上再展开。跑完,脚本打印「已上线」,退出码 0,一切正常。我顺手在浏览器里开了一下那个站,整站 403。
后来查明白:站点体量大了之后,那条从打包到解包一路贯通的管道会在中途断掉,但断在管道里的错误没有被脚本捕获。更要命的是脚本的顺序——它先把旧目录删掉,再把新内容放上去。管道一断,旧的没了,新的没上,服务器上顶着一个空目录。而脚本对此一无所知,照常打印「已上线」。
第二次在批量内容的编排上。 我用一套编排跑批量写作,每篇一个实现者、一个独立评审。跑完之后汇总告诉我:完成 0 篇。我心想这批全废了,结果去磁盘上一看,十篇文章好端端躺在那儿,字数、结构、事实全对。
反过来的情况也遇到过,而且更吓人:汇总说全部完成,我按惯例去数了一下文件,少了一小半。那些”完成”的任务里,有的写作阶段就失败了,但失败没有传上来。
第三次其实还没发生。 我那个公众号主笔 Agent 到今天为止,往公众号草稿箱写入这一段仍然没接通——前面从飞书收指令、选方向、确认提纲、核事实、写正文、生封面、结构化落盘,全都跑通了,唯独最后那一步是断的。
但我在还没接通的时候,就先把这一步的验收标准写死在文档里了:拿到返回的素材 id 之后,必须再去查一次草稿列表,确认这条草稿真的在里面,才算成功。 文档里我还专门加了一句大白话——禁止把「接口已提交」当成「草稿已创建」来汇报。
一个还没做的功能,先写好了怎么验收。这不是我谨慎,是前两次把我打服了。
我是怎么发现的:三次都不是系统告诉我的
这一段我觉得比前面重要,因为它决定了你能不能早点发现下一个同类问题。
部署那次,是我碰巧手动打开了一下页面。如果那天我没开,那个站会一直 403 到有人来问我。 编排那次,是因为我已经养成了「不看汇总、直接去磁盘数文件」的习惯——而这个习惯本身就是被之前的事故逼出来的。 草稿那次,是我在写文档、逐条推敲每一步的成功标准时,自己问了一句「接口返回成功了,然后呢」。
三次没有一次是系统主动报警的。 全是人在别的动机下顺手看了一眼。
这个事实本身就说明了问题的性质:这类失败不产生任何错误信号。没有异常、没有非零退出码、没有红色的日志。它在所有可观测的表面上都长得跟成功一模一样。
为什么会这样:请求被接受,和事情被办成,是两件事
拆开看,原因其实很朴素。
你调用一个外部能力,拿回来的那个”成功”,绝大多数时候的语义是**「我收到你的请求了」,而不是「你要的那个状态已经改变了」**。中间隔着一整条异步链路:排队、处理、写入、生效。链路上任何一环出问题,都不会回头去改你手里那个已经返回的 200。
人对这件事其实有直觉。你在网页上点了提交,看到「提交成功」,很多人还是会刷新一下看看。这个”再看一眼”的动作是白来的,不需要谁教。
Agent 没有这个直觉。 它拿到 200 就往下一步走,走得非常顺、非常果断。它不会突然停下来说”我总觉得哪里不太对”。你让它做十步,它会一路做到第十步,然后告诉你十步全做完了——哪怕第三步其实什么都没发生。
这也是为什么我把这条列为整个专题的第一条:你交给 Agent 的自动化程度越高,链路上没人”顺手看一眼”的环节就越多。
有客观真值的地方,反而更危险
这一点最反直觉,我单独说。
写内容的时候,好坏没有客观标准,所以我逼着自己每一篇都去看。恰恰因为没有真值,我不敢偷懒。
写代码不一样。构建能不能过、退出码是几,都是硬邦邦的真值。正是因为有真值,我停止了怀疑。 看到 0 就认为成了。
结果工程侧的静默失败反而是最多的。除了上面那次部署,我还撞见过:构建的过滤器写法写错了,匹配不到任何目标,命令正常退出、退出码 0——「构建通过」是假的,它压根什么都没构建。版本控制提交时路径没匹配上,静默跳过,一整批新文件根本没进提交,而提交本身是”成功”的。
有一次反而是好事:某个字段的取值超出了枚举范围,构建直接崩了。我当时挺烦,事后想想,崩掉是这一类问题里最好的结局——因为它吵。 真正难缠的是那些不吵的。
后来我改成了什么
规矩很简单,就一条:每一个会改变外部状态的动作,都要配一个回查动作。 回查的对象是目标状态,不是调用结果。
落到具体的几处:
- 部署不再用一条管道贯到底,改成先打包成文件、传过去、在目标端数一遍文件个数,数对了才切换目录。切换完之后再回查线上的状态码。
- 批量任务的验收一律回磁盘数文件,汇总只当参考,不当依据。
- 提交之后回查提交里到底包含了哪些文件,不看命令有没有报错。
- 草稿写入这一步,虽然还没接通,验收标准已经写死:返回 id 之后必须再查一次列表。
还有一个我很喜欢的副产品:这条规矩会倒逼你把岗位卡里的「成功标准」写成状态,而不是写成动作。
“把文章同步到草稿箱”是动作,没法回查。“草稿列表里能查到这条草稿”是状态,可以回查。前一种写法看起来也挺明确,但它默认了”我做了”等于”成了”——而这正是整件事的病根。我现在写任何一个 Agent 的成功标准,都先问自己一句:这句话描述的东西,我能去哪儿查?查不到,就说明这条标准没写完。
一点边界
这条判断不是万能的。回查本身也有成本,也可能失败,也可能查到过期的缓存。链路很短、失败了立刻就能看见的动作(比如往本地写一个临时文件),配回查就是过度设计。
我的取舍是:只要这个动作的结果会被下一步当作前提使用,就必须回查。 因为一旦前提是假的,后面所有步骤都在假设之上继续跑,而且跑得很顺——最后交出来的是一份看起来完整的、彻底错误的东西。
这篇写的是我自己那套流程里的实际情况,不是通行做法。你的场景、工具和团队规模不同,结论未必适用,判断方式可能比结论更值得拿走。
延伸阅读
- 下一篇(跑闭环):Agent 干活里的静默失败:退出码 0 是怎么骗过所有人的
- 专题导读与七个阶段的地图:把 Agent 当成一个要上岗的员工来带:这个专题讲什么