Max Lin
中文English

复盘

让 agent 的「做完了」可信

我几乎所有的代码都和 AI agent 一起写。用久了发现,最贵的错误不是写错代码,而是 agent 说「修好了」,其实没有:构建过了、发布了、日志里也看不出问题,而真正要交付的那个结果一直是坏的。

下面是三次真实的事故,和每次之后我改掉的东西。

1. 27 小时的崩溃

Kay 是我的语音输入工具:按住 fn 说话,松开文字就出现在光标处。1.4.4 为了让一个转圈动画在浮窗里居中,同时让浮窗跟着内容改尺寸。从这个版本起,每次松开 fn 都会崩:浮窗改尺寸和 SwiftUI 的动画撞在了同一轮布局里。

这个状态持续了约 27 小时,跨了 1.4.4、1.5.0、1.5.1 三个版本。这期间 agent 发了版本,写了「已修复」,还在知识库里记下了自动更新的实测。崩溃报告其实一直都在系统里,只是没有任何一个步骤去读它。

所有的检查都是绿的:离屏渲染正常、公证通过、空闲时 CPU 正常、自动更新装上了。但没有一项检查会在「松开 fn 出字」坏掉的时候变红。

复盘还没写完,agent 已经按推理出来的根因发了 1.5.2:它认定问题出在转圈动画,把转圈换成了不经过视图更新的画法。装上之后还是崩。

真正的修法是改结构:1.5.3 起浮窗固定尺寸,只移动、不改大小,这一类冲突从根上没了。后来浮窗的外观在一天里改了六次,浮窗本身的尺寸一次也没动过。

我还加过一道发布闸门:make release 只公证、装到本机,make promote 要读到本机一次真实的听写成功、并且没有新的崩溃报告,才放行公开发布。上线前拿历史数据试过:从 1.5.2 装上的时刻算起会被拒,从 1.5.3 算起会放行。

这道闸门只活了两个小时。每发一版都要等它,我嫌太死板,把它删了,换成一条规则:每次安装之后先读崩溃报告和听写记录,读到之前只能说「改了,没验证」。

两天后,这条规则的盲区就露出来了。1.6.0 在开始录音时把主线程卡死,只能强制退出,而且没有崩溃报告:「没有新的崩溃报告」这个读数,对卡死根本不敏感。之后补的又是结构:录音启动挪出主线程、限时两秒,失败就换内置麦克风;再加一个只在听写时开着的看门狗,主线程三秒不响应就把现场存下来。

2. 一个从来没报过警的检查

我的转写流水线有几项自检:查重复循环、查繁体字。2026 年 8 月的一天,同时发现四处检查都是跑完了、退出码 0、输出看着正常,实际上没在工作:

  • 文件名里带一个点,后处理的五个步骤被整体跳过,归档文件夹是空的。
  • 用来查同一行里重复字的 grep 在 macOS 上不支持反向引用,这项检查从写下来那天起就没工作过。
  • 后来补的按行查重复:一份 3.5 小时的播客里有 828 行连续的「对」,是模型的幻觉,占掉了 14 分钟的内容,它只报出了最后 15 行。循环里模型会吐出空行,把连续的一段切碎了。
  • 繁体检查被加了个前提「锁定中文就不会有繁体」,结果最该报警的那次反而被跳过。

从那以后有一条规则:一个从来没报过警的检查,不是「一切正常」的证据,是「没验证过」的证据。 每加一项检查,必须同时有一个已知会触发它的输入,证明它会响。交付前把每项检查的实际数字打出来,因为「数字是 0」和「检查根本没跑」,在日志上长得一模一样。

这条规则写于 8 月,Kay 的事故发生在 10 月。规则写在一个仓库里,挡不住另一个仓库里的事。

3. 读一半就开始总结

让 agent 读一份很长的材料(几万字的转写稿、长 PDF),它经常读了开头、结尾和几处搜索结果,就交出一份看起来很完整的总结。它自己也不知道漏了。

有一次要读一门 3 小时的课程,我让 agent 换一种读法:先把材料切成大小合适的块,主 agent 自己按顺序读完每一块,不交给子 agent;每读完一块就把笔记写进文件;最后在笔记开头写一份覆盖声明:读了哪个文件、多少行、每块的行号范围。

这样读出了抽样读法发现不了的东西:同一个数字前后两种说法(165 和 16.5 万);字幕里一个价格是 $641,按后文推断应该是 $6.41;开头预告要讲的一个话题,全片都没讲。

读完当天,我把这个读法做成了一个公开的 skill:deep-read。

共同的东西

三件事背后是同一个道理:

  1. 先说清楚这个东西存在的意义是什么,然后直接读那个结果,而不是读替代品。语音输入的意义是「松开出字」,不是「构建通过」。
  2. 每项检查在证明自己有用之前,都只是替代品。 先问一句:如果真正的结果坏了,这项检查的结果会不一样吗?「没有崩溃报告」在 App 卡死时不会变,所以它证明不了 App 没坏。
  3. 出了事改结构,不加规则。 能消除的危险就消除(固定尺寸的浮窗),消除不了就加一道机器检查的闸门;写一条规则提醒 agent 小心,是最弱的一种。我自己也没完全守住:Kay 的闸门被我换成了规则,两天后就付了代价。
  4. 做事的和验收的分开。 agent 天然倾向于收尾、报喜、不惹麻烦,所以要让它在没有证据的时候说不出「做完了」。

文中的作品