一、为什么会出现 A2A?
我们先从一个真实的业务场景说起。
假设我们现在做了一个智能运维 Agent 系统,里面有几个不同的 Agent:
- 告警分析 Agent:负责分析 Prometheus 告警;
- 日志检索 Agent:负责查询日志系统;
- 知识库 Agent:负责从 RAG 知识库中检索历史方案;
- 报告生成 Agent:负责把诊断过程整理成报告;
- 调度 Agent:负责判断下一步该交给谁处理。
如果这些 Agent 都在同一个项目里,同一个 Spring Boot 服务中,那我们可以通过 Java 方法调用、Graph 节点、状态机、消息队列等方式组织它们。
但如果这些 Agent 不是一个系统里的呢?
比如:
- 告警 Agent 是你自己用 Spring AI 写的;
- 工单 Agent 是另一个团队用 Python LangGraph 写的;
- 审批 Agent 是某个 SaaS 平台提供的;
- CRM Agent 是第三方厂商提供的;
- 数据分析 Agent 运行在另一个云平台上。
这时候问题来了:
它们怎么互相发现?
怎么知道对方能干什么?
怎么把任务交给对方?
怎么拿到执行结果?
怎么处理长任务?
怎么知道任务是成功、失败、等待中,还是需要补充信息?
这就是 A2A 想解决的问题。
A2A 的出现,本质上是因为 Agent 系统开始从"单体智能体"走向"网络化智能体"。
以前我们关心的是:
我的 Agent 能不能调工具?
现在开始变成:
我的 Agent 能不能和别人的 Agent 协作?
这背后的变化很关键。
二、A2A 到底是什么?
A2A,全称 Agent2Agent Protocol,可以理解为一种 Agent 之间通信和协作的开放协议。
它不是一个大模型。
它不是一个向量数据库。
它不是 RAG。
它也不是 Spring AI、LangChain、LangGraph 这种 Agent 开发框架。
它更像是一套"Agent 之间打交道的通用语言"。
举个生活化的例子。
你去公司找人办事,不能直接冲进每个办公室问:"你会干啥?能不能帮我干活?"
正常流程应该是:
- 先知道这个部门负责什么;
- 再知道找谁处理;
- 把需求说明白;
- 对方开始处理;
- 处理中可能让你补材料;
- 最后给你一个结果。
A2A 做的事情其实也类似。
它让一个 Agent 可以:
- 发现另一个 Agent 的能力;
- 读取对方的能力描述;
- 给对方发送任务;
- 跟踪任务状态;
- 接收中间消息;
- 获取最终产物;
- 处理任务失败、取消、等待等情况。
也就是说,A2A 不是让模型变聪明,而是让 Agent 之间有了协作规范。
这点非常重要。
很多人一听到 A2A,就以为它是某种"更高级的多 Agent 框架"。其实不是。A2A 更偏通信协议和协作标准,它解决的是 Agent 系统之间的互操作问题。
三、A2A 和 MCP 的区别
这里一定要讲清楚,因为很多人最容易把 A2A 和 MCP 混在一起。
一句话区分:
MCP 解决 Agent 连接工具的问题,A2A 解决 Agent 连接 Agent 的问题。
我们可以这样理解:
| 对比项 | MCP | A2A |
|---|---|---|
| 连接对象 | 工具、数据源、资源 | 另一个 Agent |
| 核心问题 | Agent 怎么使用外部能力 | Agent 怎么和 Agent 协作 |
| 典型场景 | 查数据库、读文件、调 API、访问知识库 | 委托任务、跨系统协作、多 Agent 联动 |
| 对方身份 | 工具服务 | 智能体服务 |
| 交互特点 | 更像"调用函数" | 更像"派发任务 + 等待结果" |
| 关注重点 | tool/resource/prompt | capability/task/message/artifact |
比如用户问:
帮我查一下最近 1 小时的系统错误日志,并分析是不是数据库连接池打满了。
如果是 MCP 思路,Agent 可能会调用:
- 日志查询工具;
- 数据库监控工具;
- Prometheus 查询工具;
- 知识库检索工具。
这些工具本身不会主动思考,它们只是被调用。
但如果是 A2A 思路,当前 Agent 可能会说:
这个问题需要交给"运维诊断 Agent"处理,它更擅长告警、日志、链路追踪分析。
于是它把任务发给另一个 Agent。
被调用的那个 Agent 不是简单工具,它可能自己也会规划步骤、调用工具、检索知识库、生成诊断结论。
这就是两者最大的区别。
MCP 里的工具通常是"能力"。
A2A 里的 Agent 是"带目标理解和执行过程的协作者"。
所以 MCP 和 A2A 并不冲突,它们反而是互补关系。
一个完整的 Agent 系统里可能是这样的:
用户
↓
主 Agent / Supervisor Agent
↓
A2A 调用其他 Agent
↓
每个 Agent 内部再通过 MCP 调用工具
↓
工具访问数据库、日志、文档、API、知识库
也就是说:
A2A 管 Agent 之间的协作,MCP 管 Agent 和工具之间的连接。
这就是它们最清晰的边界。
四、A2A 为什么不是简单的 HTTP 调用?
有人可能会说:
Agent 调 Agent,不就是一个 HTTP 接口吗?我写个 RestTemplate 或 OpenFeign 不就行了吗?
这句话对一半,也错一半。
从底层通信看,A2A 确实可以基于 HTTP、JSON-RPC、SSE 这些 Web 技术来实现。
但 A2A 的价值不只是"能发请求"。
真正的问题是:
- 你怎么描述一个 Agent 的能力?
- 你怎么让别的 Agent 发现你?
- 你怎么表示一个任务?
- 你怎么跟踪任务状态?
- 你怎么支持长时间任务?
- 你怎么返回结构化结果?
- 你怎么处理流式消息?
- 你怎么表达任务失败原因?
- 你怎么让不同语言、不同框架的 Agent 都能理解?
普通 HTTP 接口当然也能做,但每个团队都会自己定义一套格式。
比如 A 团队这样写:
{
"question": "分析日志",
"type": "log_analysis"
}
B 团队这样写:
{
"taskName": "analyze_logs",
"input": {
"content": "xxx"
}
}
C 团队可能又这样写:
{
"messages": [
{
"role": "user",
"content": "帮我分析日志"
}
]
}
如果没有统一协议,系统一多,就会变成接口地狱。
A2A 想做的就是把这些东西标准化。
它不是说你不能自己写 HTTP,而是说:
Agent 之间协作不能永远靠每个项目自己约定格式。
这就像微服务之间当然可以裸写 HTTP,但后来为什么会有 OpenAPI、gRPC、服务注册发现、网关、鉴权、Tracing?
因为系统复杂之后,光能调用是不够的,还需要规范。
五、A2A 中几个关键概念
为了避免讲得太抽象,我们可以把 A2A 拆成几个核心概念理解。
1. Agent Card:Agent 的能力名片
Agent Card 可以理解为一个 Agent 的"自我介绍"。
它告诉别人:
- 我是谁;
- 我能做什么;
- 我支持什么输入;
- 我支持什么输出;
- 我有哪些能力;
- 我访问地址是什么;
- 我支持哪些交互方式。
这就像一个服务的 API 文档,但它不是单纯描述接口,而是描述一个 Agent 的能力。
比如一个日志分析 Agent 的 Agent Card 可以表达:
{
"name": "LogAnalysisAgent",
"description": "负责查询和分析应用日志,定位错误堆栈和异常趋势",
"skills": [
{
"name": "analyze_error_logs",
"description": "分析指定时间范围内的错误日志"
}
]
}
这样其他 Agent 就能知道:
哦,这个 Agent 适合处理日志分析类任务。
这比硬编码调用某个接口要灵活很多。
2. Task:把问题变成可跟踪的任务
A2A 不是简单地问一句、答一句。
很多 Agent 任务是长流程的。
比如:
分析昨天凌晨数据库连接池异常,并生成复盘报告。
这个任务可能要经历:
- 查询告警;
- 查询日志;
- 查询数据库监控指标;
- 检索历史故障知识库;
- 判断根因;
- 生成报告;
- 等待人工确认。
这不是一次普通方法调用能优雅表达的。
所以 A2A 中有 Task 的概念。
Task 可以有状态,例如:
- submitted:已提交;
- working:处理中;
- input-required:需要补充信息;
- completed:已完成;
- failed:失败;
- canceled:已取消。
这样一个 Agent 把任务交给另一个 Agent 后,不是傻等,而是可以持续跟踪任务状态。
这点对企业级 Agent 很关键。
因为真实业务里很多任务不是秒级完成,而是长时间、多步骤、可中断、可恢复的。
3. Message:Agent 之间的对话消息
Message 可以理解为 Agent 之间沟通的基本载体。
一个 Agent 可以给另一个 Agent 发送消息,对方也可以回复消息。
这和普通聊天消息类似,但它不是单纯给人看的聊天内容,而是 Agent 协作过程中的信息交换。
比如:
主 Agent:请分析服务 A 在 10:00-11:00 的错误日志。
日志 Agent:需要指定环境,是 dev、test 还是 prod?
主 Agent:prod。
日志 Agent:已开始分析,发现 10:23 开始错误率升高。
你会发现,这更像两个同事之间协作,而不是一个函数调用。
这也是 A2A 和 Function Calling 的区别。
Function Calling 是模型决定调用哪个函数。
A2A 是 Agent 把一个任务交给另一个 Agent 处理。
4. Artifact:任务的最终产物
Artifact 可以理解为 Agent 执行任务后生成的结果产物。
它可以是:
- 一段文本;
- 一个 JSON 结果;
- 一份报告;
- 一个文件;
- 一张图;
- 一组结构化数据。
比如运维诊断 Agent 最终返回:
{
"rootCause": "数据库连接池耗尽",
"evidence": [
"10:23 开始 HikariPool active connections 达到上限",
"应用日志出现大量 connection timeout",
"同时间段慢 SQL 数量明显增加"
],
"suggestion": "建议扩容连接池并排查慢 SQL"
}
这就是一个结构化 artifact。
在复杂 Agent 系统中,artifact 很重要,因为它让 Agent 的产出不只是自然语言,而是可以继续被其他系统消费。
六、把 A2A 放到我们熟悉的 Spring AI 项目里理解
我们现在从 Java / Spring AI 项目的角度来理解 A2A。
假设我们有一个主 Agent:
SupervisorAgent
它负责接收用户问题,然后判断要不要交给其他 Agent。
现在系统里有三个 Agent:
RagAgent:负责知识库问答
OpsAgent:负责运维诊断
ReportAgent:负责报告生成
如果它们都在同一个 Spring Boot 应用里,我们可以这样调用:
String result = opsAgent.invoke(userQuestion);
这属于进程内方法调用。
如果它们是同一个服务里的不同 Bean,也可以通过 Spring 注入调用。
但是如果 OpsAgent 是另一个服务,甚至是另一个团队写的 Python 服务,那就不能直接 Java 方法调用了。
这时候就需要一个统一的远程协作协议。
A2A 的意义就在这里。
它可以让 SupervisorAgent 不关心对方到底是 Java 写的、Python 写的,还是某个 SaaS 平台提供的。
SupervisorAgent 只需要知道:
这个 Agent 能不能处理我的任务?
怎么把任务发给它?
怎么拿到任务状态?
怎么拿到最终结果?
这就像微服务之间通过统一协议通信一样。
只不过过去微服务传递的是确定性业务请求,而现在 Agent 之间传递的是更复杂的任务意图。
七、A2A 和 Graph 编排有什么关系?
我们最近也一直在聊 Graph、DAG、多 Agent 编排。
那 A2A 和 Graph 是不是一个东西?
不是。
Graph 更偏"内部编排"。
A2A 更偏"外部通信"。
比如在一个 Agent 系统内部,我们可以用 Graph 来组织执行流程:
用户问题
↓
Planner Node
↓
Executor Node
↓
Reflection Node
↓
Replan Node
↓
Final Answer Node
这个 Graph 是你系统内部的执行逻辑。
但 A2A 关注的是:
当这个系统需要调用另一个独立 Agent 系统时,双方怎么通信?
所以它们的关系可以这样理解:
Graph:管理一个 Agent 系统内部怎么流转
A2A:管理不同 Agent 系统之间怎么协作
当然,它们也可以结合。
比如你的 Graph 中有一个节点叫:
CallRemoteAgentNode
这个节点的作用就是通过 A2A 调用外部 Agent。
整体流程可能是:
Start
↓
理解用户问题
↓
判断任务类型
↓
如果是本地能力 → 本地工具调用
↓
如果是外部能力 → 通过 A2A 委托远程 Agent
↓
接收远程 Agent artifact
↓
汇总最终答案
这样一来,Graph 负责流程控制,A2A 负责跨 Agent 通信。
这才是比较工程化的理解。
八、A2A 对 RAG 系统有什么价值?
很多人会觉得 A2A 和 RAG 没关系。
其实不是。
传统 RAG 系统通常是这样的:
用户问题
↓
Query 改写
↓
向量检索 / BM25 检索
↓
Rerank
↓
拼接上下文
↓
LLM 生成答案
这是一个单系统内部的链路。
但在真实企业环境里,知识往往分散在多个系统:
- 一个 Agent 管公司制度文档;
- 一个 Agent 管项目文档;
- 一个 Agent 管历史工单;
- 一个 Agent 管数据库元数据;
- 一个 Agent 管日志和监控;
- 一个 Agent 管代码仓库。
如果用户问:
为什么订单服务昨天晚上出现大量超时?结合日志、监控和历史故障记录分析一下。
这时候一个 RAG 知识库可能不够。
你需要多个 Agent 协作:
监控 Agent:分析指标异常
日志 Agent:分析错误日志
知识库 Agent:检索历史故障
代码 Agent:分析最近提交
报告 Agent:汇总结论
A2A 的价值就是让这些 Agent 可以互相协作,而不是全部塞进一个超级大的 Agent 里。
这也符合未来 Agent 系统的发展趋势:
不是把一个 Agent 做得无限大,而是让多个专业 Agent 通过协议协作。
这点非常像软件工程里的微服务思想。
以前我们不建议把所有业务写进一个单体应用。
以后我们也不会建议把所有智能能力塞进一个超级 Agent。
九、A2A 带来的工程挑战
A2A 听起来很美好,但真正落地时并不简单。
1. 能力描述可信度问题
一个 Agent 说自己能分析日志,它真的能分析好吗?
一个 Agent Card 写得很漂亮,但实际效果可能很差。
这就带来一个问题:
Agent 的能力声明不等于真实能力。
所以未来 Agent 协作系统里,可能还需要:
- 能力评估;
- 调用成功率统计;
- 历史表现评分;
- 结果质量反馈;
- 黑名单 / 白名单机制。
否则主 Agent 很可能把任务交给一个"看起来很强,实际很水"的 Agent。
这和人类团队协作也一样。
一个人简历写得很强,不代表项目一定能交付。
2. 上下文传递问题
Agent 协作不是简单传一句话。
比如用户问:
结合我上周上传的那份系统架构文档,分析一下这次告警原因。
这里面包含大量上下文:
- 用户是谁;
- 文档是哪份;
- 权限是否允许;
- 历史对话说了什么;
- 当前任务目标是什么;
- 输出格式有什么要求。
如果 A2A 调用时只传一句"分析告警",远程 Agent 很可能答偏。
所以 A2A 解决通信标准,但不自动解决上下文工程。
真正落地时,仍然要设计:
- 上下文裁剪;
- 敏感信息过滤;
- 用户权限传递;
- 会话 ID;
- traceId;
- taskId;
- 引用材料;
- 输出约束。
这也是为什么 Agent 工程不是只学协议就够了。
协议解决"能不能通信",上下文工程解决"通信时带什么"。
3. 安全和权限问题
Agent 调 Agent 的时候,权限边界会更复杂。
比如 A Agent 有权限访问日志系统,B Agent 没有。
那 B Agent 通过 A2A 调用 A Agent 时,能不能间接获得日志数据?
再比如一个外部 Agent 请求内部 Agent 查询用户订单信息,它是否有权限?
所以企业里做 A2A,必须考虑:
- 身份认证;
- 权限校验;
- 数据脱敏;
- 审计日志;
- 调用链路追踪;
- 结果可解释性。
否则 Agent 之间一旦乱调,风险会非常大。
过去微服务里有接口权限问题。
未来多 Agent 系统里会有 Agent 权限问题。
4. 失败处理问题
普通工具调用失败,可能就是抛异常。
但 Agent 任务失败可能更复杂。
比如:
- 远程 Agent 不可用;
- 任务超时;
- 对方需要补充信息;
- 对方返回低置信度结果;
- 对方执行到一半失败;
- 多个 Agent 结果互相冲突。
所以主 Agent 不能只写:
try {
callRemoteAgent();
} catch (Exception e) {
return "调用失败";
}
而是要有更完整的任务状态处理:
如果远程 Agent 需要补充信息 → 回问用户
如果远程 Agent 超时 → 尝试降级方案
如果结果置信度低 → 调用另一个 Agent 交叉验证
如果多个结果冲突 → 进入 Reflection / Replan
这就和我们之前聊的 Plan-Execute-Replan 联系起来了。
A2A 提供协作通道,但真正的智能调度逻辑,仍然要由你的编排层完成。
十、一个简单的 Java 伪代码理解
虽然目前我们在 Spring AI 项目中不一定直接使用完整 A2A SDK,但可以先用伪代码理解它的调用方式。
假设我们有一个远程运维 Agent。
主 Agent 先读取它的能力信息:
AgentCard card = a2aClient.getAgentCard("https://ops-agent.example.com");
if (card.hasSkill("incident_analysis")) {
Task task = a2aClient.createTask(
"https://ops-agent.example.com",
new TaskRequest("""
请分析订单服务在 10:00-11:00 的超时告警,
结合日志、监控指标和历史故障知识库给出根因。
""")
);
TaskResult result = a2aClient.waitForResult(task.getId());
return result.getArtifact();
}
这段代码不重要,重要的是它背后的思想:
先发现能力
再提交任务
再跟踪状态
最后获取产物
这就是 A2A 思维和普通接口调用的区别。
普通接口调用更像:
我调用你这个函数
A2A 更像:
我知道你是一个 Agent,我把一个任务委托给你,你处理完后把结果交给我
这个变化很微妙,但非常关键。
十一、A2A 对 Agent 工程师意味着什么?
如果以后我们要往 Agent 工程师方向发展,A2A 这个东西不能只停留在概念层面。
我们至少要能说清楚四件事。
第一,A2A 解决的是 Agent 互操作问题
它不是用来做 RAG 的,也不是用来直接调数据库的。
它解决的是:
不同 Agent 系统之间如何标准化协作。
第二,A2A 和 MCP 是互补关系
MCP 让 Agent 能够使用工具。
A2A 让 Agent 能够调用另一个 Agent。
完整链路应该是:
Agent --A2A--> Agent --MCP--> Tool / Resource / Data
这句话一定要记住。
第三,A2A 不等于多 Agent 编排框架
Graph、DAG、Supervisor、Planner、Executor 这些是编排思想。
A2A 是通信协议。
编排层决定"该找谁"。
A2A 负责"怎么找、怎么发任务、怎么拿结果"。
第四,A2A 落地时最难的是上下文、安全和可信度
协议只是第一步。
真正企业落地还要考虑:
- 权限;
- 认证;
- 审计;
- trace;
- 上下文传递;
- 结果验证;
- 失败降级;
- 任务状态管理。
这些才是工程化难点。
十二、总结:A2A 是 Agent 时代的"协作协议"
前面我们学习 Function Calling 的时候,重点是让模型会调用函数。
学习 MCP 的时候,重点是让 Agent 能连接工具、数据和外部资源。
学习 Multi-Agent 的时候,重点是让多个 Agent 能分工完成复杂任务。
而 A2A 更进一步,它关注的是:
当 Agent 越来越多、越来越分散、来自不同团队和平台时,它们如何像一个网络一样协作?
这就是 A2A 的价值。
它不是让单个 Agent 更聪明,而是让 Agent 生态更容易连接。
未来真正复杂的智能系统,很可能不是一个超级 Agent 解决所有问题,而是多个专业 Agent 通过协议协作:
一个 Agent 负责理解问题
一个 Agent 负责检索知识
一个 Agent 负责查询日志
一个 Agent 负责分析指标
一个 Agent 负责生成报告
一个 Agent 负责审计和确认
A2A 就是这些 Agent 之间的协作语言。
所以,如果我们站在 Agent 工程师的角度看,A2A 最值得关注的不是"它用了什么协议格式",而是它代表的趋势:
Agent 正在从单点能力,走向互联协作。
这也意味着,未来做 Agent 项目,不能只会写 prompt、调模型、接工具。
还要理解:
- Agent 如何描述自己的能力;
- Agent 如何发现其他 Agent;
- Agent 如何委托任务;
- Agent 如何处理长任务;
- Agent 如何传递上下文;
- Agent 如何保证安全和可信;
- Agent 如何在复杂系统中协作。
这才是 Agent 工程真正有意思的地方。