多Agent协作为什么容易互相“甩锅”?从任务分配到结果验证设计协作工作流

发布时间:2026/10/13 23:44:28
多Agent协作为什么容易互相“甩锅”?从任务分配到结果验证设计协作工作流 一、引言多 Agent 系统里的责任真空把单 Agent 拆成 Planner、Retriever、Coder、Reviewer、Executor 之后很多团队会遇到一个反直觉的现象**系统的单点能力提升了端到端的成功率反而下降而且失败后没人能说清楚是哪里错了。**翻日志你会看到熟悉的对话Coder“我是严格按照 Planner 给的 schema 写的字段名对不上不是我的问题。”Reviewer“我审的是 SQL 逻辑没义务核对上游表结构是否存在。”Executor“我只负责执行上游交付的脚本脚本报错说明上游不合格。”Planner“我给的只是方向性描述具体实现细节需要 Coder 自己确认。”每一句都成立但任务失败了。这不是 LLM 的道德问题而是协作工作流的工程缺陷系统里没有一个角色被赋予最后一道闸门的责任也没有任何机制强制把我完成了变成我完成了且证据可复现。本文从任务分配和结果验证两个维度拆解多 Agent 甩锅的技术成因并给出一套可落地的契约化 handoff 分层验证工作流。在展开之前先明确一个观察口径这里的甩锅不是拟人化的道德指责而是三类可观测的技术现象。第一类是显性甩锅某个 Agent 明确输出我做不到因为上游没给我 X但由于系统没有回退路径任务就此挂起。第二类是隐性甩锅某个 Agent 输出了模棱两可的结论比如逻辑基本正确建议注意边界条件把判断责任重新推回给人类或下游。第三类最隐蔽是静默甩锅下游 Agent 发现上游产物有问题但没有上报而是顺手修正后继续执行导致失败被推迟、归因链被切断。如果用一句话概括本文的工程主张把多 Agent 协作看成一个带契约和守卫条件的状态机而不是一群用自然语言聊天的专家。状态机的每一次状态转移都必须有前置条件precondition、产物artifact和证据evidence任何一次转移失败都必须在原地暴露而不是带着错误继续往下走。下面四节先讲成因再讲设计。二、甩锅的四种技术成因2.1 责任扩散没有人被指派最后一道闸门社会心理学里的责任扩散在 Agent 系统里是精确成立的当 N 个 Agent 都能看到某个错误、但没有任何一个 Agent 的 prompt 明确写检查这一项是你的失败条件时检查就没人做。更糟的是LLM 天然倾向于配合上游——它把上游输出当作既定事实而不是待验证的假设。用概率模型可以把这个现象说清楚。假设每个 Agent 在没有明确指派的情况下主动检查某项约束的概率是 p而且各 Agent 的判断近似独立那么至少有一个 Agent 检查的概率是 1-(1-p)^n看起来会随 Agent 数量增加而上升。但问题在于p 本身会随 Agent 数量增加而下降当 Agent 看到链路里已经有Reviewer这个角色时它会合理地认为审查是别人的职责于是 p 趋近于 0。结果不是责任被分摊而是责任被稀释到消失。更微妙的一层是 LLM 的顺从性sycophancy模型在上下文里看到一段语气自信、结构完整的上游输出时倾向于认同其前提而不是从零重算。上游说表结构已经确认过下游的注意力就会从验证表结构转移到如何基于这个结论继续加工。这不是模型能力不足而是训练目标有用、配合、不抬杠与验证任务怀疑、证伪、找反例之间的天然张力。补救办法是把检查从一个模糊的集体义务改造成一个写在某个具体 Agent 失败条件里的硬性职责。工程上可以直接借用 RACI 矩阵Responsible实际产出该产物的 AgentCoder。Accountable为产物正确性最终负责、且失败条件被写进 prompt 的 Agent在本设计里通常不是 Coder 自己而是某个 Gate。Consulted提供输入但不承担 correctness 的一方Retriever 提供候选表。Informed只接收结果、不做判断的一方日志、看板。当一列 RACI 里出现两个 Accountable或者某个产物的 Accountable 是空的就等价于最后一道闸门不存在——这正是甩锅的结构性根源。2.2 接口是自然语言软约束无法被校验Agent 之间的消息如果是用户要求生成一份月度报表请实现那这条消息就是不可校验的。下游无法判断自己是否满足要求也无法证明自己满足了。自然语言接口的另一个后果是错误可以无限期地以理解偏差的形式潜伏直到最下游执行时才爆发。把这一点讲透需要区分软约束和硬约束软约束是报表要合理、字段要完整、口径要一致这类人类能懂、机器难判的表述硬约束是输出 JSON必须包含 month格式 YYYY-MM、revenuedecimal、order_countint且 month 取值范围在 2023-01 到 2025-12 之间这类可以被程序判定的表述。不可校验的接口会带来三个连锁后果。其一无法自动重试系统不知道差多少算差因此无法判断重试是否有意义只能整体重跑成本翻倍。其二无法自动告警因为没有判定函数监控只能看到任务失败看不到哪条约束被违反。其三无法批量回归当 prompt 或模型升级后你无法构造一组断言来自动验证这次改动有没有让老问题复发。一个常见的误解是自然语言更灵活所以更好。在探索性阶段这没错但在已经被验证过的稳定链路上自然语言的灵活性恰恰是错误传播的载体。实践中的收敛路径是先用自然语言把任务跑通再把其中被反复证明重要的约束抽成 JSON Schema / Pydantic 模型最后把该 schema 作为交接的强制格式。这个过程本质上是把 prompt 工程逐步沉淀为接口工程。2.3 验证者与生成者同源确认偏差被放大最常见的做法是让同一个模型检查自己的输出。这在 LLM 上有三重偏差叠加self-preference bias偏好自己的措辞、确认偏差倾向于确认已有结论、以及上下文污染——如果 Reviewer 看到了 Coder 的推理过程它大概率会被那段推理说服而不是独立重算一遍。三重偏差的危害程度并不相同。self-preference bias 影响的是打分尺度它会让通过率整体偏高但不会系统性漏掉某一类错误。确认偏差影响的是证据搜索方向Reviewer 会去搜索支持产物正确的证据而不是尝试构造反例。上下文污染最危险它会把验证任务从独立计算降级为评价推理过程是否流畅——一段写得漂亮但前提错误的推理反而更容易通过审查。因此在设计验证环节时有三个正交的隔离维度值得同时使用模型隔离Reviewer 与 producer 使用不同模型或不同版本让偏差不相关。上下文隔离只给 Reviewer 验收标准和最终产物不给上游的自我辩解、推理链和我已经检查过了的声明。Prompt 隔离给 Reviewer 的指令不应是请检查是否正确而应是默认这个产物有缺陷请逐条给出能证伪它的证据只有当你在给定标准下找不到任何反例时才允许放行。后者的默认假设是有罪推定与前者的有罪推定缺失完全不同。2.4 错误在传递中衰减归因链断裂上游一个 5% 的字段名错误到下游可能变成表不存在的硬失败也可能被下游顺手修正而静默吞掉。前者暴露了问题但指错了方向后者更危险系统的行为与任何单个 Agent 的意图都不一致出了问题谁都不认。归因的前提是每一步都有不可篡改的输入输出快照和可复现证据。静默修正值得单独举例因为它几乎总是以善意的形式出现。Coder 输出了WHERE user_id ...而真实表里列名是uid。Executor 在生成执行计划时发现列名不存在于是智能地把它改写成了uid任务成功。表面上看这是一次成功的自适应但它埋下了两个隐患第一这条链路的成功依赖于 Executor 恰好执行了修正一旦 Executor 被换成严格模式或该 Agent 被下线同样的输入就会失败第二Coder 从这次运行中得不到任何负反馈错误会持续产生而系统的成功率看起来一直正常——直到某天环境变化所有被掩盖的错误同时爆发。因此归因链的建设必须包含三样东西每一步的输入输出快照不可被下游修改、贯穿全链路的 trace_id让一次失败可以按时间顺序回放、以及修正必须显式上报的约定下游可以修正但修正行为本身要成为一条可查询的事件而不是隐式副作用。没有这三样是谁的错永远只能靠翻聊天记录猜。三、把协作当带契约的状态机任务分配设计核心思路只有一句话把 Agent 之间的自然语言承诺压缩成机器可校验的结构化契约。不要让上游说我写好了 SQL而要让它交付一个包含产物、证据、前提假设、未知项的 Handoff 对象from__future__importannotationsfromdataclassesimportdataclassfromenumimportEnumfromtypingimportAnyclassStatus(str,Enum):DONEdone# 声称完成必须附证据PARTIALpartial# 部分完成必须写明未覆盖范围BLOCKEDblocked# 拒绝继续必须写明缺什么dataclassclassHandoff:task_id:strproducer:strclaim:str# 一句可被证伪的完成声明artifacts:dict[str,Any]# 产物SQL / 文件路径 / diffevidence:list[str]# 可复现证据命令 输出摘要assumptions:list[str]# 我依赖但没验证的前提unknowns:list[str]# 我明确不知道的部分status:Status confidence:float0.0关键字段是evidence和assumptions。evidence把我做了变成你可以自己验assumptions把隐性依赖显性化——假设一旦写出来就可以被下游定向检查也可以被归因。当下游失败时你能立刻判断是假设不成立还是实现有误而不是陷入互相指责。逐个字段看每个都有明确的工程意图claim要求可被证伪是为了防止已尽力完成这类无法反驳的表述。好的 claim 形如已生成 migration SQL覆盖 spec 中列出的 4 个字段。artifacts产物与声明分离允许声明完成但产物缺失被自动检出。evidence证据必须是可复现的命令加输出摘要而不是我运行过了。这是把 Agent 的自我报告降级为附录、把客观输出升级为凭据。assumptions显性化的隐性依赖是归因的关键。它同时充当了下游的检查清单。unknowns与 assumptions 互补——assumptions 是我以为成立unknowns 是我知道自己不掌握。confidence不是用来炫耀把握的而是用来触发不同处置策略高置信走自动链路低置信强制人工确认。配套的 gate 函数负责在交接点拦截不合格交付FATALFATALdefgate(h:Handoff,spec:dict)-list[str]:errors:list[str][]ifh.statusisStatus.BLOCKED:return[f{FATAL}: 上游拒绝继续缺输入 -{h.unknowns}]ifnoth.evidence:errors.append(f{FATAL}:{h.producer}无证据claim 不可证伪)ifh.statusisStatus.PARTIALandnoth.unknowns:errors.append(f{FATAL}: PARTIAL 但未声明未覆盖范围)# 契约层产物必须覆盖 spec 声明的必选字段forfield_nameinspec[required_artifacts]:iffield_namenotinh.artifacts:errors.append(f{FATAL}: 缺少产物{field_name})returnerrors这套设计带来一个直接效果我不知道变成了一个合法且被鼓励的输出。BLOCKED状态比硬着头皮猜一个便宜得多——后者才是错误传播的源头。在此基础上可以把 gate 扩展成一个真正的状态机守卫包含超时、重试与回退路由fromdataclassesimportdataclass,fielddataclassclassGatePolicy:max_retry:int2# 同一 producer 的重试上限防止死循环timeout_s:int300# 超时视为 BLOCKED交回上游on_exhausted:strescalate# 重试耗尽后的路由escalate / human / abortallow_silent_fix:boolFalse# 显式禁止静默修正dataclassclassGateResult:passed:boolroute:str# next / retry:agent / escalate / humanreasons:list[str]field(default_factorylist)defguarded_handoff(h:Handoff,spec:dict,policy:GatePolicy,retry_count:dict[str,int])-GateResult:errorsgate(h,spec)ifnoterrors:returnGateResult(passedTrue,routenext)# PARTIAL 的处置不同于 FATAL前者是补做后者是回退ifh.statusisStatus.PARTIALandall(e.startswith(FATAL: PARTIAL)foreinerrors):returnGateResult(passedFalse,routeretry:h.producer,reasonserrors)nretry_count.get(h.producer,0)ifnpolicy.max_retry:retry_count[h.producer]n1returnGateResult(passedFalse,routeretry:h.producer,reasonserrors)# 重试耗尽不再让同一个 producer 无限循环升级处理returnGateResult(passedFalse,routepolicy.on_exhausted,reasonserrors)这里有一条容易被忽略的原则重试必须有上限且上限必须绑定到具体 Agent。否则一个持续产出错误契约的 Coder 会把整条流水线拖入重试—拦截—再重试的活锁从甩锅演变为停滞。另一个常见误区是契约的粒度。契约过细Agent 会因为大量边界条件无法满足而频繁返回BLOCKED系统可用性下降契约过粗等于没有契约。经验做法是从验收标准反推必选字段先把什么样算完成写成可判定的条目再把这些条目映射成required_artifacts凡是无法映射到产物的验收条目不进入契约而是进入 L2 模型评审。四、独立验证从模型评审到分层 Gate只做契约检查还不够产物本身可能格式正确但内容错误。验证必须分层且确定性检查优先于模型评审。defverify_chain(spec,h:Handoff,artifact)-dict:# L1 确定性检查解析、schema 比对、dry-run成本最低、结论最硬parse_ok,parse_msgsqlglot_parse(artifact[sql])ifnotparse_ok:return{verdict:REJECT,layer:L1,reason:parse_msg}schema_diffcompare_schema(artifact[sql],load_schema(spec[table]))ifschema_diff:return{verdict:REJECT,layer:L1,reason:f引用不存在的列:{schema_diff}}# L2 对抗性盲审Reviewer 只看 spec artifact# 不接收 producer 的 reasoning避免被说服reviewllm_review(roleadversarial_reviewer,modelspec[reviewer_model],# 与 producer 异构payload{spec:spec[acceptance_criteria],artifact:artifact,assumptions:h.assumptions},instruction默认产物有缺陷逐条找出能证伪它的证据找不到再放行,)# L3 只有 L1/L2 冲突时才升级仲裁避免无谓成本ifreview[verdict]REJECT:returnarbitrate(spec,h,artifact,review)return{verdict:ACCEPT,layer:L2,notes:review[notes]}三个设计要点异构验证者。Reviewer 用不同模型、不同 prompt、不同上下文才能降低同源偏差。盲审。只给 Reviewer 结论性产物和验收标准不给上游的自我辩解。成本分层。语法解析几乎免费LLM 评审昂贵人工仲裁更贵。让便宜的先跑把预算集中在 L2/L3。把 L1 展开一个成熟的确定性检查清单通常包括语法/格式解析、schema 与列名比对、dry-run不落库的执行计划、权限检查、资源配额预估扫描行数、是否全表扫描、幂等性检查重复执行是否产生副作用、以及危险操作黑名单无 WHERE 的 UPDATE/DELETE、DDL 变更。这些检查的共同特征是结论确定、成本极低、可以批量回归因此应该尽可能多地放在 L1把 L2 留给真正需要语义判断的问题。L2 的关键在于结构化输出 证据绑定。不要接受 Reviewer 的通过/不通过单值结论而要让它输出形如{verdict: ..., counterexamples: [...], checked_items: [...]}的结构其中每条反对意见都必须引用产物中的具体位置。这样做有两个好处一是把主观判断逼成可复核的断言二是当 L2 结论后来被证明是误判时你可以用这些断言构造回归样本反过来评估 Reviewer 的召回率。L3 的成本最高因此升级条件必须收紧。合理的升级触发包括L1 与 L2 结论冲突、L2 置信度低于阈值、产物涉及高权限或不可逆操作、以及历史上同类产物曾出现过逃逸漏放。仲裁结果不应只解决当次任务还应当被回写成 L2 的对抗样本让下一次同类错误能在更便宜的层级被拦下——这是让验证体系随运行不断变强的唯一自然机制。还有一点常被忽略验证器本身也需要被验证。你可以准备一组已知错误样本故意把列名写错、故意漏掉必填字段、故意在边界条件上出错定期跑一遍 Reviewer统计它的召回率与误杀率。如果 Reviewer 对明显错误也给出通过那它不是验证者而是新的甩锅对象。五、实战一条会甩锅的 SQL 生成流水线场景Planner 解析需求 → Coder 生成迁移 SQL → Reviewer 审逻辑 → Executor 在预发库执行。改造前Planner 输出一段自然语言方案Coder 输出 SQL 代码块Reviewer 输出逻辑基本正确建议注意边界Executor 直接跑。典型失败是 SQL 引用了user_id而实际表里叫uid。Coder 说Planner 没给 schemaPlanner 说Retriever 给了表名Retriever 说我返回的是候选表列表。整条链路无人担责。改造后Retriever 的 Handoff 里evidence必须包含DESCRIBE table的真实输出unknowns列出未取到 schema 的表Coder 的assumptions必须写明假设表字段与 Retriever 快照一致且 SQL 必须通过sqlglot解析L1 用本地 schema 快照做列名比对不依赖 LLM 判断——字段名对不上直接 REJECT附上schema_diff作为归因证据只有 L1 通过才进入盲审Executor 只接受verdict ACCEPT的产物。效果不是Agent 变聪明了而是失败从最下游爆炸提前到了交接点被拦下且拦截理由是可复现的字符串。在多数团队的内测里这类改造的收益主要体现在返工成本和排障时间上而不是单次成功率——因为错误总量没变变的是错误被发现的时机和归因成本。把改造前后对照起来看差异会更清楚维度改造前改造后错误发现位置最下游执行时交接点L1/L2失败理由自然语言描述需人工复现结构化字符串可自动告警归因方式翻聊天记录、互相推断读assumptionsevidence重试策略整体重跑定点重试到具体 producer静默修正允许且不可见显式禁止或强制上报回归能力依赖人工经验契约 已知错误样本自动回归一个改造后的失败日志大致长这样它本身就是一份归因报告[gate] tasksql-8842 producercoder statusDONE [gate] L1 parseok [gate] L1 schema_diff[orders.uid not in snapshot, orders.created_at not in snapshot] [gate] routeretry:coder retry_count1 [gate] reason: 产物引用了快照中不存在的列疑似假设字段与快照一致不成立注意最后一行系统并没有说是 Coder 的错而是指出哪条假设不成立。这是契约化 handoff 最重要的产出——它把谁的错这个无法回答的问题替换成了哪条假设被推翻这个可验证的问题。前者引发争论后者直接指向修复动作。落地路径建议分三步走第一步只做 Handoff 契约和 L1 确定性检查先把字段名对不上这类硬错误拦住投入最小、收益最直接第二步在稳定链路上引入 L2 盲审并配套已知错误样本回归第三步再补 L3 仲裁与升级路由。反过来做——先上最贵的 LLM 评审——往往既贵又难评估效果因为缺乏 L1 提供的基线。六、踩坑与优化建议别让 Reviewer 兼任 Generator。更多硬核网安与AI工具包请扫码获取完整源码即使同一模型也要换 prompt、换上下文最好换模型。验证标准要来自需求方不能由 Generator 自己定义。自己定标准自己判卷等于没有验证。confidence字段不要当装饰。低置信度交付应触发强制人工确认而不是让它停留在 prompt 里自娱自乐。更实用的做法是把 confidence 映射到处置策略高于 0.8 走自动链路0.5 至 0.8 允许一次额外盲审低于 0.5 直接升级人工。禁止静默修正但允许显式回退。下游可以拒绝不符合契约的输入并请求重做但不应该顺手改一改然后继续。修正行为若必须发生也要作为事件落盘。不要用更长的 prompt解决协作问题。职责边界、验收标准、失败条件这三件事如果没有被结构化成数据写进 prompt 只会让模型更难判断优先级。警惕契约的过度设计。字段越多Agent 返回BLOCKED的概率越高。先加必选产物再逐步增加假设声明与证据要求观察拦截率是否合理。为归因链预留 trace_id。从 Planner 到 Executor 的每一次 handoff 都应携带同一个任务标识否则事后回放只能靠时间戳拼接容易错位。把 Reviewer 的拒收理由结构化。自然语言的这里有点问题无法统计、无法回归、也无法交给上游自动修复。控制升级成本。L3 仲裁和人工介入都要有预算上限否则系统在疑难任务上会被低频高成本的仲裁拖垮。不要只看端到端成功率。更有价值的指标是拦截率、误杀率、逃逸率、平均归因时间和重试次数分布。端到端成功率掩盖了错误何时被发现这一关键信息。**让我不知道有出口

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询