摘要:很多开发者做多Agent协作时,分不清什么时候该上A2A协议。本文从工程落地角度通俗拆解A2A‑1.0,区分进程内协作与远程跨域Agent协作边界,结合Spring AI Alibaba实战案例,讲清楚A2A能干什么、什么必须业务自己实现,避免过度设计。
很多开发者在做AI Agent多智能体协作时,都会混淆一个核心问题:到底什么时候需要用A2A协议?本地多Agent协作能不能用A2A?A2A能解决哪些问题、哪些坑它管不了?
一、核心大前提:90%的本地多Agent,根本不需要A2A
首先纠正一个高频误区:A2A不是本地多Agent调度框架,它是跨机器、跨团队、跨安全域的AI智能体通信标准协议。
如果你的所有Agent角色都运行在同一个进程、同一个Spring服务内,直接本地方法调用即可,例如agent.run(input),简单高效、无网络开销、无协议冗余,完全没必要引入A2A协议。
二、严格界定:什么时候才需要启用A2A协议?
只有满足任意一条分布式、跨域协作场景,才考虑接入A2A协议,这是落地选型的核心标准:
- 独立部署:各个Agent拆分独立服务,部署在不同机器、不同集群,无法本地调用;
- 跨团队维护:不同Agent由不同业务团队独立开发、迭代、运维,需要标准化跨团队对接;
- 跨安全域调用:存在内外网隔离、甲乙双方服务对接、跨租户权限隔离等场景,需要标准化远程通信。
三、A2A的能力边界:能做什么、绝不做什么
搞懂边界,才能避免落地踩坑,这是A2A最核心的工程认知:
✅ A2A协议核心解决的问题
统一远程AI Agent的协作规范,标准化解决四大核心问题:远程Agent能力发现、标准化消息交互、长异步任务全链路跟踪、结构化结果/大文件产物交付。
❌ A2A不负责、不自动实现的能力
A2A只是通信层、数据格式层标准,不包含任何分布式一致性、任务容错能力,以下逻辑必须业务层自行实现:
- 并发读写冲突处理、乐观锁版本控制;
- 服务宕机后的任务接管、租约机制;
- 接口重试导致的重复执行、幂等校验;
- 分布式隔离令牌(fencingToken)、任务归属控制。
四、A2A核心名词拆解(通俗版+工程释义)
A2A整套协作体系由五大核心组件构成,全程对应外包工单协作通俗类比,秒懂核心逻辑:
1、Agent Card(Agent能力名片)
通俗类比:外包公司公开的宣传手册+接口说明书
工程释义:机器可读的标准化能力描述文件,是远程Agent的唯一对接入口。调用方对接前,必须先读取对方的Agent Card,明确核心信息:Agent能力范围、接口地址、入参出参Schema、认证方式、权限要求。
等同于调用第三方API前查阅的官方文档,A2A将人工文档标准化、机器自动化解析,实现Agent无感能力发现。
2、Task(全局唯一任务)
通俗类比:带唯一工单号的正式服务工单
工程释义:A2A的核心调度单元,每个任务拥有全局唯一taskId。区别于普通同步接口,A2A专为长异步Agent任务设计,任务可长时间执行、可中途暂停、可多轮恢复,不局限于单次请求响应。
3、Message(交互消息)
通俗类比:供需双方来回沟通的邮件、补充说明
工程释义:Agent间的标准化交互载体,支持多轮对话、参数补充、需求变更、状态同步,打破单次请求响应的局限,适配Agent复杂交互式协作场景。
4、Context(会话上下文)
通俗类比:工单专属归档文件夹
工程释义:全局会话容器,将同一个Task下的所有消息、操作日志、最终产物、状态变更全部关联绑定,实现全链路可追溯、可复盘。
5、Artifact(任务产物)
通俗类比:外包最终交付的报告、成果文件
工程释义:任务最终交付结果,支持多种形态:结构化JSON数据、PDF报告、代码文件、数据资源URI。针对大文件场景,A2A默认传递资源引用URI,不阻塞消息体,保障传输效率。
五、A2A细粒度任务状态机(核心重点)
普通接口只有「成功/失败」两种状态,完全无法适配Agent长任务、可暂停、可恢复的场景。A2A定义了全套细粒度任务状态枚举,精准描述任务全生命周期:
| 任务状态枚举 | 状态含义 | 场景说明 |
|---|---|---|
| TASK_STATE_UNSPECIFIED | 未知/未初始化 | 任务默认初始状态,未提交未初始化 |
| TASK_STATE_SUBMITTED | 任务已提交 | 任务创建完成,等待Agent开始处理 |
| TASK_STATE_WORKING | 任务执行中 | 远程Agent正在正常执行业务逻辑 |
| TASK_STATE_INPUT_REQUIRED | 暂停‑需外部输入 | 任务中断,缺少业务参数/用户指令,等待补充后恢复 |
| TASK_STATE_AUTH_REQUIRED | 暂停‑需权限授权 | 任务中断,缺少资源访问权限、登录授权,授权后可继续执行 |
| TASK_STATE_COMPLETED | 任务成功完成 | 执行完毕,可读取Artifact产物 |
| TASK_STATE_FAILED | 任务执行失败 | 程序异常、业务校验失败,任务终止 |
| TASK_STATE_CANCELED | 任务主动取消 | 调用方主动终止未完成任务 |
| TASK_STATE_REJECTED | 任务被拒绝 | 参数非法、权限不足,Agent直接拒收任务 |
核心重点:INPUT_REQUIRED、AUTH_REQUIRED是A2A的精髓,任务既非成功也非失败,属于挂起暂停状态,完美适配Agent长任务交互式协作场景。
六、关键避坑:A2A不解决分布式一致性问题
这是A2A落地最大的误区,再次重点强调:A2A只定义通信格式、任务字段、交互规范,不提供任何分布式容错能力。
以下核心分布式能力,必须由业务代码自行实现:
- 多Worker并发修改同一Task:A2A无乐观锁、无版本控制,需业务自行加
version字段防冲突; - 服务宕机任务接管:A2A无租约机制,需自行实现
leaseUntil、ownerAgentId归属管控; - 重试重复执行:A2A无幂等机制,需业务自行做幂等校验、
fencingToken隔离。
七、落地选型对比:进程内DAG VS 分布式A2A
一张表搞定所有场景选型,彻底告别纠结:
| 部署场景 | 调用方式 | 是否需要A2A | 是否需要分布式防护逻辑 |
|---|---|---|---|
| 所有Agent同进程、同一个Spring服务 | 本地方法调用 agent.run() | 不需要 | 不需要 |
| Agent独立部署、跨团队/跨安全域 | 网络远程调用 | 需要完整A2A协议 | 必须实现Version、租约、幂等、令牌隔离 |
八、实战案例:需求Agent + 代码Agent,基于Spring AI Alibaba
以「需求整理Agent + 代码生成Agent」为例,对比进程内借鉴A2A思想和远程微服务启用完整A2A‑1.0协议两种落地模式,基于Spring AI Alibaba框架。
场景1:同进程部署(Spring AI Alibaba,只借鉴A2A思想,不引入A2A协议)
两个Agent都在同一个Spring Boot应用中,使用Spring AI Alibaba构建Agent实例,没有网络调用,借鉴A2A结构化数据契约的设计思想,拒绝大段自然语言传递参数。
❌ 错误做法:Agent之间传递大段自然语言文本
需求Agent输出文本:“我整理好了登录模块需求,需要做token校验,接口响应不能太慢,麻烦你实现一下”
问题:Token开销高,LLM自由转述容易丢失约束条件,下游Agent需要做文本理解,输出不稳定,无法做结构化参数校验。
✅ 正确做法:Agent之间传递结构化POJO对象
借助Spring AI Alibaba的StructuredOutputConverter,强制需求Agent输出强类型RequirementOutput对象,而不是自由文本字符串。
1. 先定义POJO实体
import com.fasterxml.jackson.annotation.JsonClassDescription;
import java.util.List;
@JsonClassDescription("登录模块开发需求输出对象")
public class RequirementOutput {
private String taskId;
private String taskType;
private List<String> dependencies;
private List<String> acceptanceCriteria;
private String requirementDesc;
private String artifactUri;
// getter / setter 省略
}2. Agent内部使用StructuredOutputConverter强制结构化输出
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.converter.BeanOutputConverter;
/**
* 需求整理Agent,Spring AI Alibaba 进程内Agent
*/
public class RequirementAgent {
private final ChatClient chatClient;
// 结构化输出转换器,指定目标POJO
private final BeanOutputConverter<RequirementOutput> outputConverter
= new BeanOutputConverter<>(RequirementOutput.class);
public RequirementAgent(ChatClient chatClient) {
this.chatClient = chatClient;
}
public RequirementOutput run(String userInput) {
return chatClient.prompt()
.user(u -> u.text("整理下面业务需求,输出标准化开发需求:{input}\n{formatInstructions}")
.param("input", userInput)
.param("formatInstructions", outputConverter.getFormatInstructions()))
.call()
.entity(outputConverter); // 直接反序列化为Java对象
}
}3. 编排器直接本地调用串联两个Agent
// 编排器代码,同一个Spring进程内
RequirementAgent requirementAgent;
CodeAgent codeAgent;
// 用户原始输入
String userInput = "实现登录接口,需要token校验,接口响应小于200ms,依赖user_db";
// 需求Agent直接返回强类型对象,不是字符串
RequirementOutput reqOut = requirementAgent.run(userInput);
// 直接把POJO传给下游代码Agent,无自然语言中转
CodeResult codeRes = codeAgent.run(reqOut);说明:该模式只是借鉴A2A的“结构化产物”思想,没有Agent Card、没有网络Task状态机、没有Artifact协议对象,属于进程内最优方案。
关键点:BeanOutputConverter会自动把JSON Schema传给大模型,强制LLM输出符合POJO结构,避免自由文本带来的信息丢失。
场景2:跨团队远程部署,Spring AI Alibaba对接A2A‑1.0协议(带代码样例支撑)
业务背景:
- A团队:编排服务(Spring Boot + Spring AI Alibaba),内部运行需求Agent;
- B团队:独立微服务,部署代码Agent,对外暴露A2A 1.0标准HTTP接口;
- 两套服务属于不同服务、不同团队,跨安全域,必须走网络调用,使用完整A2A协议。
说明:Spring AI Alibaba目前没有封装完整A2A客户端SDK,业务侧基于RestTemplate/WebClient封装A2A HTTP调用,下面是简化可运行伪代码,还原完整流程。
import org.springframework.web.reactive.function.client.WebClient;
import java.util.UUID;
/**
* A团队编排服务:A2A远程调用B团队代码Agent
*/
public class A2ACodeAgentClient {
private final WebClient webClient;
// B团队代码Agent服务地址
private static final String AGENT_BASE_URL = "http://code-agent-service";
public A2ACodeAgentClient(WebClient.Builder builder) {
this.webClient = builder.baseUrl(AGENT_BASE_URL).build();
}
// 步骤1:拉取远程Agent Card(能力名片)
public String fetchAgentCard() {
return webClient.get()
.uri("/.well-known/agent-card")
.retrieve()
.bodyToMono(String.class)
.block();
}
// 步骤2:创建A2A Task,生成全局taskId
public String createA2ATask() {
String taskId = "a2a-task-" + UUID.randomUUID();
// 请求体省略A2A标准task对象
webClient.post()
.uri("/v1/tasks")
.bodyValue("""
{
"taskId":"%s",
"state":"TASK_STATE_SUBMITTED"
}
""".formatted(taskId))
.retrieve()
.toBodilessEntity()
.block();
return taskId;
}
// 步骤3:发送Message,携带结构化需求payload
public void sendMessage(String taskId, RequirementOutput reqOut) {
webClient.post()
.uri("/v1/tasks/%s/messages".formatted(taskId))
.bodyValue("""
{
"taskId":"%s",
"payload":%s
}
""".formatted(taskId, Jackson.toJson(reqOut)))
.retrieve()
.toBodilessEntity()
.block();
}
// 轮询任务状态,生产环境建议改为webhook回调
public TaskStatus pollTaskStatus(String taskId) {
String resp = webClient.get()
.uri("/v1/tasks/%s".formatted(taskId))
.retrieve()
.bodyToMono(String.class)
.block();
return parseTaskStatus(resp);
}
// 发送授权信息,恢复挂起任务 AUTH_REQUIRED
public void resumeTaskWithAuth(String taskId, String authToken) {
webClient.post()
.uri("/v1/tasks/%s/messages".formatted(taskId))
.bodyValue("""
{
"taskId":"%s",
"payload":{"authToken":"%s"}
}
""".formatted(taskId, authToken))
.retrieve()
.toBodilessEntity()
.block();
}
}编排主流程伪代码:
// 编排入口
public void runRemoteAgentFlow(String userInput){
// 1、本地需求Agent输出结构化对象(Spring AI Alibaba结构化输出)
RequirementOutput reqOut = requirementAgent.run(userInput);
A2ACodeAgentClient a2AClient = new A2ACodeAgentClient(webClientBuilder);
// 2、拉取远程Agent Card做能力校验
String agentCard = a2AClient.fetchAgentCard();
//3、创建A2A Task
String taskId = a2AClient.createA2ATask();
//4、发送结构化需求到远程Agent
a2AClient.sendMessage(taskId, reqOut);
//5、轮询状态
while(true){
TaskStatus status = a2AClient.pollTaskStatus(taskId);
if("TASK_STATE_AUTH_REQUIRED".equals(status.getState())){
// 任务挂起,业务获取授权凭证,恢复任务
String authToken = getBizAuthToken();
a2AClient.resumeTaskWithAuth(taskId, authToken);
}else if("TASK_STATE_COMPLETED".equals(status.getState())){
// 读取Artifact产物URI,下载结果文件
List<Artifact> artifacts = status.getArtifacts();
for (Artifact artifact : artifacts) {
downloadArtifact(artifact.getUri());
}
break;
}else if(List.of("TASK_STATE_FAILED","TASK_STATE_REJECTED","TASK_STATE_CANCELED").contains(status.getState())){
throw new RuntimeException("A2A任务异常:"+status.getState());
}
}
}⚠️重要工程提醒
虽然使用A2A协议完成通信,但Spring业务侧仍然需要自己在数据库维护:version乐观锁版本号、ownerAgentId任务持有者、leaseUntil租约过期时间、fencingToken隔离令牌,处理Worker宕机、并发更新、重试幂等问题。A2A协议不会帮你实现这部分分布式逻辑。
补充:生产环境不建议轮询,优先使用A2A规范webhook回调接收状态变更;示例仅演示协议交互逻辑,异常处理、超时、重试、序列化做了简化。
九、全文总结(核心干货复盘)
- A2A是跨域远程Agent通信协议,本地同进程Spring应用内多Agent直接方法调用,无需过度设计;
- 核心适用场景:Agent独立部署、跨团队维护、跨安全域调用;
- 五大核心组件:AgentCard(能力发现)、Task(长任务调度)、Message(多轮交互)、Context(链路追溯)、Artifact(产物交付);
- 核心价值:标准化长任务生命周期,支持任务暂停、外部输入、授权恢复,解决远程Agent互通;
- 核心边界:A2A只管通信与数据格式,分布式一致性、容错、幂等、租约全部业务自研;
- Spring AI Alibaba中:进程内优先用
BeanOutputConverter做结构化POJO传参;只有远程跨服务时,才对接完整A2A协议。