搜索文章

输入关键词开始搜索

Adversarial Quality Gate


最近看到一个说法:Adversarial Quality Gate

一开始我以为这是某篇论文或者某家公司正式提出的概念,所以想先追一下源头。后来才发现,这个词更像是 agent workflow 发展到一定阶段之后,自然拼出来的一种工程做法。

它不是一个单点发明,而是把传统软件工程里的质量门禁、LLM eval、LLM-as-judge、critic agent、red teaming、Self-Refine / Reflexion 这类反馈循环合在一起,用来解决一个很现实的问题:

agent 的输出不能默认可信。
如果上游产物没有经过验证,就不应该直接进入下一阶段。

这里做个记录。

对抗式质量门禁的反例与验证回路

它不是谁单独提出的

如果严格问“Adversarial Quality Gate 是谁提出来的”,答案大概率是:没有一个明确的单一提出者。

这点很重要。因为如果把它当成一个正式学术术语,就容易走错路,开始找“首篇论文”“标准定义”“权威框架”。但从现在能看到的资料和工程实践来看,它更像是几条线汇合出来的结果:

  • 传统 CI/CD 里的 Quality Gate
  • LLM 应用里的 eval 和 golden set;
  • 用强模型做语义评价的 LLM-as-a-Judge
  • 多 agent 流程里的 critic / verifier;
  • AI red teaming 和反例生成;
  • Self-Refine、Reflexion、Constitutional AI 这一类生成、批判、修正循环;
  • 生产发布里的 promote / hold / rollback 决策。

所以我更愿意把它理解成一个工程组合模式,而不是一个被某篇论文命名的新概念。

这个判断会影响后面的落地方式:不要纠结“标准定义是什么”,而是要问“我的 workflow 里,哪些产物不能直接放行,应该怎么拦住”。

传统 Quality Gate 是它的底座

Quality Gate 本来是软件工程里的老概念。

代码要进入下一阶段之前,先过一组检查:编译、lint、单测、覆盖率、安全扫描、复杂度、漏洞数量。过了才能合并、发布或者部署;不过就退回去修。

放到 agent workflow 里,流程其实也类似:

上游 agent 产物

Quality Gate 检查

通过:进入下一阶段
失败:返工 / 重试 / 升级模型 / 人工介入

区别在于,传统质量门禁主要处理确定性产物,比如代码、配置、构建结果。

但 agent 的输出经常不是这种东西。它可能是一份方案、一个 PRD、一个 SQL、一个调研结论、一段操作计划、一次代码修改,甚至是一组工具调用结果。这里面有很多问题不是单测能发现的:

  • 是否遗漏了用户的约束;
  • 是否编造了引用;
  • 是否把不确定的判断写得太肯定;
  • 是否只解决了表面问题;
  • 是否在边界条件下会失败;
  • 是否和项目已有规则冲突;
  • 是否生成了看起来正确但无法执行的方案。

所以到了 agent 时代,质量门禁不能只停留在 lint + test。它要继续往上加语义检查、事实核查、critic 审查和反例测试。

“Adversarial” 的关键是主动找错

普通质量检查更像是在问:

这个结果看起来对不对?

对抗式质量检查问的是:

我能不能证明它是错的?
有没有一个边界条件可以打穿它?
有没有证据不足、偷换概念、路径错误、格式不合规、隐藏副作用?

这就是 Adversarial Quality Gate 和普通 Quality Gate 最大的差别。

它不是给上游 agent 做礼貌评价,而是专门站在反方视角审查产物。比如 coding agent 写完代码之后,critic 不应该只说“整体不错”,而应该问:

  • 这段代码有没有违反现有架构边界?
  • 测试是不是真的覆盖了失败路径?
  • 有没有用 anyts-ignore 这种方式绕过类型问题?
  • 有没有改到用户没有要求的地方?
  • 这个修复是否只对 demo case 有效?
  • 如果输入为空、字段缺失、权限不足、网络失败,会发生什么?

