多 Agent 协作通信怎么设计?

把"一个大上下文"拆成多个"小上下文 + 通信协议 + 共享状态"——分工必然带来信息损失,所以通信设计是 Multi-Agent 系统的命门。本文专讲:Agent 之间到底传什么、消息长什么样、拓扑怎么选、协议怎么定、错误怎么兜底,并给出一份可直接照抄的设计蓝图。

Message Schema Topology Shared State Handshake A2A Protocol Reliability

1. 一句话讲清:通信设计的本质

多 Agent 协作的难点从来不是"让两个模型对话",而是如何在分工后,把信息无损、可控、可恢复地从一个 Agent 传到另一个

🎯

通信要解决 3 件事

传什么(消息结构)、怎么传(拓扑与通道)、传坏了怎么办(协议与可靠性)。缺任何一环,系统就会"各说各话"或"踢皮球"。

🕳️

核心矛盾:分工 vs 信息损失

拆分上下文能解决单 Agent 的窗口溢出,但每个 Agent 只拿到"别人传给它的那点信息"。设计通信,本质是在带宽有限下最小化信息损失

本文定位:同目录 multi-agent-explained.html 讲"Multi-Agent 是什么、怎么协作、选什么框架";本文件是配套实操篇,专门钻进"通信"这一关——消息、拓扑、协议、可靠性,配一份可落地的设计蓝图。

2. 通信到底在传什么?

Agent 之间传递的不是"一句话",而是一组结构化信封。一个最小可用通信单元至少包含 5 个字段:

一条 Agent 消息(Envelope) sender谁发的 receiver发给谁(或广播) type消息类型(task/result/query/error…) payload业务内容(JSON/文本) 共享状态 / 黑板 所有 Agent 可访问 • task_status: 进行中 • shared_context: 全局事实 • artifacts: 各 Agent 产出 • trace_id: 全链路追踪 消息 = 增量;状态 = 全集快照
通信 = 在"消息(增量传递)"和"共享状态(全集快照)"之间做权衡。消息丢了能补,状态错了全乱。
🆔

身份字段

sender / receiver / message_id / reply_to:让消息可寻址、可关联、可做请求-响应配对。

🏷️

类型字段

type 决定接收方怎么处理:task(派活)、result(交差)、query(问)、error(报错)、signal(控制)。

📦

载荷字段

payload 是业务内容,结构化(JSON)优于自然语言,便于程序解析、校验、重试。

3. 消息格式设计:自然语言 vs 结构化

消息内容的"编码方式"直接决定系统能不能规模化。三种主流做法,从弱到强:

编码方式样子优点缺点适用
纯自然语言"帮我查下竞品A的销量"灵活、零成本难解析、易歧义、不可校验、易丢字段原型、人参与的调试
半结构化"Action: search[竞品A]"能解析、好控制格式约束弱、易格式漂移单 Agent ReAct
强结构化(JSON){"type":"task","payload":{...}}可校验、可重试、可类型安全需定义 Schema、啰嗦生产推荐

生产级消息 Schema 样例

// 一个强结构化消息的完整骨架
{
  "message_id": "msg_8f3a",          // 全局唯一,用于去重/追踪
  "sender": "orchestrator",        // 发送方 Agent 标识
  "receiver": "researcher_1",       // 接收方;"broadcast" 表示广播
  "type": "task",                // task | result | query | error | signal
  "trace_id": "trace_2026",          // 串联一次用户请求的全链路
  "reply_to": "msg_7c1b",           // 若这是对某消息的回复
  "payload": {
    "task": "collect_competitor_sales",
    "args": { "company": "A", "month": "2026-07" },
    "timeout_sec": 60,
    "expected_schema": { "sales": "number" }  // 对结果的格式契约
  },
  "deadline": "2026-08-24T15:00:00Z"  // 超时边界
}
设计要点:① 给每条消息一个 message_idtrace_id,否则无法去重、追踪、排查;② 用 expected_schema 把"结果长什么样"写在任务里,接收方交差时才能被校验;③ 自然语言尽量只出现在 payload 的"不可结构化"部分(如分析结论)。

4. 拓扑结构怎么选

"谁可以跟谁说话"是通信设计的第一道架构决定。四种常见拓扑:

中心辐射 Hub W W W 流水线 A B C 只能顺向下游传 Back-pressure 难 层级 / 分组 Mgr T1 T2 T3 全互联 / Mesh A B C D E
中心辐射最易控(主流);流水线适合固定工序;层级适合大规模分组;Mesh 最灵活但最难排查。
拓扑通信路径优点缺点选型
中心辐射 Hub只经 Orchestrator可控、易排查、无环路Hub 成瓶颈、单点生产首选
流水线 PipelineA→B→C 单向简单、背压清晰无法回退、难并行固定工序
层级 Hierarchical经理↔组员可扩展到大量 Agent层级深了延迟高大团队分组
全互联 Mesh任意两点直连最灵活、鲁棒复杂度指数级、难调试探索/研究

5. 共享状态 vs 消息传递

Agent 间同步信息有两条根本路径,理解它们的权衡是通信设计的核心决策:

📨 消息传递(Message Passing)

信息只通过"发送消息"流动。每个 Agent 私有上下文,互不直接读内存。

  • 优点:低耦合、易并联、可重放、天然审计。
  • 缺点:带宽有限,只传增量,容易丢上下文;要显式设计"传什么"。
  • 典型:AutoGen 的 GroupChat、CrewAI 的 Crew 轮转。

🗂️ 共享状态 / 黑板(Shared State)

所有 Agent 读写同一块"黑板"(blackboard / state object)。

  • 优点:信息全集可见,不用反复传;新 Agent 随时接入都能看到全局。
  • 缺点:要处理并发写冲突、版本、一致性;状态错了全局崩。
  • 典型:LangGraph 的 State、黑板模式。
消息传递 A B 只传这一句话 A 看不到 B 的其他记忆 共享状态 Blackboard 全局可见 A B A、B 都读写同一块状态
经验:用"共享状态存稳定的全局事实,用消息传递驱动动作与增量"——两者常混合。
最佳实践:把"稳定全局事实"(任务目标、已确认数据、各 Agent 产出)放共享状态;把"动作指令、请求-响应、异常"走消息。这样既不全量广播浪费 token,也不因私有上下文丢关键信息。

6. 通信协议与握手

光有消息格式还不够,要有"规矩"约束通信时序。三类协议,复杂度递增:

🔁

请求-响应(RPC 风格)

发 task,等 result,靠 reply_to 配对。最简单,适合点对点调用。timeout 必带。

📢

发布-订阅(Pub/Sub)

Orchestrator 广播事件,关心它的 Agent 订阅处理。解耦好,适合一对多通知。

🤝

协商 / 握手

两 Agent 先"报价-确认"再干活(如能力协商、任务认领)。最稳,适合去中心化。

握手时序:任务派发到交付

Orchestrator Worker Blackboard 1 task(assign) 2 write(status:doing) 3 result(reply_to) 4 write(artifact) 5 ack / 下一步
一次完整握手:派活 → 写状态 → 交差(带 reply_to)→ 落盘产出 → 确认。每一步都可被追踪与超时。
行业新动向 —— A2A(Agent2Agent)协议:Google 2025 年提出的开放协议,目标是让不同厂商、不同框架的 Agent 互相通信。核心概念:Agent Card(描述能力/接口的"名片")、Task(带状态机的任务对象)、Message(含 Part 多模态内容)。如果你的系统要跨框架互通,值得关注;内部同框架系统用自有消息 Schema 即可。

7. 交互演示:看一次消息总线里发生了什么

点"跑一轮",观察一条用户请求如何在 Orchestrator 与多个 Worker 之间通过消息总线流转(带 reply_totrace_id、超时与错误分支)。

再点"注入一次失败",看错误怎么被协议兜住

8. 错误处理与可靠性

多 Agent 链路长、参与方多,错误是常态而非例外。通信层必须内置四类兜底:

⏱️

超时与重试

每条 task 带 timeout;超时未回 result 则重试或转派。重试要幂等(同任务跑多次结果一致)。

🔄

失败转移(Failover)

Worker 崩了,Orchestrator 把任务转给备份 Worker,或从共享状态恢复半成品。

🆔

幂等与去重

message_id 去重,避免重试导致重复执行;写共享状态用版本号防并发覆盖。

🛑

死循环防护

设全局最大轮次 / 最大消息数;两 Agent 互相等待或互踢皮球时强制终止并告警。

最常见的三种通信故障:静默丢失——消息发了没人收(receiver 不存在/离线)→ 必须有 ack 确认;② 格式漂移——某 Agent 返回不合 expected_schema → 校验失败即报错并请求重发;③ 状态撕裂——并发写共享状态互相覆盖 → 用乐观锁/版本号。

9. 一个可落地的通信设计蓝图

把前面所有要点收口成一份"照着抄"的设计清单。一个稳健的 Multi-Agent 通信系统应当包含:

消息信封(Envelope)

统一必含:message_idsenderreceivertypetrace_idpayloaddeadline。所有 Agent 收发都走同一套。

通道与拓扑

默认中心辐射:所有消息经消息总线(或 Orchestrator)。总线负责路由、去重、持久化、超时检测。

共享状态(Blackboard)

存稳定全局事实与各方产出,带版本号;消息只传动作与增量。新 Agent 接入即可读全局。

协议与握手

请求-响应为主(带 reply_to);长任务用状态机(pending→doing→done/error);跨框架互通看 A2A。

可靠性底座

ack 确认、超时重试(幂等)、failover、最大轮次防护、完整 trace 日志(谁调谁、输入输出、耗时、错误)。

一句话蓝图:统一信封 + 总线路由 + 黑板存全局 + 请求响应握手 + 五道可靠性兜底。先把这五条定下来,再决定用 CrewAI / LangGraph / 自研。

10. 主流框架里通信是怎么实现的

框架通信机制消息/状态模型通信设计启示
CrewAI顺序/层级 Process 轮转Agent 依次发言,上下文拼接消息≈"上一个人说的话",轻量但难精细控制
LangGraph状态图节点流转State 共享对象 + Conditional Edge通信≈"状态更新 + 条件路由",最适合精细通信设计
AutoGen / AG2GroupChat 群聊消息列表广播,Speaker 选择消息传递范式,天然审计、可重放
自研总线消息队列(如 Redis Stream)Envelope + 主题订阅 + 持久化完全自控,可上 A2A、跨服务部署
选型映射:想要"消息传递 + 群聊"风格 → AutoGen;想要"共享状态 + 可控路由" → LangGraph;想要"开箱即用的角色轮转" → CrewAI;想要跨进程/跨框架且完全可控 → 自研消息总线(Redis/Kafka + 自有 Envelope)。

11. 常见坑与设计 Checklist

🕳️

坑:自然语言当消息

用纯文本传指令,下游解析靠"猜",字段一多就丢。→ 改用强结构化 JSON Envelope。

🌀

坑:无超时无限等

Worker 卡死,Orchestrator 永远阻塞。→ 每条消息必带 deadline

📉

坑:上下文全靠传

私有上下文导致下游 Agent 缺少上游关键背景。→ 稳定全局事实放黑板。

🔍

坑:无 trace 难排查

出错了不知道谁发的、卡在哪。→ trace_id + 全链路日志。

✅ 通信设计 Checklist

  • ☐ 消息是否统一了 Envelope(id / sender / receiver / type / trace_id / payload / deadline)?
  • ☐ 拓扑是否明确(中心辐射 / 流水线 / 层级 / mesh),且默认走可控的中心辐射?
  • ☐ 稳定全局事实是否进了共享状态,动作与增量是否走消息?
  • ☐ 是否有请求-响应配对(reply_to)、ack 确认、超时与幂等重试?
  • ☐ 是否有最大轮次 / 最大消息数防死循环、死锁防护?
  • ☐ 结果是否用 expected_schema 校验,格式漂移能否被发现并重发?
  • ☐ 并发写共享状态是否有版本号/乐观锁防撕裂?
  • ☐ 是否每条消息都可被 trace、重放、审计?
收口:通信设计的目标不是"让 Agent 聊得开心",而是在分工带来的带宽约束下,把信息损失降到最低,并保证出错可恢复、过程可追踪。把这页的蓝图和 Checklist 落到代码里,Multi-Agent 系统就稳了一大半。