多 Agent 系统通信的实现原理与最佳实践

302 阅读20分钟

2026 年 7 月 28 日,Anthropic 发布了 MCP 协议的第五次大版本修订。

这次更新的核心变化只有一句话 :协议层不再维护会话状态。initialize 握手、Mcp-Session-Id 头——全删了。

每个请求自己携带身份、能力、版本号,任何一个服务器实例都能处理,普通的轮询负载均衡器可以直接用。

这个消息在开发者社区里没激起多大水花。但这个变化值得注意:一个为"上下文"(Context)设计的协议,核心连接方式却是无状态的。

HTTP 2.0 之后主流方案都在往有状态方向走(WebSocket、gRPC streaming、SSE),一个专门给 AI Agent 做工具接入的协议,却反着走到 REST 式的无状态路线上去了。

同年 3 月,A2A(Agent-to-Agent Protocol)发布了 v1.0 正式版,25,000 多个 GitHub star,六种语言的官方 SDK(Python、JS、Go、Java、.NET、Rust)。

Azure AI Foundry 和 Amazon Bedrock 都内置了原生支持。

A2A 最核心的设计选择是 :Task 对象携带完整生命周期状态。

submitted → working → input-required → completed/failed/canceled——这是一个有始有终的工作单元,不是无状态的函数调用。

MCP 的无状态化转型,本质上是职责边界的厘清——MCP 的职责是工具接入,不是会话管理。

状态应该由上层(A2A 的 Task 层、或者应用自己的编排层)来管,MCP 只管"我给你调个工具、拿个资源"。

两套协议不是竞争关系,是分层分工。


A2A 的底层:Agent 怎么发现彼此

A2A 的核心数据结构是 AgentCard——一份 JSON 自描述清单,发布在 Agent 的 /.well-known/agent-card.json 路径下(遵循 RFC 8615 的 well-known URI 规范)。

任何支持 A2A 的客户端,只需要对这个路径发一个 HTTP GET,就能知道对方是谁、能干什么、怎么认证。

这和 MCP 的发现机制有本质区别。MCP 的 Server 需要客户端显式配置连接参数(stdio 的子进程启动命令,或者 Streamable HTTP 的 URL),连接建立之后才能通过 tools/list 查询能力。

A2A 的 AgentCard 是静态的、可缓存的、不需要先建立连接的。你甚至可以把一个公开 Agent 的 AgentCard 当作文档来读。

v1.0 版本给这个发现机制加了一道关键安全措施 :Signed Agent Card。

AgentCard 的 JSON 经过 JCS(JSON Canonicalization Scheme, RFC 8785)规范化后,用 JWS(JSON Web Signature, RFC 7515)签名。

接收方可以验证签名,确认这张卡片确实来自它声称的来源域,没有被中间人篡改。

这听起来像 HTTPS 证书机制(确实类似),但有一层关键差异。HTTPS 证书验证的是"你在和正确的服务器通信",Signed Agent Card 验证的是"这个 Agent 声称的能力清单确实由该域名的所有者签发"。

在多 Agent 场景里,一个编排 Agent 可能要从几十个外部 Agent 里选人——每个都声称"我能做数据分析",但只有一个有签名可验证。没签名的,直接拒掉。

AgentCard 里声明的最关键字段是 skills:一组 AgentSkill 对象,每个包含 id、name、description、tags 和 examples。

注意这不是 MCP 的 tools——tools 是"我能调用什么函数"(原子操作),skills 是"我能完成什么任务"(复合能力)。

一个调用方通过 AgentCard 看到对方有个 financial_analysis skill,它不需要知道这个 skill 内部调了哪几个 MCP tool、用了什么模型、跑了什么 pipeline。

它只需要把任务描述丢过去,然后等结果。

这层抽象就是 A2A 设计原则里的 "opacity"(不透明性)——Agent 之间基于声明的能力协作,不暴露内部实现。

