☰
Agent通信协议选型指南:JSON-RPC、MCP、A2A、ACP对比与实战
2026/10/14 6:41:36 网站建设 项目流程

1. 为什么 Agent 通信协议突然成了热门话题

如果你最近半年在关注 AI Agent 相关的开发,会发现一个很有意思的现象:几乎每隔几周就会冒出一个新的通信协议标准。MCP、A2A、ACP、ANP……名字一个比一个抽象,文档一个比一个长,但真正落到代码里,很多人第一反应是——我直接用 HTTP 加 JSON 不就行了吗,为什么还要搞这么多层?

这个问题我在实际做多 Agent 系统集成的时候被问过不下十次。刚开始我也觉得这些协议是过度设计,直到我试着把一个本地工具调用 Agent、一个云端推理 Agent、一个企业内部知识库 Agent 串起来跑一个完整任务流,才发现如果没有统一的通信约定,光是字段命名和错误码对齐就能耗掉一整天。

Agent 通信协议要解决的核心问题其实很朴素:让不同的 Agent 能够互相理解对方在说什么、能做什么、需要什么。听起来简单,但一旦涉及跨进程、跨网络、跨厂商、跨信任域,复杂度就指数级上升。JSON-RPC 是最早被拿来用的方案,因为它足够简单、足够通用,但它在描述能力、流式传输、能力协商这些方面很快就碰到了天花板。于是 MCP 从工具调用切入,A2A 从 Agent 间协作切入,ACP 从消息语义切入,各自试图在某个维度上做得更好。

这篇文章适合三类人看:一是正在做 Agent 系统架构、纠结选哪个协议的技术负责人;二是写过简单 Agent 调用、想理解协议层设计逻辑的开发者;三是被各种协议名词搞晕、想搞清楚它们之间到底什么关系的学习者。我会从实际使用角度出发,把 JSON-RPC、MCP、A2A、ACP 这几条线串起来讲清楚,包括它们各自解决什么问题、核心机制怎么运作、实际落地时要注意什么。

2. 从 JSON-RPC 说起:最朴素的 Agent 通信起点

2.1 JSON-RPC 为什么会被 Agent 开发者选中

JSON-RPC 本身不是为 Agent 设计的,它是一个很古老的远程调用规范,核心思想就一句话:用 JSON 格式描述一次方法调用,包含方法名、参数和请求 ID。2.0 版本规范定义了请求对象、响应对象和通知对象三种结构,请求必须有jsonrpc、method、params、id四个字段,响应必须有jsonrpc、result或error、id。

Agent 开发者选它的理由很直接:轻量、无状态、语言无关。你不需要引入 gRPC 那一套 protobuf 编译流程,也不需要理解 REST 的资源语义,只要双方约定好方法名和参数结构,就能跑起来。我最早做的一个本地 Agent 调用链就是用 JSON-RPC over stdio 实现的,主进程通过标准输入输出和子进程 Agent 通信,代码量不到两百行。

但用久了问题就暴露出来了。JSON-RPC 只规定了“怎么调用”,没规定“调用什么”。方法名是自定义的,参数结构是自定义的,错误码也是自定义的。两个不同团队写的 Agent,即使都用 JSON-RPC,也没法直接互通,因为一方叫get_weather,另一方叫fetchWeatherInfo,参数一个用city,一个用location。这就像两个人都说中文,但一个说方言一个说普通话,沟通成本极高。

2.2 JSON-RPC 在 Agent 场景下的三个硬伤

第一个硬伤是能力描述缺失。JSON-RPC 没有内建的服务发现或能力声明机制。Agent A 想知道 Agent B 能做什么,只能靠外部文档或者硬编码。在实际多 Agent 系统里,Agent 是动态加入和退出的,靠人工维护能力清单根本不现实。

