Skip to content

第14章 一个人做,还是一群人做——Multi-Agent ​

小a的 Agent 越来越忙,三个任务来回切换,顾此失彼。他修 bug 修到一半,想起还有功能没写;写功能写到一半,又记起文档没动。他实在忍不住了,去找老z。

“一个人忙不过来,多招几个兄弟总行吧?”他问。

“先别急着招人。”老z说,“Skill 能复用经验,却不会增加并行度。你那个‘同时交出去’的想法,我只有一个问题:这三件活,真的能独立吗?”

小a愣住了。他确实没想过这个问题。

本章讨论子代理、通信和编排的工程取舍;不把“多 Agent”视为能力更强的必然结论。

先把名字对齐 ​

中文术语英文全称或缩写本书工作定义不等于什么
子代理subagent被委派边界任务的独立执行者必然拥有独立权限
多 Agent 系统multi-agent system两个以上执行者通过任务或消息协作的系统自动更可靠的系统
编排器/控制面orchestrator/control plane分配、取消、汇总和观察任务的协调层最终质量保证人
任务所有权/共享状态task ownership/shared state谁可修改何物、哪些状态共同可见的契约一段共享长上下文

先判断是否值得拆分 ​

“那什么情况下,多 Agent 才真的值得?”小a问。

“多 Agent 有效的前提是任务能并行、交付物能明确合并、共享状态可控制。”老z说,“相反,若每一步都依赖前一步刚产生的判断,拆分只会增加协调回合和上下文复制。”

“为什么‘依赖前一步的判断’就是不能拆的信号?”小a问。

“因为判断不能并行。”老z说,“假设第二步的方案强依赖第一步的结论,第二步只能等第一步做完才能开始——所谓并行只是各自排队,收益为零,还多付了交接的成本。要判断一个任务能不能拆,就看拆开后每个子任务是不是‘拿到输入就能独立产出可核验结果’:是,才值得拆;不是,就还是串行更简单。”

“那合并的代价怎么估?”小a追问。

“合并是拆分的隐性成本,常常在最后才发现。”老z说,“三个子任务都产出了,汇总者要把三份输出合并成一份一致的结果——如果三份输出格式不同、口径不同、互相冲突,合并的功夫可能超过并行省下的时间。所以拆分前就该定义‘每一份输出长什么样、由谁合并、冲突时听谁的’,而不是等结果出来了再想办法。”

老z在纸上画了拆与不拆的两种走法:

text
不拆(串行):
  输入 ──> A步 ──> B步 ──> C步 ──> 结果       总时长 = A+B+C,零交接

拆(并行):
  输入 ──> A子任务 ──┐
              B子任务 ──┼─> 汇总/合并 ──> 结果   总时长 ≈ max(A,B,C) + 合并
              C子任务 ──┘

“串行的总时长是三步相加,但每一轮上下文都短、交接为零。”老z指着图说,“并行的总时长是‘最长的那一步加合并’——合并这格常常被忘记。如果三步里两步强依赖,max 就退化成三步相加,你还倒贴一次合并。拆不拆,比的就是‘省下的等待’和‘多付的合并’,不是比个数。”

情形更可能合适的选择原因
单一文件的小修复单 Agent交接成本高于并行收益
独立资料检索与测试设计并行子代理输出可独立核验
同一文件的大规模修改先划分所有权或顺序执行避免冲突和覆盖
高风险发布明确审批链不能把责任交给“投票”

“那多找几个 Agent 投票,结果会更可靠吗?”小a问。

“不必然。**它们可能共享同样的错误资料或提示,形成相关错误。**独立核验、不同证据源和明确的验收标准,比数量更重要。”

“等等,‘相关错误’是什么意思?它们不是独立的吗?”小a追问。

“并行执行,不等于错误独立。”老z说,“三个子代理读同一份过期文档,会得出三个一致的错误结论;你看到三票一致,反而更放心,这就是问题。要让投票真有意义,得让它们查不同的源、用不同的检索方式,甚至用不同的提示——否则你投的不是票,是同一份错误的回声。”

“那怎么判断我这三个子代理是不是‘真独立’?”小a问。

“一个粗糙的自检:去掉任意两个,剩下的那个还能不能独立得出可核验的结论?”老z说,“如果一个的产出只是把另一个的输出改了个格式,它们就不是独立执行者,而是同一条流水线上的两个工位——这时候你需要的不是并行,而是分工,下一节会讲。”

比喻:招人

多招人能不能加快进度,取决于活能不能拆开。活互相依赖,招再多也只是多了几张嘴在同一个文件上打架。

三种常见结构 ​

“那多 Agent 一般怎么组织?”小a问。

“常见有三种结构。”老z说:

  1. 委派式:主 Agent 分配边界明确的子任务,汇总结果并负责最终动作。
  2. 流水线式:一个角色产出供下一个角色检查或转换,适合依赖顺序清晰的流程。
  3. 竞争/复核式:多个执行者独立给出方案,再由独立标准或人工裁决。它消耗更多模型调用,不应默认使用。

“不管哪种结构,都要注意什么?”小a问。

“无论结构如何,都应让任务卡包含输入、允许的工具、文件所有权、输出格式、停止条件与验收方式。没有这些边界的‘协作’只是在转发模糊上下文。”

“这三种我怎么挑?”小a问。

“看任务之间是并行还是串行依赖。”老z说,“委派式的前提是子任务彼此独立,谁先完成不影响别人;流水线式的前提是后一步必须等前一步的产物,它换来的是每个角色上下文更短、更聚焦,而不是并行提速;竞争式只在‘正确性难判定、单人容易漏’时才值得那几倍的调用成本。把委派式套到强依赖的任务上,你会得到一堆互相等待的子任务和一份空转的账单。”

“三种结构的代价能放一张表里比吗?”小a问。

结构前提换来的好处付掉的代价最常见的失效
委派式子任务彼此独立并行提速、职责清晰汇总和合并成本子任务看似独立实则共享同一份输出
流水线式后一步依赖前一步产物每步上下文短、聚焦串行等待、交接偏差交接时把结论和过程一起打包转发
竞争/复核式正确性难判定、单人易漏减少单一视角盲区成倍的模型调用参与者共享资料,产出相关错误

“这张表的第三列和第四列是对着长的。”老z说,“每一样好处都对应一样代价。挑选结构不是选‘听起来高级’的那个,是确认‘代价付得起、失效可发现’的那个。竞争式如果付不起调用成本,它带来的‘更可靠’就是假象。”

“那我那个 bug 修复属于哪种?”小a问。

“典型流水线:检索证据 → 改代码 → 跑验证。”老z说,“但前提是你能把‘检索’和‘改代码’的责任边界划清。如果检索者连改哪里都给不出建议、改代码的人又得回头自己重新查一遍,那这一步其实是伪装成两步的一步,不如交给单个 Agent 一次做完。”

“那任务卡里的‘停止条件’具体写什么?”小a追问。

“写明子代理什么时候该停、停下来时交什么。”老z说,“比如检索者的停止条件是‘找到定义点或查满五份来源’,交出的是‘函数位置和签名’而不是它读过的全部网页;验证者的停止条件是‘跑完指定用例集’,交出的是‘通过/失败清单和失败用例的可复现命令’。停止条件越模糊,子代理就越倾向于把上下文一股脑搬回来,汇总者还得再筛一遍。”

“那任务卡里的‘文件所有权’为什么单独列一项?”小a问。

“因为所有权是冲突的源头。”老z说,“一个文件被两个子代理同时声明‘我负责’,写起来就是竞态;没有被任何子代理声明的文件,改错了没人认账。所有权要能回答‘这个文件此刻归谁管’,并且和权限一致——只读角色不能拥有可写文件。所有权声明错,后面所有的冲突裁决都跟着错。”

通信、状态与隔离 ​

“那它们之间怎么‘说话’?”小a问。

“消息应尽量传递结论、证据位置和未决问题,而不是整段隐藏推理。”老z说,“共享文件、共享会话和共享凭据会让并行变成竞争:需要锁、分支、工作区隔离或只读副本。”

“为什么不直接共享上下文,反而省事?”小a问。

“因为‘省事’的代价是污染。”老z说,“一个检索子代理的上下文里塞满了网页片段,如果原样转给修改者,修改者就得在一堆无关检索结果里找自己要改的那行。结论式消息——‘函数 X 在文件 Y 第 200 行,签名是 Z’——只搬结论,不搬过程,下游上下文才不会被撑大或带偏。”

“好消息和坏消息,各长什么样?”小a问。

“好消息是短而可核验。”老z说,“‘支付函数在 payments.py 第 40 行,签名是 pay(amount, currency),调用方在 orders.py 第 12 行,未发现其他引用’——每一句都能在源码里查到。坏消息是把三份检索结果整段贴给下游:‘我读了 A 网页、B 文档、C 论坛,它们大概是这样说的……’——句子不能单独核验,还夹带了一大堆来源判断。传递的每一句都应该问:接收方能独立验证它吗?不能,就说明消息里混进了不该传的过程和观点。”