AgentCard 的具体结构:

{
  "name": "Financial Analyst Agent",
  "description": "企业财报分析与风险评估",
  "version": "1.0.0",
  "url": "https://finance-agent.example.com/a2a",
  "protocolVersions": ["1.0.0"],
  "capabilities": {
    "streaming": true,
    "pushNotifications": true
  },
  "skills": [
    {
      "id": "financial_analysis",
      "name": "财报分析",
      "description": "分析企业季度和年度财报,输出风险评分与关键指标",
      "tags": ["finance", "risk", "quarterly-report"],
      "examples": [
        "分析苹果 2026 Q2 财报的毛利率变化趋势",
        "对比特斯拉和比亚迪的现金流健康状况"
      ]
    }
  ],
  "securitySchemes": {
    "bearer": { "type": "http", "scheme": "bearer" }
  }
}

任务怎么流转:Task 生命周期与流式通信

AgentCard 解决的是"找到谁",Task 解决的是"怎么协作"。

A2A 里的 Task 是一个完整的工作单元,有全局唯一 ID、有生命周期状态机、有输入输出的 Artifact 容器。它的状态机只有六个状态:

•submitted:任务已提交,等待开始•working:Agent 正在处理•input-required:需要外部输入(通常是等人类审批或补充信息),任务挂起•completed:正常完成,Artifact 可用•failed:执行失败,附带错误信息•canceled:被调用方主动取消

这个状态机里一个关键设计是 input-required。它解决了一个在异步 Agent 系统里经常被忽视的问题:人类在回路里怎么不阻塞整个系统。

传统 RPC 调用,超时就失败了——人类审批可能需要几个小时,这没法用"超时"处理。

A2A 的设计是:任务遇到需要人介入的节点,状态切到 input-required,推送通知给调用方,然后整条链路该干嘛干嘛,不会有一个 Agent 傻等着。

Task 内部的消息(Message)和产出物(Artifact)通过 Part 承载。Part 是一个联合类型(union type),可以是文本(TextPart)、文件引用(FilePart,URI + MIME 类型)、或者结构化数据(DataPart,任意 JSON object)。

多个 Part 组成一条 Message,多条 Message 组成一个 Task 的对话历史。多个 Artifact 组成 Task 的最终产出,支持增量追加(流式生成场景)。

这层数据模型让 A2A 可以同时处理"聊天式协作"和"结构化工作流"——你可以在同一个 Task 里先用自然语言描述需求,再收一个结构化的 JSON 分析结果。


通信传输层上,A2A 提供了一组操作原语,核心是 SendMessage(请求-响应)和 SendStreamingMessage(流式订阅):

SendMessage 是标准请求-响应模式。客户端发一条 Message,服务端同步返回 Task 对象(可能已完成,也可能还在 working),客户端之后通过 GetTask 轮询结果。

SendStreamingMessage 是流式模式。客户端发消息的同时订阅 SSE(Server-Sent Events)通道,服务端实时推送 TaskStatusUpdateEvent(状态变更)和 TaskArtifactUpdateEvent(产出物增量更新)。

SSE 流在 Task 到达终态(completed/failed/canceled)时关闭。

两种模式的取舍取决于任务时长。Google 的建议是:预期 2 秒内完成的任务用 SendMessage 轮询,超过 2 秒的用 SendStreamingMessage 流式。

这个 2 秒阈值来自于 TCP 连接建立开销和 HTTP 请求延迟的经验值——短任务做流式反而因为建连开销拖慢整体。

还有一种更彻底的模式:Push Notification。Agent 可以主动向调用方配置的 webhook URL 推送状态更新。这对于跨服务器、跨时区的长时间任务尤其有用——调用方不需要维护一个 HTTP 长连接,Agent 完成后自己找上门来。

传输层还有一层考虑:v1.0 的 A2A 把传输绑定从 JSON-RPC 扩展到了 gRPC,不是简单加个选项,而是把 Protocol Buffers 的 .proto 文件提升为"规范源"(normative source of truth)。