这一步的目的不是让流程变复杂,而是承认一个事实:agent 很容易生成“看起来完成了”的结果。越是这种结果,越需要有人或者另一个 agent 去主动找漏洞。

一个可用的 Gate 至少要有动作

我之前容易把 judge 和 gate 混在一起。后来发现这两个不是一回事。

Judge 只是评价。Gate 必须能决定流程是否继续。

一个真正有用的 Adversarial Quality Gate,通常要包含几类检查:

第一类是结构检查。比如 Markdown 是否包含必要章节,JSON 是否可解析,SQL 是否只读,输出字段是否完整。这类最好用确定性脚本,不要上来就用 LLM。

第二类是规则检查。比如不能编造引用,不能跳过用户明确约束,不能执行危险操作,不能修改 public API,必须包含测试或验证证据。

第三类是自动化测试。代码可以跑 unit test、type check、lint、e2e;SQL 可以跑 explain;配置可以跑 schema 校验;浏览器交互可以跑 smoke test。

第四类是 LLM judge。用 rubric 去判断 correctness、completeness、evidence、constraint following、risk awareness。但这里要小心,LLM judge 自己也会有偏差,所以它不应该是唯一依据。

第五类是 critic agent。它的工作是找漏洞、找矛盾、找边界条件、找证据不足。这个角色要比普通 reviewer 更“难相处”一点,否则就起不到对抗作用。

第六类是反例生成。不是只看正常样例,而是主动构造坏输入、缺失字段、脏数据、prompt injection、工具失败、多轮上下文冲突。对于 coding agent,这一步最好能直接生成 failing test。

但这些还不够。

最关键的是第七类:门禁动作。

PASS      进入下一阶段
REVISE    退回上游 agent 修改
RETRY     换 prompt / 换模型 / 补上下文后重试
ESCALATE  升级到更强模型或人工
REJECT    终止流程
ROLLBACK  回滚到上一个稳定版本
LOG       把失败样例加入 eval set

没有动作的 judge 只是评论员;有动作的 judge 才能成为 gate。

更准确的定义

原始定义是:

Adversarial Quality Gate 是 agent workflow 中的强制质量控制节点,它使用规则检查、自动化测试、LLM judge、critic agent、反例生成等方式,对上游 agent 的产物进行对抗式验证;只有满足预设 Agent Eval 标准的产物才能进入下一阶段。

这个定义整体是对的,但我会改两个地方。

第一,不要说得像行业里已经有一个统一的 Agent Eval 标准。大多数情况下,标准是每个项目自己定义的。

第二,要把失败后的动作写进去。否则它只是 review,不是 gate。

我觉得更稳的中文版本是:

Adversarial Quality Gate 是 agent workflow 中的运行时或流水线级质量门禁。它结合确定性规则、自动化测试、结构校验、LLM judge 打分、critic agent 审查和反例生成,对上游 agent 的产物进行主动找错式验证。只有满足预定义 eval contract 的产物才能进入下一阶段;否则会被退回修改、重试、升级模型、人工介入、拒绝,或者沉淀为新的 eval case。

这里我更想用 eval contract,而不是“Agent Eval 标准”。

因为 contract 这个词会提醒我们:这不是一个抽象质量口号,而是一份可执行的验收契约。它应该能回答:

  • 产物必须满足哪些结构;
  • 哪些规则不能违反;
  • 哪些测试必须通过;
  • 哪些证据必须出现;
  • 哪些失败要阻断;
  • 哪些失败可以重试;
  • 哪些失败必须人工介入。

先把 Agent Eval 定义清楚

这里还有一个容易混淆的点:Agent Eval 不是“让一个 LLM judge 看一下最终答案好不好”。

如果在团队内部定义,我会这样写:

