Featured image of post 多Agent 系统架构设计(二):Agent 之间到底怎么「说话」?通信层的架构选择

多Agent 系统架构设计(二):Agent 之间到底怎么「说话」?通信层的架构选择

假设你已经读完了上一篇,确定了你的多 Agent 系统用哪种编排模式(Orchestrator-Worker、Peer-to-Peer、Supervisor 还是 Chain)。

恭喜——你只走了一半的路。

下一个问题是:这些 Agent 之间到底用什么「语言」和「通道」来对话?

是让 Agent 直接调用对方的 API(同步 RPC 风格)?还是通过一个消息队列异步发消息?是用 MCP 协议让 Agent 调用工具,还是用 A2A 协议让 Agent 之间协作?如果系统里有 50 个 Agent,每个都要跟其他 49 个通信,你还敢用点对点直连吗?

你可能觉得这都是「实现细节」,等架构搭好了再决定也不迟。

但通信层的选择,会反过来决定你的编排模式能不能跑起来。

一个 Supervisor 模式如果选了同步 RPC 通信,那 Supervisor 挂了,整个系统就卡死了。一个 Peer-to-Peer 模式如果选了事件总线,那状态一致性维护就变成了一个分布式共识问题。

这篇文章是《多Agent 系统架构设计》系列的第二篇。我们从分布式系统工程师的视角,把通信层的几个核心维度拆开来看:同步 vs 异步、点对点 vs 广播、有状态 vs 无状态、可靠 vs 尽力而为。然后再看 MCP、A2A、事件总线(Kafka/Pulsar)各自在架构中的角色,以及——基于 MCPZERO 网关的实战经验——网关层在通信中扮演的「安全控制平面」角色。

总览:三种通信方式的核心差异

在深入细节之前,先看一张全景对比表。这张表会贯穿全文,你可以随时回来参考。

维度 MCP (Model Context Protocol) A2A (Agent-to-Agent) 事件总线 (Kafka/Pulsar)
定位 Agent → 工具连接 Agent ↔ Agent 协作 Agent ⇢ 异步消息通道
消息格式 JSON-RPC 2.0(请求/响应) JSON 任务卡片(Task/Artifact/Message) 二进制/Avro/Protobuf Record
同步/异步 同步(请求-等待-响应) 异步(任务委派-轮询/通知) 纯异步(生产-消费)
可靠性 无状态,客户端负责重试 内置任务状态机 + 状态同步 持久化日志 + 消费者偏移管理
容错 依赖客户端侧超时/重试 协议级超时 + 状态查询 分区副本 + ISR + Exactly-Once
耦合度 紧耦合(一对一请求) 松耦合(任务委派模式) 极松耦合(发布-订阅)
适用场景 单个 Agent 的工具调用链 多个 Agent 之间的任务协作 大规模 Agent 的事件广播/日志
安全模型 无内置认证,依赖传输层 身份断言 + 代理凭证 SASL/SSL + ACL + 审计日志

这张表说明一个关键事实:MCP、A2A、事件总线不是替代关系,而是不同的抽象层级。 它们解决的问题不同,适用的场景也不同。一个成熟的多 Agent 系统通常会同时使用三者。

同步 vs 异步:Agent 等不等得起?

这是通信层最基础的选择。我先给你一个类比:

同步调用就像你在办公室喊同事:「帮我查一下这个数字,我等你。」——你站在原地,等同事查完告诉你,才继续干自己的活。

异步调用就像你给同事发一条微信:「有空帮我查一下这个数字,查完发我。」——你转头继续干自己的活,等同事回复了再处理。

什么时候用同步?

  • Agent 需要对方的返回才能继续。比如一个翻译 Agent 问知识库 Agent:「这个词在数据库里有吗?」——没有答案,翻译 Agent 没法继续。
  • 调用链不超过 2-3 跳。超过 3 跳的同步链,延迟会累加,而且中间任何一环失败,整个链都断。
  • 对方 Agent 的响应时间可预测(通常在 1-5 秒以内)。