“那‘共享状态’到底指什么?共享文件算吗?”小a问。

“算,而且共享状态不只有共享文件一种。”老z说,“共享文件、共享会话、共享数据库、共享配置——凡是两个执行者都会读写的同一份状态都算。它们各自的冲突模式不一样:共享文件是互相覆盖,共享会话是互相插入无关内容,共享数据库是同时写入同一行。每种共享状态都需要对应的控制手段,不能说‘我们共用同一个工作区’就自动安全。”

“那不同共享状态的冲突,各长什么样?”小a追问。

老z列了一张表:

共享状态冲突的样子控制手段代价
共享文件两个子代理同时写同一文件,互相覆盖文件所有权、锁、分支工作区串行化等待或合并裁决
共享会话一个子代理的消息混进另一个的上下文会话隔离、消息归属任务 ID上下文复制成本
共享数据库同时写同一行、读到未提交的改动事务、版本号、只读副本锁和重试开销
共享配置一方改了配置,另一方还在用旧值配置快照、版本化、变更通知同步复杂度

“这些控制的共同点:把‘并发自由写’换成‘显式的所有权或串行化’。”老z说,“前者出问题时你找不到是谁写的,后者至少能追到是谁、什么时候、基于哪个版本。共享状态可以存在,但必须有一条‘谁有权改、改了谁知道’的规则,不能靠大家默契。”

“隔离工作区会不会很贵?”小a问。

“贵,但贵在一次性设置。”老z说,“建独立工作区、配各自权限、挂只读快照,这些是一次性成本;它换来的好处——一个子代理不会覆盖另一个的产物、不会读到别人的中间状态——是每次运行都在生效的。设置成本高、运行成本低,这正是值得付的样子;反过来,设置便宜、每次运行都在互相打架,那才真贵。”

“权限呢?”小a问。

“权限也应随角色缩小。检索任务不需要写文件,测试任务不需要发布凭据。”老z说,“子代理的工具调用、成本和失败必须能归属到任务 ID,主 Agent 才能在超时、冲突或异常外发时停止它。”

“给每个子代理都发一套自己的凭据,太麻烦了吧?”小a问。

“麻烦,但比起共用一份高权限令牌更可控。”老z说,“共用意味着任何一个子代理被诱导外发,整套凭据就泄了;按角色发受限令牌,单个泄露只伤到那个角色的范围。这不是‘方便不方便’,是‘一个失败能扩到多大’。”

“那隔离只指凭据吗?”小a问。

“不止。隔离分三面:文件、凭据、网络。”老z说,“文件隔离是每个子代理只有自己的工作区或只读快照;凭据隔离是每个角色只持有自己那份令牌;网络隔离是每个子代理的外发目的地单独受限。三面各管一类泄露面,只有都写了才算隔离——只隔离文件、凭据还是共用的,一个被诱导就能把别人的令牌一起带出去。”

“那隔离的程度怎么定?”小a追问。

“按角色的风险定。”老z说,“只读检索角色风险低,隔离可以薄——只读快照加无网络就够了;持有发布凭据的角色风险高,隔离要厚——独立凭据、独立网络、逐次审批。隔离不是平均分配的,是跟着‘泄了伤多大’走:伤得越重的角色,笼子越厚。”

成本不是附带问题 ​

“多 Agent 是不是更费钱?”小a问。

“是。每个子代理都可能产生上下文、工具调用和重试。并行降低墙钟时间,不保证降低总成本;汇总者还需要判断冲突输出。”老z说,“实践上先测量单 Agent 的失败点,再只为可验证的瓶颈增加并发,通常比先搭‘团队’更稳。”

“怎么‘测量失败点’?”小a问。

“先让单 Agent 跑真实任务,记三件事:哪一步最慢、哪一步最容易失败、哪一步输出最容易被下游推翻。”老z说,“如果最慢的那一步是‘读三份大文档’,它就是并行能真省时间的候选;如果最失败的是一步需要全局判断的决策,把它拆出去只会放大错误——几个子代理各自拿局部信息,做出来的决策反而更差。瓶颈能被测量,才值得为它加并发;说不清瓶颈在哪,加的每个子代理都是猜。”

“那‘并行省时间’这话到底是真还是假?”小a追问。

