基于A2A协议将智能体注册到Nacos3.x
·
1.配置和简介
Nacos3.x比Nacos2.x多了可以注册智能体的功能。

配置密钥,32位即可


启动分为集群模式和单机模式,单机模式下,默认存储在derby下。
2.智能体注册中心:
AgentScope也是自带注册中心的,叫AgentScopeA2aServer。
现在我们是把当前项目的注册中心改成nacos。
1.通过SpringBoot,以Bean的形式注册到注册中心
2.手动写入注册中心,好处能够自定义智能体卡片对象。通过Builder方法传入。
本项目采用Nacos为注册中心。
那么springBoot怎么知道我的注册中心是Nacos?
通过yml文件配置即可:
agentscope:
a2a:
server:
enabled: true
card:
name: TripPlanner Agent
description: 行程规划agent
nacos:
server-addr: localhost:8848
username: nacos
password: nacos
创建一个生成智能体的工具类:
@Slf4j
@Service
public class AgentUtils {
//从配置中读取敏感资源,不能使用static
@Resource
private Properties properties;
public ReActAgent.Builder getReActAgentBuilder(String name, String description) {
return ReActAgent.builder()
.name(name)
.description(description)
.model(DashScopeChatModel.builder()
//请求语言大模型的apikey
.apiKey(properties.getAlibabaDashscopeKey())
//所使用的语言大模型
.modelName(properties.getModelName())
.stream(true)
.build());
}
public static Flux<Event> streamResponse(AgentBase agent, String prompt) {
return agent.stream(Msg.builder().role(MsgRole.USER)
.content(List.of(TextBlock.builder().text(prompt).build())).build());
}
}
主管智能体在nacos上获得了智能体卡片并知道了这个智能体的功能,然后就会把任务分发下去。
在routeMakingAgent目录下的agent包下创建这个类:
!注意主管智能体是不用注册到nacos的
@Component
@Slf4j
public class RouteMakingAgent {
@Resource
private AgentUtils agentUtils;
@Resource
private BaiduMapMCP baiduMapMCP;
@Bean
public ReActAgent getRouteMakingAgent() {
//创建百度地图MCP客户端
baiduMapMCP.getBaiduMapMCP();
//初始化百度地图MCP客户端
McpClientWrapper mcpClient = baiduMapMCP.initBaiduMapMCP();
ToolUtils toolUtils = new ToolUtils();
//将百度地图MCP注册到工具包
Toolkit toolkit = toolUtils.getToolkit(mcpClient);
//打印挂载的工具
Set<String> toolNames = toolkit.getToolNames();
log.info("=============");
toolNames.stream().forEach(
value -> log.info("挂载的工具名称:" + value)
);
log.info("=============");
//注入到nacos
return agentUtils.getReActAgentBuilder("RouteMakingAgent", "擅长路线制定规划")
//工具包
.toolkit(toolkit)
.build();
}
}
@Component
public class TripPlannerAgent {
@Resource
private AgentUtils agentUtils;
@Resource
private SuggestSightAgent suggestSightAgent;
@Bean
public ReActAgent getTripPlannerAgent() throws Exception {
/* **********************
*
* 1.
* AgentScope框架自带了注册中心: AgentScopeA2aServer
*
* 2.
* AgentScope框架将智能体卡片注册到注册中心,有2种方案:
* a. 通过SpringBoot, 以Bean的形式自动注入
* b. 手动写入注册中心, 主要针对于AgentScopeA2aServer
*
*
* *********************/
Toolkit toolkit = new Toolkit();
//子智能体
toolkit.registration().subAgent(
suggestSightAgent::getSuggestSightAgent
).apply();
//构建skill ,将工具包和skill结合
ReActAgent.Builder builder = agentUtils.getReActAgentBuilder(
"TripPlannerAgent",
"擅长处理景点行程规划"
)
//挂载工具包
.toolkit(toolkit);
return builder.build();
}
}
写一个工具类让主管智能体去nacos发现是否有这样的智能体,读取智能体卡片,
@Slf4j
public class RemoteAgentTool {
@Tool(description = "擅长制定最优驾车路线的Agent")
public void callRouteMakingAgent(
@ToolParam(name = "prompt", description = "驾车的起点和终点") String prompt
) throws NacosException {
log.info("============");
log.info("工具方法:路线制定智能体...正在调用中");
log.info("============");
A2aAgent agent = A2aAgent.builder()
.name("RouteMakingAgent") //必须和注册中心的智能体名字一样
.agentCardResolver(
//创建 Nacos 的 AgentCardResolver
new NacosAgentCardResolver(NacosUtil.getNacosClient()))
.build();
prompt = "调用百度地图MCP, 制定最优驾车路线:" + prompt;
PromptUtils promptUtils = new PromptUtils();
Msg userMsg = promptUtils.getPrompt(prompt);
log.info("============");
log.info("获取到的远程Agent描述:" + agent.getDescription());
log.info("============");
AgentUtils.streamResponse(agent, "调用百度地图MCP");
}
@Tool(description = "从Nacos注册中心获取行程规划Agent")
public void callTripPlannerAgent() throws NacosException {
A2aAgent agent = A2aAgent.builder()
.name("TripPlannerAgent")
.agentCardResolver(
//创建 Nacos 的 AgentCardResolver
new NacosAgentCardResolver(NacosUtil.getNacosClient()))
.build();
//远程Agent运行
agent.call().block();
}
}
创建一个百度地图MCP客户端
@Slf4j
@Component
public class BaiduMapMCP {
@Resource
private Properties properties;
//MCP 客户端
private volatile McpClientWrapper baiduMapMCP = null;
//MCP 客户端初始化
private volatile boolean mcpInitialized = false;
public void getBaiduMapMCP() {
//创建MCP客户端
baiduMapMCP = McpClientBuilder.create("BaiduMap-mcp")
//和MCP Server以SSE方式进行通信
.sseTransport(properties.getBaiduMapAddr())
//请求超时
.timeout(Duration.ofSeconds(120))
//异步请求
.buildAsync()
.block();
}
/**
*
* description: 初始化百度地图MCP客户端
* @param :
* @return io.agentscope.core.tool.mcp.McpClientWrapper
*/
public McpClientWrapper initBaiduMapMCP() {
//通过Optional判断百度MCP客户端是否为null
Optional<McpClientWrapper> mcpClientWrapper = Optional.ofNullable(baiduMapMCP);
if(mcpClientWrapper.isPresent()) {
if(!mcpInitialized) { //线程锁
synchronized (this) {
if (!mcpInitialized) {
try {
//MCP客户端初始化, 通过阻塞线程让客户端和服务端成功建立联系。
baiduMapMCP.initialize().block();
//获取MCP服务端工具列表
if(baiduMapMCP.isInitialized()) {
log.info("=============");
log.info("百度地图MCP 客户端初始化成功!");
log.info("=============");
baiduMapMCP.listTools().block().forEach(tool -> {
log.info("==================");
log.info("百度地图MCP工具列表:" + tool.name());
log.info("==================");
});
mcpInitialized=true;
}
} catch (Exception e) {
log.error("百度地图MCP客户端初始化失败: {}", e.getMessage(), e);
baiduMapMCP = null;
}
}
}
}
}
return baiduMapMCP;
}
}
在魔塔社区配置百度地图的客户端,这里使用百度地图,SSE协议就用SSE,

通过工具包挂载到智能体上面,在RouteMakingAgent的代码里面有详解,
具体的工具包类:
那么百度地图的MCP的客户端走第二个getToolkit方法,这是重写的方法。
public class ToolUtils {
private final Toolkit toolkit;
public ToolUtils() {
toolkit = new Toolkit();
}
public Toolkit getToolkit(Object tool) {
toolkit.registerTool(tool);
return toolkit;
}
public Toolkit getToolkit(McpClientWrapper mcp) {
toolkit.registerMcpClient(mcp);
return toolkit;
}
}
主管智能体会根据智能体的description的描述来分配任务,所以description有两种配置方式,
1.yml文件配置(优先级最高)
agentscope:
a2a:
server:
enabled: true
card:
name: TripPlanner Agent
description: 行程规划agent
nacos:
server-addr: localhost:8848
username: nacos
password: nacos
@Component
public class TripPlannerAgent {
@Resource
private AgentUtils agentUtils;
@Resource
private SuggestSightAgent suggestSightAgent;
@Bean
public ReActAgent getTripPlannerAgent() throws Exception {
Toolkit toolkit = new Toolkit();
//子智能体
toolkit.registration().subAgent(
suggestSightAgent::getSuggestSightAgent
).apply();
//构建skill ,将工具包和skill结合
return agentUtils.getReActAgentBuilder(
"TripPlannerAgent",
"擅长处理景点行程规划" //这里就是我对这个处理景点智能体的描述
)
//挂载工具包
.toolkit(toolkit)
.build();
}
}
打开nacos:可以发现还是以yml文件为主

解决方法:注释description即可,但同时要先删除nacos已经注册的智能体卡片。
更多推荐
所有评论(0)