Google Cloud 智能体注册表¶
Agent Development Kit (ADK) 中的 Agent Registry 客户端库允许开发者发现、查找并连接到 Google Cloud Agent Registry 中编目的 AI 智能体和 MCP 服务器。这支持使用受治理的组件进行基于智能体的应用的动态组合。
使用场景¶
- 加速开发:从中央目录轻松查找和重用现有智能体和工具(MCP 服务器),而无需重新构建它们。
- 动态集成:在运行时发现智能体和 MCP 服务器端点,使应用程序对环境变化更加稳健。
- 增强治理:在 ADK 应用程序中使用来自注册表的受治理和已验证的组件。
前置条件¶
- 一个 Google Cloud 项目。
- 在你的 Google Cloud 项目中启用 Agent Registry API。
- 为你的环境配置身份验证。你应该使用应用程序默认凭据(
gcloud auth application-default login)进行登录。 - 将环境变量
GOOGLE_CLOUD_PROJECT设置为你的项目 ID,将GOOGLE_CLOUD_LOCATION设置为相应的区域(例如global、us-central1)。 - 按照安装部分的说明安装适用于你所用语言的 ADK。
有关从 ADK 智能体连接到 Google Cloud 的更多信息,请参阅连接 Google Cloud 和 Agent Platform。
安装¶
Agent Registry 集成是核心 ADK 库的一部分。
必要的依赖项¶
google.adk.integrations.agent_registry 模块在模块作用域内同时导入了 A2A SDK
和 Agent Identity 身份验证提供者,因此仅安装核心包时导入 AgentRegistry 会抛出
ImportError。请同时安装 a2a 和 agent-identity 附加组件:
与智能体配合使用¶
在 ADK 智能体中使用 Agent Registry 集成的主要方式是通过 Agent Registry 客户端动态获取远程智能体或工具集。
from google.adk.agents.llm_agent import LlmAgent
from google.adk.integrations.agent_registry import AgentRegistry
import os
# 1. 初始化
project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")
location = os.environ.get("GOOGLE_CLOUD_LOCATION", "global")
if not project_id:
raise ValueError("GOOGLE_CLOUD_PROJECT environment variable not set.")
registry = AgentRegistry(
project_id=project_id,
location=location,
)
# 2. 列出资源
print("Listing Agents...")
agents_response = registry.list_agents()
for agent in agents_response.get("agents", []):
print(f" - {agent.get('name')} ({agent.get('displayName')})")
print("Listing MCP Servers...")
mcp_servers_response = registry.list_mcp_servers()
for server in mcp_servers_response.get("mcpServers", []):
print(f" - {server.get('name')} ({server.get('displayName')})")
# 3. 使用远程 A2A 智能体
# 替换为你的已注册智能体的完整资源名称
agent_name = f"projects/{project_id}/locations/{location}/agents/YOUR_AGENT_ID"
my_remote_agent = registry.get_remote_a2a_agent(agent_name=agent_name)
# 4. 使用 MCP 工具集
# 替换为你的已注册 MCP 服务器的完整资源名称
mcp_server_name = f"projects/{project_id}/locations/{location}/mcpServers/YOUR_MCP_SERVER_ID"
my_mcp_toolset = registry.get_mcp_toolset(mcp_server_name=mcp_server_name)
# 5. 示例智能体组合
main_agent = LlmAgent(
model="gemini-flash-latest", # 或你偏好的模型
name="demo_agent",
instruction="You can leverage registered tools and sub-agents.",
tools=[my_mcp_toolset],
sub_agents=[my_remote_agent],
)
package main
import (
"cmp"
"context"
"fmt"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/adk/v2/agent"
"google.golang.org/adk/v2/agent/llmagent"
"google.golang.org/adk/v2/agentregistry"
"google.golang.org/adk/v2/cmd/launcher"
"google.golang.org/adk/v2/cmd/launcher/full"
"google.golang.org/adk/v2/model/gemini"
"google.golang.org/adk/v2/tool"
)
func main() {
ctx := context.Background()
// 1. 初始化
projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
if projectID == "" {
log.Fatal("GOOGLE_CLOUD_PROJECT environment variable not set.")
}
location := cmp.Or(os.Getenv("GOOGLE_CLOUD_LOCATION"), "global")
registry, err := agentregistry.New(ctx, agentregistry.Config{
ProjectID: projectID,
Location: location,
})
if err != nil {
log.Fatalf("Failed to create the registry client: %v", err)
}
// 2. 列出资源。All* 迭代器按需获取分页数据,
// 并将获取失败的页面报告为单个 (nil, error)。
fmt.Println("Listing Agents...")
for a, err := range registry.AllAgents(ctx) {
if err != nil {
log.Fatalf("Failed to list agents: %v", err)
}
fmt.Printf(" - %s (%s)\n", a.Name, a.DisplayName)
}
fmt.Println("Listing MCP Servers...")
for s, err := range registry.AllMCPServers(ctx) {
if err != nil {
log.Fatalf("Failed to list MCP servers: %v", err)
}
fmt.Printf(" - %s (%s)\n", s.Name, s.DisplayName)
}
// 3. 使用远程 A2A 智能体
// 替换为你的已注册智能体的完整资源名称
agentName := fmt.Sprintf("projects/%s/locations/%s/agents/YOUR_AGENT_ID", projectID, location)
myRemoteAgent, err := registry.RemoteAgent(ctx, agentName)
if err != nil {
log.Fatalf("Failed to resolve the remote agent: %v", err)
}
// 4. 使用 MCP 工具集
// 替换为你的已注册 MCP 服务器的完整资源名称
mcpServerName := fmt.Sprintf("projects/%s/locations/%s/mcpServers/YOUR_MCP_SERVER_ID", projectID, location)
myMCPToolset, err := registry.MCPToolset(ctx, mcpServerName)
if err != nil {
log.Fatalf("Failed to connect to the MCP server: %v", err)
}
// 5. 示例智能体组合
model, err := gemini.NewModel(ctx, "gemini-flash-latest", &genai.ClientConfig{})
if err != nil {
log.Fatalf("Failed to create the model: %v", err)
}
rootAgent, err := llmagent.New(llmagent.Config{
Name: "demo_agent",
Model: model,
Instruction: "You can leverage registered tools and sub-agents.",
Toolsets: []tool.Toolset{myMCPToolset},
SubAgents: []agent.Agent{myRemoteAgent},
})
if err != nil {
log.Fatalf("Failed to create the agent: %v", err)
}
config := &launcher.Config{AgentLoader: agent.NewSingleLoader(rootAgent)}
l := full.NewLauncher()
if err := l.Execute(ctx, config, os.Args[1:]); err != nil {
log.Fatalf("Run failed: %v\n\n%s", err, l.CommandLineSyntax())
}
}
Google MCP 服务器和远程 A2A 智能体的身份验证¶
远程 A2A 智能体¶
对远程 A2A 智能体的调用不会自动进行身份验证。如果你正在连接到 Google A2A 智能体,请在创建远程智能体时提供一个经过身份验证的 HTTP 客户端。
将配置了 Google 身份验证头的 httpx.AsyncClient 传递给 get_remote_a2a_agent 方法。
import httpx
import google.auth
from google.auth.transport.requests import Request
class GoogleAuth(httpx.Auth):
def __init__(self):
self.creds, _ = google.auth.default()
def auth_flow(self, request):
if not self.creds.valid:
self.creds.refresh(Request())
request.headers["Authorization"] = f"Bearer {self.creds.token}"
yield request
httpx_client = httpx.AsyncClient(auth=GoogleAuth(), timeout=httpx.Timeout(60.0))
remote_agent = registry.get_remote_a2a_agent(
f"projects/{project_id}/locations/{location}/agents/YOUR_AGENT_ID",
httpx_client=httpx_client,
)
使用 WithA2AHTTPClient 传递经过身份验证的 *http.Client,或使用 WithA2AHeaders 传递静态头信息。
import (
"golang.org/x/oauth2/google"
"google.golang.org/adk/v2/agentregistry"
)
httpClient, err := google.DefaultClient(ctx, "https://www.googleapis.com/auth/cloud-platform")
if err != nil {
log.Fatalf("Failed to load Application Default Credentials: %v", err)
}
remoteAgent, err := registry.RemoteAgent(ctx, agentName,
agentregistry.WithA2AHTTPClient(httpClient),
)
请在客户端的 Transport 上设置超时时间,而不是使用 http.Client.Timeout,因为后者应用于整个请求,可能会截断流式响应。
Google MCP 服务器¶
对于 Google MCP 服务器,身份验证头会自动传递。
如果自动身份验证未按预期工作,你可以使用 AgentRegistry 构造函数中的 header_provider 参数手动提供头信息。
import google.auth
from google.auth.transport.requests import Request
from google.adk.integrations.agent_registry import AgentRegistry
def google_auth_header_provider(context):
creds, _ = google.auth.default()
if not creds.valid:
creds.refresh(Request())
return {"Authorization": f"Bearer {creds.token}"}
registry = AgentRegistry(
project_id=project_id,
location=location,
header_provider=google_auth_header_provider
)
对 *.googleapis.com 端点的请求会复用注册表客户端本身的凭据。对于任何其他端点,或要覆盖该默认行为,请传入 WithMCPHTTPClient 和 WithMCPHeaders。
toolset, err := registry.MCPToolset(ctx, mcpServerName,
agentregistry.WithMCPHTTPClient(httpClient),
agentregistry.WithMCPHeaders(map[string]string{"X-Tenant-Id": "acme"}),
)
以这种方式设置的头信息将应用于工具集向 MCP 服务器发送的每个请求。它们不会影响对 Agent Registry API 本身的调用。
API 参考¶
AgentRegistry 类提供以下核心方法:
list_mcp_servers(self, filter_str, page_size, page_token):获取已注册的 MCP 服务器列表。get_mcp_server(self, name):获取特定 MCP 服务器的详细元数据。get_mcp_toolset(self, mcp_server_name):从已注册的 MCP 服务器构建一个 ADK McpToolset 实例。list_agents(self, filter_str, page_size, page_token):获取已注册的 A2A 智能体列表。get_agent_info(self, name):获取特定 A2A 智能体的详细元数据。get_remote_a2a_agent(self, agent_name):为已注册的 A2A 智能体创建一个 ADK RemoteA2aAgent 实例。
agentregistry.Client 类型为每种资源类型提供三种发现方法:List* 返回单页结果,Get* 通过完整资源名称返回单个资源,All* 返回一个按需获取分页数据的 iter.Seq2。
ListAgents(ctx, opts ...ListOption)、GetAgent(ctx, name)、AllAgents(ctx, opts ...ListOption):已注册的 A2A 智能体。ListMCPServers(ctx, opts ...ListOption)、GetMCPServer(ctx, name)、AllMCPServers(ctx, opts ...ListOption):已注册的 MCP 服务器。ListEndpoints(ctx, opts ...ListOption)、GetEndpoint(ctx, name)、AllEndpoints(ctx, opts ...ListOption):已注册的模型端点。RemoteAgent(ctx, name, opts ...RemoteAgentOption):将已注册的 A2A 智能体解析为可用作子智能体的agent.Agent。MCPToolset(ctx, name, opts ...MCPToolsetOption):将已注册的 MCP 服务器解析为tool.Toolset。
列表选项包括 WithFilter、WithPageSize 和 WithPageToken。All* 迭代器会自行管理分页令牌。来自 Agent Registry API 的非 2xx 响应将以 *agentregistry.APIError 的形式返回,其中包含 StatusCode 和响应 Body。
配置选项¶
AgentRegistry 构造函数接受以下参数:
project_id(str,必填):Google Cloud 项目 ID。location(str,必填):Google Cloud 位置/区域,例如 "global"、"us-central1"。header_provider(Callable,可选):一个可调用对象,接受 ReadonlyContext 并返回一个自定义头信息字典。这些头信息将包含在get_mcp_toolset返回的 McpToolset 对目标 MCP 服务器发出的请求中。这些头信息不会影响对 Agent Registry API 本身的调用,也不会影响 RemoteA2aAgent 发出的请求。对于这些请求,请将经过身份验证的httpx.AsyncClient传递给get_remote_a2a_agent,如远程 A2A 智能体部分所示。
agentregistry.New 构造函数接受一个 Config 结构体:
ProjectID(string,必填):Google Cloud 项目 ID。Location(string,必填):Google Cloud 位置/区域,例如 "global"、"us-central1"。HTTPClient(*http.Client,可选):用于 Agent Registry API 调用的客户端。当为 nil 时,ADK 会从应用程序默认凭据构建一个客户端,并从GOOGLE_API_USE_MTLS_ENDPOINT和GOOGLE_API_USE_CLIENT_CERTIFICATE解析端点(包括 mTLS)。此客户端也会复用于到*.googleapis.com端点的 McpToolset 流量,但不会用于 A2A 流量。
到已解析端点的出站连接则按调用分别配置:RemoteAgent 使用 WithA2AHTTPClient 和 WithA2AHeaders,MCPToolset 使用 WithMCPHTTPClient 和 WithMCPHeaders。