“墙钟时间经常省,总 token 一定不省。”老z说,“三个并行子任务,三个独立上下文,加上汇总者还得读三份输出做合并——总调用数和总 token 都比单 Agent 跑一遍高。省的是你等待的那段时间,付的是更多的模型调用。如果你的瓶颈是‘等不起’而不是‘算不起’,并行值得;如果是‘算不起’,并行反而更糟。”

“那有没有办法把这部分成本也降下来?”小a问。

“只让真正并行的部分并行。”老z说,“把强依赖的步骤收回到主 Agent,只把确实能并行的子任务——比如检索几份不相干的资料——拆出去。每多一个子代理就多一份上下文复制和一次汇总,不是免费的。”

“那成本能归属到每个子代理吗?”小a问。

“必须能。每个子任务的 token、调用次数和耗时都要挂在它的任务 ID 上。”老z说,“没有按任务归集的成本,你只能看到‘总额涨了’,说不出是哪一个子代理烧的、哪一类动作最贵——也就没法决定下一步砍谁。成本归属和状态回传是同一份数据的两面:一张任务表,既看进度,也看账。”

“那有没有反过来的情况,单 Agent 反而更贵?”小a追问。

“有,瓶颈在等待外部资源时。”老z说,“比如要查三份不相干的大型文档,单 Agent 串行查要等三次 I/O;并行三个子代理同时查,墙钟时间压到最长的那一份。这里省的是等待,付的是三份独立上下文——如果单 Agent 的等待本身就贵过那点上下文成本,并行就值。判断标准始终是‘瓶颈在哪’,不是‘多就是好’。”

“能不能给成本列一个对照?”小a问。

“可以,用同一个任务分别跑两种方案,看三类账。”老z说,

账目单 Agent并行子代理差值来源
模型调用次数1 次主循环3 次子循环 + 1 次汇总汇总和每份独立子上下文
总 token一份完整上下文链三份独立上下文 + 汇总读取上下文复制和重复资料
墙钟时间A+B+C 串行max(A,B,C) + 汇总省在等待,付在合并
重试次数失败才重试每份子上下文都可能重试失败率随调用数上升

“对照表不是让你背数字,是提醒你三件事。”老z说,“一是总成本几乎总在涨,能接受的涨法才有意义;二是重试不是免费的,调用数一多,单个子代理的偶发失败就变成高概率事件;三是只有‘墙钟时间’这一行可能下降。先把这三行记下来,再谈并行值不值。”

控制面与失败传播 ​

“那谁负责‘叫停’?”小a问。

“多 Agent 需要一个控制面维护任务状态、预算、权限和取消,而不是只靠执行者互发文本。”老z说,“示意: 调研任务超时后,控制面取消其后续网络调用,将‘证据不足’交给汇总者;汇总者不能把超时当作支持结论。子任务失败可以隔离为局部结果,也可以阻塞整体交付,取决于任务卡是否把它列为必要依赖。隔离工作区和凭据会增加设置成本,却能避免一个子任务覆盖另一个的产物。”

“为什么不直接让子代理之间互相喊停?”小a问。

“因为执行者没有全局视角。”老z说,“一个子代理只知道自己超时了,不知道这次取消是‘局部降级’还是‘整个任务终止’;如果靠它去通知下游,下游又该信到什么程度?控制面是唯一掌握预算、任务树和所有权的一方,由它发取消,所有子任务才有一致的停止语义。”

“那控制面自己怎么知道‘现在进行到哪了’?”小a追问。

“靠每个子代理回传的状态。”老z说,“任务卡里要写明每完成一步回传什么:进行中、已完成、已失败、等待外部输入。控制面把这四类状态挂在任务树上,它才能回答‘谁在等、谁在跑、谁超了预算’。如果子代理不回传状态,控制面只能凭超时猜——那它就不是控制面,只是挂钟。”

“那取消是立刻生效,还是有延迟?”小a追问。

“通常是尽力而为,不是瞬间。”老z说,“子代理可能正卡在一个工具调用里,控制面只能等到它回到循环边界才能让它看到取消信号。所以任务卡里必须写明‘取消后如何安全收尾’:正在写的文件是丢弃还是落盘、已经发出的网络请求无法收回。把取消当瞬时操作来设计,会在长任务里留下半成品。”

“那子任务失败,会不会连累整个任务?”小a问。

“取决于任务卡怎么声明依赖。”老z说,“同一个失败,可能是局部降级,也可能是整体终止。检索超时如果只是‘少一份参考’,可以降级继续;如果这份检索是后续所有决策的输入,就必须终止或换路。失败模式也要写进任务卡,和停止条件一样明确——不写清楚,子代理失败时控制面就只能猜。”

“失败的传播方式有哪几种?”小a追问。

“三种典型。”老z画了一张图:

text
失败 ──> ① 隔离:只降级该子任务的产出,其他照常
         │       例:检索超时,标记"证据不足"继续
         ├──> ② 阻塞:等待该子任务或改由主控接管
         │       例:流水线中间一步失败,下游全部等待
         └──> ③ 终止:传播取消,整体收尾
                 例:主控判断该失败不可恢复,取消全部

“三种不是任选的,是任务卡预先声明的。”老z说,“①适合‘少了也能干活’的旁路,③适合‘一条线断整体停’的核心路径,②是最容易拖出死锁的——下游一直等着,谁也没叫停。所以每个子任务都要标注‘失败后属于哪一类’,控制面按声明执行,而不是现场发挥。”

协作不是共享一段长上下文 ​

“能不能把完整场景串一遍?”小a问。

“常见拓扑包括主控委派、流水线交接和独立复核。无论哪种,任务所有者必须负责最终合并;子任务应传递结论、证据位置和未决问题,而不是要求接收者相信完整隐藏推理。”老z说,“共享状态采用只读快照、明确文件所有权或串行写入;两个执行者同时改同一文件不是‘并行’,而是竞争。”

“主控委派的拓扑画出来是什么样?”小a问。

“以那个修复缺陷的贯穿场景为例。”老z画了一张图:

text
                    ┌─────────────┐
                    │   主控 Agent   │ 分配/汇总/验收
                    └──────┬──────┘
           ┌───────────────┼───────────────┐
           ↓               ↓               ↓
     ┌──────────┐    ┌──────────┐    ┌──────────┐
     │  检索者   │    │  修改者   │    │  验证者   │
     │ 只读+检索  │    │ 拥有目标模块 │    │ 拥有测试目录 │
     │ 输出:证据位置│    │ 输出:改动+说明 │    │ 输出:通过/失败 │
     └──────────┘    └──────────┘    └──────────┘
        只读快照          可写副本            只读

“三个子任务里只有修改者是可写副本,另外两个是只读。”老z指着图说,“主控拿回三份结论——证据位置、改动说明、测试结果——自己合并,跑验收。这张图回答了两件事:谁拥有什么、谁负责最后一步。拓扑画不出来,说明边界还没想清楚,就别开工。”

“举个例子?”小a问。

“贯穿场景:修复缺陷时,检索者只读代码和文档,验证者拥有测试目录,修改者拥有目标模块,主控合并并运行验收。”老z说,“正常路径是各自产出可核验证据;失败路径一是检索超时,主控降级为单 Agent 或终止;二是修改与验证结论冲突,按测试和源码证据裁决;三是主控取消,向所有子任务传播取消并等待已开始写入的安全收尾。”

“每个子代理的任务卡,能不能给我看一份?”小a问。

“以验证者为例。”老z写了一段:

text
角色:验证者
输入:修改者改动的文件列表 + 变更说明
允许工具:read、run_test(无写文件、无网络、无发布)
文件所有权:测试目录(只读),无任何可写文件
输出格式:通过/失败清单,失败用例附可复现命令
停止条件:跑完指定用例集
失败模式:测试基础设施不可用 → 报告"无法验证",由主控裁决
验收方式:主控重跑一次关键用例核对

“这份卡把刚才讲的那些边界——输入、工具、所有权、停止条件、失败模式、验收——变成了可检查的字段。”老z说,“读它的人——无论是一个子代理还是你——都知道它该做什么、能碰什么、什么时候停、失败了算哪一类。任务卡不是文档装饰,它是多 Agent 系统里最小的契约单位。没有卡,‘协作’就是在转发模糊上下文。”

“那投票能解决‘它们一起错’吗?”小a问。

“不能。多个 Agent 从同一错误资料得出相同错误结论是相关错误,投票不能解决;并行还会增加总 token、协调延迟和上下文复制成本。”老z说,“步骤强依赖、风险不可隔离或合并无明确规则时不应拆分。”

“那‘不该用多 Agent’的情况,能不能列一张表?”小a追问。

“能,而且这张表比‘什么时候该用’更重要。”老z列了一张:

信号为什么不该拆单 Agent 更合适的做法
每一步都依赖上一步的判断并行收益为零,只剩协调成本一个 Agent 串行跑完整条链
合并规则说不清冲突裁决会退化成谁嗓门大单个 Agent 保有一致视角
子代理会共享同一份资料产出相关错误,并行等于放大单 Agent + 明确验收标准
风险无法按角色隔离任一子代理泄露等于全员泄露收紧权限,不做并发
任务本身没有验收标准谁都不知道算不算做完先定义验收,再谈拆分

“这张表的信号,在单 Agent 里都不存在。”老z说,“依赖顺序天然满足,不需要合并,不会有两个执行者争状态。所以判断的顺序是:先看这张表有没有命中——命中任何一条就别拆;全没命中,再看并行省下的等待值不值多付的成本。”

“那遇到‘修改和验证冲突’,主控凭什么裁决?”小a追问。

“凭可复现的证据,不凭谁更笃定。”老z说,“测试目录的失败用例是可复现的——重跑一遍要么过要么不过;修改者的论断则可能只是‘我觉得这样改是对的’。主控偏向可复现的一方,把另一方的结论降级为待证。如果两边都不可复现——比如都只是自然语言断言——那这个任务本身就还没到能拆给多 Agent 的程度,先回去把验收标准补出来。”

“那‘只读快照’和‘分支工作区’有什么区别?”小a问。

“快照是只读副本:子代理看到的是某时刻的状态,不能改原文件,适合检索、分析这类只读任务。”老z说,“分支工作区是可写副本:子代理改的是自己的副本,主控再决定如何合并回主线。区别在于合并代价——只读快照没有合并问题,可写副本需要主控处理冲突。所以‘让每个子代理都有自己的工作区’不是免费的,它把冲突从‘运行时互相覆盖’挪到了‘合并时由主控裁决’,至少后者是显式的。”

要点

多 Agent 是并发与分工工具,不是自动增智。独立性、合并方式、隔离和验收——四样缺一样,单 Agent 更可控。

小结 ​

多 Agent 是并发的工具,不是增智的法术。它的价值在于把一个大任务拆成几个可以同时推进的子任务,从而缩短总时间——但这只在子任务彼此独立时才成立。判断要不要上多 Agent,要回答四个问题:任务之间是否真正独立,一个的输出不依赖另一个的输出;各自的产出能否无冲突地合并;失败时能否定位到是哪个执行者的责任;每个执行者的权限和隔离边界是否清晰。这四个条件里只要有任何一个答不上来,多 Agent 带来的就不是效率,而是更难调试的偶发 bug 和更模糊的责任归属。

增加执行者不会提升单个执行者的智力,只会增加协调的复杂度。两个 Agent 同时改同一个文件,合并冲突需要有人裁决;一个 Agent 改了配置,另一个还在用旧配置做决策,这个错误归属到谁。这些都是单 Agent 不会遇到、却因引入多 Agent 而出现的问题。把单 Agent 作为默认选择,只在独立性、可合并性和可归属性都被验证之后,才把并行用在实际能并行的部分。

多 Agent 的三种结构——委派、流水线、竞争——各有各的前提和代价。委派换并行提速、付汇总成本;流水线换上下文聚焦、付串行等待;竞争换视角多样性、付成倍调用。三种结构里,最常见的失效都不是模型变笨,而是边界没划清:子任务看似独立实则共享同一份输出,交接时把结论和过程打包转发,参与者共享资料产出相关错误。任务卡是把边界写成字段的唯一办法——输入、允许工具、文件所有权、输出格式、停止条件、失败模式、验收方式,每一项都可检查、可归属、可审计。

控制面是唯一掌握全局的一方:预算、任务树、所有权和取消都归它管。失败会以三种方式传播——隔离、阻塞、终止——每种都要写进任务卡,不能现场发挥;取消是尽力而为,不是瞬时,任务卡必须写明取消后如何安全收尾。沟通上只传递可核验的结论、证据位置和未决问题,不搬整段推理;共享状态靠只读快照、文件所有权或串行写入控制,不能靠默契。多 Agent 不是单 Agent 的加强版,而是一套额外的工程系统——协调成本、合并规则、隔离边界、失败语义,每一项都要显式设计,缺一项,单 Agent 更可控。

动手核验 ​

  1. 把一个任务拆成两个可并行子任务,并为每个子任务写输入、文件所有权、权限和验收条件。
  2. 设计一次输出冲突:两个子代理对同一结论不同意,明确谁用什么证据裁决。
  3. 记录单 Agent 与两个子代理的调用次数、耗时和返工次数,再判断并行是否值得。
  4. 给一个子代理设置超时,观察控制面的取消是立刻生效还是要等它回到循环边界,并记录这段时间内它是否还在写文件。