a2a.proto 定义数据结构,HTTP+JSON 和 JSON-RPC 的序列化格式从它派生。这意味着 A2A 的核心数据模型和传输协议是解耦的:你可以用 JSON-RPC over HTTP 和 gRPC 跟同一个 Agent 聊天,AgentCard 里的 AgentInterface 让你知道它支持哪种。

这跟 MCP 差别很大。MCP 的传输层只有 stdio 和 Streamable HTTP 两种,JSON-RPC 是唯一的消息编码格式。

A2A 选择多传输绑定,是因为它要面对的场景比"工具调用"复杂得多——有些场景需要 gRPC 的双向流来做 Agent 之间的大规模数据交换,有些场景只需要一条 HTTP POST 抛个任务过去。


MCP 的无状态转型:从会话到自描述请求

回到 MCP 的 2026-07-28 更新。这个版本改的不只是"删了 session"这么简单,它触及的是一个更根本的问题:MCP 在 Agent 通信栈里的职责边界。

之前的 MCP 是这样的:客户端先 initialize 握手,服务器返回 Mcp-Session-Id,此后所有请求都带着这个 ID。

这意味着同一个客户端的连续请求必须路由到同一个服务器实例——要么用粘性会话(sticky session),要么所有实例共享一个 session store。

在本地 stdio 模式下这没问题(一个子进程就一个连接),但在远程 Streamable HTTP 模式下,这对负载均衡器和水平扩展是个不小的限制。

2026-07-28 改了什么?六个 SEP(Specification Enhancement Proposals)协同作用,完成了无状态化。最核心的三项变化:

1删除 initialize/initialized 握手——每次请求在 _meta 字段里携带协议版本、客户端信息、客户端能力声明。2MRTR(Multi Round-Trip Requests)替代了旧版的 elicitation/create 和 sampling/createMessage——当服务器需要在处理中途向客户端要更多信息时,返回一个 InputRequiredResult,而不是保持 SSE 长连接等待。3缓存的引入——tools/list、resources/list 等高频查询响应可以带 ttlMs 和 cacheScope 字段,网关层可以直接缓存,减少对 MCP 服务器的请求压力。

配套优化还包括 server/discover RPC 主动查询、UnsupportedProtocolVersionError 直接返回、以及 Mcp-Method 和 Mcp-Name HTTP 头用于网关路由。

这些改动背后的设计判断是 :MCP 的职责是工具接入,不是会话管理。会话是有状态的,状态应该由上层(A2A 的 Task 层、或者应用自己的编排层)来管。

MCP 只管"我给你调个工具、拿个资源"——单次调用、独立完成、无副作用(至少协议层看上去是无副作用的)。

这个判断在工程上是成立的。如果 MCP 要同时管工具调用和会话状态,它会变成一个"胖协议"——既要处理 OAuth 认证、又要维护 SSE 长连接、还要在不同服务器实例之间同步 session state。

胖协议的演进速度慢、跨语言 SDK 适配复杂、出 bug 时定位困难。瘦下来之后,每个 MCP Server 只做一件事:收请求、调工具、返回结果。其余的事情交给上层。


但在多 Agent 场景下,MCP 授权模型的设计约束会凸显出来。

MCP 的授权模型分两层:stdio 模式靠宿主进程的权限(服务器作为子进程运行,继承宿主应用的文件系统和网络权限),Streamable HTTP 模式靠 OAuth 2.1(客户端通过授权服务器获取 scope-token)。

但在多 Agent 场景里,当一个编排 Agent 需要让 3 个子 Agent 分别访问 3 个 MCP Server 时,"谁授权了谁"这件事会迅速复杂化。

A2A 在 OAuth 2.0 授权框架下支持受限 token 委派:编排 Agent 拿到用户授权的 token,在向下委派任务时把 token 换成一个 scope 更小的子 token——"你能访问数据库,但只能查,不能写"。

