☰
ADK A2A 协议远程智能体接入:从零到一的智能体互通实战指南
2026/10/23 1:59:48 网站建设 项目流程

ADK A2A 协议远程智能体接入:从零到一的智能体互通实战指南

【免费下载链接】adk-docsAn open-source, code-first toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.项目地址: https://gitcode.com/GitHub_Trending/ad/adk-docs

如果你有多个 ADK 智能体分布在不同的进程里需要互相调用,A2A 协议就是标准的打通方式。本文用三步从暴露到消费跑通链路,并解决端口冲突、agent 卡片缺失这类高频坑。

先跑起来(Quick Start)

仓库里有一个现成的 Go 示例 examples/go/a2a_basic,直接启动一个远端 A2A 服务:

export GOOGLE_API_KEY=你的模型Key cd examples/go/a2a_basic/remote_a2a/check_prime_agent go run main.go # 启动 A2A 服务,端口 8001 curl http://localhost:8001/.well-known/agent-card.json

跑完你会看到go run打出Starting A2A prime checker server on port 8001,而最后那条curl会返回一份 JSON 智能体卡片,里面带name、skills、url三个字段。卡片能取到,就说明这个智能体已经"开门营业",可以被其他智能体调用了。Python 版本则是pip install google-adk[a2a]后用to_a2a()加uvicorn起服务,下文实操部分会展开。

它到底在干什么(A2A 原理拆解)

问题:你的客服智能体跑在自己的服务里,库存智能体是另一个团队维护、跑在另一个进程里。直接 import 对方的代码?对方的任何接口改动都会让你跟着崩,而且根本拿不到人家的源码。

方案:给库存智能体加一层 A2A Server,把它"我是谁、会干什么"写成一份固定地址可访问的智能体卡片(agent card);调用方只需要知道这张卡片的 URL。

机制:ADK 把这件事拆成两个组件。服务提供方用to_a2a()把现成的 Agent 包成一个 Starlette 应用,自动生成智能体卡片——从你的 Agent 配置里提取 description、工具和技能,挂在.well-known/agent-card.json这个约定地址下;消费方用RemoteA2aAgent指向卡片 URL,ADK 会自动拉取卡片、完成网络请求、事件序列化和格式转换。对你的 root agent 来说,它只是sub_agents列表里多了一个成员。

智能体卡片就像门店的招牌加营业时间:顾客不需要知道仓库内部怎么运转,照着招牌上的地址下单就行。

顺带一提,ADK 的 A2A 集成还内置了三个能力:透传模型的推理轨迹(Reasoning)、追踪超长耗时工具调用避免超时、在智能体之间传递文件产物(Artifacts)。

选型对比——什么时候用 A2A,什么时候别用

维度本地子智能体(sub_agents)RemoteA2aAgent(A2A)自写 REST API + tool 函数
部署复杂度最低,同一进程中,远端需单独跑 A2A 服务中高,接口需自己定义和维护
延迟内存内调用,最低多一跳网络,毫秒到秒级与 A2A 相当,但鉴权错误处理全靠自己
适用团队规模单人或同一团队多团队、跨组织协作小规模、固定对接两三个服务
语言要求与宿主同语言跨语言:Python/Go/Java/Kotlin 均支持任意语言,但接口是私有约定

几个判断句:如果你的协作只是"把一个应用内的任务拆成模块",直接写本地子智能体;如果远端智能体由别的团队维护,或用不同语言编写(比如 Python 主智能体接 Java 库存服务),选 A2A;如果只是临时对接一个现成 HTTP 服务、对方又不打算改造成 A2A,先用 tool 函数包一层 REST,等对接面变大再迁移。

明确不适合的情况:高频低延迟的内部调用、子智能体需要直接读写主智能体内存状态的场景——序列化和网络开销会让 A2A 变成负资产。

动手实践:从 A2A 暴露到消费

Step 1:用 to_a2a() 暴露智能体

from google.adk.agents import Agent from google.adk.a2a.utils.agent_to_a2a import to_a2a inventory_agent = Agent( model="gemini-flash-latest", name="inventory_agent", instruction="你是库存查询智能体,查询库存时必须调用 query_stock 工具。", tools=[query_stock], ) a2a_app = to_a2a(inventory_agent, port=8001) # port 只是写进卡片URL,真正监听端口由 uvicorn 决定

这一步做了什么:把普通 Agent 变成可被网络访问的 A2A 应用,智能体卡片由 ADK 自动生成,不用手写。

Step 2:起服务并验证卡片

uvicorn my_app:inventory_agent_module --host localhost --port 8001 # 注意 --port 要和 to_a2a 的 port 一致 curl http://localhost:8001/.well-known/agent-card.json

预期输出(节选):

{"name": "inventory_agent", "url": "http://localhost:8001", "description": "你是库存查询智能体……", "version": "0.0.1", ...}

卡片能取到、url字段指向正确地址,服务端才算就绪。

Step 3:用 RemoteA2aAgent 消费

from google.adk.agents import Agent from google.adk.agents.remote_a2a_agent import RemoteA2aAgent remote_inventory = RemoteA2aAgent( name="inventory_agent", description="远程库存查询智能体", agent_card="http://localhost:8001/.well-known/agent-card.json", # 填 Step 2 验证过的卡片地址 ) root_agent = Agent( model="gemini-flash-latest", name="service_root", sub_agents=[remote_inventory], # 和本地子智能体写法完全一样 )

远程智能体和本地智能体在代码里长得一模一样,root agent 用自然语言决定何时把任务委托给它,剩下的网络细节 ADK 全包了。

除了to_a2a(),还有一种暴露方式是adk api_server --a2a:它可以直接和adk web搭配调试,且能指向一个含多个智能体的父目录,但要求每个智能体文件夹里手动写好agent.json卡片,细节见 docs/a2a/quickstart-consuming.md。

一个完整的业务场景

场景:电商客服智能体要回答"这个 SKU 还有货吗",而库存能力在另一个团队维护的库存服务里。

Before(没有 A2A):

  • 客服团队没有标准接口可用,只能求库存团队导一个内部 REST API,自己写鉴权、自己解析私有 JSON
  • 库存服务接口字段一改,客服侧必须跟着发版
  • 两边靠口头约定的契约耦合,出问题时各说各话

After(接入 A2A):

  • 库存智能体用to_a2a()暴露,会干什么、收什么格式全写在卡片里,这就是正式契约
  • 客服侧只加一个RemoteA2aAgent,对话里自然语言即可触发库存查询
  • 库存服务升级只改服务端和卡片,客服侧代码不动

调试时把adk web指向消费方智能体,左侧 Trace/Events 面板能看到远程调用事件的完整链路,和调本地工具的体验一致。

踩坑与注意事项

  1. 现象:RemoteA2aAgent拉卡片失败,或调用永远 404。原因:to_a2a(port=8001)只是把 8001 写进卡片 URL,它本身不监听端口;uvicorn --port起在别的端口时,卡片就指向了不存在的地址。解法:port参数必须和uvicorn --port保持一致,起完服务先curl卡片确认再连消费端。

  2. 现象:adk api_server --a2a服务正常启动,但对方找不到你的智能体。原因:这条命令只暴露包含agent.json文件的智能体文件夹,没有卡片等于不存在。解法:在智能体目录补上agent.json(至少含name、url、skills),并核对卡片里url与服务的实际路径前缀一致。

  3. 现象:起调试界面时端口被占用,服务起不来。原因:adk web默认占 8000 端口,示例里的 A2A 服务在 8001;如果你把 A2A 也改成 8000 就会撞车。解法:保持约定,8000 留给调试 UI,A2A 服务从 8001 起排,多智能体时逐个递增。

一个to_a2a()让你的智能体上线,一个RemoteA2aAgent让对方把它当本地子智能体用,这就是 A2A 的核心链路。Python 暴露与消费的完整流程见 docs/a2a/quickstart-exposing.md 和 docs/a2a/quickstart-consuming.md,Go、Java、Kotlin 版本指南汇总在 docs/a2a/index.md。可运行的双端示例在 examples/go/a2a_basic/,流式模式下遇到消息重复可以再看 docs/a2a/a2a-extension.md。

【免费下载链接】adk-docsAn open-source, code-first toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.项目地址: https://gitcode.com/GitHub_Trending/ad/adk-docs

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询