澄清了A2A和MCP的定位区别:MCP连接Agent与工具,A2A连接Agent与Agent;大多数团队当前只需MCP,但A2A在第三方Agent集成场景有价值。
先从各自的位置说起,因为整个混淆来自于一个类别错误。
MCP(Model Context Protocol)是 Anthropic 在 2024 年底发布的标准,定义了单个 agent 如何访问其工具和上下文:数据库、API、文件、搜索索引。它定义了几个原语(tools、resources、prompts),使用 JSON-RPC 通信,其心智模型是垂直的。你的 agent 在顶部;它能调用的东西在它下面。关键是你的 agent 可以枚举这些工具,知道它们的名字、输入 schema 和输出形状。用 A2A 自己的话说,工具是一个"具有明确定义、结构化输入输出的原语",做着"具体的、通常无状态的"工作。
A2A(Agent2Agent)是 Google 在 2025 年 4 月引入的协议,几个月后交给了 Linux 基金会,现在作为一个厂商中立的项目存活在那里。其心智模型是水平的。你的 agent 与其他 agent 作为对等体对话。A2A 自己描述中最重要的词是"不透明":另一个 agent 是一个自主系统,"会推理、规划、使用多种工具、在更长的交互中保持状态",而这些它都不会向你展示。你看不到它的工具,看不到它的 prompt,看不到它的记忆。你给它一个任务,然后把它当作黑盒处理。
所以图景不是"A2A 对 MCP"。而是一个 agent 向下连接到自己的工具(MCP)和水平连接到其他 agent(A2A)。一个认真的多 agent 部署通常两者都运行:A2A 连接其他 agent,每个 agent 内部用 MCP 连接自己的工具。

在列举 A2A 添加了什么之前,先诚实地说说普通工具调用已经做了多少,因为它已经做了很多,而这才是你首先应该使用的。
当你的 agent 调用一个工具时(无论你是手动连接还是通过 MCP),你得到一个干净的契约。有一个名字和一个 JSON schema。调用通常是同步的:你问,你阻塞,你得到一个结构化结果或错误。两端都是你的,所以你可以更改 schema、添加字段、修复 bug 并重新部署。类型系统就在那里。如果工具返回了错误的形状,你会在自己的代码库中立即发现。
// An MCP-style tool: a contract you own and can enumerate
{
"name": "get_order",
"description": "Fetch an order by id",
"inputSchema": {
"type": "object",
"properties": { "order_id": { "type": "string" } },
"required": ["order_id"]
}
}
这就是基线。它简单、有类型、同步,而且是你的。90% 的"让我的 agent 做 X"恰恰就是这样的,叠加第二个 agent 协议纯粹是开销。所以 A2A 的门槛不是"它是否能帮助 agent 协作"。门槛是"我的问题是否有工具调用真正无法承载的形状"。以下情况下它确实无法承载。
三样东西,而且它们是一个套餐,因为它们都出于同一个设计目标:与一个你无法窥探内部的 agent 通信。
有了工具,你能看见整个契约。有了 A2A,你看不了,而且这是特性,不是缺陷。远程 agent 通过 Agent Card 宣传它能做什么——一个描述其身份、技能、端点和认证的小 JSON 文档,但不透露任何关于"如何做到"的信息。你永远不会了解到它的内部工具或推理过程。为什么你想要更少的可见性?因为另一个 agent 属于另一个团队、另一家公司或另一个信任边界,耦合到其内部正是你花多年时间学会不要对微服务犯的错误。A2A 让黑盒成为集成的单位。
// An A2A Agent Card: capability advertisement, no internals leaked
{
"name": "Fraud Review Agent",
"description": "Reviews a transaction and returns a risk decision",
"url": "https://risk.acme.com/a2a",
"version": "1.4.0",
"capabilities": { "streaming": true, "pushNotifications": true },
"skills": [
{ "id": "review_transaction", "description": "Assess a transaction for fraud risk" }
]
}
工具调用是一个函数:它返回,就结束了。很多真实的 agent 工作并不是这个形状。它运行几分钟、几小时,或者跨越一个人工审批步骤。A2A 将其建模为一个有生命周期的 Task:它经历提交(submitted)、工作中(working)、需要输入(input-required)等状态,最终完成(completed)或失败(failed)。你发一条消息,调用立即返回一个仍在工作的 Task,agent 在后台继续运行。你有三种方式获取进度:同步轮询、用于实时更新的 Server-Sent Events 流,或者在整个任务断开连接且运行时间很长时向 webhook 推送通知。尝试用单个工具调用表达"启动这个,它将花费一小时,当人工批准时 ping 我的 webhook"。你做不到,干净利落地做不到。那是一个 Task。
// message/send returns a Task that is still running, not a final answer
{
"jsonrpc": "2.0", "id": 1, "method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [{ "kind": "text", "text": "Review transaction tx_88213" }]
}
}
}
// -> Task { "id": "t_9f2", "status": { "state": "working" } }
// later: poll tasks/get, or receive a push notification, or read the stream
有了工具,你在构建时就知道有什么可用;你写进去的。A2A agent 发布 Agent Card,所以客户端可以发现一个有能力的对等体并与之协商,包括双方使用哪些内容类型和模态。这与你导入一个函数然后调用,和找到一个广告说它能做这项工作的服务之间的区别。这只在你无法控制、或不想控制完整目录的边界处才有意义。