MCP 目前没有内置这套委派链机制,它假定每个 MCP 客户端是一个独立的 trust principal。

但这不意味着 MCP 在多 Agent 场景里没用。恰恰相反 ——每个 Agent 都应该有自己的 MCP 连接。

A2A 管 Agent 之间怎么协作,MCP 管每个 Agent 自己怎么调用工具。这是一个分层架构,不是一个"选 A 还是选 B"的问题。


五种通信拓扑,以及什么时候该用哪种

协议层面讲完了,现在看架构层面——Agent 之间以什么拓扑组织。

业界有大量框架(LangGraph、CrewAI、AutoGen 等)在实现层面对拓扑做了封装,但说到底层结构,可以归纳为五类(这个分类来自 arXiv:2502.14321 的通信视角综述):

1. 星型(Hierarchical)

一个中央编排 Agent 负责拆任务、分派给子 Agent、收结果、组装。所有通信都经过中心节点。

LangGraph 的 Supervisor 模式、CrewAI 的 Hierarchical Process 都是这种。

优点是可调试性最好:所有状态变更都经过一个点,你只需要审查编排 Agent 的日志就能知道全局发生了什么。

缺点是中心节点是单点瓶颈,它既要拆任务又要合结果,当 Agent 数量超过 15 个,编排 Agent 自己的 context window 会成为硬限制。

2. 网型(Flat/Mesh)

Agent 之间对等通信,没有中心节点。A2A 协议的原始设计就支持这种——任何一个 Agent 都可以通过 AgentCard 发现另一个,直接发起 Task。

优点是故障隔离:一个 Agent 挂了不影响其他人。

缺点是调试难度指数级:10 个 Agent 互相通信产生的消息量是 O(n²),"为什么 Agent C 收到了错误数据"这件事可能追溯到 3 跳之前的 Agent A。

3. 团队型(Team)

Agent 按角色分组成团队,团队内部紧密协作,团队之间通过指定接口通信。MetaGPT 的"产品经理-架构师-工程师-测试"结构就是团队型的典型实现。

这种拓扑适合角色边界清晰的任务,如软件开发、内容审核、供应链管理等。

弊端在团队之间的接口设计:接口太窄(只传最终结果),下游团队拿到不完整信息;接口太宽(传全部上下文),又会触发 context 膨胀。

4. 社会型(Society)

Agent 在一个共享环境里自由交互,没有预设的通信路径。行为模式通过环境规则涌现。

Generative Agents(斯坦福的 25 个 Agent 小镇实验)是典型例子。

这种模式适合社会模拟和博弈研究,不适合生产系统——它的行为不可预测,出错时没有"回滚到上一个正确状态"的路径。

5. 混合型(Hybrid)

星型管外层流程,网型管内层协作。

比如一个编排 Agent 负责整体 workflow,把其中"代码审查"这一步委派给 3 个审查 Agent 互相 debate,用 majority voting 决定最终结果。

这是 2026 年生产系统里最常见的模式,因为它在可控性和灵活性之间找到了工程上可操作的平衡点。


选哪种拓扑,取决于三个约束:

•Agent 数量:少于 5 个,星型最省事;5-15 个,考虑混合型;超过 15 个,必须用网型或团队型(星型的编排瓶颈已经到了)。•任务的可分解性:能清晰分解成独立子任务的,星型效率最高;子任务之间有交叉依赖的,网型更合适。•审计要求:需要完整追踪"谁在什么时候为什么做了这个决定"的,星型最优(一个节点有全量日志);对审计要求不高的内部实验,网型更灵活。

关于拓扑和模型选择的关系,有一组数据值得注意:AdaptOrch 项目(arXiv:2602.16873)测试发现,拓扑结构对系统性能的影响比模型选择更大。

在相同的 Agent 数量下,正确的拓扑选择能带来 12-23% 的性能提升,而换一个更大更贵的模型,收益远小于这个幅度。


