Agent 说“完成了”,系统为什么不能直接相信?

0 阅读3分钟

Agent 说“完成了”,系统为什么不能直接相信?

1. 最终消息不是工作事实

做 Agent 工程时,很容易写出这样的逻辑:

if (agent.finalMessage.includes('completed')) {
  task.status = 'done'
}

真正运行一段时间后就会发现,最终消息最多只能代表 Agent 声称完成。它不能证明测试通过、产物存在、数据已经落库,也不能说明是否产生了用户没有要求的副作用。

完整研究版见:完成是一项声明,而不是已接受状态。这里重点讨论怎样把这个判断放进编码运行时。

2. 第一道门:确定性回读

能够确定性验证的内容,应该优先交给程序:

  • Git diff 是否符合修改范围;
  • 必需测试是否全部通过;
  • 构建产物是否存在;
  • 文件哈希和提交 SHA 是否一致;
  • 远端分支或业务系统是否真的进入目标状态。

这些检查解决的是“环境里实际发生了什么”,而不是“Agent 认为自己做了什么”。

3. 第二道门:解释执行轨迹

确定性检查通过以后,再让验证器处理语义问题:执行过程是否合理,失败由 Agent 还是环境造成,最终结果是否满足用户意图,有没有额外副作用。

Microsoft Research 的 Universal Verifier 采用了类似分解:过程与结果分离,可控与不可控失败分离,并针对每条准则寻找相关截图证据。它提供的不是一个永远正确的完成 Oracle,而是一种按声明寻找证据的验证方式。

4. 第三道门:谁拥有接受权

验证结果仍不等于最终接受。高风险任务的接受者可以是 QA、管理员、策略引擎或明确授权的人,但不应该仍然是刚刚执行任务的那个 Agent。

因此更合理的状态转换是:

running
→ completion_claimed
→ verifying
→ accepted | rejected | escalated | undetermined

5. 失败、阻塞和未确定必须分开

Agent 按正确步骤执行,却被验证码或缺少凭据拦住,这不是成功,也不能简单归类为工作者失败。验证结果可能是:

{
  "claim": "completed",
  "process": "passed",
  "outcome": "not_reached",
  "failure_class": "external_blocker",
  "acceptance": "undetermined"
}

保留这种冲突,后续才能决定重试、请求权限、修复环境还是人工接管。否则恢复 Worker 只能面对一个模糊的 failed,不知道从哪里继续。

6. 把完成证据写进契约

一个可执行的完成契约至少需要说明:

  • Agent 可以提交哪些完成声明;
  • 每类声明需要哪些回读和测试证据;
  • 验证器版本和判断依据怎样记录;
  • 谁拥有接受、拒绝和覆盖判断的权限;
  • blockedescalatedundetermined 怎样进入后续恢复流程。

这比在最终提示词里加一句“请确认已经完成”更可靠,因为契约约束的是状态转换,而不是说话方式。

7. 研究结论的边界

Universal Verifier 的论文结果很有价值,但外部 Browserbase 数据上的误报率仍为 8%。它不能直接证明任何生产系统已经具备通用验收能力。真正值得采用的是:执行者可以提交完成声明,但不能单独决定系统已经接受完成。

参考:论文 · 开源实现

Other language: English version

如果你正在使用 Cursor、Codex 或其他编码 Agent,你现在会用哪些证据,来决定它是真的完成了,而不是只说完成了?