两条命令打通远程智能体: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
Agent Development Kit(ADK)里的 A2A(Agent2Agent)协议,解决的是一个很具体的问题:当你的主智能体需要调用一个独立部署的智能体时,双方用什么格式说话?A2A 给出了标准答案——每个远程智能体对外提供一张"智能体卡片"描述自己的能力,调用方凭这张卡片发起请求。ADK 在 Python、Go、Java 中都已提供 A2A 支持(实验特性),并把暴露与消费两端的网络细节基本都包掉了。
先判断:这次协作真需要走网络吗
ADK 中智能体之间协作有两条路。本地子智能体(sub_agents)和主智能体跑在同一个进程里,通信走内存,快且无序列化开销,适合把复杂任务拆成"数据校验""实时分析"这类内部模块。而远程 A2A 智能体是独立服务,跨网络通信,多一层延迟,换来的是边界清晰。
判断标准可以简化成四个问句:
- 对方是不是一个独立服务(比如别家提供的金融建模智能体)?
- 对方是不是由另一个团队维护?
- 对方是不是用别的语言或别的框架写的?
- 你是否需要在组件之间钉死一份正式契约?
四条只要中一条,就值得上 A2A。反过来,如果子智能体要直接读主智能体的内部状态、或者操作高频低延迟,本地子智能体更合适——A2A 的序列化成本在那种场景下纯属拖累。
典型场景也好认:订单、库存、物流拆成各自的服务互相调用;Python 主链路集成一个 Java 遗留组件;或者搭一个多团队共建智能体的平台,用协议保证兼容性。
第一步:把智能体变成网络服务
方式一:一行 to_a2a() 暴露
这是最轻量的路线。to_a2a()把你现有的 ADK 智能体包装成 A2A 应用,并自动从智能体代码中提取技能、能力和元数据,生成智能体卡片:
from google.adk.a2a.utils.agent_to_a2a import to_a2a # 把现有智能体包装为 A2A 应用,卡片自动生成 a2a_app = to_a2a(root_agent, port=8001)然后用 uvicorn 起服务即可。想自己定义卡片也行:agent_card参数既接受AgentCard对象,也接受卡片 JSON 文件路径。
⚠️ 这里有个容易踩的坑:to_a2a()本身不绑定端口,port参数只用来拼卡片里对外宣告的 URL,必须和你 uvicorn 实际监听的--port一致,否则调用方按卡片地址访问时会打到一个空端口上(默认值是 8000)。
方式二:adk api_server --a2a 托管
这条路线更适合边开发边调试,因为它和adk web打通,智能体可以直接在 Dev UI 里测试:
# 安装 A2A 依赖后,启动 A2A 服务,在 8001 端口暴露 check_prime_agent pip install google-adk[a2a] adk api_server --a2a --port 8001 contributing/samples/a2a/a2a_basic/remote_a2a它的工作方式是按文件夹托管:指定一个父目录,里面凡是带agent.json卡片的智能体文件夹都会被自动挂到同一台服务器上。所以这条路线下卡片要自己写(文件名必须精确叫agent.json,缺少这个文件的服务端根本不会暴露该智能体)。启动成功后终端会打印Uvicorn running on http://127.0.0.1:8001,此时卡片地址形如http://localhost:8001/a2a/check_prime_agent/.well-known/agent-card.json,浏览器打开即可核对内容。
第二步:像用本地工具一样消费远程智能体
消费端只需要一个组件:RemoteA2aAgent。它拿着智能体卡片的 URL(或AgentCard对象、本地卡片文件路径)就能找到远端服务,网络通信、数据格式转换都在幕后完成:
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent # 通过卡片 URL 挂接远程素数检查智能体 prime_agent = RemoteA2aAgent( name="prime_agent", description="Agent that handles checking if numbers are prime.", agent_card="http://localhost:8001/a2a/check_prime_agent/.well-known/agent-card.json", )把它塞进sub_agents之后,对开发者来说它和一个本地子智能体没有区别:
root_agent = Agent( model="gemini-flash-latest", name="root_agent", instruction="掷骰子委托给 roll_agent,素数检查委托给 prime_agent", sub_agents=[roll_agent, prime_agent], )仓库里的a2a_basic示例就是这个结构:本地的roll_agent管掷骰子,远程的prime_agent管素数判定。服务都起来后,输入"Roll a 10-sided die and check if it's prime",你会看到 root agent 先让本地子智能体掷出 8,再把 8 交给远端prime_agent,最终回答"8 不是素数"——两次委托,一次走内存,一次走网络,业务代码里完全看不出差别。
避坑与进阶配置
几个实际项目里最常碰到的问题:
- 端口冲突:本地联调时
adk web默认占着 8000,远程 A2A 服务请固定换 8001(或别的端口),这也是官方示例的惯例。 - SDK 版本:ADK 的 A2A 集成同时兼容
a2a-sdk0.3.x 和 1.x,版本自动检测、业务代码不用改;但新集成建议直接面向 1.x。 - 新旧两套客户端路径:
RemoteA2aAgent的use_legacy参数默认True,走旧版协议路径;设成False后客户端会向远端发送 A2A extension,启用新版 executor。 - 调试日志:
adk api_server加--log_level debug可以看到更细的请求日志。
需要更细的控制时,两端都留了钩子。服务端可以把A2aAgentExecutorConfig直接传给A2aAgentExecutor,覆盖a2a_part_converter、gen_ai_part_converter、request_converter等转换器,或用execute_interceptors(before_agent/after_event/after_agent)在请求与事件流转中插入中间件;客户端侧则通过config传入A2aRemoteAgentConfig,提供request_interceptors(before_request/after_request)来改写 A2A 请求或拦截响应事件。
另外,A2A 集成还保留了几项容易被忽略的能力:跨智能体传递模型推理轨迹(Reasoning)、跟踪长耗时工具调用(Long-Running Tools)、以及在智能体之间传递文件产物(Artifacts)。
💡 想动手跑通的话,建议直接看仓库里的示例:Go 版在 examples/go/a2a_basic/,Python 示例的结构在 docs/a2a/quickstart-exposing.md 和 docs/a2a/quickstart-consuming.md 里有逐步说明,Go/Java 的暴露与消费 quickstart 也都在 docs/a2a/ 下。
下一步
- 跑通 Python 暴露端:docs/a2a/quickstart-exposing.md
- 跑通 Python 消费端:docs/a2a/quickstart-consuming.md
- 新版 A2A extension 协议细节:docs/a2a/a2a-extension.md
- 其他语言入口:docs/a2a/quickstart-exposing-go.md、docs/a2a/quickstart-exposing-java.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),仅供参考