AgentScope、A2A、Nacos 这三个词放在一起,我做智能体开发的朋友里已经有越来越多人在问了。我的感受是,过去一年大家做多智能体,早就不缺模型能力,也不缺框架,最头疼的是"我这个 agent 怎么跟别人写的 agent 协作"以及"我连对方跑在哪台机器上都不知道"这两个特别基础的问题。AgentScope 2.0 正式纳入 A2A 模式之后,再配合 Nacos 做服务注册与发现,这套组合确实把多智能体协作从"各自造轮子"往"开放生态"这个方向推进了一大步。这篇文章会完整拆一下这套方案:A2A 协议到底解决什么、Nacos 在中间扮演什么角色、AgentScope 2.0 怎么接入、以及在真正落地时我踩过的坑和排查思路。内容偏工程实践,适合正在做智能体开发、想把销售智能体、客服智能体这类业务 agent 真正做成协作网络的同学参考。
1. 智能体协作的真实困境:为什么需要 A2A
1.1 单机智能体与多智能体协作的差异
今年很多团队其实已经过了"做个会调用工具的 agent"的阶段。第一阶段的智能体基本都在单进程里跑:LLM 接收指令,调工具函数,返回结果。这种模式用哪个框架都能搞定,AgentScope、LangChain、LlamaIndex 都可以,根本不需要考虑网络通信。AgentScope 在这个阶段给的是智能体生命周期管理、消息传递、多角色流程编排这些能力,开发者主要把精力放在提示词和工具设计上。
但一旦进入真实业务,事情就变了。销售智能体要跟 CRM 系统里的数据智能体配合,客服智能体要调用订单查询智能体,供应链智能体需要跟库存优化智能体协商补货计划。这些 agent 可能由不同团队开发,用不同框架,部署在不同服务器上,甚至跑在完全不同技术栈的运行时里。它们之间的协作调用,不能再靠"同一个进程里 import 一下"来解决,而是要面对分布式系统里最经典的一堆问题:网络寻址、服务发现、协议约定、容错重试、任务状态管理。
大多数团队的现状是:每个智能体都暴露一堆 HTTP 接口,但接口风格千奇百怪。有的返回 JSON,有的直接返回 Markdown 文本,有的用 WebSocket,有的用 SSE 流式输出。调用方必须为每一个上游智能体写一套专属客户端,接口文档更新后还得跟着改代码,耦合程度高到没法维护。所以我经常说,多智能体协作的"壁垒",本质上不是模型能力问题,而是工程协议问题。
1.2 A2A 协议想解决什么
A2A(Agent-to-Agent)协议就是在这种背景下出现的。它是一个面向智能体互操作性的开放协议,核心思路非常朴素:定义一套统一的"智能体对外通信语言",让不同框架、不同厂商的 agent 都按这套语言暴露能力。你不需要关心对面是 AgentScope 写的还是别的框架写的,只要它实现了 A2A 标准,你就能调用它。
A2A 里有两个很重要的概念。第一个是 AgentCard,可以理解成智能体的"名片"。它用 JSON 描述这个智能体的名字、擅长什么、能力边界、支持流式输出还是多轮任务。其他智能体先拿到这张名片,确认对方能力之后,再决定要不要协作。第二个是 Task,也就是任务对象,代表一次完整交互的上下文,包含任务状态流转和消息记录。Task 是 A2A 的核心抽象,所有请求都围绕任务来推进,而不是简单的"发一个请求收一个响应"。
所以 A2A 解决的问题,是把智能体之间的交互从"私有接口调用"提升为"标准协议通信"。这个地位跟 HTTP 协议很像:大家的业务语言可以千差万别,但网络通信说同一种语言。热词里有人搜"AgentScope 2.0 有 A2A 模式的智能体协作吗",答案是肯定的。从官方文档和社区信息来看,2.0 版本支持将本地 agent 包装成 A2A 服务端对外提供能力,也提供了 A2A 客户端用来调用远端智能体。你不需要再手动拼 HTTP 请求、处理流式输出、维护任务状态机,框架帮你把协议层的活封装掉了,开发者只写业务逻辑。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 整体方案:AgentScope + A2A + Nacos 的三角架构
2.1 三个组件各管哪一段
做系统设计,得先把角色分清楚,不然很容易把三个东西混为一谈。AgentScope 负责智能体的生命周期和业务编排,A2A 负责智能体之间的通信协议,Nacos 负责"找到对方在哪"。三者各司其职,组合起来才是完整的多智能体协作基础设施。
- AgentScope 2.0:智能体框架层。用它定义智能体、绑定大模型、写工具函数、编排多智能体流程。
- A2A:通信协议层。规定智能体之间用什么格式交换信息、任务如何流转、能力如何描述。它只定义"说什么话",不负责"去哪找人"。
- Nacos:基础设施层。提供服务注册、服务发现、健康检查、配置管理。A2A 只知道协议,不知道目标智能体跑在哪台机器上,Nacos 来补齐这个信息。
这个分工是整套方案最妙的地方。之前很多人做多智能体协作,总是把协议和寻址混在一起。要么自己发明一套私有通信协议,然后把地址硬编码在配置文件里;要么用了注册中心,但智能体之间的消息格式还是各写各的。AgentScope 2.0 加 A2A 加 Nacos 的组合,把这两件事彻底解耦了:协议层归协议层,寻址归寻址,各自可以独立演进。
2.2 为什么选 Nacos 作为协作底座
"为什么一定要用 Nacos"是我在技术交流时被问最多的问题。坦白说,注册中心这个位置能替换的组件不少,Consul、Etcd、ZooKeeper 都能做,Redis 也能硬做。但我的选择理由很实际,主要看三点。
第一是服务注册和配置管理二合一。多智能体系统里的配置项特别敏感,大模型 API Key、模型名称、温度参数、数据库地址、知识库路径,散落在十几个智能体服务里。靠改配置文件再重启是最原始的玩法。Nacos 自带配置中心,支持动态刷新,配合 Spring Cloud 的 @RefreshScope 或 Nacos 配置监听机制,配置变更可以秒级生效而不重启进程。智能体迭代快,这种动态配置能力在生产环境太关键了。
第二是命名空间和分组的隔离能力。一个真正落地的智能体系统,一定会有开发、测试、预发、生产多套环境,还有销售域、客服域、供应链域这样的业务域划分。Nacos 的 namespace 做环境隔离,group 做业务域隔离,再配合服务名的前缀规范,整个智能体网络的拓扑可以梳理得特别清楚。Namespace 规划这里坑很多,我后面专门章节展开。
第三是社区生态成熟。Nacos 在 Java 生态里几乎是标配,Spring Cloud Alibaba、Dubbo 都已经深度集成。如果团队里还有常规微服务,它们也能注册到同一个 Nacos,智能体服务和普通微服务在基础设施层面真正统一了,运维只需要维护一套注册中心。对于已经有微服务体系的团队来说,这套方案的接入成本非常低。
2.3 与 Dify、扣子这类平台的定位差异
有同学问,Dify、扣子这些平台也能编排智能体,为什么还要自己搞 AgentScope 加 Nacos?我的看法是,它们解决的场景不一样。Dify 和扣子偏低代码应用搭建,你在平台上做知识库、配工作流、发布一个聊天机器人,效率确实高,但智能体跑在平台自己的运行时里。外部系统想用一种标准协议去发现并调用你搭出来的 agent,往往只能走平台提供的专属 API,agent 之间的协议体系也是封闭的。
AgentScope 2.0 则是在代码框架层给你更高自由度。智能体跑在你自己的服务里,进程、网络、存储都由你掌控。配合 A2A 协议,你搭的销售智能体可以被任何实现了 A2A 的智能体发现和调用,不管对方用什么框架。这才叫开放智能体生态。所以如果你只是快速做一个聊天机器人,用 Dify、扣子完全没问题;但如果你有跨团队协作、跨系统开放的诉求,框架加协议加注册中心是更合适的底座。
3. 环境准备与 Nacos 部署
3.1 Nacos 安装与启动
先把 Nacos 跑起来,这是整套方案的地基。安装方式我建议本地开发优先用 Docker,生产环境再用物理机或云主机部署。
bash复制docker run --name nacos-server \
-e MODE=standalone \
-e NACOS_AUTH_ENABLE=true \
-p 8848:8848 \
-p 9848:9848 \
-d nacos/nacos-server:v2.5.4
我特意加了 NACOS_AUTH_ENABLE=true,就是尽早把鉴权打开。Nacos 控制台默认账号是 nacos/nacos,如果不开启鉴权又暴露到公网,相当于把注册中心裸奔在公网上,这在生产上绝对不能接受。另外很多人容易忽略 9848 这个端口,Nacos 2.x 之后服务注册发现走的是 gRPC,需要额外有 9848。只映射 8848 的话,控制台能打开但服务就是注册不上去,这是新手非常容易踩的问题。
物理机部署的流程也简单:去 GitHub Releases 下载对应版本的压缩包。Windows 直接解压后运行 startup.cmd -m standalone,Linux 和 Mac 运行 startup.sh -m standalone。启动完成后控制台地址是 http://localhost:8848/nacos。如果你要用 MySQL 做外部存储,先把 conf 目录下的 mysql-schema.sql 在数据库里执行完,建好库表,再在 application.properties 里配置数据源,最后重启。这一步很多人报错,我后面专门讲一个高频问题。
3.2 命名空间与安全配置
Nacos 跑起来之后,第一件事不是着急注册服务,而是规划命名空间。我见过太多项目把所有环境塞进 public 默认命名空间,开发环境把生产地址冲掉的情况,排查到下午发现是 namespace 配错了。规划习惯是:每个环境一个 namespace,用有含义的 ID,不要用随机 UUID。例如 development、testing、production,这样看日志一眼就知道当前环境。在这个基础上,用 group 做业务域隔离,销售域智能体统一用 GROUP_SALES,客服域用 GROUP_SERVICE。
安全配置方面,除了开启鉴权,还建议做到几点:控制台不要暴露公网,放到内网通过堡垒机访问;默认密码必须改掉,用强密码;数据库里的敏感配置不要明文写在 Nacos 的配置中心里,能用环境变量就用环境变量,能接 KMS 就接 KMS。热词里有人搜"nacos namespaces 未授权访问漏洞"和"nacos namespace 未授权访问漏洞",这个问题在旧版本里确实存在。除了升级到官方安全修复后的版本,更重要的是把鉴权打开,配置好访问控制,不要让自己的注册中心裸奔。
3.3 Spring Boot 工程接入 Nacos
智能体服务我用 Spring Boot 做载体比较多,接入 Nacos 最常用的姿势是 Spring Cloud Alibaba。先加依赖:
xml复制<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2023.0.1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2023.0.1.2</version>
</dependency>
版本号这里要特别提醒:nacos-client 与 Spring Cloud Alibaba 之间有版本兼容矩阵,不要直接拉最新版就硬上。我之前遇到过 Spring Cloud Alibaba 2021.x 配 nacos-client 2.2.x 出现 gRPC 连接不稳定的情况,后来换成官方推荐匹配的版本才恢复正常。具体选哪个版本,以官方文档的版本说明为准。
然后在 application.yml 里配置:
yaml复制spring:
application:
name: agent-sales
cloud:
nacos:
discovery:
server-addr: ${NACOS_ADDR:127.0.0.1:8848}
namespace: ${NACOS_NAMESPACE:development}
group: ${NACOS_GROUP:GROUP_SALES}
config:
server-addr: ${NACOS_ADDR:127.0.0.1:8848}
namespace: ${NACOS_NAMESPACE:development}
file-extension: yaml
group: ${NACOS_GROUP:GROUP_SALES}
主类加 @EnableDiscoveryClient,启动后去 Nacos 控制台的服务列表看,如果 agent-sales 出现在对应 namespace 下,说明注册成功了。这些配置我建议都用环境变量注入,不要让 namespace 和服务名硬编码,否则切环境只能改代码重新部署。配置动态刷新的原理也很简单:Nacos 配置中心的 dataId 变化后,通过长轮询通知客户端,Spring Cloud 里用 @RefreshScope 标注的 Bean 会被重新创建,从而加载新值。
4. AgentScope 2.0 接入 A2A 模式并注册到 Nacos
4.1 明确 A2A 模式的接入目标
先正面回答热词里大家最常搜的问题:AgentScope 2.0 有 A2A 模式的智能体协作吗?答案是肯定的。2.0 版本内置了 A2A 支持,你可以把一个本地智能体快速包装成 A2A 服务端对外暴露,也可以作为客户端调用其他暴露了 A2A 接口的智能体。这就让 AgentScope 变成了一个开放节点,而不是一座孤岛。
我做最小可行性验证时,用三个智能体做了一条完整链路:订单查询智能体、库存校验智能体、销售推荐智能体。三个智能体部署成三个独立的 Spring Boot 服务,全部注册到同一个 Nacos,服务名分别是 agent-order、agent-stock、agent-sales。销售推荐智能体处理用户请求时,先调用订单查询和库存校验两个智能体,汇总结果后给出推荐结论。这是一次典型的多智能体协作过程,涉及服务发现、协议调用、任务状态管理三个关键环节。
4.2 将智能体暴露为 A2A 服务端
AgentScope 这方面做得比较省心的是,你不需要自己编写 JSON-RPC 处理逻辑,框架已经把协议层封装好了。你的核心工作就两件事:定义清楚 AgentCard,以及把业务处理函数注册成任务执行入口。
AgentCard 简单理解就是对外声明"我是谁、我能干什么"。核心字段包括 name、description、url、version、capabilities。capabilities 里可以声明这个智能体是否支持流式输出、是否支持多轮任务等能力。如果你在 Nacos 注册时把 AgentCard 路径放进服务元数据,客户端就能通过元数据直接拿到 A2A 端点,不用先猜路径再逐个尝试。
任务处理入口就是接收 A2A 协议的任务请求,解析用户输入,交给业务逻辑处理,最后把结果写成任务状态和消息返回。这一层跟业务耦合最深,我建议单独抽一个 Service 类,不要在 Controller 层写大模型调用逻辑。协议层、业务层分离开,后面才好维护。
注意:A2A 协议的任务状态机是有明确约束的,大致是 submitted、working、completed、failed、canceled 这几个状态之间的流转。不要把业务异常直接变成 HTTP 500,而应该返回 failed 状态并在消息里说明原因,这样调用方才能正确处理。
4.3 通过 Nacos 完成寻址与通信
服务端准备好了,客户端如何找到它?这就是 Nacos 的用武之地。我不主张在代码里写死目标智能体地址,那样又回到老路了。标准做法是:调用方通过 Nacos NamingService 查询目标服务名,拿到健康的服务实例列表,再结合实例的 IP、端口和元数据里的 A2A 路径,拼出完整的 A2A 服务端点。
伪代码大致如下:
java复制List<Instance> instances = namingService.selectInstances("agent-order", true);
if (instances == null || instances.isEmpty()) {
throw new RuntimeException("agent-order service not found in Nacos");
}
Instance target = instances.get(0);
String a2aEndpoint = "http://" + target.getIp() + ":" + target.getPort() + "/a2a";
String agentCardUrl = "http://" + target.getIp() + ":" + target.getPort() + "/.well-known/agent-card.json";
拿到端点之后,用 AgentScope 的 A2A 客户端发起调用,传入任务消息,然后轮询任务状态或者通过流式方式拿到结果。整个过程中,调用方不需要关心目标智能体是什么框架写的、部署在哪台机器上,这些细节都被 Nacos 和 A2A 屏蔽掉了。而且 Nacos 自带的健康检查会让客户端尽量避开不健康的实例,实际生产环境里,某个智能体服务重启或扩容,对调用方是完全透明的。
如果你的团队走 Dubbo 体系,Nacos 同样可以作为 Dubbo 的注册中心。换句话说,在一个大型组织里,Spring Cloud 服务、Dubbo 服务、AgentScope A2A 智能体服务可以全部注册到同一个 Nacos,大家共享一套服务发现基础设施。从运维角度看,这比每个框架各搞一套注册中心要清爽得多。
4.4 一个最小协作调用流程
把上面的内容串起来,一次完整的跨智能体调用是这样的:
- 销售智能体启动,把自己注册到 Nacos,服务名 agent-sales,元数据里标明 A2A 端点路径。
- 订单查询、库存校验两个智能体同样完成注册。
- 销售智能体收到用户请求后,先从 Nacos 查 agent-order、agent-stock 的可用实例。
- 用 A2A 客户端向订单智能体发送任务:"查询用户 ID 为 10001 最近三个月的订单列表"。
- 订单智能体处理完,返回 completed 状态和订单数据。
- 销售智能体继续向库存智能体发任务,校验商品库存情况。
- 汇总全部结果后,销售智能体把最终推荐结论返回给上游用户。
这个流程看起来简单,背后的工程含义却很重要:每一次调用都涉及服务发现、健康检查、超时重试、任务状态追踪。这些基础设施复杂度不应该由业务代码承担,A2A 和 Nacos 的搭配,本质就是把这一层复杂度隔离掉,让开发者能专注在智能体的业务能力上。
5. 常见问题与排查实录
5.1 服务注册不上的几个典型原因
服务注册不上是新手最容易遇到的问题,直接上一张速查表。
| 现象 | 常见原因 | 排查手段 |
|---|---|---|
| 启动报 Connection refused | 8848 或 9848 端口没放通 | 用 telnet 测试到服务端的端口连通性 |
| 控制台能看到服务但客户端查不到 | namespace 或 group 不一致 | 对比两端配置,客户端用的是 namespace 的 ID,不是名称 |
| 服务时好时坏,经常掉线 | gRPC 端口 9848 未开放或网络不稳定 | 检查防火墙是否放通 9848,看实例健康状态 |
| 服务能注册但调用超时 | 服务提供方负载过高,健康检查失败 | 到 Nacos 控制台看实例健康状态,查对应服务日志 |
排查服务发现问题,最简单的方式是先到 Nacos 控制台的服务列表确认服务是否存在且健康。如果控制台正常但代码查不到,九成是 namespace 或 group 对不上。Nacos 的 namespace 有"ID"和"名称"两个概念,客户端配置时用的是 ID,不是显示名称。很多人把这两者混了,查出来的结果自然是空的。
5.2 命名空间一直为 null 的问题
热词里有个"nacos 命名空间一直为 null",我也踩过。最常见的原因是本地开发时 IDE 的环境变量没有传给启动进程。Spring Cloud 读取 nacos.config.namespace,如果你在配置文件里写的是 ${NACOS_NAMESPACE:},而环境变量没有设置,这个值自然就是 null。另一个原因是配置加载阶段不对,如果 Nacos 配置写在 application.yml 里但始终读不到,很可能是你的项目没有加载 bootstrap 配置,需要引入 spring-cloud-starter-bootstrap 依赖。
我建议团队在项目根目录放一个 .env.example 文件,把所有可配变量列清楚,新同事 clone 下来照着配就行,避免开发环境各自为政。但要注意,凡是对外敏感的信息不要放进 .env 这样的版本库文件,应该走专门的密钥管理。
5.3 ECS 上 Nacos 连接 MySQL 一直报错
热词里"ECS 配 Nacos 的 MySQL 一直报错,访问不了 MySQL"是非常高频的问题。我帮人排查过几次,原因基本集中在四类。
第一是 MySQL 8.x 密码加密方式变化。如果用的是 mysql-connector-java 8.x 以上的驱动,需要在 Nacos 配置里增加 allowPublicKeyRetrieval=true 和 useSSL=false,否则会报 Public Key Retrieval is not allowed。
第二是授权 host 问题。MySQL 用户只授权了 localhost,应用服务器从别的 IP 连接,当然会被拒绝。检查一下 MySQL 用户表的 host 是否包含了 Nacos 所在机器的 IP。
第三是防火墙和网络策略。ECS 安全组没有放通 3306 端口,或者 MySQL 配置绑定了 127.0.0.1,外部无法访问。
第四是数据库初始化没做对。mysql-schema.sql 没执行成功,启动时报表不存在。遇到这种问题,不要急着改代码,先从网络连通性、认证授权、库表初始化三层逐层排查。
5.4 A2A 调用中常见的协议层问题
A2A 是标准协议,但接入第三方智能体时还是会碰到协议层问题。最常见的是 AgentCard 的 URL 路径不标准。标准路径是 /.well-known/agent-card.json,有些实现放在了 /agent/card。解决方案是在 Nacos 注册时把实际的 AgentCard 路径放到服务元数据里,客户端优先读取元数据。
第二个常见问题是长任务超时。任务执行超过客户端等待时间,如果服务端不支持 SSE 或流式推送,客户端只能频繁轮询。轮询间隔需要设计合理,不要写死 100ms 的循环,否则既费服务端资源,又容易触发限流。做 SSE 时要处理好连接复用和断线重连,这是实现权限系统和流式任务时架构上容易忽略的地方。
第三个容易被忽略的点:多轮任务必须保存任务 ID 和上下文。有的团队把 A2A 调用做成无状态的一次性请求,第二轮消息不知道怎么关联上一轮。协议里 Task 本身就是会话载体,需要正确保存 taskId,后续消息在同一个 Task 下追加内容,而不是每次新建任务。
6. 从方案到落地:几点实在的建议
6.1 先跑通最小协作链路,再逐步扩容
别一开始就铺大网,把十几个智能体一次性全部接进 A2A 和 Nacos,出问题的时候根本分不清是协议问题、寻址问题还是业务逻辑问题。我建议从最核心的两三个智能体开始,先完整跑通一条端到端协作链路,确认 A2A 的任务状态流转、Nacos 的服务发现、配置动态刷新都正常,再逐步扩容。这个节奏看起来慢,实际是最稳的。
6.2 规范要前置,安全要守住
服务命名、namespace、group、A2A 端点路径、AgentCard 版本,这些规范最好在项目启动前就定下来,写进团队技术文档。后期几十个智能体上线后再想统一规范,成本非常大。安全底线也要提前设计:Nacos 必须开启鉴权,改强密码,不暴露公网;A2A 服务端要做好身份认证和请求鉴权。智能体与智能体之间往往都是高权限操作,一旦被非法调用,损失可能远超一个数据库泄露。
6.3 可观测性建设不能省
多智能体调用链比单体应用长得多,一次用户请求背后可能串了四五个智能体。项目一定要接入链路追踪,至少要在日志里记录每次 A2A 调用的 taskId、目标服务、耗时和状态。我的做法是把 taskId 放进日志上下文,排查问题的时候通过 taskId 把整条协作链路拉出来,一眼定位是哪一步出了问题。没有这个基础,多智能体出了问题就像在一个漆黑的房间里找一只不叫的猫。
多智能体协作的工程化现在还在快速演进。A2A 协议给出通信层的标准,Nacos 解决服务发现和配置管理,AgentScope 2.0 把这些能力集成到框架层,开发者的精力终于可以回到业务本身。这套组合我们在内部几个项目已经跑通了,稳定性和扩展性都达到了预期。如果你也在搭自己的智能体协作网络,建议先照着这套思路把最小链路跑起来,有了体感之后再根据自己的业务场景去扩展。