Agent Eval 是对 agent 系统在真实或仿真任务中“是否正确完成目标、是否按可接受路径执行、是否安全、是否稳定、是否经济”的系统性评估机制。它评估的不是单次 LLM 输出,而是 model + prompt + tool + memory + context + workflow + runtime harness 的整体表现。

这个定义里最关键的是“整体表现”。

一个 agent 最终回答对了,不代表流程一定是对的。它可能调用了不该调用的工具,读了错误的上下文,绕过了权限边界,修改了不该修改的环境状态,或者用很高的 token 成本碰巧撞到了答案。

这里最容易犯的错,是把 final answer 当成 outcome

final answer 是 agent 自己说“我完成了”。outcome 是环境最后真的变成了什么样。比如一个订票 agent 说“已经订好了”没有意义,要看数据库里有没有 reservation;一个 coding agent 说“测试通过了”也不够,要看测试命令是不是真的跑过,结果是什么,工作区有没有被改坏。

所以 Agent Eval 不能只看最后一句话,而要看目标、路径、工具调用和环境状态是否对得上。

具体来说,至少要看这些东西:

  • 最终目标有没有完成;
  • tool call 是否正确、必要、合规;
  • 上下文选择是否足够,是否引入了无关或错误信息;
  • 执行路径是否可接受,有没有危险捷径;
  • 环境状态变化是否符合预期;
  • 失败时有没有可诊断的 trace;
  • 成本、延迟、稳定性是否在可接受范围内。

这也意味着 Agent Eval 不能只停留在离线 benchmark。它应该接入 CI/CD、灰度、线上 trace、人工抽检和生产监控。单一 LLM judge 也不够,最好是确定性检查、LLM judge、human review、prod monitoring 的组合。

Anthropic 在 2026 年的 Demystifying evals for AI agents 里,把 agent eval 拆成了几个对象:tasktrialgradertranscript / traceoutcomeevaluation harnessagent harness

这组拆法对工程落地很有帮助。

transcript / trace 是完整执行记录,不只是最终回答,还包括输出、工具调用、中间结果和交互过程。outcome 是最终环境状态,比如订票 agent 不能只说“我订好了”,还要看数据库里是不是真的有 reservation。evaluation harness 是端到端跑 eval 和聚合结果的基础设施。agent harness 则是让模型真正作为 agent 运转的 scaffold,包括 prompt、工具、上下文、记忆和运行控制。

这个区分能避免一个常见误解:我们不是在评估“模型一句话答得好不好”,而是在评估“这个 agent 系统在一套运行环境里是否可靠”。

还有一点也要注意:eval contract 不应该把路径写死。

Agent 有时候会找到一个我们没预设、但确实有效的执行路径。如果 grader 只认一种固定 tool call 顺序,就会误伤正确方案。但如果 grader 只看最终答案,又会放过危险捷径。所以比较合理的做法是分层判断:

  • 最终环境状态必须正确;
  • 安全、权限、数据边界这些硬约束不能破;
  • 关键过程证据必须留下 trace;
  • 对可替代的执行路径保持一定弹性。

这一步其实挺难。太松会让 agent 钻空子,太死又会把 eval 写成脚本背诵。这里的平衡,决定了 gate 到底是在提高质量,还是在制造假稳定。

放到 AI Coding 流程里

如果放到 AI Coding 或 Codex / Claude Code 这类流程里,我觉得一个比较现实的版本应该是这样:

Builder Agent
  生成代码 / 文档 / 方案

Deterministic Gate
  typecheck / lint / unit test / schema check

Spec Gate
  检查是否满足需求、约束、验收标准

Critic Gate
  找漏洞、边界条件、架构问题、证据不足

Adversarial Gate
  生成反例、失败用例、恶意输入、异常路径

Judge Gate
  根据 rubric 打分,低于阈值则失败

Decision
  PASS / REVISE / RETRY / ESCALATE / REJECT

Memory & Eval Update
  把失败原因写入 tests / eval set / project rules / AGENTS.md