四种典型失败模式

下面这些坑不在论文里,是生产环境的工程团队实际踩过的。

1. 无限循环(Infinite Agentic Loops)

这是多 Agent 系统里常见且代价高昂的故障模式。两个或更多 Agent 陷入循环通信:Agent A 产出代码,Agent B 发现问题要求修改,Agent A 改了但引入新 bug,Agent B 再次拒绝——理论上永远不会停下来。

问题会同时从三个方向爆发:API 费用(每次循环都是一次 LLM 调用)、CPU(循环不暂停)、context 膨胀(每次循环都在对话历史里追加内容)。

IAL-Scan 项目(arXiv:2607.01641)扫描了 6,549 个 Agent 项目的代码仓库,在 47 个项目中找到了 68 个"无限循环漏洞"——多数集中在 LangGraph 和 AutoGen 框架。

这些漏洞的 69.1% 来自三个原因:

•重试反馈没有次数上限•工具调用迭代没有次数上限•多 Agent 对话没有轮次上限

通用防护手段:所有 Agent 强制设硬上限(MAX_TURNS=10、MAX_TOOL_CALLS_PER_AGENT=20、recursion_limit),再加上状态哈希检测——如果连续两轮的系统状态相同,自动中断。

没有这些限制的多 Agent 系统存在较高的故障风险。

2. 上下文丢失与漂移(Context Drift)

Agent 之间的每次交接都是一次"传话游戏"。第一个 Agent 输出 3,000 个 token 的分析报告,传给第二个 Agent。

第二个 Agent 拿到的不只是报告,还有编排 Agent 的指令、第一个 Agent 的产出、第二个 Agent 自己的 system prompt——如果这些加起来超过它的 context window,模型会从最早或最不相关的内容开始丢弃。

丢掉的可能恰好是第一个 Agent 输出的关键结论。

对此,一个被验证过的缓解方案是按 Agent 隔离上下文(per-agent scoped memory snapshot)。每个 Agent 的输入只包含它当前任务需要的 state key,而不是整个系统的共享状态。

合并策略(last-write-wins 或 majority vote)显式声明,不在隐式行为里埋雷。某生产团队实施了这个方案后,context 损坏事故显著减少。

3. 幻觉级联放大(Cascading Hallucination)

这是多 Agent 系统里危害最隐蔽的故障模式——因为它的表面没有任何报错。

Agent A 产出了"苹果 2026 Q2 毛利率 48.5%"(实际是 46.9%)。Agent B 拿到这个数据,用它做行业对比分析,得出"苹果毛利率超行业均值 12 个百分点"的结论。

Agent C 拿到 B 的分析,写成最终报告:"苹果盈利能力远超同业"。三个 Agent 每一步都"执行正确"(格式对、逻辑对、没有报错),但最终输出从第一跳就错了,后面两跳只是把错误包装得越来越像真的。

arXiv:2606.07941 的论文专门研究了多 Agent 系统中的集体幻觉现象。图网型拓扑里,错误信息会在 Agent 之间交互传播并相互强化,每个下游 Agent 不仅接收了上游的错误输入,还会基于它做"论证补充",让错误看起来更可信。

缓解方案不是靠模型能力提升(幻觉问题在可预见的未来不会消失),而是靠验证节点:在关键交接点,用外部数据源做事实核查。

MCP 在这个场景里有天然优势:每个 Agent 的内部工具调用可以绑定验证逻辑,"拿到的数据点先跟权威数据库对一下,对不上就标 uncertain"。

4. 回声室放大(Echo Chamber Amplification)

当多个 Agent 在同一个问题上达成一致时,系统会变得越来越自信,即使这个"一致"从一开始就建立在错误的基础上。

三个 Agent 都觉得"A 方案最优",不是因为 A 真的最优,而是因为 Agent B 和 C 看到了 Agent A 的结论后,用"A 是对的这个前提"去搜证据来支持它。这和人类的"确认偏误"机制几乎完全一致。

