框架与协议迁移
18

多 Agent 实际协作:并行取证、结果汇总与失败转人工

把“制度检索、订单核验、风险判断”分别交给三个 Agent,再由一个协调器汇总,表面上很容易显得更智能。放进生产后,每次交接都会增加模型调用、Token、延迟和失败点,责任反而可能更模糊。

是否拆成多 Agent,要看子任务能不能独立验收、工具或权限是否真的需要隔离,以及收益能否覆盖交接成本。事实不足、动作需要主观授权或风险无法自动承担时,正确的下一步通常是等待人工,而不是继续增加 Agent。

配套代码先用 CollaborationPolicy 决定是否拆分,再由 MultiAgentCoordinator 并行调用两个真实 AgentScope 专家。制度 Agent 只能查询退款政策,工单 Agent 只能读取工单;两者都成功后,第三个 Agent 才能汇总。任一专家失败或超时,协调器跳过汇总并返回 HUMAN_REQUIRED。

三种编排方式对应不同责任结构

第一种是单 Agent:一个模型上下文持有目标、状态和工具,适合步骤少、责任一致、上下文高度共享的任务。

第二种是多 Agent:多个执行单元各自拥有角色、工具或上下文,通过明确协议交接。它适合相对独立的子任务,不适合把同一问题重复问三遍再投票。

第三种是人工介入:系统暂停自动执行,由有权限的人确认、补充事实、选择分支或接管。人工介入不是出现异常后才展示的一句“转人工”提示,而是状态机中的正式步骤。

两个专家并行取证,成功后汇总,失败则转人工

选择顺序应从最简单的结构开始。确定性代码能解决,就不用 Agent;一个 Agent 能在受控工具内完成,就不要拆分。只有拆分后能证明质量、吞吐或责任边界改善,才采用多 Agent。风险或事实无法由机器判断时,进入人工。

拆分多 Agent 的三个前提

拆分前先检查三个前提:

前提 判断方法
子任务可以独立验收 例如工单处理包含“检索制度”“核验订单状态”“形成回复建议”。三项都有明确输入输出、可以分别超时和重试,才具备拆分基础;若每一步都依赖上一段完整自然语言思考,拆开只会丢上下文
工具或权限需要隔离 知识 Agent 只能读制度文档,订单 Agent 只能查低敏订单状态,执行 Agent 才能申请写操作。不同身份和工具目录能形成真实安全边界,仅仅使用不同 System Prompt 不构成权限隔离
交接成本小于收益 每次交接都会增加序列化、模型调用、Token、延迟、失败点和观测成本。只有并行缩短关键路径、专业上下文明显改善质量,或责任隔离降低风险,收益才可能覆盖成本

一个适合拆分的工单调查场景

配套入口采用一个边界清楚的工单调查场景:

协调器创建任务
├─ 制度 Agent:调用 query_refund_policy 读取到账规则
└─ 工单 Agent:调用 query_ticket 读取 T-100 状态
汇总器接收结构化结果
-> 生成建议
-> 必要时请求人工确认

两个子任务并行执行,各自有独立 Toolkit、权限、RuntimeContext 和超时。协调器不共享数据库,不复制客户完整资料,只发送同一个最小问题。某个专家失败时,汇总器不会被调用,任务直接进入人工,而不是让另一个 Agent 猜测。

另一类场景是跨团队或跨系统的长任务。例如研发变更评审中,代码安全、依赖许可和发布风险由不同服务负责。它们本来就有独立 owner、SLA(服务级别协议)和审计,多 Agent 协议只是把现有责任边界接起来。

这些场景保留单 Agent 更清楚

  • 一个问答只需一次检索和一次生成;
  • 把计划、执行、反思机械拆成三个角色,却共享同一模型和全部工具;
  • 子 Agent 输出没有 Schema,只传大段自然语言;
  • 所有 Agent 都能调用高风险写工具;
  • 通过“多数票”决定退款、权限或合规动作;
  • 任务必须严格顺序执行,拆分后不能并行;
  • 没有单 Agent 基线,无法证明复杂度带来收益。

