文章目录
- [1. A2A 概述](#1. A2A 概述)
-
- [1.1 什么是 A2A](#1.1 什么是 A2A)
- [1.2 核心场景](#1.2 核心场景)
- [1.3 与单 Agent 模式对比](#1.3 与单 Agent 模式对比)
- [2. A2A 架构](#2. A2A 架构)
-
- [2.1 三核心组件](#2.1 三核心组件)
- [2.2 注册与发现流程](#2.2 注册与发现流程)
- [3. 发布 A2A 智能体(服务提供者)](#3. 发布 A2A 智能体(服务提供者))
-
- [3.1 定义本地 Agent](#3.1 定义本地 Agent)
- [3.2 配置 A2A Server](#3.2 配置 A2A Server)
- [3.3 启动后自动暴露的端点](#3.3 启动后自动暴露的端点)
- [4. 调用远程 Agent(服务消费者)](#4. 调用远程 Agent(服务消费者))
-
- [4.1 AgentCardProvider](#4.1 AgentCardProvider)
- [4.2 通过 A2aRemoteAgent 远程调用](#4.2 通过 A2aRemoteAgent 远程调用)
- [4.3 A2aRemoteAgent 的本质](#4.3 A2aRemoteAgent 的本质)
- [5. 基于 Nacos 的注册与发现](#5. 基于 Nacos 的注册与发现)
-
- [5.1 完整配置](#5.1 完整配置)
- [5.2 配置项说明](#5.2 配置项说明)
- [5.3 注册与发现区别](#5.3 注册与发现区别)
- [5.4 验证 Nacos 注册](#5.4 验证 Nacos 注册)
- [6. 完整示例:注册 → 发现 → 调用](#6. 完整示例:注册 → 发现 → 调用)
-
- [6.1 示例代码](#6.1 示例代码)
- [6.2 执行流程](#6.2 执行流程)
- [7. 多 Agent 注册策略](#7. 多 Agent 注册策略)
-
- [7.1 默认行为](#7.1 默认行为)
- [7.2 多 Agent 场景](#7.2 多 Agent 场景)
- [8. 故障排查](#8. 故障排查)
-
- [8.1 Agent 没有注册到 Nacos](#8.1 Agent 没有注册到 Nacos)
- [8.2 AgentCardProvider 无法发现 Agent](#8.2 AgentCardProvider 无法发现 Agent)
- [8.3 远程调用失败](#8.3 远程调用失败)
- [9. 架构总览](#9. 架构总览)
- [10. 关键 API 速查](#10. 关键 API 速查)
- [11. 依赖项](#11. 依赖项)
1. A2A 概述
1.1 什么是 A2A
随着智能体应用的广泛落地,智能体间的分布式部署 与远程通信 成为关键问题。Google 推出的 Agent-to-Agent(A2A)协议 专门解决这一问题:
A2A 使不同框架、不同厂商、部署在不同机器的智能体能够进行有效的通信和协作。
在 Spring AI Alibaba 中,A2A 允许将一个本地 ReactAgent 发布为远程服务,其他应用通过注册中心发现并调用它。
1.2 核心场景
应用 A 应用 B
┌─────────────────┐ ┌─────────────────┐
│ 数据分析 Agent │ ←── A2A ───→ │ 业务调度 Agent │
│ (数据计算服务) │ │ (编排多个Agent) │
└─────────────────┘ └─────────────────┘
│ │
└────────── Nacos 注册中心 ────────────┘
· 注册 AgentCard
· 发现可用 Agent
· 负载均衡
1.3 与单 Agent 模式对比
| 维度 | 单 Agent | A2A 分布式 Agent |
|---|---|---|
| 部署 | 单应用 | 多应用、跨机器 |
| 通信 | 本地调用 | 远程 REST API |
| 发现 | 直接注入 Bean | 注册中心动态发现 |
| 扩展 | 垂直扩展 | 水平扩展 |
| 异构 | 同一框架 | 不同框架/语言 |
2. A2A 架构
2.1 三核心组件
┌──────────────────────────────────────────────────┐
│ A2A 架构 │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────┐│
│ │ A2A Server │ │ A2A Registry │ │Discovery││
│ │ │ │ │ │ ││
│ │ 暴露本地Agent │ │ AgentCard │ │发现远程 ││
│ │ 为REST服务 │ │ 注册与存储 │ │Agent ││
│ └──────┬───────┘ └──────┬───────┘ └────┬────┘│
│ │ │ │ │
│ · ReactAgent · Nacos · Nacos │
│ · AgentCard · 服务列表 · AgentCard│
│ · REST API · 健康检查 · 负载均衡 │
└──────────────────────────────────────────────────┘
| 组件 | 职责 | 对外接口 |
|---|---|---|
| A2A Server | 将本地 ReactAgent 暴露为 A2A 服务 | /.well-known/agent.json、/a2a/message |
| A2A Registry | Agent 信息注册到注册中心 | Nacos A2A Registry API |
| A2A Discovery | 从注册中心发现可用 Agent | AgentCardProvider |
2.2 注册与发现流程
Agent Provider Nacos Registry Agent Consumer
│ │ │
│ 1. 应用启动,构建 AgentCard │ │
│─────────────────────────────────►│ │
│ 注册 AgentCard 元数据 │ │
│ │ │
│ │ 2. 查询可用 Agent │
│ │◄────────────────────────────│
│ │ 返回 AgentCard 列表 │
│ │ │
│ 3. 远程调用 │ │
│◄──────────────────────────────────────────────────────────────│
│ A2aRemoteAgent.invoke() │ │
│ │ │
3. 发布 A2A 智能体(服务提供者)
3.1 定义本地 Agent
java
@Configuration
public class A2AAgentConfig {
@Bean(name = "dataAnalysisAgent")
public ReactAgent dataAnalysisAgent(ChatModel chatModel) {
return ReactAgent.builder()
.name("data_analysis_agent")
.model(chatModel)
.description("专门用于数据分析和统计计算的本地智能体")
.instruction("""
你是一个专业的数据分析专家,擅长处理各类数据统计和分析任务。
你能够理解用户的数据分析需求,提供准确的统计计算结果和专业的分析建议。
""")
.outputKey("messages")
.build();
}
}
3.2 配置 A2A Server
yaml
spring:
ai:
alibaba:
a2a:
server:
version: 1.0.0
card:
name: data_analysis_agent
description: 专门用于数据分析和统计计算的本地智能体
provider:
name: Spring AI Alibaba Documentation
organization: Spring AI Alibaba
注意:
server.card.name必须与ReactAgentBean 的.name()一致。
3.3 启动后自动暴露的端点
启动应用后,A2A Server 自动暴露两个 REST API:
| 端点 | 作用 |
|---|---|
GET /.well-known/agent.json |
AgentCard 元数据(Agent 名、描述、能力) |
POST /a2a/message |
Agent 调用端点(接收消息并转发给 ReactAgent) |
验证 AgentCard:
bash
curl http://localhost:8080/.well-known/agent.json
4. 调用远程 Agent(服务消费者)
4.1 AgentCardProvider
AgentCardProvider 是从注册中心发现远程 Agent 的核心接口:
java
public interface AgentCardProvider {
// 根据 Agent 名称获取 AgentCard
AgentCard getAgentCard(String agentName);
}
4.2 通过 A2aRemoteAgent 远程调用
java
@Component
public class RemoteAgentCaller {
private final AgentCardProvider agentCardProvider;
public RemoteAgentCaller(AgentCardProvider agentCardProvider) {
this.agentCardProvider = agentCardProvider;
}
public void callRemoteAgent() {
// 构建远程 Agent 代理
A2aRemoteAgent remote = A2aRemoteAgent.builder()
.name("data_analysis_agent")
.agentCardProvider(agentCardProvider) // 从 Nacos 获取 AgentCard
.description("数据分析远程代理")
.build();
// 远程调用(与本地 Agent 调用接口一致)
Optional<OverAllState> result = remote.invoke(
"请根据季度数据给出同比与环比分析概要。");
result.ifPresent(state ->
System.out.println("远程结果: " + state.value("output")));
}
}
4.3 A2aRemoteAgent 的本质
A2aRemoteAgent
│
├── 通过 AgentCardProvider 获取远程 Agent 的 URL
│
├── 将 invoke() 请求序列化为 A2A 消息
│
├── POST /a2a/message 发送到远程 Agent
│
└── 反序列化响应 → OverAllState
A2aRemoteAgent 实现了与本地 ReactAgent 相同的 invoke() 接口,调用方无需关心 Agent 是本地还是远程。
5. 基于 Nacos 的注册与发现
5.1 完整配置
yaml
spring:
ai:
alibaba:
a2a:
nacos:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
discovery:
enabled: true # 启用服务发现(查询其他 Agent)
registry:
enabled: true # 启用服务注册(注册本地 Agent)
server:
version: 1.0.0
card:
name: data_analysis_agent
description: 专门用于数据分析和统计计算的本地智能体
provider:
name: Spring AI Alibaba Documentation
organization: Spring AI Alibaba
5.2 配置项说明
| 配置项 | 说明 | 必须 |
|---|---|---|
nacos.server-addr |
Nacos 服务地址 | 使用 Nacos 时是 |
nacos.username / password |
Nacos 认证 | 可选 |
registry.enabled |
将本地 Agent 注册到 Nacos | 服务提供者须设为 true |
discovery.enabled |
从 Nacos 发现其他 Agent | 服务消费者须设为 true |
server.card.name |
AgentCard 名称 | 是(须与 ReactAgent.name 一致) |
server.card.description |
Agent 描述 | 可选 |
server.card.provider |
提供者信息 | 可选 |
5.3 注册与发现区别
| 功能 | 配置项 | 作用 | 角色 |
|---|---|---|---|
| Registry(注册) | registry.enabled: true |
将本地 Agent 注册到 Nacos | 服务提供者 |
| Discovery(发现) | discovery.enabled: true |
从 Nacos 查询其他 Agent | 服务消费者 |
两者可独立启用,也可同时启用:
- 同时启用时,应用既是提供者也是消费者
- 可以调用其他
Agent,也可以被其他Agent调用 Nacos中的AgentCard对消费者来说是透明的(包括自身)
5.4 验证 Nacos 注册
启动应用后,打开 Nacos 控制台验证:
bash
# 1. 打开 Nacos 控制台
open http://localhost:8848/nacos
# 2. 登录(默认 nacos/nacos)
# 3. 进入服务管理 → 服务列表
# 应看到注册的 A2A Agent(如 data_analysis_agent)
6. 完整示例:注册 → 发现 → 调用
6.1 示例代码
java
@Component
public class A2ADemo {
private final ChatModel chatModel;
private final AgentCardProvider agentCardProvider;
private final ReactAgent localAgent;
public A2ADemo(ChatModel chatModel,
AgentCardProvider agentCardProvider,
@Qualifier("dataAnalysisAgent") ReactAgent localAgent) {
this.chatModel = chatModel;
this.agentCardProvider = agentCardProvider;
this.localAgent = localAgent;
}
public void runDemo() {
// ===== 1. 本地直连:验证本地 Agent 可用 =====
Optional<OverAllState> localResult = localAgent.invoke(
"请对上月销售数据进行趋势分析,并给出关键结论。");
localResult.ifPresent(state ->
System.out.println("本地调用成功: " + state.value("messages")));
// ===== 2. 远程发现:通过 AgentCardProvider 获取 AgentCard =====
A2aRemoteAgent remote = A2aRemoteAgent.builder()
.name("data_analysis_agent")
.agentCardProvider(agentCardProvider) // 从 Nacos 自动获取
.description("数据分析远程代理")
.build();
// ===== 3. 远程调用:与本地调用一致的接口 =====
Optional<OverAllState> remoteResult = remote.invoke(
"请根据季度数据给出同比与环比分析概要。");
remoteResult.ifPresent(state ->
System.out.println("远程调用成功: " + state.value("messages")));
}
}
6.2 执行流程
runDemo()
│
├─ 1. localAgent.invoke()
│ └─ 直接调用本地 ReactAgent,无需网络
│
├─ 2. A2aRemoteAgent.builder()
│ ├─ 通过 AgentCardProvider 查询 Nacos
│ └─ 获取远程 Agent 的 URL(如 http://host1:8080)
│
└─ 3. remote.invoke()
├─ 序列化请求为 A2A JSON 消息
├─ POST http://host1:8080/a2a/message
├─ 远程 ReactAgent 处理请求
└─ 反序列化响应 → OverAllState
7. 多 Agent 注册策略
7.1 默认行为
默认情况下,应用只注册一个 Agent Bean。如果有多个 ReactAgent Bean,需要通过 @Qualifier 指定哪个 Agent 用于 A2A Server。
7.2 多 Agent 场景
如需暴露多个 Agent,推荐策略:
方案 A:每应用一个 Agent(推荐)
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 应用 1 │ │ 应用 2 │ │ 应用 3 │
│ Agent: 分析 │ │ Agent: 搜索 │ │ Agent: 写作 │
│ port: 8081 │ │ port: 8082 │ │ port: 8083 │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
└─────────────────┼─────────────────┘
Nacos Registry
每个 Agent 独立部署、独立扩展、独立升级。
8. 故障排查
8.1 Agent 没有注册到 Nacos
可能原因:
registry.enabled: true未配置Nacos连接配置错误(server-addr、username、password)Nacos服务未启动
排查步骤:
bash
# 检查 Nacos 是否运行
curl http://localhost:8848/nacos/v1/console/health
# 查看应用日志
# 搜索 "A2A Registry" 或 "AgentCard" 关键字
8.2 AgentCardProvider 无法发现 Agent
可能原因:
discovery.enabled: true未配置Agent未成功注册到Nacosagent name不匹配
排查步骤:
bash
# 检查 AgentCard 是否可访问
curl http://localhost:8080/.well-known/agent.json
# 在 Nacos 控制台查看服务列表
8.3 远程调用失败
可能原因:
- 目标
Agent的端点不可达(网络/防火墙) A2A消息格式不兼容- 目标
Agent异常或超时
排查步骤:
bash
# 测试远程端点
curl -X POST http://remote-host:8080/a2a/message \
-H "Content-Type: application/json" \
-d '{"message": "test"}'
# 查看两端的 A2A 传输日志
9. 架构总览
┌──────────────────────────────────────────────────────────────────┐
│ Nacos Registry │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ AgentCard: 数据分析 │ │ AgentCard: 智能搜索 │ ... │
│ │ url: host1:8081 │ │ url: host2:8082 │ │
│ │ status: HEALTHY │ │ status: HEALTHY │ │
│ └─────────────────────┘ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
▲ 注册 ▲ 注册
│ │
┌─────────┴─────────┐ ┌────────┴──────────┐
│ 应用 A (提供者) │ │ 应用 B (提供者) │
│ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │ ReactAgent │ │ │ │ ReactAgent │ │
│ │ (数据分析) │ │ │ │ (智能搜索) │ │
│ └──────┬──────┘ │ │ └─────────────┘ │
│ │ │ │ │ │
│ A2A Server │ │ A2A Server │
│ · agent.json │ │ · agent.json │
│ · /a2a/message │ │ · /a2a/message │
└───────────────────┘ └───────────────────┘
▲ ▲
│ 发现 + 调用 │ 发现 + 调用
│ │
┌────────┴──────────────────────────┴──────┐
│ 应用 C (消费者) │
│ ┌────────────────────────────────────┐ │
│ │ A2aRemoteAgent │ │
│ │ · 通过 AgentCardProvider 发现 │ │
│ │ · 负载均衡选择远程 Agent │ │
│ │ · 远程调用 → 聚合结果 │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────────┘
10. 关键 API 速查
| API / 类 | 作用 |
|---|---|
ReactAgent.builder().name("...") |
定义本地 Agent |
A2aRemoteAgent.builder().name("...") |
创建远程 Agent 代理 |
AgentCardProvider.getAgentCard(name) |
从注册中心获取 Agent 元数据 |
GET /.well-known/agent.json |
获取 AgentCard |
POST /a2a/message |
调用远程 Agent |
spring.ai.alibaba.a2a.registry.enabled |
启用服务注册 |
spring.ai.alibaba.a2a.discovery.enabled |
启用服务发现 |
11. 依赖项
xml
<!-- A2A Nacos Starter(含 Server + Registry + Discovery) -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-a2a-nacos</artifactId>
</dependency>