解决思路不是让 Agent 更聪明,而是在结构上阻断同质化:

•引入外部视角:用 web search 或知识库做独立验证•引入分歧机制:显式指派一个 Agent 扮演"反对者"角色•引入不确定性量化:要求 Agent 对每个输出附带置信度,低置信度的输出不给下游 Agent 做决策依据


一行代码不用改的生产经验

把协议和拓扑放进生产环境,有几条实践在反复验证中站住了脚。

每条 Agent 交接都是 API 契约——用 JSON Schema 校验上游输出,不合规的直接拒掉,而不是用"下游 Agent 应该能容错"来自欺欺人。

MCP 的工具定义本身就是 JSON Schema,A2A 的 Task Artifact 可以附带 schema 声明,这些机制已经在了,缺的是工程纪律。

流式 > 轮询,缓存共用 > 独立推理。FLASHAGENTS(MLSys 2026)与 KVCOMM(arXiv:2510.12872)都验证了 KV Cache 跨 Agent 复用的收益:KVCOMM 在 5 个 Agent 的设置中把首 token 延迟从 430ms 降到 55ms(7.8 倍),FLASHAGENTS 在链式调用中实现了 3.5 倍的推理加速。

实现复杂度不低,但对于高频交互的多 Agent 系统,这是值得的投入。

OpenTelemetry + W3C Trace Context——在每次 A2A 调用时传播 traceparent 头,记录 taskId、contextId 和认证 Agent 的身份。

没有分布式 trace 的多 Agent 系统在生产环境是一个黑箱。"为什么这个 ticket 的处理花了 3 分钟"这类问题会浪费大量排查时间。

安全不只是"认证" 。MCP 的 stdio 模式在 2026 年 4 月被 OX Security 发现了一个 RCE 漏洞:客户端读取的 MCP 配置里的 server 启动命令字符串会被直接传给操作系统的 shell 执行,如果配置文件被攻击者写入,就获得了任意代码执行权限。

A2A 的 Signed Agent Card 是必要的,但不够,在实际部署中,API Gateway 统一做 OAuth 2.0/OIDC 验证、rate limiting、请求日志,是标准做法。


分歧和收敛

A2A 和 MCP 之外还有几个协议在演进。

IBM 的 ACP(Agent Communication Protocol)最初是为 BeeAI 平台设计的 REST 式 Agent 通信协议,支持多模态消息和异步流式传输。

2025 年 8 月 ACP 并入 A2A,减少 Agent-to-Agent 层的碎片化。

ANP(Agent Network Protocol)走了另一条路:基于 W3C DID(Decentralized Identifier)和 JSON-LD 的去中心化方案,目标场景是跨组织的 Agent 市场("我的 Agent 公开接任务,你的 Agent 通过 DID 发现我,不需要中心化的注册中心")。

目前的落地还少,但设计理念对去中心化场景有参考价值。

Agora 是一个更激进的方向——它不固定协议,而是让 Agent 自己协商用什么协议通信("元协议")。这个方向的实用化还有距离。

值得关注的是正在进行的标准化努力。IETF 在 2026 年 7 月的维也纳会议上以 154-51 的票数决定成立 agentproto 工作组,虽然初始范围提案被 38-124 否决(社区认为范围没想清楚),但方向是明确的——Agent 通信正被当作互联网基础设施层的问题来对待。

W3C 也在 2025 年 5 月成立了 AI Agent Protocol Community Group(由 ANP 社区发起)。

整个协议生态在往一个方向收敛 :分层共存,不是单一胜者。就像 HTTP、WebSocket、gRPC 在同一个互联网基础设施里各管各的层——MCP 管工具接入,A2A 管 Agent 协作,AG-UI(Agent-User Interaction)管前端交互。

三层的职责边界正在变清晰。


参考来源: