审查、辩论与结果裁决
多 Agent 审查是让其他 Agent 检查已有结论或产物,并将检查结果用于修订或验收。辩论进一步允许参与者交换论点、质疑依据和修改判断。它们都需要一个最终决策步骤:哪些问题成立、需要改什么、哪些分歧暂时无法解决。
审查者需要可检查的材料和明确标准,发现的问题还要进入修改流程。例如检查代码时,它应能看到需求、当前实现和相关测试,说明哪一处不满足要求,而不能只凭作者的完成摘要判断是否通过。
几种做法的区别
| 做法 | 参与者看到什么 | 输出怎样被使用 |
|---|---|---|
| 独立核查 | 原始任务、来源或代码;可以先不看其他 Agent 的结论 | 对照各自查到的事实,发现遗漏或冲突 |
| 产出—评审回路 | 评审者读取候选产物和验收标准 | 返回可定位的问题,作者修改,再检查新版本 |
| 交互辩论 | 参与者能读取并回应对方的论点和证据 | 经有限轮次交换后,按证据和标准裁决 |
| 独立采样与聚合 | 各次生成先独立进行,通常不互相反馈 | 对答案归一化、计数、评分或选择 |
独立采样与聚合可以由同一个模型完成,并不要求创建多个持续运行的 Agent。Self-consistency 就采用多次采样再聚合答案的思路。辩论则会改变参与者后续获得的信息:A 看过 B 的意见后可能修正结论,也可能被 B 的错误说服。
这些方法可以组合。先让两个检查者独立提交结果,再只围绕有分歧的地方讨论,通常比一开始就把所有意见放进共享对话更容易保留独立发现。是否值得增加这一轮,需要看任务中的遗漏能否通过另一种检查方式被发现。
从一个有缺陷的查询接口开始
假设任务是实现“用户查询自己的工单状态”。提交的第一版包含以下材料:
| 证据编号 | 材料 |
|---|---|
| E1 | 需求规定:普通用户只能查询属于当前租户、且由自己提交的工单 |
| E2 | 请求入口已验证登录身份,得到 tenant_id 和 user_id,但没有检查工单归属 |
| E3 | 查询语句只有 SELECT status FROM tickets WHERE ticket_id = :ticket_id;查询后直接返回结果 |
作者认为接口只读,因此风险较低。评审者按照 E1 检查数据读取范围,会发现 E3 只按工单号查找,没有使用 E2 提供的身份信息。用户如果提交另一个人的有效工单号,查询就可能返回对方的状态。
这里可以直接定位到一个具体问题:读取路径缺少资源级授权检查。“已登录”和“只读”都不能满足 E1 中的归属约束。评审没有必要先安排“乐观派”和“悲观派”讨论接口是否安全;需求和查询语句已经足以确定要修改的地方。
反馈应包含检查对象的版本、问题依据与修改后的验收条件。例如:
{
"artifact_version": "v1",
"finding_id": "F1",
"location": "工单查询条件",
"problem": "查询没有限制租户和工单提交人",
"evidence": ["E1", "E2", "E3"],
"required_change": "在读取工单内容前校验当前身份是否有权访问该工单",
"acceptance_cases": [
"当前用户查询自己的工单,可以读取状态",
"查询同租户其他用户的工单,不能读取状态",
"查询其他租户的工单,不能读取状态"
]
}“加强安全性”无法直接指导修改;上述反馈则能让作者知道要检查哪条路径,以及改完后如何判断问题是否解决。评审者也应区分已经由材料证明的问题和仍待核实的疑点。如果没有读到完整授权路径,就应先指出缺少哪部分信息,再补查,不能仅凭一个局部查询断言整个系统存在漏洞。
从问题反馈到新版本验收
对于这个只允许用户查自己工单的接口,作者可以把租户和提交人条件加入查询,参数从经过验证的请求上下文获取:
SELECT status
FROM tickets
WHERE ticket_id = :ticket_id
AND tenant_id = :current_tenant_id
AND requester_id = :current_user_id;这时产物进入 v2。评审者需要读取新查询和参数来源,再检查 F1 中的三个用例;只看到 SQL 多了两个条件,还不足以确认参数来自可信身份。如果客户端仍能任意指定 current_user_id,原有问题就没有解决。
一次完整回路可以表示为:
版本号把意见绑定到具体产物。作者修改后,旧意见可能已经失效;评审者不能继续根据 v1 的截图要求修复 v2。若另一位 Agent 同时修改了接口,则要先确认复审读取的是当前待交付版本。
评审者是否能直接改文件,由产物的写入职责决定。在作者继续编辑时,评审者返回评论或 patch,能减少互相覆盖;如果任务已明确将某个文件的修改权交给评审者,它也可以直接修复,再由其他检查确认。不能把“审查者”这个角色名称当成永远只读或天然可写的权限规则,具体方式见多 Agent 的文件与产物协作。
哪些分歧需要讨论
授权缺失已经确定,但修复放在哪里仍可能有不同方案:A 建议在查询函数内增加条件,B 建议统一调用授权服务。此时讨论应围绕系统已有约束展开。
第一轮让双方各自说明方案覆盖哪些调用入口、依赖哪些现有组件、还需要改哪些代码。第二轮只回应对方尚未覆盖的情形,例如批量查询是否绕过了单条查询的检查。参与者可以修改自己的方案,不需要为了保持“正方”或“反方”身份坚持原结论。
裁决者据此检查:所有读取入口是否都满足 E1,新增组件是否已经存在,是否改变接口行为,以及测试能否覆盖这些路径。如果材料表明系统已有统一授权服务且所有入口都必须经过它,可以沿用该服务;如果相关入口尚未核实,就先补查调用路径。仅凭一个 Agent 说“集中管理更好”,无法确定方案适合当前代码。
讨论中的分歧还要分清性质:
| 分歧 | 处理依据 |
|---|---|
| 对代码或资料的事实判断不同 | 回到代码、原始来源或可复现的执行结果 |
| 对同一约束提出不同实现 | 比较各方案是否满足要求、依赖和改动范围 |
| 对速度、成本、准确性的取舍不同 | 使用任务预先给定的优先级;缺少优先级时保留待决项 |
| 读取了不同版本的产物 | 先统一待检查版本,再重新判断 |
能同时保留的结果可以合并,例如两个检查者分别发现授权遗漏和错误响应泄露。互相矛盾的结果则需要裁决或保留分歧,不能为了生成一段顺畅的总结,将两种不能同时成立的判断写成“总体可用”。
多数意见为什么仍可能错
如果三个 Agent 都只读取作者的说明“这是一个只读接口”,它们可能一起漏掉授权检查。即使换了角色名称或模型,输入材料相同、检查方式相同,错误也可能高度相关。简单投票只会放大这份共同遗漏。
有用的差异来自检查工作本身:一个 Agent 核对需求和数据访问路径,另一个核对参数来源与测试覆盖;必要时运行测试或查阅原始文档,为裁决提供模型文字以外的依据。使用不同模型可能带来不同发现,但不能据此保证独立性或正确率。
交互还会带来从众。参与者看到一个语气确定的早期结论后,可能不再继续核查。先独立提交发现,再交换证据,可以减少相互影响;裁决阶段仍要逐条检查理由。让模型充当裁决者,也只是增加了一个可能出错的执行者。涉及代码行为时,以具体实现和验证结果约束裁决;涉及事实时,保留来源与适用范围。
怎样结束评审
评审通过需要对应当前版本的验收条件,例如 F1 已修复,三个授权用例均满足要求,并且没有未处理的阻塞问题。所有 Agent 都说“同意”,不能替代这些检查。
运行层还要设置最大修改轮数、总耗时和预算。达到上限后保存当前产物、已解决问题、仍未解决的问题及依据。若连续两轮只是改写同一条意见,没有新增证据或可执行修改,也应结束讨论,进入补充材料、保留分歧或交由指定负责人决策的出口。
这样交付的结果可能是已通过的版本,也可能是“这部分已确认,另一部分仍缺证据”。下一步处理的是具体未决事项,无需重新播放全部讨论。运行记录与成本比较见多智能体的评估、成本与追踪。
参考资料
- Anthropic:Building effective agents,其中的 evaluator-optimizer 模式讨论了产出与反馈循环。
- Du 等:Improving Factuality and Reasoning in Language Models through Multiagent Debate,介绍多轮交换意见的辩论方法与实验。
- Wang 等:Self-Consistency Improves Chain of Thought Reasoning in Language Models,介绍多次采样并聚合答案的方法。