Agent 协议三选一:MCP、A2A、Function Calling 到底什么时候用哪个?
三种 Agent 协议听起来都在做同一件事——让 Agent 调用工具。但 Function Calling、MCP、A2A 的定位完全不同,选错了不仅代码白写,整个架构方向都会偏。
最近做多 Agent 系统的时候,遇到一个问题:Agent 到底该怎么"调用"东西?
一开始觉得这有什么好选的,不就是给模型注册几个 tool,它自己会决定什么时候调。后来发现事情远没那么简单——单 Agent 的时候 function calling 够用,但一旦切换到多 Agent 协作,工具数量从五六个暴涨到几十个,不同 Agent 要用不同的工具集,还要考虑安全、审计、跨模型兼容……function calling 那套简陋的机制根本撑不住。
于是我开始研究 MCP 和 A2A。然后发现一个更有意思的问题:
这三个东西不是互相替代的,它们根本不在同一层。
但很多教程把它们放在一起比较,导致开发者选型时一头雾水。今天这篇就理清楚:它们各自解决什么问题,什么时候用哪个,以及实际项目中怎么组合。
Function Calling:最朴素的"直接调用"
Function Calling 本质上就一个东西:模型输出一个结构化的 JSON,你的业务代码接到这个 JSON 后去执行真正的函数。
没有协议层,没有服务发现,没有权限管理。就是:
- 你在 prompt 里注册了 N 个工具的 schema
- 模型推理后选择调用哪个工具,输出 JSON-RPC 风格的调用请求
- 你的代码拿到这个请求,直接调用对应的函数
OpenAI 最早做这个,现在几乎所有模型都支持。它最大的优点就是简单——零额外基础设施,单 Agent 场景下几分钟就能跑通。
但代价也很明显:
- 工具注册信息占上下文窗口。工具越多,每轮推理的 token 成本越高
- 跨模型不兼容。OpenAI 的 schema 格式和 Claude 的不完全一样,换个模型就得改注册代码
- 没有运行时安全层。模型调用什么、不调用什么,全凭它自己判断,你没有任何中间拦截机制
- 没法热更新。新增一个工具必须重启应用,重新初始化 Agent
什么时候用 Function Calling?一句话:单 Agent、工具少于 10 个、没有跨模型需求、只做原型验证。 超出这个范围的场景,它就不够用了。
MCP:给工具调用套上标准化外壳
MCP(Model Context Protocol)解决的就是 function calling 最疼的问题——标准化。
它的思路是抽出一个独立的 MCP Server 层,统一管理工具的定义、注册和调用。Agent 不直接调函数,而是通过 MCP Client 去和 MCP Server 通信,走 JSON-RPC 协议。
这样做带来了几个关键变化:
- 工具定义与 Agent 解耦。一个 MCP Server 可以同时服务多个 Agent,不管这些 Agent 跑的是 GPT 还是 Claude
- 工具描述不占用上下文窗口。Agent 只在需要时通过 MCP Client 查询可用工具列表,而不是把所有工具 schema 塞进 prompt
- 支持热更新。新增工具只需要重启 MCP Server,不需要重启 Agent
- 统一 Schema 校验。MCP Server 可以在执行前校验参数格式,无效调用直接拒掉
听起来很美好,但 MCP 也有自己的问题。
最大的问题是它本质上是 Client-Server 架构。一个 MCP Server 暴露一组工具,Agent(作为 Client)去查询和调用。这意味着如果你有多个 Agent 协作,每个 Agent 都需要单独配置 MCP Client,没有一个全局的"工具路由"层。
另一个问题是权限粒度全靠自己实现。MCP 协议本身不定义权限控制,如果你需要细粒度权限(比如 Agent A 只能用工具 1 和 2,Agent B 可以用工具 1、2、3),得自己在 MCP Server 里写中间件。
还有一个容易被忽略的点:MCP 没有标准化 Agent 之间的通信。它只定义了 Agent 到工具的接口。如果你有两个 Agent 需要互相传递任务、共享状态,MCP 帮不上忙。
A2A:Agent 之间的通用语
A2A(Agent-to-Agent)是 Google 提出的协议,定位和 MCP 完全不同。
MCP 解决的是"Agent 怎么调工具",A2A 解决的是"Agent 之间怎么通信"。
A2A 定义了一套任务协商机制:Agent A 可以把自己的子任务委派给 Agent B,Agent B 可以接受、拒绝、或者提出修改建议。整个过程走 HTTPS + JSON-RPC,支同步和异步两种模式。
它的核心价值在于让不同框架、不同厂商的 Agent 能互相协作。你的 LangGraph Agent 可以和别人的 CrewAI Agent 通信,只要双方都实现了 A2A 协议。
这对多 Agent 系统的架构有深远影响。之前的做法是"在一个框架内建多 Agent",现在变成了"独立部署各自 Agent,通过协议互操作"。服务边界更清晰,故障隔离更好。
但 A2A 也不是银弹。它目前的成熟度远不如 function calling,生产级实现还很少。而且 A2A 不解决工具调用的问题——Agent B 接到任务后,它自己怎么调工具?这还得走 MCP 或者直接 function calling。
实战组合:三层架构
在实际项目中,这三个东西不是非此即彼,而是可以组合使用。
我目前在做的系统里走的模式是三层叠加:
- 最底层:Function Calling(或 MCP)。单个 Agent 内部,用 function calling 快速注册核心工具。工具多了之后迁移到 MCP,获得标准化和热更新能力。
- 中间层:MCP Server。管理所有工具的注册、校验和权限控制。所有 Agent 通过 MCP Client 查工具列表、调工具。
- 最上层:A2A(或自定义 Agent 通信协议)。多 Agent 之间通过 A2A 委派任务。主 Agent 收到用户请求后,拆成子任务分发给不同专业 Agent,每个专业 Agent 用 MCP 调自己的工具集。
在这个架构下,每一层只解决一个维度的问题,互不干扰。
什么时候用什么
如果你还在纠结选哪个,这里给一个粗暴的判断标准:
- 只用一种模型,工具少于 10 个 → Function Calling,别折腾
- 跨模型、工具超过 10 个、需要热更新 → 上 MCP
- 多 Agent 需要分工协作、跨框架 → 上 A2A
- 全都要、严肃生产系统 → 三层都搭,但别一次到位,先跑通 function calling,再逐步迁移
选型不是选最先进的,而是选最适合你当前阶段和预期复杂度的。你不需要在 MVP 阶段就搭完善的 MCP + A2A 架构,但你需要知道当 function calling 撑不住的时候,下一步往哪走。
评论
发表评论