第二个硬伤是流式传输支持弱。大模型推理天然是流式的,token 一个一个往外吐。JSON-RPC 的请求-响应模型是同步的,虽然可以通过通知机制模拟流式,但没有标准化的流式语义,每个实现各搞一套,互操作性很差。

第三个硬伤是错误语义不统一。JSON-RPC 定义了错误码范围,但 Agent 场景下的错误类型远比“方法不存在”“参数无效”复杂得多。工具调用超时、模型拒绝回答、权限不足、上下文超长,这些都需要结构化的错误信息,而 JSON-RPC 的 error 对象只有一个 code 和 message,表达能力不够。

实操心得:如果你只是做单机、单团队、Agent 数量少于五个的简单场景,JSON-RPC 完全够用,不要为了追新而过度设计。但一旦涉及跨团队协作或者 Agent 动态注册,就要考虑更上层的协议了。

3. MCP:从工具调用切入的标准化尝试

3.1 MCP 的核心设计思路

MCP 全称 Model Context Protocol,它的切入点非常明确:解决大模型如何标准化地调用外部工具和数据源。在 MCP 出现之前,每个模型厂商都有自己的 function calling 格式,OpenAI 一套、Anthropic 一套、开源模型又一套,开发者要写适配层写到崩溃。MCP 试图做一层抽象,让工具提供方只需要实现一次 MCP Server,就能被所有支持 MCP 的客户端调用。

MCP 的架构是典型的客户端-服务端模型。MCP Host 是运行大模型的宿主环境,MCP Client 是 Host 内部负责和 Server 通信的组件,MCP Server 是暴露工具能力的服务。通信层支持两种传输方式:stdio 用于本地进程通信,HTTP with SSE 用于远程通信。消息格式基于 JSON-RPC 2.0,但在此基础上定义了标准化的方法集。

MCP 定义了三类核心原语:Tools(可调用的函数)、Resources(可读取的数据)、Prompts(预定义的提示模板)。Tools 是最常用的,每个工具包含名称、描述和 JSON Schema 格式的输入参数定义。这个设计的好处是,大模型可以直接读取工具描述和参数 schema,自动生成符合格式的调用请求。

3.2 MCP 的能力协商与生命周期

MCP 相比裸 JSON-RPC 最大的进步是引入了能力协商机制。客户端和服务端在连接建立时会交换各自支持的能力集,包括支持哪些原语、是否支持通知、是否支持日志等。这个握手过程通过initialize方法完成,客户端发送协议版本和自身能力,服务端返回协议版本、自身能力和服务器信息。

连接建立后进入正常操作阶段,客户端可以调用tools/list获取工具列表,调用tools/call执行具体工具。服务端可以主动发送通知,比如工具列表变更、资源更新等。最后通过shutdown和exit方法优雅关闭连接。

这个生命周期设计看起来简单,但实际用起来有几个细节要注意。协议版本协商如果双方不一致,需要有一方降级或者拒绝连接。能力协商的结果决定了后续哪些方法可以调用,如果客户端没声明支持 resources,服务端就不应该主动推送资源更新通知。

3.3 MCP 实际落地时的坑

我在实际接入 MCP 的时候踩过几个坑。第一个是工具描述的质量直接决定调用准确率。MCP 把工具描述暴露给大模型,模型根据描述决定调不调、怎么调。如果描述写得含糊,模型就会乱调。我见过一个工具描述写的是“获取信息”,模型完全不知道这个工具是查天气还是查股票,调用成功率极低。后来改成“根据城市名称查询当前天气状况,返回温度和天气描述”,准确率立刻上去了。

第二个坑是stdio 传输的进程管理。MCP Server 作为子进程启动,如果 Server 崩溃了,Client 需要有重启机制。如果 Server 输出大量日志到 stderr,可能阻塞管道导致通信卡死。实际部署时建议把日志重定向到文件,stdout 只用于协议消息。

第三个坑是大参数传输。有些工具需要传入大段文本或者二进制数据,JSON-RPC 的 params 字段会变得非常大,影响传输效率。MCP 目前没有标准化的分块传输机制,实际使用时要控制单次调用参数大小,或者改用 Resources 原语来传递大数据。

对比维度裸 JSON-RPCMCP
能力描述无标准,靠约定标准化 Tools/Resources/Prompts
能力协商无initialize 握手交换能力集
流式支持需自行实现支持通知机制,流式语义较清晰
错误语义通用错误码可扩展的结构化错误
适用场景单团队简单调用跨厂商工具生态

4. A2A:Agent 之间如何平等对话

4.1 A2A 要解决的问题和 MCP 完全不同

MCP 解决的是“模型怎么调工具”,本质上是主从关系,模型是主,工具是从。但多 Agent 系统里还有另一类通信:Agent 和 Agent 之间的协作。这种场景下没有绝对的主从,每个 Agent 都有自己的目标、能力和状态,需要协商、委派、反馈。A2A 就是针对这个场景设计的。

A2A 全称 Agent-to-Agent Protocol,核心抽象是Agent Card。每个 Agent 通过 Agent Card 描述自己:名称、描述、支持的技能、认证方式、通信端点。这有点像 MCP 的 tools/list,但描述的是 Agent 整体而不是单个工具。Agent Card 通常放在一个众所周知的路径下,比如/.well-known/agent.json,其他 Agent 可以通过这个路径发现它。

A2A 的通信模型是任务导向的。客户端 Agent 向服务端 Agent 发送任务请求,服务端 Agent 返回任务状态和结果。任务可以长时间运行,支持流式更新和推送通知。这个设计比简单的请求-响应更适合 Agent 协作场景,因为很多 Agent 任务需要几分钟甚至几小时才能完成。

4.2 A2A 的任务生命周期管理

A2A 定义了一套完整的任务状态机:submitted、working、input-required、completed、canceled、failed、rejected、auth-required、unknown。这个状态机是 A2A 相比其他协议最有价值的部分之一,因为它把 Agent 协作中常见的中间状态都考虑进去了。

input-required状态特别值得说。在多 Agent 协作中,一个 Agent 执行任务到一半发现缺少关键信息,需要向发起方或者用户请求补充。如果没有这个状态,要么任务直接失败,要么 Agent 只能阻塞等待。A2A 允许 Agent 主动进入input-required状态,附带需要补充的信息说明,发起方可以异步响应后再继续任务。

流式更新通过 SSE 实现,服务端 Agent 可以在任务执行过程中持续推送状态变更和中间结果。这对于需要展示推理过程的场景很有用,比如一个研究 Agent 在搜集资料时,可以实时把找到的每条信息推送给前端展示。

4.3 A2A 和 MCP 的关系不是替代而是互补

很多人第一次接触这两个协议时会困惑:既然有了 MCP,为什么还要 A2A?答案很简单,它们解决的是不同层次的问题。MCP 管的是 Agent 内部怎么调工具,A2A 管的是 Agent 之间怎么协作。一个完整的系统可能同时用到两者:Agent A 通过 A2A 把任务委派给 Agent B,Agent B 在执行过程中通过 MCP 调用各种工具。

实际架构中,A2A 通常作为上层协作协议,MCP 作为下层工具接入协议。A2A 的 Agent Card 里可以声明该 Agent 支持哪些 MCP 工具,这样其他 Agent 在委派任务时就能知道对方的能力边界。这种分层设计让系统既有灵活的协作能力,又有标准化的工具接入方式。

注意事项:A2A 的 Agent Card 发现机制依赖网络可达的 well-known 路径,在内网或者隔离环境中需要额外配置服务发现。另外 Agent Card 里的认证信息要小心处理,不要暴露敏感凭证。

5. ACP:消息语义层的另一种思路

5.1 ACP 关注的是消息本身的结构

ACP 全称 Agent Communication Protocol,它的切入点和前两者又不一样。MCP 关注工具调用,A2A 关注任务协作,ACP 关注的是消息本身的语义结构。它试图定义一套通用的消息格式,让 Agent 之间的所有通信——不管是请求、响应、通知还是流式数据——都遵循统一的结构。

ACP 的消息模型包含几个核心字段:消息 ID、会话 ID、发送方、接收方、消息类型、负载内容、时间戳、关联 ID。这个结构比 JSON-RPC 丰富得多,特别是会话 ID 和关联 ID 的设计,让多轮对话和请求-响应关联变得很自然。

ACP 还定义了消息的优先级和过期时间。在实际 Agent 系统中,有些消息是紧急的(比如任务取消),有些是可以延迟的(比如状态同步)。有了优先级字段,传输层可以根据优先级做调度。过期时间则避免了过期消息占用处理资源。

5.2 ACP 的会话管理机制

ACP 把会话作为一等公民。一个会话可以包含多轮消息交换,会话有明确的生命周期:创建、活跃、挂起、关闭。这个设计对于需要多轮交互的 Agent 任务很友好,比如一个谈判 Agent 和另一个 Agent 来回协商参数,整个过程在一个会话里完成,上下文不会丢失。

会话状态可以持久化,这意味着 Agent 重启后可以恢复之前的会话。这对于长时间运行的任务很重要。我见过一个场景,一个数据分析 Agent 处理大批量数据需要几个小时,中间服务重启了,如果没有会话持久化,所有中间状态都丢了,只能从头再来。

ACP 的会话管理还支持会话迁移。一个会话可以从一个 Agent 实例迁移到另一个实例,这在负载均衡和故障转移场景下很有用。不过会话迁移的实现复杂度较高,需要解决状态同步和消息重放的问题,实际落地时要谨慎评估。

5.3 三种协议的实际选型建议

说了这么多,实际做项目时到底怎么选?我的经验是看你的核心需求是什么。

如果你的主要场景是让大模型调用各种外部工具和数据源,MCP 是最成熟的选择,生态支持也最广。如果你的场景是多 Agent 协作完成复杂任务,Agent 之间有明确的分工和委派关系,A2A 的任务模型更合适。如果你需要精细控制消息语义、做复杂的会话管理,ACP 提供了更丰富的原语。

但现实项目往往是混合的。我做过的一个项目就是 A2A 做 Agent 间协作,MCP 做工具接入,内部消息格式参考 ACP 的设计。协议之间不是互斥的,关键是理解每个协议解决的核心问题,然后按需组合。

协议核心抽象主要解决典型场景
JSON-RPC方法调用远程过程调用简单 Agent 调用
MCPTool/Resource/Prompt工具标准化接入模型调工具
A2AAgent Card/TaskAgent 间协作多 Agent 任务委派
ACPMessage/Session消息语义与会话复杂对话与状态管理

6. 协议背后的设计权衡与实操避坑

6.1 为什么不能有一个统一协议

每次聊到这个话题,总有人问:为什么不能有一个协议把所有事情都干了?这个问题我在设计内部系统时也想过,但实际做下来发现,不同场景的约束条件差异太大,强行统一会导致协议臃肿。

工具调用场景要求低延迟、高并发、schema 严格,因为模型要频繁调用工具,每次调用都要快速返回。Agent 协作场景要求状态可追踪、支持长任务、支持异步,因为任务可能跑很久。消息语义场景要求灵活、可扩展、支持多种消息类型。把这些需求塞进一个协议,结果就是每个场景都用不到一半的功能,但都要承担全部的实现复杂度。

另一个原因是演进速度不同。工具调用协议随着模型能力变化快速迭代,Agent 协作协议相对稳定,消息协议则变化最慢。分开设计可以让各自独立演进,不会互相拖累。

6.2 实际集成时的常见问题排查

问题一:协议版本不匹配导致握手失败。这是最常见的问题。MCP 和 A2A 都有版本协商机制,如果客户端和服务端支持的版本范围没有交集,连接就会失败。排查方法是先看双方声明的版本号,确认是否有重叠区间。实际部署时建议在配置里显式指定协议版本,不要依赖自动协商。

问题二:流式传输中断。SSE 连接可能因为网络波动、代理超时、服务端重启等原因中断。如果没有重连机制,任务就卡住了。我的做法是在客户端实现指数退避重连,同时服务端要支持从断点继续推送。A2A 的任务状态机在这里很有用,重连后先查任务当前状态,再决定从哪继续。

问题三:工具调用参数校验失败。MCP 工具的参数 schema 如果写得太严格,模型生成的参数可能因为格式微差被拒绝。比如 schema 要求integer,模型给了"5"字符串。实际使用中建议在服务端做一层宽松校验,能转换的自动转换,只对真正非法的参数报错。

问题四:Agent Card 发现失败。A2A 的 Agent Card 放在 well-known 路径,如果服务部署在子路径下或者有反向代理,路径可能不对。排查时先用 curl 直接访问 Agent Card 的完整 URL,确认返回的是合法 JSON。另外注意 Content-Type 要正确,有些实现只接受application/json。

问题五:会话状态不一致。ACP 的会话状态如果客户端和服务端不一致,会导致消息处理混乱。比如客户端认为会话已关闭,服务端还在等待消息。解决方法是引入会话状态同步机制,定期或者关键操作前做一次状态对齐。

实操心得:协议集成时一定要先写一个最小可用的连通性测试,不要一上来就集成完整业务逻辑。我通常的做法是先跑通握手、再跑通一个最简单的工具调用或任务委派、最后才接入真实业务。这样出问题时排查范围小,定位快。

6.3 性能优化的几个关键点

协议层的性能优化主要围绕三个方向:减少往返次数、压缩消息体积、并行化处理。

减少往返次数方面,MCP 的批量调用和 A2A 的任务批处理都能显著降低网络开销。如果一次需要调用十个工具,逐个调用和批量调用的延迟差距可能达到十倍。实际使用中要尽量把能合并的请求合并。

压缩消息体积方面,JSON 本身比较冗余,字段名重复出现。如果传输量大,可以考虑在传输层做 gzip 压缩,或者使用更紧凑的序列化格式。不过要注意,压缩会增加 CPU 开销,在低延迟场景下要权衡。

并行化处理方面,多个独立的工具调用或者任务委派可以并行发起。但要注意并发控制,避免压垮下游服务。我通常会给每个下游服务设置并发上限,超过上限的请求排队等待。

7. 我对 Agent 协议演进的一点观察

做了一年多 Agent 系统集成,我最大的体会是:协议的价值不在于技术多先进,而在于有多少人用。JSON-RPC 技术上很简单,但因为它足够通用,成了很多协议的基础层。MCP 能快速铺开,很大程度上是因为它背靠的生态有足够多的工具提供方愿意接入。A2A 和 ACP 还在演进中,生态成熟度还需要时间验证。

另一个观察是,协议之间的边界正在模糊。MCP 最新版本开始支持一些 Agent 协作相关的原语,A2A 也在考虑如何更好地集成工具调用。未来可能会出现某种程度的融合,但短期内多协议并存仍是常态。

对于开发者来说,与其纠结选哪个协议,不如先把核心业务逻辑和接口抽象做好。协议只是通信层,业务逻辑才是核心价值。我见过太多项目在协议选型上花了大量时间,结果业务逻辑写得一塌糊涂。先把业务跑通,协议层可以后续替换和优化。

最后分享一个实际项目中的小技巧:在协议层之上加一个薄薄的适配层,把不同协议的消息统一转换成内部格式。这样即使底层协议换了,上层业务代码不用动。这个适配层的成本很低,但带来的灵活性很高,值得在项目初期就考虑进去。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询