Spring AI Alibaba 1.x 系列【75】分布式智能体
文章目录
- 1. A2A 概述
- 1.1 什么是 A2A
- 1.2 核心场景
- 1.3 与单 Agent 模式对比
- 2. A2A 架构
- 2.1 三核心组件
- 2.2 注册与发现流程
- 3. 发布 A2A 智能体(服务提供者)
- 3.1 定义本地 Agent
- 3.2 配置 A2A Server
- 3.3 启动后自动暴露的端点
- 4. 调用远程 Agent(服务消费者)
- 4.1 AgentCardProvider
- 4.2 通过 A2aRemoteAgent 远程调用
- 4.3 A2aRemoteAgent 的本质
- 5. 基于 Nacos 的注册与发现
- 5.1 完整配置
- 5.2 配置项说明
- 5.3 注册与发现区别
- 5.4 验证 Nacos 注册
- 6. 完整示例:注册 → 发现 → 调用
- 6.1 示例代码
- 6.2 执行流程
- 7. 多 Agent 注册策略
- 7.1 默认行为
- 7.2 多 Agent 场景
- 8. 故障排查
- 8.1 Agent 没有注册到 Nacos
- 8.2 AgentCardProvider 无法发现 Agent
- 8.3 远程调用失败
- 9. 架构总览
- 10. 关键 API 速查
- 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
@ConfigurationpublicclassA2AAgentConfig{@Bean(name="dataAnalysisAgent")publicReactAgentdataAnalysisAgent(ChatModelchatModel){returnReactAgent.builder().name("data_analysis_agent").model(chatModel).description("专门用于数据分析和统计计算的本地智能体").instruction(""" 你是一个专业的数据分析专家,擅长处理各类数据统计和分析任务。 你能够理解用户的数据分析需求,提供准确的统计计算结果和专业的分析建议。 """).outputKey("messages").build();}}3.2 配置 A2A Server
spring:ai:alibaba:a2a:server:version:1.0.0card:name:data_analysis_agentdescription:专门用于数据分析和统计计算的本地智能体provider:name:Spring AI Alibaba Documentationorganization: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:
curlhttp://localhost:8080/.well-known/agent.json4. 调用远程 Agent(服务消费者)
4.1 AgentCardProvider
AgentCardProvider是从注册中心发现远程Agent的核心接口:
publicinterfaceAgentCardProvider{// 根据 Agent 名称获取 AgentCardAgentCardgetAgentCard(StringagentName);}4.2 通过 A2aRemoteAgent 远程调用
@ComponentpublicclassRemoteAgentCaller{privatefinalAgentCardProvideragentCardProvider;publicRemoteAgentCaller(AgentCardProvideragentCardProvider){this.agentCardProvider=agentCardProvider;}publicvoidcallRemoteAgent(){// 构建远程 Agent 代理A2aRemoteAgentremote=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 │ └── 反序列化响应 → OverAllStateA2aRemoteAgent实现了与本地ReactAgent相同的invoke()接口,调用方无需关心 Agent 是本地还是远程。
5. 基于 Nacos 的注册与发现
5.1 完整配置
spring:ai:alibaba:a2a:nacos:server-addr:127.0.0.1:8848username:nacospassword:nacosdiscovery:enabled:true# 启用服务发现(查询其他 Agent)registry:enabled:true# 启用服务注册(注册本地 Agent)server:version:1.0.0card:name:data_analysis_agentdescription:专门用于数据分析和统计计算的本地智能体provider:name:Spring AI Alibaba Documentationorganization:Spring AI Alibaba5.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控制台验证:
# 1. 打开 Nacos 控制台openhttp://localhost:8848/nacos# 2. 登录(默认 nacos/nacos)# 3. 进入服务管理 → 服务列表# 应看到注册的 A2A Agent(如 data_analysis_agent)6. 完整示例:注册 → 发现 → 调用
6.1 示例代码
@ComponentpublicclassA2ADemo{privatefinalChatModelchatModel;privatefinalAgentCardProvideragentCardProvider;privatefinalReactAgentlocalAgent;publicA2ADemo(ChatModelchatModel,AgentCardProvideragentCardProvider,@Qualifier("dataAnalysisAgent")ReactAgentlocalAgent){this.chatModel=chatModel;this.agentCardProvider=agentCardProvider;this.localAgent=localAgent;}publicvoidrunDemo(){// ===== 1. 本地直连:验证本地 Agent 可用 =====Optional<OverAllState>localResult=localAgent.invoke("请对上月销售数据进行趋势分析,并给出关键结论。");localResult.ifPresent(state->System.out.println("本地调用成功: "+state.value("messages")));// ===== 2. 远程发现:通过 AgentCardProvider 获取 AgentCard =====A2aRemoteAgentremote=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 处理请求 └─ 反序列化响应 → OverAllState7. 多 Agent 注册策略
7.1 默认行为
默认情况下,应用只注册一个Agent Bean。如果有多个ReactAgentBean,需要通过@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服务未启动
排查步骤:
# 检查 Nacos 是否运行curlhttp://localhost:8848/nacos/v1/console/health# 查看应用日志# 搜索 "A2A Registry" 或 "AgentCard" 关键字8.2 AgentCardProvider 无法发现 Agent
可能原因:
discovery.enabled: true未配置Agent未成功注册到Nacosagent name不匹配
排查步骤:
# 检查 AgentCard 是否可访问curlhttp://localhost:8080/.well-known/agent.json# 在 Nacos 控制台查看服务列表8.3 远程调用失败
可能原因:
- 目标
Agent的端点不可达(网络/防火墙) A2A消息格式不兼容- 目标
Agent异常或超时
排查步骤:
# 测试远程端点curl-XPOST 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. 依赖项
<!-- A2A Nacos Starter(含 Server + Registry + Discovery) --><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-a2a-nacos</artifactId></dependency>