快速入门:通过 A2A 使用远程智能体¶
本快速入门涵盖每位开发者最常见的出发点:"有一个远程智能体,我如何让我的 ADK 智能体通过 A2A 使用它?" 这对于构建复杂的多智能体系统至关重要,因为不同的智能体需要协作和交互。
概述¶
本示例展示了 Agent Development Kit (ADK) for Kotlin 中的 Agent2Agent (A2A) 架构,演示了本地智能体如何将部分任务委派给在其他地方运行的智能体。
┌─────────────────┐ ┌────────────────────────┐
│ Root Agent │────────▶│ Remote Prime Agent │
│ (Local) │◀────────│ (localhost:8001) │
└─────────────────┘ └────────────────────────┘
- Root Agent(
root_agent):委派给子智能体的本地编排器 - Prime Agent(
prime_agent):一个远程 A2A 智能体,用于检查数字是否为质数,运行在独立的 A2A 服务器上
添加 A2A 依赖¶
A2A 支持以单独的工件发布。A2A SDK 客户端也需要在编译类路径上,因为 A2AAgent 的 httpClient 参数默认为 JdkA2AHttpClient():
implementation("com.google.adk:google-adk-kotlin-a2a:0.8.0")
implementation("org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Final")
启动远程智能体服务器¶
要使用远程智能体,首先需要有一个正在运行的远程智能体。adk-kotlin 尚不支持通过 A2A 暴露智能体,因此服务器必须来自其他地方——A2A 是一种线路协议,所以任何语言都可以。
adk-python 中的 a2a_basic 示例提供了本页面委派到的质数智能体。在 adk-python 检出目录中:
A2A 协议要求每个智能体发布一个描述其功能的智能体卡片,该卡片在其自身前缀下的知名路径上提供:
在继续之前检查卡片是否可达:
此客户端可以连接的服务器
Kotlin 客户端读取 A2A 1.0 卡片,因此卡片必须携带一个 supportedInterfaces 数组,其条目各自具有 protocolBinding。为 A2A 0.3 编写的卡片声明一个顶层 url 和 preferredTransport,而 A2AAgent 会以 AgentCardResolutionError: Failed to parse agent card 拒绝它们。
示例的已签入 agent.json 是 0.3 风格的卡片,但 adk-python 不会原样提供该文件:它在启动时解析卡片,在 a2a-sdk 1.x 下,该解析会将 url 和 preferredTransport 提升为 supportedInterfaces。adk-python 要求 a2a-sdk>=0.3.4,<2,因此全新安装会解析到 1.x,线路上的卡片为 A2A 1.0。
adk-java 中的 a2a_server 示例固定使用 0.3.x A2A SDK,提供 0.3 卡片,因此不能作为本页面的服务器使用。
提供你自己的卡片
任何发布 A2A 1.0 卡片的服务器都可以。客户端接受的最小卡片,从 <your-base-url>/.well-known/agent-card.json 提供:
{
"name": "check_prime_agent",
"description": "Checks whether numbers are prime.",
"version": "1.0.0",
"url": "http://localhost:9090",
"preferredTransport": "JSONRPC",
"capabilities": { "streaming": true },
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["application/json"],
"skills": [],
"supportedInterfaces": [
{ "protocolBinding": "JSONRPC", "url": "http://localhost:9090" }
]
}
将该基础 URL——http://localhost:9090——作为下面的 agentCardUrl。
连接到远程智能体¶
A2AAgent 获取该卡片并从中读取远程智能体的描述,以及远程是否支持流式传输。你传递的 name 是此智能体在你自己智能体树中的标识符,独立于卡片公布的名称。它是一个挂起函数,因此从协程中调用:
// A2AAgent is a suspending factory: it fetches the remote agent's card from
// <url>/.well-known/agent-card.json and takes the description and streaming
// capability from it. The name is yours -- it identifies this agent in your
// tree, independent of the name the card advertises. The constructor of the
// returned agent is internal, so this factory is the only way to build one.
val primeAgent =
A2AAgent(
name = "prime_agent",
agentCardUrl = "http://localhost:8001/a2a/check_prime_agent",
)
如果你已经持有一个 AgentCard——例如你自己解析的,或签入到配置中的静态卡片——有一个非挂起的重载可以直接接受它:A2AAgent(name = ..., agentCard = ...)。
作为子智能体使用¶
返回的智能体是一个 BaseAgent,因此它可以像本地智能体一样放入 subAgents 中。ADK 通过线路处理 A2A 协议:
// The remote agent is a BaseAgent, so it goes in subAgents like any local one.
// ADK handles the A2A wire protocol from here.
val rootAgent =
LlmAgent(
name = "root_agent",
model = Gemini(name = "gemini-flash-latest"),
instruction =
Instruction(
"You are a helpful assistant that can check prime numbers " +
"by delegating to prime_agent.",
),
subAgents = listOf(primeAgent),
)
后续步骤¶
Kotlin 智能体尚不支持通过 A2A 暴露;adk-kotlin 目前仅提供消费端。要暴露智能体,请参阅其他语言的快速入门: