news 2026/10/11 3:41:44

多Agent协作别靠群聊:边界、状态与结果汇聚的工程框架

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
多Agent协作别靠群聊:边界、状态与结果汇聚的工程框架

我接手过不少多智能体协作的项目,最近踩的坑尤其典型。企业内部有个自动化场景,总共四个 Agent 参与:客服工单接入、粗分类、方案推荐、用户回访话术起草。第一版设计图省事,直接把四个 Agent 拉进一个虚拟讨论组,让它们自由发言,谁有想法就说一句,看起来特别前沿。实际跑了不到一周,工单处理时长的中位数涨了将近一倍,有的工单被两个 Agent 重复认领,还有的工单因为中间有人反问一句就卡住了。最后团队成员看到 Agent 在群里互相 @,第一反应不是觉得智能,而是心里发毛:这活儿到底听谁的?

后来我才彻底想明白一句话:多 Agent 不该在群里开会。企业任务里的协作,依赖的不是自由讨论,而是边界、状态和汇聚结果这三件套。这篇文章就是从这次的教训出发,给同样在搞多 Agent 系统的朋友捋一套可以直接落地的协作框架,重点聊聊每个 Agent 的职责边界怎么划、状态怎么同步、结果怎么汇聚,适合正在设计多智能体任务编排、或者考虑把 Agent 接入业务流程的团队参考。

1. 问题先摆出来:多 Agent 开会为什么越来越乱

1.1 我差点被“让 Agent 们拉个群聊”的方案坑了

最开始接到这个任务时,需求方其实讲得挺模糊:希望工单进来之后,多个智能体各自处理一部分,最后自动生成处理建议。我一开始想到的方案很自然:给每个 Agent 一个发言窗口,让它们围绕工单内容“讨论”出结论。为了让 Agent 之间互相理解,我甚至在系统提示词里写了一句话:你可以看到其他人的发言,需要时可以直接回复。

听起来像是一个大人际场面的线上会议室,对吧?实际上跑起来完全不是那么回事。几个 Agent 不会像人一样遵守发言顺序,也不会主动收敛话题。客服分类 Agent 发了一条“该工单属于账单问题”,方案推荐 Agent 紧接着说“建议优先退款”,而接入 Agent 又插进来补一句“用户情绪偏激动”。信息是有了,但没有人负责把这些信息变成统一的结论。更糟糕的是,因为每个 Agent 都以为别人会做收口,最终输出里常常出现互相矛盾的内容:一边说不符合退款条件,一边又建议发起退款流程。

那次失败让我意识到一件事:人类开会能收敛,是因为我们默认存在会议主持人、议程和最终决策机制。Agent 群聊里如果不显式设置这些规则,那不叫协同,叫信息广场。

1.2 群聊式协作的本质缺陷:三个失控

我把这种自由发言式协作的毛病总结成三个失控点,简化说要害。

第一是上下文失控。群里每个 Agent 都维护自己的体会,当消息数量一多,它们对同一份工单的理解会出现偏差。A 理解成用户要求开发票,B 理解成用户投诉发票迟迟未收到,最后两个 Agent 都在围绕“发票”展开,但处理方向完全不同。

第二是状态失控。自由讨论里没有谁在记录“这件事现在进行到哪一步”,没有明确的状态归属。结果就是同一个工单被重复处理,或者所有 Agent 都在等别人先动,形成死等。

第三是结果失控。即使大家七嘴八舌讲了很多,因为没有明确的汇总规则,最终的结果经常是“谁最后发言谁定”。这不是基于事实做决策,而是顺序和采样偏差在替你定结论。

群聊不是不能用,但它只适合探索型任务,像是头脑风暴出点子。可企业任务往往要求确定性的流程闭环:谁来干、干到什么程度、产出物交到哪里。这恰恰要求我们用更工程化的方式约束 Agent。

2. 让每个 Agent 守好自己的边界

2.1 边界是什么:任务口径、数据权限、输出契约

我后来重新设计协作框架时,第一件事不是画架构图,而是给每个 Agent 划边界。边界这个词听上去抽象,落在工程里其实就是三样东西:任务口径、数据权限、输出契约。

任务口径指的是这个 Agent 只负责哪一段任务,不负责什么。比如分类 Agent 只输出工单类型标签,它不负责判断该不该退款,更不负责联系用户。有了口径之后,Agent 不会随便越界去“好心帮忙”。

数据权限解决的是 Agent 能读什么、不能读什么。还是拿工单举例,分类 Agent 只需要读到工单正文和用户ID,不需要看到历史账单明细;而退款方案 Agent 则需要访问订单流水、优惠券记录。这个限定既是为了信息隔离,也是在减少无关上下文对模型的干扰。

输出契约是边界里最容易被忽略的部分。每个 Agent 对外输出的信息必须遵循固定结构,比如 JSON 里有哪些字段、字段取什么值范围、拿不到信息时怎么表达缺失。这样后续汇聚层才能稳定读取。没有契约,Agent 写一段自然语言总结,看起来智能,实际上没法被下游程序可靠处理。

2.2 边界怎么落地:角色定义 + 任务卡片

我在代码里用一版很直接的数据结构来承载边界定义,本质上就是把每个 Agent 当成一个“有职责的岗位”,而不是一个自由角色。

agent_role = { "agent_id": "triage_agent", "scope": "classify_ticket_and_extract_customer_intent", "read_permissions": ["ticket_text", "customer_id"], "write_permissions": ["ticket_category", "priority_score"], "input_contract": {"ticket_text": "string", "customer_id": "string"}, "output_contract": { "ticket_category": "enum[账单, 技术故障, 退货退款, 投诉]", "priority_score": "float[0.0, 1.0]", "summary": "string, 不超过50字" }, "escalation_rule": "如果用户情绪词命中[愤怒, 极度不满], 标记为高优先级" }

注意这里有个关键词叫“escalation_rule”,意思是边界里还应该写清楚这个 Agent 遇到什么情况可以升级,以及升级给谁。因为我们不能让一个分类 Agent 在处理不了时就胡思乱想,它必须有一条显式的安全通道。

另外我在实际操作里会把每个 Agent 的角色定义写进系统提示词,同时把任务卡片作为每条任务实例的输入前缀。任务卡片本质上就是一次具体任务的边界实例化:当前任务编号、当前 Agent 的职责、允许读取的字段、输出格式要求。

这样做的收益很直接:Agent 不再需要依赖对其他 Agent 的“理解”来行动,它只需要专注自己的那一小块工作,做完交活就行。调试验证时也方便,谁没按契约输出,一眼就能看出来。

3. 状态:唯一可信的事实来源

3.1 为什么状态管理比“互相通知”更重要

有了边界之后,Agent 各自干各自的活,但一个新问题出现了:它们之间如何知道彼此的进度?很多人的第一反应是建立通知机制,A 干完了就告诉 B。但我建议把重心放在共享状态上,而不是消息传递上。

原因是消息通知天然是异步且易丢失的。A 发了消息,B 没在线,消息就丢了;或者 A 发了两条消息,B 只处理了后一条,状态就错乱了。这就像团队协作里靠“口口相传”管理任务,总有人漏听。

共享状态的核心思路是:所有 Agent 不直接通信,而是读写一个共享的任务状态对象。状态对象记录当前任务的全生命周期信息,包括任务编号、当前阶段、负责人、产出物、异常标记。任何 Agent 想了解进度,只需要查看这个对象,不需要去问别人。

3.2 状态机的设计:待处理、执行中、受阻、已完成

状态不能是自由字符串,必须是有限状态。我给这个工单任务设计了四态,虽然简单,但已经能应对大多数企业流程:

  • pending:任务已创建,等待被领取处理
  • running:有 Agent 正在执行
  • blocked:任务受阻,需要人工介入或等待外部输入
  • completed:所有必要步骤完成,产出物已提交

可能有人觉得四态太简单了,实际上复杂系统的状态不是数量多,而是转移规则清晰。我把状态转移逻辑显式放在编排层,Agent 无权随意修改状态,只能通过上报动作让编排层决定下一步。这样不会出现两个 Agent 同时把状态改成 running 的情况。

一个典型的流转是这样的:接入 Agent 创建工单,状态置为 pending;分类 Agent 认领后置为 running;分类完成并写入类别,编排层把状态切回 pending,但这时候开始等待方案 Agent。方案 Agent 拉起后状态又变为 running。如果某个 Agent 发现自己需要用户补充信息,它就上报 blocked,等到外部输入到达后再恢复。

我在系统里专门写了一个状态变更记录表,每次转移都留下日志。后面排查问题变得特别轻松,只要看状态记录就能还原整个任务过程,不需要再猜 Agent 到底经历了什么。

3.3 状态同步机制:事件驱动与共享存储

状态管理不能光靠一个公共变量,工程上我推荐“共享存储加事件通知”的组合。共享存储可以是一个简单的 Redis 键值结构,也可以是一张数据库表,关键是它是唯一的事实来源。事件通知负责在状态变更时提醒订阅方,让下游 Agent 能及时被唤醒。

具体流程就是:某个 Agent 完成任务后,编排层更新共享状态,同时发布一个事件,事件内容带上任务ID和新状态。等待队列里的下游 Agent 收到事件后开始工作。这个过程简单但可靠,因为即使事件丢失,我们依然可以从共享状态里恢复进度;相反如果只有通知没有共享状态,事件一丢整个流程就断了。

在实现上我会写一个很薄的编排函数,核心逻辑只有三件事:更新状态、存储产出物、发布事件。所有 Agent 都必须通过这个函数上报,不允许旁路直写。这个约定虽然基础,但能挡住前期项目里一大半的协作事故。

4. 汇聚结果:最后的收口动作

4.1 从“大家讨论”到“结构化汇总”

边界和状态解决了过程协作的问题,最后一步是把多个 Agent 的产出合并成一份可用的结果。这一步我称之为汇聚结果。群聊式方案里没有汇聚这个动作,大家讨论完,结论靠“感觉”。而企业任务不能靠感觉,必须有一个显式的收口机制。

汇聚动作一般发生在一个协调 Agent 或一段编排代码里。它负责三件事:收集所有子 Agent 的结构化产出,检测彼此之间是否有冲突,然后按预置规则合并出最终结论。为了让这个步骤可靠,前面提到的输出契约就显得至关重要了:只有结构化数据才能稳定地做冲突检测和合并,自由文本永远无法保证。

4.2 冲突检测与合并策略

冲突检测是汇聚层最容易忽略的环节。多 Agent 协同处理同一件事,出现矛盾几乎是常态。比如分类 Agent 把工单标为“退货退款”,而方案 Agent 基于同一份工单建议“补偿优惠券而不是退货”,这不算冲突,因为一个是分类,一个是具体动作。真正需要检测的是同一指标上出现的不一致。

我在系统里预设了几类常见冲突规则:同一工单是否同时被标记为不同优先级?是否同时出现“通过”和“拒绝”两种状态?是否出现金额不一致的退款额度?检测到冲突之后,我并不会立刻让某个 Agent 重新跑一遍,而是进入人工决策分支,因为自动纠错容易掩盖根源问题。

合并策略我通常采用等级制:有些字段以某个 Agent 的输出为准,有些字段以另一个 Agent 的输出为准。比如工单分类以分类 Agent 为准,推荐方案以方案 Agent 为准,而最终汇总的简报由汇总 Agent 基于上下文重新生成。这就像团队里不同角色各司其职,最终文档由主笔人统一润色,而不是所有人往同一份文档里填内容。

4.3 结果验收与人工兜底

汇聚结果完成后,不能直接认为万事大吉。我会在整条链路里保留一个验收环节:校验最终输出是否符合交付模式,必填字段是否齐全,数值范围是否合法。这些规则都是提前定义好的,代码不复杂,但能挡住很多低级错误。

另外,人工兜底通道必须存在。企业任务和实验性任务不一样,一旦面向真实用户,错误是有成本的。我在系统里专门留了一个“人工复核队列”,凡是冲突检测不过、置信度偏低、或者用户情绪标记为严重不满的工单,都进入这个队列。设计的时候可能会觉得这是退步,但实际运行下来发现,这个兜底通道反而让整个系统更敢于自动执行,因为团队知道有最后一道网在。

5. 一个完整实操示例:客服工单自动处理

5.1 任务定义与边界划分

这一节我完整还原一个模拟项目 X 的实现过程,方便你对照设计。这个项目用四个 Agent 处理客服工单:接入 Agent、分类 Agent、权益方案 Agent、回访话术 Agent。为了让流程能跑通,我对每个 Agent 的职责做了非常细的划分。

agents = { "intake_agent": { "scope": "解析工单文本,提取用户id和主诉", "inputs": ["ticket_text"], "outputs": ["customer_id", "complaint"], }, "triage_agent": { "scope": "判断工单类型、优先级和风险等级", "inputs": ["customer_id", "complaint"], "outputs": ["ticket_category", "priority", "risk_level"], }, "benefit_agent": { "scope": "根据用户权益和历史订单,给出可执行处理方案", "inputs": ["customer_id", "ticket_category", "priority"], "outputs": ["suggested_action", "refund_amount"], }, "reply_agent": { "scope": "生成面向用户的回访或答复话术", "inputs": ["customer_id", "complaint", "suggested_action"], "outputs": ["reply_text"], }, }

注意 reply_agent 的输入里没有 refund_amount,这是我刻意做的隔离设计:话术 Agent 只需要知道处理动作的方向,不需要接触到具体金额数值。这样可以避免它在生成话术时替用户做“值不值得”的判断。

5.2 状态流转实现

定义好边界后,我实现一个极简的编排函数。它接收当前任务对象和一个 Agent 上报的产出,更新状态,然后决定下一步。代码不复杂,但把状态转移规则显式化了。

def handle_agent_report(task, agent_id, output): task.progress[agent_id] = output if agent_id == "intake_agent": task.stage = "triage" task.status = "pending" emit_event(task.id, "triage_ready") elif agent_id == "triage_agent": if output.get("risk_level") == "high": task.stage = "manual_review" task.status = "blocked" else: task.stage = "benefit" task.status = "pending" emit_event(task.id, "benefit_ready") elif agent_id == "benefit_agent": task.stage = "reply" task.status = "pending" emit_event(task.id, "reply_ready") elif agent_id == "reply_agent": task.stage = "done" task.status = "completed" save_task(task)

这里面有个细节想强调:高风险工单在这里被直接拉到 manual_review,不让权益方案和回访话术自动生成。因为真实业务里,高风险工单往往需要人工先确认用户情绪和背景,直接放 Agent 去生成回复容易火上浇油。这条规则看起来很简单,但在初期设计时很容易因为“追求全自动”而忽略掉。

5.3 结果汇聚与最终输出

四个 Agent 跑完后,最终输出由一段汇聚代码而不是某个 Agent 完成。因为汇聚逻辑需要确定性,交给大模型自由发挥反而容易失控。我用代码把关键字段拼装成标准结果格式。

def aggregate_result(task): triage = task.progress["triage_agent"] benefit = task.progress["benefit_agent"] reply = task.progress["reply_agent"] conflict = check_conflict(triage, benefit) if conflict: enqueue_for_manual_review(task.id, reason=conflict) return final_result = { "ticket_id": task.id, "category": triage["ticket_category"], "priority": triage["priority"], "action": benefit["suggested_action"], "refund_amount": benefit.get("refund_amount"), "reply_text": reply["reply_text"], "review_required": triage["risk_level"] == "medium", } return final_result

我在这个项目里还加了另一个合并规则:回复话术里提到的退款金额必须和 benefit_agent 给出的金额一致。如果 reply_agent 里写了一个数字,而结构化的 refund_amount 是另一个数字,最终展示给用户之前就会被拦截下来。这类校验肯定不是 AI 能做好的事,用规则代码反而更稳。

6. 常见问题与排查经验

6.1 典型故障现象与定位

多 Agent 系统一旦进入生产,问题就千奇百怪。我汇总了几类特别常见的:

现象根因排查思路
任务卡在 pending 不动状态流转事件丢失,或下游 Agent 没有订阅查看状态变更日志,确认是否发出事件
多个 Agent 重复处理同一任务缺少认领机制,两个消费者同时拉取在状态里加 owner 字段,原子性地做认领
最终结果出现相互矛盾字段输出契约未严格校验在汇聚前加 schema 校验,强制枚举有效性
Agent 输出“我不知道”但任务标记为 completed输出契约里缺少缺失值表达增加字段 unknown_reason,检测后转入人工队列
某个 Agent 长期占用任务不释放缺少超时机制为每个状态加超时阈值,超时自动置为 blocked

第一类问题出现频率最高。事件驱动系统的经典毛病就是事件发出后,订阅者没收到或者还没来得及消费,任务就永远停在那里。我会在状态变更日志里加一个“should_have_consumed”字段,每次发布事件时把预期消费者写进日志,排查时直接看谁没消费,省去了大量问询时间。

6.2 几个必须留意的显式规则

除了排查故障,我在几次项目里总结出几条写进系统提示词和代码注释的规则,虽然不是复杂算法,但实战价值非常高。

第一,Agent 之间不直接对话。任何信息传递都通过状态对象和事件完成,禁止在系统提示词里鼓励 Agent 互相参考对方的最终输出。一旦逻辑上允许 Agent 直接引用另一个 Agent 的产出,汇聚层就很难判断数据来源可信度。

第二,每条任务必须有一个唯一的负责人字段。这个 owner 可以是单个 Agent,也可以是“人工”。当多个 Agent 都有权处理某一步时,必须在编排层加锁或者用原子认领,而不是靠 Agent 自觉。

第三,状态必须支持回滚。我在本地用“状态快照加 append-only 日志”来实现回滚,一旦后续发现某个 Agent 的产出有问题,可以回到任务上一个稳定点,而不是推倒重来。

第四,给 Agent 设置“不做权”。边界定义里不要只写它做什么,更要写它不做什么。比如分类 Agent 不评价退款合理性,权益方案 Agent 不直接回复用户。这个“不做权”能减少 Agent 在信息不足时强行发挥的冲动。

6.3 什么时候才可以“开会”

讲到这里并不是说多 Agent 交流一无是处。在实际测试里,我把群聊式方案保留给了两个特殊场景:任务前期的目标对齐和任务完成后的复盘总结。

目标对齐阶段,多个参与 Agent 在还没有具体任务输入时,先对目标、约束、优先级达成共识。这个共识会作用到后续每个 Agent 的提示词里。复盘阶段,在任务已经完成、结果已经确定之后,让多个 Agent 聚在一起回顾过程、提炼经验,帮助优化下一轮提示词和规则。这两个场景的共同点是:低频、低风险、结果不直接面向用户。

至于任务执行过程中,群聊式交流我还是建议彻底禁用。你把群聊当成离线评审工具没问题,别把它当成在线执行引擎。

6.4 对这套协作方式的持续迭代思考

边界、状态和汇聚结果这三件套不是一个一次性设计,而是需要跟随业务持续迭代。我在实际运营中发现,业务方常常会提出新的字段需求:工单要增加“是否是会员”维度、方案要增加“多方案对比”、回访要增加“渠道偏好”。每次新增字段,都要顺着边界定义、状态数据结构、汇聚校验三个位置同步修改,漏掉任何一环都会在运行期暴露问题。

所以我会在项目里额外维护一份变更清单,每次接口调整时强制走一遍三个层面的关联检查。这样做看起来增加了工作量,但能省掉后续大量定位成本。多 Agent 系统不怕改,怕的是改不完整,最后状态里存着一堆没人消费的字段,或者汇聚出来的结果有一半是空的。

我个人在这些项目里最大的体会是:多 Agent 协作的工程难度,不在于每个 Agent 本身聪明不聪明,而在于你敢不敢用工程手段去约束它们。群聊式方案之所以诱人,是因为它看起来接近人类协作;但企业软件真正需要的不是拟人化,而是可预期、可观察、可拦截。给每个 Agent 画好边界,把状态显式地放在一起,让结果收口在确定的汇聚逻辑上,这套框架几乎可以平移到任何企业任务里。下次再有人跟你说“让 Agent 们自己商量着办”,你可以先把这篇文章甩给他,然后问他:那出了分歧,听谁的?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/11 3:39:33

国家承认的职业资格证书有哪些:先分清制度类别,再对照目录核验

很多人问"国家承认的职业资格证书有哪些",期待的是一份可以直接照着报名的名单。但这个问题很难用一张榜单回答,原因不在于信息不够,而在于"国家承认"本身对应着几套不同的制度。国家职业资格、职业技能等级、专业技术资…

作者头像 李华
网站建设 2026/10/11 3:38:37

机器人弧焊I-Puls工艺参数设置与焊缝质量提升指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/11 3:38:28

行业认证证书包括哪些?先分清颁证主体,再看与职业资格的区别

“行业认证证书”并不是一个法定的统一证书类别,而是对按颁证主体和行业领域划分的一类证书的统称。它通常包括:国家职业资格中的行业类、行业协会/学会认证、企业/厂商认证、国际行业认证,以及部分培训/能力证书。判断某张证书是不是“行业认…

作者头像 李华
网站建设 2026/10/11 3:38:18

6轴机械臂强化学习实践:TensorFlow环境搭建与PPO/DDPG算法应用

简介:这是一份面向机器人控制与前端JavaScript开发者的TensorFlow.js实验项目,重点演示六轴机械臂的强化学习流程。作者用乐高EV3砖块和伺服器搭建实体机械臂,并借助网页端AI训练模型,让模型自动旋转各轴,最终把机械臂…

作者头像 李华
网站建设 2026/10/11 3:38:10

Notepad++ 7.3.2免安装版:便携部署、配置迁移与避坑指南

简介:Notepad 7.3.2 官方免安装版以 ZIP 压缩包形式分发,专为程序员、Web 开发者及需要频繁处理代码或文本的用户准备,面向未安装软件或受权限限制的工作环境,提供一套无需安装、解压即用的源代码编辑工具。压缩包内共 143 个文件…

作者头像 李华
网站建设 2026/10/11 3:36:15

代码生成中的Token效率与模型推理协议实战指南

1. 这不是“省Token”的问题,而是模型能力边界的实操博弈最近在多个技术群和开发者社区里,反复看到类似标题的提问:“写代码,希望节省token,但智商要高怎么选配置……”——这句话表面看是问参数调优,实测下…

作者头像 李华