把这三样东西回头读一遍,注意它们是同一个想法戴着三顶帽子。不透明、长运行任务和发现都是对同一种情况的答案:另一个 agent 不是你的。它是另一个团队的服务、厂商的产品、合作伙伴的系统。你无法导入它的函数,不应该看到它的内部,而且它不会在你的请求时间线上完成。
这才是真正的检验,而且它比"我是否有多 agent"要尖锐得多。你完全可以一个代码库里有五个 agent,全部是你的,连接它们的正确方式仍然是普通的函数调用或 MCP,因为你拥有它们,你可以枚举它们,而且有类型的调用在任何你能使用网络协议的地方都胜过网络协议。在两个你控制的 agent 之间放 A2A 是典型的过度工程:你用编译时检查的调用换来一个不透明的 JSON-RPC 往返,什么都没换回来,因为你为之付出代价的不透明正在保护你免受一个并不存在的边界的侵害。
A2A 在组织图的边缘赚回它的位置。你的 agent 需要风险团队 agent 的风险决策,而那个团队按自己的节奏发布,不会给你它们的内部实现。你集成一个你根本无法窥探内部的厂商研究 agent。一个合作伙伴暴露了一个预订 agent,你通过 A2A 与之协商。在每种情况下你真正需要的都不是"协作"。而是在两个不应该知道彼此内部构造的系统之间的一条稳定接缝。
这就是简化后的决策。
默认使用工具调用,当你有超过几个工具或希望它们在 agent 之间可复用时用 MCP 将其标准化。这覆盖了绝大多数"让我的 agent 能做 X"。它有类型、同步,而且是你的。
当对端是一个你不拥有或无法窥探内部的 agent、当工作是长运行的或需要在时间上有人工介入、或者你需要发现并协商一个有能力的对等体而非硬编码它时,使用 A2A。如果这些都不成立,你就是在添加一个协议来解决一个你根本没有的问题。
而且要知道它们可以组合,因为这才是你超过一个 agent 后实际会运行的架构。A2A 自己的文档用了一个汽车修理厂例子:客户通过 A2A 与修理厂的管理 agent 对话,管理 agent 通过 A2A 委托给机械师 agent,机械师通过 MCP 访问其诊断工具。向外跨边界,A2A。向内到你自己的工具,MCP。agent 在两侧是同样的东西;只是轴不同。

把协议名字和层次图剥开,你只剩下一个决定一切的问题:我调用的 agent 是我的吗?
如果是,保持简单。调用函数,连接工具,当工具集增长时用 MCP 标准化。你保留了你的类型、你的同步流,以及同时修复两端的能力。如果不是,那就是 A2A 从开销变成真正让两个你没有联合控制的系统协同工作的东西的时刻,两者都不必伸进对方的内部。
"A2A 对 MCP"从来都不是真正的问题。真正的问题是你的边界在哪里,以及边界另一边的 agent 是一个意外的黑盒还是一个设计好的黑盒。把这个弄对,协议自己就选好了。
PS: 英语不是我的母语,所以我用 AI 辅助了校对和措辞。所有的想法和技术内容都是我自己的。最初发表于 andrioboyko.com。