同步模式最典型的例子就是 MCP。Agent 调用一个 MCP 工具时,发送请求,等待工具返回结果,拿到结果继续推理。这是标准的请求-响应模式,优点简单,缺点——调用链越长,系统越脆弱

什么时候用异步?

  • Agent 可以并行做其他事。比如一个分析 Agent 同时问 5 个数据源 Agent 要数据,等所有结果回来再整合。
  • 任务执行时间不确定(几秒到几分钟都有可能)。
  • 需要解耦生产者和消费者。比如一个监控 Agent 不停发告警,多个订阅 Agent 各自处理。

异步模式的典型代表是 A2A 协议中的任务委派:Agent A 创建一个 Task,Agent B 获取后处理,Agent A 可以轮询或接收通知来获取结果。这期间 Agent A 可以处理其他事情。

混合模式:最务实的方案

在实际系统里,很少有纯同步或纯异步的通信层。更常见的是:

Agent 收到用户请求(同步,用户在线等)
  → 编排 Agent 派发子任务给 3 个 Worker(异步,通过事件总线)
  → 每个 Worker 调用自己的工具链(同步,MCP 调用)
  → 结果汇总到编排 Agent(异步,通过事件总线)
  → 编排 Agent 返回最终结果给用户(同步)

每一层选择不同的通信模式,核心原则是:调用链越短,越适合同步;调用链越长、越需要弹性,越适合异步。

点对点 vs 广播:谁跟谁说话?

第二个维度是拓扑结构——Agent 之间是「一对一」还是「一对多」?

点对点(Point-to-Point)

一个 Agent 明确知道要跟谁说话。比如 Supervisor Agent 把任务派给指定的 Worker Agent。这种模式适合确定性路由——你知道哪个 Agent 能处理什么任务。

MCP 就是典型的点对点模式。Agent 知道要调用哪个工具的哪个 endpoint,建立连接,发送请求,拿到结果,断开连接。简单、直接、可预测。

广播(Fan-out / Pub-Sub)

一个 Agent 发出消息,多个感兴趣的 Agent 各自接收处理。比如一个「日志收集 Agent」发出一条异常事件,安全 Agent、监控 Agent、告警 Agent 各自处理。

事件总线模式天然适合广播。Kafka 的 Topic 和 Consumer Group 机制,让一个生产者发送的消息可以被多个消费者组以不同的速率消费。

点对点 + 广播的混合

A2A 协议在这个维度上比较灵活。一个 Agent 可以创建一个 Task 并指定给某个 Agent(点对点),也可以把 Task 发布到 Agent Card 注册表,让有能力处理的 Agent 主动领取(类似广播+竞标)。

MCP 在架构中的角色:工具连接层

MCP(Model Context Protocol)是这三个里面最「底层」的。它的定位非常明确:Agent 到工具的连接协议

一个 Agent 要调用一个数据库、一个 API、一个文件系统、一个搜索引擎——这些都需要 MCP 来提供标准化的接口。MCP 的请求-响应模型决定了它不适合做 Agent 之间的通信,但非常适合做 Agent 与工具之间的通信。

MCP 在通信层面的几个关键特征:

  1. 无状态:每次请求都是独立的,服务器不维护客户端状态。2026 年 7 月的新规格引入了一些扩展机制,但核心仍然是无状态的。见 《MCP 变天了!》 的详细解读。
  2. 同步阻塞:Agent 发送请求后必须等待响应。对于工具调用来说,这是合理的——你需要知道工具执行的结果才能继续推理。
  3. 一对一:一个 Agent 连接一个 MCP 服务器。没有广播概念。
  4. 可靠性在客户端:MCP 协议本身不提供重试或幂等语义。如果超时或失败,由 Agent 客户端决定是否重试。

在架构图里,MCP 应该是通信层的最底层——它不负责 Agent 之间的协作,只负责 Agent 与外部工具的连接。

A2A 在架构中的角色:Agent 协作层

A2A(Agent-to-Agent)协议是 Google 在 2025 年推出的,定位是 Agent 与 Agent 之间的协作协议

如果说 MCP 是「Agent 的手」,那 A2A 就是「Agent 之间的电话」。我之前写过一篇详细的协议对比:《Agents 互联!A2A/MCP/ANP/ACP 四大协议详解》,这里不再重复协议的技术细节,而是聚焦通信层的架构视角。

A2A 在通信层面的几个关键设计:

  1. 任务驱动:A2A 的核心抽象是 Task。一个 Agent 创建 Task,另一个 Agent 处理 Task。这本质上是异步消息模式,但通过任务状态机(Task State Machine)提供了可靠性的保障。
  2. 状态同步:A2A 协议内置了任务状态查询机制。Agent A 可以随时问 Agent B:「你那边那个 Task 怎么样了?」——这解决了异步通信中常见的「消息丢失后不知道」的问题。
  3. 身份断言:A2A 协议要求 Agent 在通信时携带身份断言(Identity Assertion),这为后续的认证和授权提供了基础——这也是它比 MCP 更有「安全基因」的地方。
  4. 松耦合:Agent A 不需要知道 Agent B 的内部实现,只需要知道 Agent B 发布的 Agent Card(能力声明)。这是服务发现模式在 Agent 世界里的映射。

在架构图里,A2A 应该是通信层的中层——它处理 Agent 之间的任务协作,构建在底层传输之上。

事件总线(Kafka/Pulsar):异步解耦层

当你的系统里有 20 个、50 个、甚至上百个 Agent 时,点对点的连接就不再可行了。每个 Agent 维护 49 个连接——不仅连接数爆炸,状态管理和故障隔离也变成了噩梦。

这时候你需要事件总线。

为什么 Kafka/Pulsar 适合做 Agent 通信层?

Kafka 和 Pulsar 的设计哲学天然适合多 Agent 系统的通信需求:

  • 持久化日志:消息一旦写入就不丢失,即使消费者宕机,重启后可以从上次消费的位置继续。
  • 分区并行:多个 Agent 可以并行消费同一个 Topic 的不同分区,天然支持水平扩展。
  • Consumer Group 机制:一组 Agent 构成一个 Consumer Group,每个消息只被组内一个 Agent 消费——这正好对应 Orchestrator-Worker 模式中「任务分发」的场景。
  • Backpressure 处理:如果消费者处理不过来,消息积压在 Kafka 里,不会压垮生产者。这是同步 RPC 做不到的——在同步模式下,慢消费者会直接阻塞生产者。

什么时候用事件总线?

场景 为什么事件总线合适
日志/事件采集 多个 Agent 产生事件,多个 Agent 消费,天然广播
任务分发 Orchestrator 把任务写入 Topic,Worker 从 Topic 消费
状态变更通知 Agent 状态变化时广播给所有订阅者
审计/追踪 所有 Agent 通信写入审计 Topic,安全 Agent 独立消费

事件总线的代价

事件总线不是银弹。它引入的复杂度包括:

  • 延迟增加:消息经过磁盘持久化再消费,延迟通常在毫秒到秒级,不适合需要亚秒级响应的场景。
  • 运维复杂度:Kafka 集群的运维本身就是一门学问——分区重平衡、ISR 同步、磁盘水位管理。
  • 状态一致性更难:当多个 Agent 从同一个 Topic 消费时,谁先处理、谁后处理、处理过程中系统崩溃了怎么办——这些都需要额外的机制来保证。

网关层做什么:通信的「安全控制平面」

从 MCPZERO 网关的实战经验出发,我想讲一个经常被忽略的层——网关层

MCP、A2A、事件总线各自定义了通信的「协议语法」,但都没有定义通信的「安全策略」。谁来认证 Agent 的身份?谁来做流量控制和限流?谁来审计 Agent 间的所有通信?

这就是网关层的工作。

网关在通信层中的定位

