Agent 质量门的误报比漏报更危险
我这条内容流水线的形状是这样的:每一篇有一个实现者 Agent 负责写,一个独立的评审 Agent 负责查,两个 Agent 互不通气,评审员只拿到落盘的文件和那份写作规范。人不在中间,人在两端——开工前把规格和事实源定死,收工后做验收。中间那道「有没有写砸」的判断,交给规格、独立评审和脚本三层来兜。
脚本那一层,就是我说的机械质量门:不理解内容,只按字符串规则扫,扫出可疑的就报。它的存在理由很朴素——评审 Agent 和我都会漏,机器不会累。
然后有一次,这道门首轮报出来的问题,一条真的都没有。
首轮报告全是误报
那一批我给门加了一条新判据,跑完拿到一份命中清单,看着挺唬人。我本来的打算是照着清单逐条改。
改到第一条就卡住了。它命中的是文章模板自带的一句合规声明——那句话是模板统一注入的,不是实现者写的,也不该被删。往下第二类,命中的是规范里强制要求写的否定句,也就是我自己在写作规范里明文规定「这一段不许省」的那种表述,门看到否定式就报了。第三类更直接:命中的是代码示例里的数字。代码块里的字符串本来就该原样保留,门不区分正文和代码块,一并算进去。
三类加起来,把清单填满了。逐条对下来,没有一条需要改文章。
这不是孤例。后来我回看提交历史,同一道质量门被单独记过两次修复,提交信息写得很清楚:一次是「修质量门误报(协议否定句)」,另一次是「修质量门第三类误报(关键帧结构)」。
注意后面那条的措辞——它自称是第三类。也就是说实际处理过的误报类型比留下记录的更多,中间那一类当时顺手就改了,没单独成条。两次留痕、没有一次是因为漏报,这道门上线之后我花在它身上的力气,几乎全在压误报。
当时是怎么发现的
这一段比现象本身重要,因为发现方式是可以复用的,而现象是一次性的。
发现它的动作特别土:我没有按报告改,而是把每一条命中拉回原文看上下文。命中报告只给你一个位置和一个匹配到的片段,那个片段脱离上下文看起来都很像违规——一句被截出来的否定表述,一个孤零零的数字,你不看它前后是什么,根本判不了。我是把每一条都翻回文章里那一段读完,才发现第一条不该改、第二条也不该改,一路到最后一条。
如果我当时省掉这个动作,直接把清单丢给实现者去改,结果会是:模板自带的合规声明被删掉,规范强制要求的否定句被改成模棱两可的表述,代码示例里的数字被改成占位符。也就是说,门会亲手拆掉它本来要保护的东西。这比它什么都没查出来糟糕得多。
第二个发现渠道是提交历史。单看一次修复,你只会觉得「这次判据没写好,改一下就行」;把同一道门的几次修复排在一起看,才看得出这不是偶发失误,而是这类门上线初期的固定形态。判断一个问题是偶发还是结构性,靠的是把同类记录排在一起看,不是靠单次归因。
为什么会这样
我事后想明白的原因是:机械门只能看见字符,看不见来源和意图,而被它扫的文本里,天然就存在大量「长得像违规」的合法结构。
- 模板注入的内容和作者写的内容混在同一份产物里,门分不清哪句是谁写的;
- 规范里越是强制要求写的句子,句式越固定,也就越容易被规则整片命中;
- 代码块和正文在纯文本层面没有区别,门不做区分就会把示例当成陈述。
再往上一层看,还有一种更隐蔽的误报:门的口径本身错了。我这边遇到过模板注释没有被剥离就计入正文长度,导致长度门长期给出假结果——它一直在报,报的是自己算错的东西。反方向也有:中日韩字数如果用按字节计的命令行工具去数,结果会虚高好几倍,长度门就形同虚设,什么都拦不住。同一道门,口径偏一边是乱报,偏另一边是白设。
判据写宽的诱惑很大,因为写宽显得「查得全」。但查得全和查得准在这里不是一回事。
改成了什么
我做了三件事。
第一,命中不等于问题,每一条都必须看上下文才能定性。 这条现在是硬纪律。门的输出不是结论,是待核清单。我不再把命中报告直接转给下游去改。
第二,判据宁可写窄。 明确接受漏一些,也不要乱报。这个取舍看起来是在降低门的能力,实际是在保住门的可信度——门只要还被认真对待,漏的那部分还有评审和抽查兜;门一旦不被当回事,漏的和报的一起归零。
第三,把已知的误报形态前置写进评审员的任务书。 我的写作规范末尾专门留了一节,列出评审时最容易误报的几处,要求先看上下文再判:正文尾那段「样本有限」「未必适用」的声明是规范强制要求写的,不是心虚措辞;复盘类文章里「我当时以为……结果不是」是这种词形的结构本身,不是逻辑混乱;讲「不许写易变数字」这条规则时,举例中出现的数字是示例,不是违规。这一节的最后一句写的是:宁可漏判,不要乱判。
这三件事有个共同点——它们都不是把门修得更聪明,而是限定门的输出该怎么被使用。
顺带说一句分层。我这边的机械门只负责可数的东西:长度、链接、格式、孤儿页。事实对不对,它查不出来,也不该指望它查。查得出的和查不出的分清楚了,门才不至于因为「它应该能查出来吧」而被赋予它承担不了的信任。
可迁移的判断
这一次我带走的是这句:
误报的代价不是多花时间,是让执行者开始整体忽略这道门——此时门等于不存在。
多花时间是可以摊的成本,忽略是不可逆的状态变化。人被一道门骗过几次之后会开始跳过它;而在 Agent 流水线里这件事更难察觉,因为下游是一个不会抱怨的执行者。它不会跟你说「这条报错了吧」,它要么照单全改,要么在你把判据放宽之后再也命中不了什么。两种结局,你从报告上都看不出来。
所以我现在给自动检查定判据时,先问自己一个问题:这条判据第一次跑,如果报出来的命中里大半都要我回一句「这条其实没事」,我还会认真读剩下那些吗? 答案是否定的话,判据就得再收窄一格,或者干脆先不上线。
这篇写的是我自己那套流程里的一次实际情况,不是通行做法。你的场景、工具和团队规模不同,结论未必适用,判断方式可能比结论更值得拿走。
延伸阅读
- 上一篇(跑闭环):文件落盘不等于子代理写完了
- 下一篇(跑闭环):Agent 的验收样本要按失败分支覆盖,不是按成功次数累计
- 这个专题的主论点:Agent 调用没报错,不等于这件事办成了
- 专题导读与七个阶段的地图:把 Agent 当成一个要上岗的员工来带:这个专题讲什么