护栏能让 AI 编程智能体做得更好吗?270 次运行给出的答案
来自博客
作者:Rakesh Menon 2026 年 10 月 15 日 6 分钟阅读
每个用编程智能体的团队,最后都会吵同一件事。有人搭好了一套脚手架:一份指令文件、一道提交前的关卡、一个钩子(hook)——测试没跑过就不许说“完成”。另一个人则发现,智能体照样能把测试跑过。
然后某个早上,这道关卡连着六次拦下了智能体,于是有人忍不住问:这些护栏到底值不值,还是纯粹走个过场?这问题最后通常靠信念解决,因为护栏的成本是等出来的,收益则是那些从未发生的问题。
为了写书,我做了一次实验。
在 270 次无人值守的编程智能体运行中,覆盖三个模型、七个任务,所有改动最终都被接受,护栏也没有提高一次通过率。它们的影响体现在运行到“完成”时留下的东西上:在后四个任务中,有护栏的 60 次运行里有 9 次留下了缺陷,没有护栏的 60 次里是 15 次——这个样本量下差距太小,还不能下结论。
一次通过了全部测试的运行
任务 T7 要求实现周期性发票。其中一次运行既没有指令文件也没有钩子,第一次尝试就通过了隐藏的验收测试。接着,项目自带的检查在它留下的成果上跑了一遍,有一项失败了:它改了数据库结构,却没有按团队规则为每次结构变更附上对应测试——而这条规则,这次运行压根没看到。
实验是怎么设计的
实验在 2026 年 10 月 13 日和 14 日进行,用的是 Claude Code 2.1.296,每个任务、每种条件和每个模型各跑五次,交叉穿插:先用 Sonnet 和 Opus 跑三个日常功能(T1 到 T3),再用 Haiku、Sonnet 和 Opus 跑四个更难的任务(T4 到 T7)。如下图所示,none 什么都不给,只有任务和代码;rules 额外加一份指令文件;gates 再加一道提交前关卡,以及一个在缺少最新测试证据时拒绝“完成”的钩子。验收测试是隐藏的;在 T4 到 T7 上,项目自带检查的任何失败都计为“完成时的缺陷”。
相邻条件之间正好差一层;方括号标出的是跨模型比较。
护栏到底有没有提高通过率?
没有。270 次运行全部被接受,其中 267 次在第一次“完成”时就通过了隐藏测试:无护栏组 90 次全过,规则组 90 次过 89,关卡组 90 次过 88。我事先写好的统计检验显示,任何模型在不同条件下都没有明显差异。
护栏真正起作用的地方
回到 T7。没有指令文件时,15 次 T7 运行中有 14 次在没改测试的情况下改动了 schema,不论用哪个模型;加上规则后,30 次里一次都没发生。这条规则要求迁移和它的数据库测试必须一起改:见“同时更新清单”(P04),第 3 章有实测数据(这类文件后面还会细说)。
把 T4 到 T7 合起来看,“完成”时的缺陷数是:无护栏 60 次中 15 次,规则组 60 次中 14 次,关卡组 60 次中 9 次。Sonnet 的差距最大,1 比 5,但即便如此也只有 p = 0.18:算是领先,还不能算证据。
有一点要注意:T4 不改动已有测试就做不完,而指令文件规定测试对智能体是只读的。在这条规则下,30 次运行中有 23 次把功能做出来了,却留下旧测试失败,然后请人来改。规则组和关卡组的所有缺陷都来自这里。规则本身没错(为什么要有它,见第 6 章,有免费样章),但没人来处理,而“请人来改”和“留下 bug”被算成了同一类。
通过率几乎没动;真正变化的是运行结束后留下的东西,而只读测试规则还起了反作用。数据来源:作者的 270 次运行。
每次被接受的改动,成本是多少?
“每次被接受改动的成本”(P32),第 12 章,把每次运行的成本(包括失败的运行)除以被接受的改动数。T4 到 T7,每个单元格 20 次运行:
| 模型 | 无护栏 | 规则 | 关卡 |
|---|---|---|---|
| Haiku | $0.06 | $0.04 | $0.05 |
| Sonnet | $0.27 | $0.28 | $0.30 |
| Opus | $0.97 | $0.84 | $0.82 |
护栏几乎没改变成本;模型带来的差距超过十倍。270 次运行合计约 $115.58,这是智能体工具按标价自己估算的,不是实际账单。

本文是精简版。书里有按模型、按任务的完整分析,还讲了怎么给每道护栏定价,以及怎么淘汰那些不再划算的护栏(第 12、13 章)。
哪些防护还值得保留?
每个防护都是一次押注:当同一个错误再次出现时,赌模型还会再犯。在《Guards Pay Rent》(第 12 章,P33)里,作者给每一种防护都标了价:延迟、噪音和日常维护的成本,要跟它真正拦下的错误对账。
这些实验无法告诉你的事
每个组合跑 5 次,是这套协议的最低要求。覆盖 7 个任务、一个小型代码库、一个 agent,以及同一家厂商的 3 个模型,状态截至 2026 年 10 月。任务、测试和运行框架都是我写的,这可能对这套框架本身有利;而缺陷的统计方式,用的又是它自己那套防护规则。
自己验证
所有东西都在配套仓库里:运行记录在 experiment/results/,T4 到 T7 的计划写于这些运行开始之前,放在 BATCH-2.md,还有 reproduce.ts,它能把书里引用的每个数字都重新算一遍:
node experiment/results/reproduce.ts
那 T7 那次运行呢?数通过次数,它完美无缺;看它留下了什么,它只是 14 次运行之一——把一处 schema 改动交接出去,却没带任何测试。你得出哪个答案,取决于你量的是什么;关于「流程仪式感」(ceremony,指各种必须走的流程)的争论也是一样。
常见问题
这套测试框架值吗?
从通过率和成本上看不出来:每种条件下首次运行 90 次能过 88 到 90 次,各模型每次被接受改动的成本差距都在 15 美分以内。它体现在运行结束后留下的东西上,代价是一些运行因为要等一个不在场的人而卡住;这值不值,得自己判断。
哪个模型每次被接受的改动最便宜?
Haiku:T4 到 T7 上每次被接受的改动花费 0.04 到 0.06 美元,Sonnet 是 0.27 到 0.30 美元,Opus 是 0.82 到 0.97 美元;60 次运行全部在第一次说「完成」时就通过。对小而需求写全的任务,这就够了,但这说明不了更大规模的工作。
我能在自己的代码上跑同样的实验吗?
可以。仓库里有实验协议、7 个带隐藏验收测试的任务,还有一个评分脚本——它会把失败的运行也计入每次被接受改动的成本。换成你自己待办清单里的任务,每种条件至少跑 5 次,交叉进行,报告时既给平均值,也给波动范围。