┌─────────────────────────────────────────────────────┐
│                    通信层全景                         │
│                                                       │
│  ┌─────────────────────────────────────────────────┐ │
│  │  应用层:Agent 逻辑(推理、规划、决策)           │ │
│  ├─────────────────────────────────────────────────┤ │
│  │  通信协议层:MCP / A2A / 事件总线                 │ │
│  ├─────────────────────────────────────────────────┤ │
│  │  网关层:认证 / 限流 / 审计 / 路由 / 安全策略    │ │
│  ├─────────────────────────────────────────────────┤ │
│  │  传输层:HTTP/2 / WebSocket / gRPC / TCP         │ │
│  └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘

网关做四件事

  1. 认证:谁在跟谁说话?A2A 的身份断言机制需要网关来验证。MCP 没有内置认证,需要网关在传输层补上。
  2. 限流:一个 Agent 疯狂调用另一个 Agent,怎么办?网关层做 token bucket 或 leaky bucket 限流。
  3. 审计:所有 Agent 之间的通信写入审计日志——谁在什么时间调用了谁、传递了什么数据、结果如何。这在合规场景(如金融、医疗)中是刚需。
  4. 路由:Agent 不需要知道目标 Agent 的地址,只需要知道「我要找谁」。网关根据 Agent Card 注册表做服务发现和路由。这在动态 Agent 上下线的情况下特别重要。

我们的经验

在 MCPZERO 中,我们实现了一个 MCP 网关层。最初我们以为只需要做「MCP 请求的转发」,但实际运行后发现,80% 的价值来自安全控制平面,只有 20% 来自协议转发。认证失败、限流告警、审计日志——这些才是用户真正关心的东西。

实战场景:三种通信方式怎么选?

场景 1:一个 Agent 需要查数据库

Agent → 通过 MCP → Database Tool → 返回结果

选型:MCP(点对点、同步、工具调用)

这就是 MCP 最擅长的场景。Agent 需要查一个数据,等待结果,继续推理。不需要异步,不需要广播,不需要 Agent 协作。

场景 2:一个 Supervisor Agent 派任务给 10 个 Worker

Supervisor → 写入 Topic → Kafka → Worker 1, Worker 2, ..., Worker 10
              ← 结果 Topic ←

选型:事件总线(异步、广播、解耦)

如果 Supervisor 直接跟 10 个 Worker 同步 RPC,延迟会叠加,管理 10 个连接也很麻烦。用 Kafka:Supervisor 把任务写入 Task Topic,Worker 从各自的分区消费,完成后再把结果写回 Result Topic。Supervisor 不需要等待所有 Worker 完成——它可以在所有结果回来后一次性处理。

场景 3:两个 Agent 协作完成一个复杂任务

Agent A(分析 Agent)→ A2A Task → Agent B(可视化 Agent)→ 返回图表

选型:A2A(异步、任务驱动、状态同步)

Agent A 需要 Agent B 帮它生成一张图表。Agent A 创建 A2A Task,指定 Agent B 处理。Agent A 可以轮询进度,也可以等 Agent B 通知。如果 Agent B 处理到一半崩了,Agent A 通过状态查询知道任务中断,重新创建 Task 给另一个 Agent C。

写在最后

通信层是多 Agent 系统的「血管」。选对了,血流顺畅,系统弹性扩展;选错了,要么连接数爆炸,要么消息丢失,要么故障传递整个系统崩掉。

让我用一句话总结这个系列前两篇的核心逻辑:

编排模式决定「谁指挥谁」,通信层决定「谁跟谁怎么说话」——两者加起来,才构成多 Agent 系统的骨架。

下一篇,我们讨论演进路径——从单 Agent 到多 Agent 系统,你应该怎么演进?是直接上 A2A 还是先用 Kafka 解耦?什么时候该加网关层?MCP 和 A2A 的集成模式有哪些?

📌 本系列连载:一、《编排模式》 → 二、通信层(本篇)→ 三、演进路径 → 四、Agent 即服务

By AI博士 万戈