当前位置: 首页 > news >正文

使用agentscope自动注册agent应用到nacos以及对a2a协议的思考

参考资料

  • https://java.agentscope.io/zh/task/a2a.html#a2a-server
  • https://mp.weixin.qq.com/s/-pp43gOTkTtkuxAt_szFIw

本文主要记录了在测试agent自动注册nacos过程中对a2a的一些思考,可能存在一些理解的偏差,请审慎自主思考阅读。

借助A2A 对接能力可以实现像调用本地工具一样自然地调用远端 A2A Agent,实现跨语言、跨框架的协同。agentscope能够将应用包装成符合 A2A 规范的服务端点。

这里使用agentscope runtime启动agent,并同时注册在nacos中,如下示例

# 创建 Nacos Registry 实例
registry = NacosRegistry(nacos_client_config=ClientConfigBuilder().server_address("localhost:8848")# 其他可选配置项.build()
)
agent_app = AgentApp(app_name="TourGuideAgent",app_description="专业导游智能体,提供旅游咨询、路线规划和景点介绍服务",# 在 a2a_config 中配置 registry 和技能a2a_config=AgentCardWithRuntimeConfig(port=8091,registry=registry,agent_card={"skills": [AgentSkill(id="attraction_recommendation",name="景点推荐",description="根据旅游目的地和时间,推荐当地热门景点和小众景点",inputModes=["text"],outputModes=["text"],tags=["景点", "推荐", "旅游"]),AgentSkill(id="travel_consultation",name="旅游咨询",description="解答关于交通、住宿、美食、天气等旅游相关问题",inputModes=["text"],outputModes=["text"],tags=["旅游咨询", "交通", "住宿", "美食"])]}),
)@agent_app.query(framework="agentscope")
async def query_func(self,msgs,request: AgentRequest = None,**kwargs,
):# 创建ReAct智能体实例agent = ReActAgent(name="TourGuide",model=OpenAIChatModel(model_name="gpt-4o-mini",api_key="sk-uzpq0u0n5FN14HorW45hUw",client_kwargs={"base_url": "http://172.31.14.46:4000"},stream=True,  # 启用流式响应),sys_prompt="你是一位专业的导游,熟悉各地的旅游景点、历史文化和风土人情。请为游客提供详细的旅游咨询、路线规划和景点介绍。回答时要热情友好,信息准确,并尽可能提供实用的旅游建议。",memory=InMemoryMemory(),formatter=OpenAIChatFormatter(),)agent.set_console_output_enabled(enabled=False)# 执行智能体并流式返回消息async for msg, last in stream_printing_messages(agents=[agent],coroutine_task=agent(msgs),):yield msg, lastif __name__ == "__main__":import asyncioasync def main():result = await agent_app.deploy(LocalDeployManager(host="0.0.0.0", port=8091), mode=DeploymentMode.DAEMON_THREAD)stop_event = asyncio.Event()await stop_event.wait()asyncio.run(main())

启动服务后,可以观察到nacos中已经自动注册了a2a服务

image-20260122230110461

使用如下客户端请求

async def main() -> None:# 1. 从 Nacos 获取 Agent Cardagent_card = await NacosAgentCardResolver(remote_agent_name="TourGuideAgent",nacos_client_config=ClientConfig(server_addresses="http://127.0.0.1:8848",),).get_agent_card()print(f"获取到 Agent Card: {agent_card.name}")# 2. 调用 agent 获取回复agent = A2AAgent(agent_card=agent_card)msg = Msg(name="user",content="告诉我亚马逊有哪些计算服务?",role="user",)await agent(msg)if __name__ == "__main__":import asyncioasyncio.run(main())

这个时候我希望了解下获取a2a card已经agent之间通信的细节,于是通过抓包的方式来检查。

由于已经将agent card注册在nacos中,并且在客户端中通过NacosAgentCardResolver检索,因此客户端能够通过nacos获取a2a card信息,类似如下内容

$ curl localhost:8091/.well-known/agent-card.json{"additionalInterfaces":[],"capabilities":{"pushNotifications":false,"stateTransitionHistory":false,"streaming":false},"defaultInputModes":["text"],"defaultOutputModes":["text"],"description":"专业导游智能体,提供旅游咨询、路线规划和景点介绍服务","name":"TourGuideAgent","preferredTransport":"JSONRPC","protocolVersion":"0.3.0","skills":[{"description":"根据旅游目的地和时间,推荐当地热门景点和小众景点","id":"attraction_recommendation","inputModes":["text"],"name":"景点推荐","outputModes":["text"],"tags":["景点","推荐","旅游"]},{"description":"解答关于交通、住宿、美食、天气等旅游相关问题","id":"travel_consultation","inputModes":["text"],"name":"旅游咨询","outputModes":["text"],"tags":["旅游咨询","交通","住宿","美食"]}],"url":"http://172.31.14.46:8091/a2a","version":"1.0.0"}

然而在操作过程中发现无法获取到访问8848端口的请求,

  1. 程序成功运行并获取到了 a2a card,但是抓包只看到 8091 端口的流量
  2. 但是程序访问了 Nacos,不存在缓存机制(已经重启了客户端)

通过strace我们发现client实际访问nacos使用的是9848端口

# strace -f -e trace=network python agentscope/a2a/client.py
[pid 1146518] connect(12, {sa_family=AF_INET, sin_port=htons(9848), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
[pid 1146520] connect(12, {sa_family=AF_INET6, sin6_port=htons(9848), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_scope_id=0}, 28) = -1 EINPROGRESS (Operation now in progress)
[pid 1146518] connect(13, {sa_family=AF_INET, sin_port=htons(9848), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
[pid 1146519] connect(13, {sa_family=AF_INET6, sin6_port=htons(9848), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_scope_id=0}, 28) = -1 EINPROGRESS (Operation now in progress)
[pid 1146475] connect(14, {sa_family=AF_INET, sin_port=htons(8091), sin_addr=inet_addr("172.31.14.46")}, 16) = -1 EINPROGRESS (Operation now in progress)

Nacos 的 gRPC 端口通常是 9848,也就是说客户端Nacos SDK 使用了 gRPC 协议来通信,具体代码入口为。关于这一点的说明见,https://nacos.io/blog/faq/nacos-user-question-history15295/

Nacos 从 2.0 版本开始引入了 gRPC 协议作为客户端与服务器之间的通信方式。Nacos 2.0 引入 gRPC 的主要目的是为了提升性能和扩展性

# agentscope/a2a/_nacos_resolver.py
client = await NacosAIService.create_ai_service(...)
return await client.get_agent_card(...)# v2/nacos/ai/nacos_ai_service.py
self.grpc_client_proxy = AIGRPCClientProxy(...)
return await self.grpc_client_proxy.get_agent_card(...)

继续查看抓包结果,追踪HTTP流结果如下

image-20260122233546447

可见客户端向agent的/a2a发起post请求

{"id": "8725cad3-0d83-48d2-bed3-da456fca651e","jsonrpc": "2.0","method": "message/send","params": {"configuration": {"acceptedOutputModes": [],"blocking": true},"message": {"kind": "message","messageId": "3fef013a-842c-462c-9be6-d5bdf23a4b28","parts": [{"kind": "text","text": "告诉我亚马逊有哪些计算服务?"}],"role": "user"}}
}

响应内容如下,响应内容和ADK的示例还是有区别的,可能是由于A2A协议本身也在变动中。

{"id": "8725cad3-0d83-48d2-bed3-da456fca651e","jsonrpc": "2.0","result": {"kind": "message","messageId": "msg_46df2210-d0f8-463c-a108-ae69bd62c2b5","parts": [{"kind": "text","text": "您提到服您推荐一个适合初学者的“第一个 AWS 计算项目”?😊"}],"role": "agent"}
}

这里有一个问题,a2a调用并没有提到需要使用那些技能,这一点和mcp tool中通过明确的schema定义支持的工具是有区别的,我理解由于a2a本身是供agent之间相互调用的协议,因此a2a card中携带的内容实际上起到的作用类似于对agent的描述。

所以,a2a更像是意图委托,Client并不关心 Server 具体用了什么函数和方法,只是发送一个自然语言的任务。Remote Agent 接到任务后,自己进行推理,决定是否需要使用其他工具来完成这个任务。

所以当我们将remote agent的系统提示定义为一个技术专家,但是skill中指定导游的技能时,会得到以下回复。因为skill只决定了client agent是否会发送相关的请求,而remote agent的输出并不会受到skill的影响。

image-20260122235413288

http://www.jsqmd.com/news/286026/

相关文章:

  • YCDISM2026 GUI项目进行中...
  • 学Simulink--风电电机控制场景实例:基于Simulink的DFIG转子电流限幅保护策略仿真
  • 解决:all predefined address pools have been fully subnetted
  • 2026毕业季必备:6款免费降AI率工具实测推荐
  • 学Simulink——风电电机控制场景实例:基于Simulink的风电变流器死区补偿与非线性校正仿真
  • SCI论文降AI率工具推荐:留学生和科研党必看的5款利器
  • 降AI不伤文:保留专业术语的6个实用技巧
  • 2026降AI工具红黑榜:亲测10款后只推荐这3个
  • 论文降AI工具TOP5横评:哪款效果最好、性价比最高
  • 知网AIGC检测不通过?这份避坑指南请收好
  • 类和对象(下)
  • 2026年国产持妆粉底液厂家专业深度测评(排名前五)
  • 工业显示器在智能办公用品申领柜中的应用
  • Rust入门一:从内存安全到高性能编程
  • 从源码视角来看Pinia!
  • 2026年国产持妆粉底液专业深度测评:排名前五品牌权威发布
  • 2026年国产持妆粉底液专业深度测评:排名前五供应商权威榜单
  • 初学范畴论的一些体会
  • 2026年专业深度测评:国产持妆粉底液厂家排名前五权威榜单
  • 2026毕业论文降AI必备:这5款工具帮你AI率降到10%以下
  • 【计算机毕业设计案例】基于springboot的就业招聘面试试题管理系统(程序+文档+讲解+定制)
  • 2026年8款免费降AI率工具实测推荐,毕业生必看
  • 【计算机毕业设计案例】基于SpringBoot+Vue咖啡售卖商城平台的设计与实现基于springboot的咖啡共赏平台(程序+文档+讲解+定制)
  • 毕业生必看:知网AIGC检测不通过怎么办?超全解决方案
  • 解决 Java UnsatisfiedLinkError: libfontmanager.so 加载失败问题
  • Java毕设项目推荐-基于springboot的面试试题管理系统基于springboot面试刷题平台系统的设计与实现【附源码+文档,调试定制服务】
  • 长春婚纱照,记录下你们爱情故事中的每一个动人瞬间
  • Java毕设项目推荐-基于springboot在线咖啡点单平台基于springboot的咖啡共赏平台【附源码+文档,调试定制服务】
  • 基于微信小程序的汽车维修预约系统【源码+文档+调试】
  • 学习日记day65