这里最容易被忽略的是最后一步。

如果每次 gate 只是当场拦一下,那它只是一次性检查。真正有价值的是把失败沉淀下来:变成测试、变成规则、变成 eval case、变成项目文档。这样下一次 agent 执行时,错误不需要再靠人肉记忆来防。

这其实也是我最近越来越明显的一个感受:AI coding 的质量,不只取决于模型强不强,也取决于项目里有没有把错误变成机制。

工程上怎么落地

如果要把这个概念落到 Harness Engineering,我不建议只做“让另一个 agent 看一眼”。那样很容易变成形式主义:多了一层 review,但没有真正的阻断条件,也没有可复用的失败样例。

更合理的门禁结构应该是:

Gate = deterministic checks + model-based eval + adversarial critique + threshold policy

这里每一项都不能少。

deterministic checks 负责能被机器稳定判断的部分,比如类型、lint、schema、权限、文件边界、测试结果。

model-based eval 负责开放式判断,比如方案是否覆盖需求、证据是否充分、推理是否跳步。

adversarial critique 负责主动找错,不是泛泛评价,而是构造反例、边界条件和失败路径。

threshold policy 负责最后的决策:多少分可以过,哪些问题必须阻断,哪些问题可以重试,什么时候要升级到人工。

以代码生成场景为例,门禁可以拆成这样:

Gate 类型检查内容是否适合 adversarial
Plan Gate方案是否覆盖边界、依赖、风险、回滚很适合
Code Gate编译、单测、lint、接口兼容部分适合
Test Gate是否覆盖核心路径、异常路径、回归风险很适合
Security Gate权限、注入、敏感信息、越权风险很适合
Architecture Gate是否过度设计,是否破坏模块边界很适合
Release Gate是否满足上线条件、监控、回滚、灰度很适合

这张表也说明了一件事:不是所有 gate 都要完全 adversarial。

比如 Code Gate 里的编译、lint、接口兼容,本身就适合确定性检查;但 Architecture Gate、Security Gate、Plan Gate、Test Gate 就非常适合对抗式审查。因为这些地方最容易出现“表面合理、实际有坑”的问题。

所以真正的重点不是给所有环节都套一个 critic,而是先判断:

  • 哪些问题可以用脚本稳定拦住;
  • 哪些问题需要模型做语义判断;
  • 哪些问题必须主动构造反例;
  • 哪些问题一旦出现就不能继续往下走。

几个容易被忽略的 eval 细节

第一,正例和反例要一起设计。

比如你希望 agent 在资料不足时主动搜索,就不能只测“应该搜索时有没有搜索”。还要测“不应该搜索时,能不能不搜索”。否则 agent 很容易学出一个错误策略:只要不确定就搜索,甚至不管上下文里已经有答案,也要多调用一次工具。

这类问题在 coding 场景也一样。不能只测“有 bug 时能不能改”,还要测“没有必要改时能不能停住”。很多 agent 的破坏性不是来自不会写代码,而是来自过度行动。

第二,pass@kpass^k 要分清楚。

pass@k 更像 demo 指标:多试几次,只要有一次成功就算能做。这个指标对探索能力有用,但它不能直接代表生产可靠性。

生产更关心的是 pass^k:连续多次都成功。假设一个 agent 单次成功率是 75%,连续三次都成功就只剩 42% 左右。这个数字会让人冷静很多。因为真实用户要的不是“多试几次总有一次能成”,而是“每次交给它都不要出大问题”。

所以 agent gate 不能只证明“它有能力做成一次”,还要证明“它能稳定地做对很多次”。

第三,不要只看总分,要读 transcript。

Eval 分数只是入口。分数低,可能是 agent 不行,也可能是 task 写得不清楚、grader 写死了、环境状态不稳定、工具返回有波动。如果只看 aggregate score,很容易把 eval 本身的问题误判成 agent 的问题。