所谓 Reviewer Agent 也要谨慎。如果 Reviewer 使用同一模型、同一上下文和同一错误信息,它可能稳定重复原错误。高风险验证更适合确定性规则、独立数据源、不同权限的服务或人工复核。

人工介入承担四类职责

人工介入不能统一成一个“确认”按钮。

第一类是授权:系统已经形成明确动作,请有权限的人批准或拒绝,例如退款、状态变更、外发邮件。

第二类是补充事实:系统缺少订单号、客户关系或异常说明,需要用户提供输入后继续。

第三类是选择分支:多个方案都合法,但涉及业务偏好,例如选择补偿方式或处理队列。

第四类是接管:模型或工具连续失败、发现冲突、涉及投诉升级,自动任务终止,由人工继续处理。

不同职责对应不同状态、界面和审计。把“请确认”同时用于补信息和高风险授权,会让用户不知道自己承担了什么责任。

把人工等待建模为正式状态

人工介入从事件到确认单再回到任务

AgentScope 的 RequireUserConfirmEvent 可以表达 Runtime 需要确认。当前 CollaborationPolicy 只生成一个确认事件,测试也只检查事件类型。这个事件没有绑定 taskId、actionId 或规范化参数,因此还不是可直接展示给用户的业务确认单。正式链路还要完成:

Runtime 发出确认需求
-> 应用服务生成 Confirmation
-> 前端展示动作、原因、影响和有效期
-> 用户批准或拒绝
-> 服务端重新校验身份与业务状态
-> 执行动作或关闭分支
-> Runtime 接收稳定结果继续/结束

业务确认单必须绑定 taskId、actionId、规范化参数哈希、申请人、所需角色、策略版本和过期时间。用户点击后由服务端校验,不能让前端提交一份可修改的动作 JSON。

超时、拒绝和撤回都是正式结果。任务状态应能表达 WAITING_FOR_INPUT、WAITING_FOR_CONFIRMATION、REJECTED、EXPIRED 和 HUMAN_TAKEOVER,不能长期停在 RUNNING。

协调器只负责拆分与汇总

多 Agent 需要协调,但协调器的职责应尽量确定:创建子任务、分发最小上下文、等待结果、执行超时策略、校验返回 Schema、汇总证据和推进状态。

如果协调器还可以任意改写子任务、选择全部工具、修改权限并决定高风险动作,它就变成更难控制的超级 Agent。生产中可以让模型帮助形成计划,但服务端必须把计划编译成允许的 WorkUnit,并限制依赖和副作用。

代码用 WorkUnit 记录两个关键属性:是否独立、是否有副作用。CollaborationPolicy 根据这两个属性选择单 Agent、多 Agent 或人工确认,不让模型自己决定是否需要监管。选中多 Agent 后,MultiAgentCoordinator 才会并行运行至少两个专家,并在所有必要结果到齐后调用汇总器。

示意规则是:

存在副作用              -> HUMAN_REQUIRED
多个独立只读工作单元    -> MULTI_AGENT
其他情况                -> SINGLE_AGENT

实际策略还会加入数据分级、工具风险、任务时限、成本预算和资料完整性,但最终选择仍由服务端规则决定。

Agent 之间传递结构化工作单元

Agent 之间的交接数据应结构化、最小化并带有版本。一个调查结果可以定义:

{
  "workUnitId": "policy-check-1",
  "status": "COMPLETED",
  "facts": [],
  "citations": [],
  "riskFlags": [],
  "confidence": "INSUFFICIENT_EVIDENCE"
}

不要传完整思维过程,也不要把上游 Agent 的自然语言当作下游系统指令。下游只消费声明过的字段,并重新检查引用、tenant 和来源。外部 Agent 返回的内容与普通第三方输入一样不可信。

交接还要记录 producer、schemaVersion、taskId、traceId 和生成时间。过期结果、错误任务结果和未知 Schema 应拒绝进入汇总。

每个 Agent 只接收所需上下文

拆成多 Agent 后,不应把原会话完整复制给每个子任务。制度 Agent 只需要规范化问题、tenant 可见范围和有效时间;订单 Agent 只需要订单标识与受信身份;风险 Agent 只接收完成判断所需的低敏事实。最小上下文既减少 Token,也降低横向数据扩散。

子 Agent 如果需要更多信息,应通过声明过的输入请求返回协调器,由协调器检查是否允许补充。不能允许它自行遍历其他 Agent 的 Memory、读取共享文件目录或查询不属于当前任务的数据。

Memory 也应按任务和角色隔离。长期用户偏好可以由应用层筛选后提供,不能把一个 Agent 写入的自然语言记忆自动视为另一个 Agent 的可信事实。共享事实最好来自版本化业务记录,或者带来源的结构化 artifact(任务产物)。

拆分前确定预算与部分失败策略

三个 Agent 并行不代表成本只有一次。每个 Agent 可能多轮调用模型和工具,汇总器还要再次生成。任务创建时应分配模型调用数、Token、工具调用数、最大并发和截止时间,并由协调器累计。

预算耗尽后的行为要预先定义:返回已有资料、降级为单 Agent、请求人工,还是终止。不要让模型自己决定继续“再调查一步”。对高峰流量,子任务队列还需按 tenant 和任务类型限流,避免一次复杂调查占满全部模型与下游连接。

并行任务的 p95 通常受最慢的关键子任务主导,也会受子任务耗时分布和相关性影响。拆分前应画出依赖图,只有位于同一并行层且没有副作用依赖的 WorkUnit 才一起执行。为了展示多 Agent 而并行查询同一数据库,往往只会制造连接池尖峰。

预算之外,协调器还要在创建任务前确定部分失败怎样处理。并行任务经常出现两个成功、一个超时,此时要明确是全部成功才继续、允许缺少非关键结果,还是超时后转人工。

不能让模型临时判断“这个结果大概不重要”。关键性属于业务配置。若制度条款缺失,工单回复不能给确定承诺;若一个辅助分类失败,可能仍可继续但要标记质量降级。

取消也要向子任务传播,但已经产生的远程副作用不能假装回滚。每个子任务应声明只读或写、是否可取消、是否有补偿动作。协调器只做协议层协调,业务补偿由对应服务拥有。

用质量、成本和恢复能力判断收益

至少建立单 Agent 基线,再比较:

  • 端到端任务成功率;
  • 关键事实和引用完整率;
  • 高风险误执行次数;
  • p50/p95 时延;
  • 模型与工具调用数;
  • Token 和单任务成本;
  • 人工介入率与平均处理时间;
  • 部分失败后的可恢复率。

多 Agent 如果只提高了回答长度,却让成本翻倍、错误更难定位,就不值得上线。对部分场景有效时,按能力或任务复杂度路由,不必把所有请求统一迁移。

把成功与失败两条路径都跑一遍

在项目根 config/application-default.yml 填好统一的 OpenAI 兼容配置后,运行 MultiAgentCollaborationApplication。这条在线路径会真实调用三个 ReActAgent:两个专家并行调用各自 Tool,汇总 Agent 只消费专家结果。控制台会打印 decision=MULTI_AGENT、status=COMPLETED、两份专家结果和最终回答。

再运行 MultiAgentFailureApplication。它用确定性专家制造工单服务不可用,不消耗模型 Token;控制台应打印 status=HUMAN_REQUIRED,而预设的汇总答案永远不会出现。这条补充路径证明失败短路由协调器控制,不依赖模型是否愿意“谨慎回答”。

CollaborationPolicy 仍负责拆分前决策:依赖上下文的只读单元保留单 Agent,多个独立只读单元才拆分,带副作用的工作单元返回 RequireUserConfirmEvent。

演示结果用 SpecialistResult 包装名称、答案或错误。接入跨服务 Agent 时,再扩展 taskId、schemaVersion、引用和身份委托,并补持久任务、消息投递、观测与人工工作台。

多 Agent 不是 Agent 能力成熟度的标志。生产系统要明确什么时候不拆、什么时候停下来等人,以及每次交接由谁负责。当协作单元需要访问远程企业工具时,工具发现与调用协议必须同时受本地白名单和权限策略控制;MCP 只统一协议,不替业务系统完成授权。

搜索全部 52 篇文章。

查看配图