真正值得看的,是失败样例里的 trace:它选了什么上下文,调用了什么工具,在哪一步开始偏,最后环境变成了什么样。这个过程看清楚之后,才知道应该改 prompt、改工具、改 grader,还是补测试数据。

第四,不要一开始追求完美 eval suite。

更实际的做法,是先从 20-50 条真实失败开始:线上 bad case、人工测试路径、历史事故、用户反馈、容易误判的边界场景。先把这些变成第一版 eval。等通过率稳定之后,再把它们沉淀成 regression suite,防止后续模型、prompt、工具或 workflow 改动时退化。

这也符合前面说的:Adversarial Quality Gate 的价值不只是当场挡住错误,而是把错误变成以后会自动触发的检查。

发展脉络可以这样看

如果按时间线简单理解,大概有几步。

第一步是传统 CI/CD 的质量门禁。代码不达标,不准合并,不准发布。

第二步是 LLM 出现之后,开放式输出需要 eval。因为模型输出不是只有 pass / fail,很多时候要靠数据集、golden set、人工偏好、LLM judge 去评估。

第三步是生成、批判、修改循环。Self-Refine、Reflexion、Constitutional AI 这类工作说明,模型不只是生成器,也可以承担反馈、批判、反思和修正的一部分。

第四步是多 agent workflow 里出现稳定角色分工。planner、researcher、coder、tester、reviewer、critic、verifier 开始分开。critic / verifier 不再只是“可选建议”,而是 workflow 里的固定节点。

第五步才是 Adversarial Quality Gate 这种说法开始工程化。每个阶段的产物都要过 gate,gate 有明确 eval contract,失败会返工、升级、阻断或记录为新样例。

这里的重点不是哪个词最早出现,而是这个方向背后的共识变强了:

agent 从 demo 走向生产之后,输出必须经过可执行的质量治理,不能只靠“看起来还行”。

经验教训

这次整理之后,我对这个词有几个判断。

第一,Adversarial Quality Gate 不是新魔法。它是传统质量门禁在 agent workflow 里的升级版,只是检查对象从代码扩展到了方案、推理、工具调用和多阶段产物。

第二,不要迷信 LLM judge。LLM judge 有用,但它只是其中一层。能用脚本、schema、测试解决的,优先用确定性检查。

第三,critic agent 的目标要明确。它不是“再帮我润色一下”,而是“尽量证明这个结果不可靠”。如果提示词太温和,它大概率只会给出一些无关痛痒的建议。

第四,反例比正常样例更值钱。正常样例只能证明 happy path 能跑,反例才能暴露系统边界。

第五,gate 一定要连接动作。失败之后是修改、重试、升级、拒绝,还是记录为新 eval case,要提前定义清楚。

经验沉淀也应该进入自动化

这里还有一层更值得做:Gate 不应该只负责当场拦截错误,还应该负责把错误变成以后会自动触发的检查。

如果每次失败都只是人脑记住,那这个系统没有真的进化。真正有价值的是把失败流入几个长期资产:

  • 能写成脚本的,变成 deterministic check;
  • 能复现的,变成 regression task;
  • 属于流程遗漏的,变成 checklist;
  • 属于 agent 行为偏差的,变成 prompt / skill / rule proposal;
  • 属于高风险边界的,进入 adversarial task bank。

这件事可以借助 AI Coding 工具里的 hooks 或类似触发器来做。比如在 gate 失败、测试失败、人工 review 提出高严重问题、同类错误重复出现时,自动启动一个 Lesson Extractor

但这里不能完全自动写入长期规则。

一开始我也会下意识觉得:既然要自进化,那就让系统自动把经验写进 AGENTS.md、skills、eval suite 或项目规则里。后来想了一下,这样很危险。一次偶然失败可能会被写成永久规则;一个局部项目经验可能会污染全局规则;几条规则之间还可能互相冲突。最后不是系统变聪明,而是上下文越来越重,agent 越来越难执行。

所以更稳的做法不是“自动写规则”,而是“自动生成沉淀建议,然后经过验证再合入”。

failure trace

Lesson Extractor

rule / test / eval / doc proposal

verification

human approval for high-impact changes

merge into long-term memory

这里的关键是分类。不是每个教训都应该进全局规则。

比如一次失败是“某个测试没跑”,它应该变成 CI 或脚本;一次失败是“agent 总是过度修改无关文件”,它可以变成 gate policy;一次失败是“某个业务边界没考虑”,它更适合变成 regression task,而不是写进全局提示词。

一个 Lesson Extractor 至少应该产出这些字段:

  • 这次问题是什么;
  • 证据来自哪段 trace 或哪个失败 case;
  • 它应该沉淀成规则、测试、eval case、checklist,还是文档;
  • 这个沉淀会影响哪个范围:当前任务、当前项目、团队通用规则,还是个人工作流;
  • 怎么验证这个沉淀真的能防止问题复现;
  • 是否需要人工确认。

这样系统才有自进化能力:不是越跑越多日志,而是越跑越多可执行的质量资产。

我觉得 Adversarial Quality Gate 的最终形态,不是一个会打分的 reviewer,而是一个能把失败自动转化为规则、测试、eval case 和流程资产的自演进系统。

Agent Eval 落地 Checklist

如果团队真的要做 Agent Eval,我觉得可以先用这份 checklist 做自查。它不一定一次全部做到,但至少能看出现在缺的是样例、grader、trace,还是 gate policy。

  • 每个 agent 场景都有一份 Eval Charter,先写清楚这个 agent 到底要被评估什么;
  • 每个任务都有明确的 input、expected outcome 和 forbidden behavior;
  • task bank 按 golden / regression / adversarial / capability 分类,别把所有样例混在一起;
  • 每次 eval run 都记录 model、prompt、tool、harness、sandbox 的版本;
  • 每个 trial 使用独立 workspace,避免共享状态污染结果;
  • 全量采集 trace,包括 LLM call、tool call、retrieval、diff、outcome 和 cost;
  • 能用 deterministic grader 的地方优先用确定性检查,LLM judge 只负责语义质量;
  • LLM judge 要有结构化 rubric,并且允许回答 Unknown,不要逼它乱判;
  • 高风险场景要有人类校准,不能完全交给 judge model;
  • gate policy 要区分 hard fail 和 soft fail,不能所有问题都一个处理方式;
  • CI/CD 按变更类型触发不同 eval suite,比如 prompt 改动、tool 改动、runtime 改动不应该跑同一组检查;
  • 线上 trace 要抽样进入 online eval,不要只依赖离线样例;
  • 所有失败 case 最终都要沉淀为 regression task;
  • 定期人工读 transcript,校准 grader,而不是只看通过率;
  • eval suite 要防止饱和,持续加入更难任务,否则分数会越来越好看,但系统不一定更可靠。

后续如果我要在自己的 agent workflow 里落地这个东西,不会一开始就做一个很复杂的多 agent 系统。我会先从几个最小动作开始:

  • 把每个产物的 eval contract 写清楚;
  • 先收集 20-50 条真实失败、手工测试路径和高风险流程,做成第一版 eval suite;
  • 能确定性检查的先写脚本和测试;
  • 正例和反例一起补,避免 agent 为了通过单边指标学出错误策略;
  • 对 plan、test、security、architecture 这些高风险环节加 adversarial critique;
  • 给每个 gate 定义 threshold policy,而不是只输出一段评价;
  • 不只看最终答案和总分,要看 trace、outcome 和环境状态变化;
  • 每次失败都沉淀成测试、规则或反例,不让同一个问题反复靠人记住。

这样它才不是一个听起来很高级的词,而是一个真正能提高交付质量的工程机制。