Next ‘26 开发者主旨演讲:使用技能和工具构建 ADK 智能体

1. 简介

在此 Codelab 中,您将使用智能体开发套件 (ADK) 构建一个复杂的马拉松规划智能体。您将逐步了解智能体的各种功能,从结构良好的系统提示到动态技能加载和 MCP 工具映射。最后,您将在本地测试代理并将其部署到代理运行时 (Agent Engine)。

您将执行的操作

  • 初始化新的 ADK 代理项目
  • 使用结构化构建器撰写可靠的系统提示
  • 添加 Google 地图 MCP 工具,以获取现实世界的位置背景信息
  • 将技能动态加载到代理的工具集中
  • 在本地测试代理执行
  • 将智能体部署到 Agent Engine (Cloud Run)

所需条件

  • 网络浏览器,例如 Chrome
  • 启用了结算功能的 Google Cloud 项目
  • 基本熟悉 Python

此 Codelab 适合希望构建专业生成式 AI 代理的中级开发者。

预计时长:45 分钟

本 Codelab 中创建的资源费用应低于 2 美元。

2. 准备工作

创建 Google Cloud 项目

  1. Google Cloud 控制台的项目选择器页面上,选择或创建一个 Google Cloud 项目
  2. 确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能

启动 Cloud Shell

Cloud Shell 是在 Google Cloud 中运行的命令行环境,预加载了必要的工具。

  1. 点击 Google Cloud 控制台顶部的激活 Cloud Shell
  2. 连接到 Cloud Shell 后,验证您的身份验证:
    gcloud auth list
    
  3. 确认您的项目已配置:
    gcloud config get project
    
  4. 如果项目未按预期设置,请进行设置:
    export PROJECT_ID=<YOUR_PROJECT_ID>
    gcloud config set project $PROJECT_ID
    

验证身份验证:

gcloud auth list

确认您的项目:

gcloud config get project

根据需要进行设置:

export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID

启用 API

运行以下命令可启用所有必需的 API:

gcloud services enable \
  aiplatform.googleapis.com \
  run.googleapis.com \
  secretmanager.googleapis.com \
  mapstools.googleapis.com \
  storage.googleapis.com \
  cloudresourcemanager.googleapis.com \
  serviceusage.googleapis.com

创建 Google 地图 API 密钥

如需使用 Google 地图 MCP 工具,您需要生成 Google 地图 API 密钥。

  1. 在 Google Cloud 控制台中,使用搜索栏前往 Google Maps Platform > 凭据
  2. 如果系统提示,请确认您的 Google Cloud 项目。
  3. 点击创建凭证,然后选择 API 密钥
  4. 复制生成的 API 密钥。下一步操作将会用到该地址。

3. 设置您的环境

在此 Codelab 中,代码托管在 GitHub 上。您将克隆包含目录结构和所需子组件(例如 skills/ 目录)的代码库。

  1. 克隆代码库并前往项目文件夹:
git clone https://github.com/GoogleCloudPlatform/next-26-keynotes
cd next-26-keynotes/devkey/demo-1
  1. 设置 Python 虚拟环境并安装 ADK:
uv venv
source .venv/bin/activate
uv sync
  1. 设置您的地图 API 密钥。应用会从环境变量中读取该值:
export GOOGLE_MAPS_API_KEY="<YOUR_MAPS_API_KEY>"

配置环境变量

模拟器代理使用 .env 文件进行配置。复制示例文件,并使用您的项目 ID 对其进行更新。

  1. 复制示例环境文件:
cp planner_agent/sample.env planner_agent/.env
  1. 打开 planner_agent/.env,使用实际的 Google Cloud 项目 ID 更新 GOOGLE_CLOUD_PROJECT 字段,并使用您创建的 Google Maps API 密钥更新 GOOGLE_MAPS_API_KEY 字段。

文件内容应如下所示:

GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID>
GOOGLE_CLOUD_LOCATION=global
GOOGLE_MAPS_API_KEY=<YOUR_MAPS_API_KEY>
GOOGLE_CLOUD_AGENT_ENGINE_ENABLE_TELEMETRY=true
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true
ADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS=true

4. 创建新的 ADK 代理

探索定义代理的核心文件:planner_agent/agent.py

build-agents-with-skills 代码库中,智能体使用 ADK 的 Agent 类进行初始化。它指定了底层模型、身份名称,并提取了在其他模块中定义的指令和工具。

打开 planner_agent/agent.py 以检查初始化代码:

instruction="Answer user questions to the best of your knowledge"
description="A helpful assistant for user questions."
tools=[]

# ...

root_agent = Agent(
    model='gemini-3-flash-preview',
    name='planner_agent',
    description=description,
    instruction=instruction,
    tools=tools
)

Agent 类可抽象出消息记录、工具编排和大语言模型通信,让您专注于智能体的行为。

目前,该代理非常通用。您可以像与任何其他 LLM 互动一样与它互动。

uv run adk run planner_agent

此命令将开始与代理对话。它使用 gemini-3-flash-preview 作为模型,可以回答基本问题。

Running agent planner_agent, type exit to exit.
[user]: What is the length of a Marathon
[planner_agent]: The official length of a marathon is **26.2 miles**, which is
equivalent to **42.195 kilometers**.

代理已经知道一些关于马拉松的事实。不过,这还不足以规划一场包含规则和路线规划的马拉松。

5. 创建系统提示

系统提示(指令)决定了代理的行为。此项目不使用单个巨型字符串,而是使用 PromptBuilder (planner_agent/utils.py) 来动态组合指令。

打开 planner_agent/prompts.py,查看提示如何划分为各个逻辑部分:

from collections import OrderedDict
from .utils import PromptBuilder

ROLE = """\
...
"""

RULES = """\
...
"""

WORKFLOW = """\
...
"""

###

# Planner instructions with no tools mentioned
PLANNER_INSTRUCTION_NO_TOOLS = PromptBuilder(
    OrderedDict(
        role=ROLE,
        rules=RULES,
        tools=TOOLS_PROMPT_ONLY,
        workflow=WORKFLOW_PROMPT_ONLY,
    )
).build()

# Planner instruction with skills and tools defined
PLANNER_INSTRUCTION = PromptBuilder(
    OrderedDict(
        role=ROLE,
        rules=RULES,
        skills=SKILLS,
        tools=TOOLS,
        workflow=WORKFLOW,
    )
).build()

planner_agent/agent.py 中,此内容已导入。

找到包含 TODO: Replace Instruction and Description 的部分,然后取消对 instructiondescription 变量重新赋值的注释。

相应代码部分应如下所示:

instruction=PLANNER_INSTRUCTION_NO_TOOLS
description="Expert GIS analyst for marathon route and event planning."

您正在导入代理的提示版本,该版本未引用任何工具。您将在后面的步骤中添加工具。

您可以测试此版本的代理:

uv run adk run planner_agent

在对话窗口中,发送以下提示:

Plan a marathon for 10000 participants in Las Vegas on April 24, 2027 in the
evening timeframe

过一会儿,您应该会收到类似如下所示的回答:

Running agent planner_agent, type exit to exit.
[user]: Plan a marathon for 10000 participants in Las Vegas on April 24, 2027 in the evening timeframe
[planner_agent]: Here is the comprehensive marathon plan for Las Vegas.

As requested, I have designed this event for an evening start on April 24, 2027. Because certain parameters (theme and budget) were not specified, I have applied pragmatic defaults: this will be a "Neon Nights" scenic theme to capitalize on the evening Strip, operating on a moderate-to-high budget given the infrastructure needed to secure major Las Vegas corridors.

### 1. Intent Alignment
*   **City & Theme:** Las Vegas, Nevada. Theme: "Neon Nights" an evening race maximizing the visual impact of the illuminated city.
*   **Date & Time:** Saturday, April 24, 2027. Late April evenings in Las Vegas offer optimal running weather (temperatures dropping from ~70°F at sunset to ~60°F). Race start is 6:30 PM (sunset is approx. 7:20 PM).
...
...

通过明确的提示,输出结果已经非常接近预期结果。在下一步中,您将添加工具,以将智能体提升到新的水平。

6. 添加技能和工具

如需在 planner_agent/agent.py 中启用技能和工具,请找到包含 TODO: Replaces Tools 的部分,并将接下来的两行取消注释。您的代码应如下所示:

instruction=PLANNER_INSTRUCTION
tools=get_tools()

这是此步骤中唯一需要更改的代码。本部分的其余内容将介绍技能和工具背后的概念。

技能

智能体技能是 ADK 智能体可用于执行特定任务的独立功能单元。智能体技能根据智能体技能规范封装了任务所需的必要指令、资源和工具。技能的结构使其能够以增量方式加载,从而最大限度地减少对代理操作上下文窗口的影响。

对于马拉松规划代理,定义了 3 项技能:

  1. gis-spatial-engineering - 负责处理 GeoJSON 数据以创建马拉松路线。
  2. 地图 - 使用 Google 地图工具搜索地点和天气信息。
  3. race-director - 验证马拉松路线是否符合规划指南。

技能可以包含脚本、其他资源和参考文件。

应用会加载所有技能,并在 planner_agent/tools.py 中将它们作为工具提供。请注意 get_tools() 函数中是如何实现这一点的:

def get_tools() -> list:
    """Build the planner's tool list with lazy-loaded skills."""
    from google.adk.code_executors.unsafe_local_code_executor import UnsafeLocalCodeExecutor

    skills_dir = pathlib.Path(__file__).parent / "skills"

    skills = []
    if skills_dir.exists():
        skills = [
            load_skill_from_dir(d)
            for d in sorted(skills_dir.iterdir())
            if d.is_dir() and not d.name.startswith("_") and (d / "SKILL.md").exists()
        ]

    additional_tools = _load_additional_tools(skills_dir)

    skill_toolset = SkillToolset(
        skills=skills,
        code_executor=UnsafeLocalCodeExecutor(),
        additional_tools=additional_tools,
    )

    tools = [
        skill_toolset,
        PreloadMemoryTool(),
    ]

    tools.extend(get_maps_tools())

    return tools

最有趣的部分是 ADK 中的 load_skill_from_dir 方法。在 ADK 中,还可以通过内嵌方式创建技能。虽然在此 Codelab 中未使用,但它看起来大致如下所示:

from google.adk.skills import models

greeting_skill = models.Skill(
    frontmatter=models.Frontmatter(
        name="greeting-skill",
        description=(
            "A friendly greeting skill that can say hello to a specific person."
        ),
    ),
    instructions=(
        "Step 1: Read the 'references/hello_world.txt' file to understand how"
        " to greet the user. Step 2: Return a greeting based on the reference."
    ),
    resources=models.Resources(
        references={
            "hello_world.txt": "Hello! So glad to have you here!",
            "example.md": "This is an example reference.",
        },
    ),
)

添加了映射工具

马拉松规划工具需要空间背景信息才能生成路线。您可以通过集成 Google 地图 MCP(Model Context Protocol)服务器来提供此信息。

planner_agent/tools.py 中,请注意 MCP 服务器是如何通过 ApiRegistry 工具注册的:

from google.adk.integrations.api_registry import ApiRegistry

class MapsApiRegistry(ApiRegistry):
    """ApiRegistry subclass that strips ADC headers to force API key auth."""

    def get_toolset(self, *args, **kwargs):  # noqa: ANN002, ANN003
        toolset = super().get_toolset(*args, **kwargs)
        conn = getattr(toolset, "_connection_params", None)
        headers = getattr(conn, "headers", None) if conn else None
        if headers:
            headers.pop("Authorization", None)  # type: ignore[union-attr]
            headers.pop("x-goog-user-project", None)  # type: ignore[union-attr]
        return toolset

def get_maps_tools() -> list:
    """Return Maps MCP toolset if configured."""
    project_id = os.getenv("GOOGLE_CLOUD_PROJECT", "").strip()
    maps_key = _resolve_maps_key()

    if not project_id or not maps_key:
        return []

    # Map the MCP server location on Google Cloud
    mcp_server_name = f"projects/{project_id}/locations/global/mcpServers/google-mapstools.googleapis.com-mcp"
    
    # Initialize the custom API registry that supports header injection
    api_registry = MapsApiRegistry(
        api_registry_project_id=project_id,
        header_provider=header_provider,
    )
    return [api_registry.get_toolset(mcp_server_name=mcp_server_name)]

添加 MCP 工具集后,智能体便会自动获得查询 Google 地图以获取路线、海拔和位置详细信息的能力!

7. 在本地运行代理

现在,代理、提示和工具已连接在一起,请在本地运行代理。这次,您将使用 adk web,以便查看技能加载和工具调用事件。

uv run adk web

您应该会看到类似如下内容

INFO:     Started server process [99665]
INFO:     Waiting for application startup.

+-----------------------------------------------------------------------------+
| ADK Web Server started                                                      |
|                                                                             |
| For local testing, access at http://127.0.0.1:8000.                         |
+-----------------------------------------------------------------------------+

INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
  1. 打开浏览器,然后前往终端中显示的网址(通常为 http://localhost:8000)。
  2. 在左上角的下拉菜单中,选择 planner_agent
  3. 在对话窗口中,发送以下提示:
Plan a marathon for 10000 participants in Las Vegas on April 24, 2027 in the
evening timeframe

您应该会看到技能正在加载,并且工具正在被调用。片刻之后,智能体便会生成马拉松计划。

界面应如下所示:

ADK Web 界面

8. 部署代理

如果您对代理在本地的表现感到满意,则可以将其部署到 Agent Engine,后者可在 Cloud Run 上安全地托管代理。

如需部署智能体,请使用 ADK CLI 部署命令:

uv run adk deploy agent_engine \
  --env_file planner_agent/.env --region=us-central1 \
  planner_agent

部署完成后,CLI 会输出代理的安全托管端点。现在,您可以将此端点集成到前端应用、聊天机器人或其他后端系统中。您还可以使用代理运行时 Playground 来测试代理。

输出如下所示:

Files and dependencies resolved
Deploying to agent engine...
✅ Created agent engine: projects/<PROJECT_ID>/locations/us-west1/reasoningEngines/<AGENT_ID>

您可以使用提供的 Python 脚本与代理进行通信。

  1. 复制示例环境文件:
cp sample.env .env
  1. 打开 .env,然后使用您的实际 Google Cloud 项目 ID 更新 GOOGLE_CLOUD_PROJECT 字段。

文件应如下所示:

GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID>
GOOGLE_CLOUD_LOCATION=us-central1
  1. 您可以列出项目中的代理。
python main.py list

您应该会看到类似如下内容

Listing deployed agents...

ID: <AGENT_ID> | Display Name: planner_agent

获得已部署的代理 ID 后,您可以发送提示:

export AGENT_ID=<AGENT_ID>
python main.py prompt --agent-id ${AGENT_ID} --message "Plan a marathon for
10000 participants in Las Vegas on April 24, 2027 in the evening timeframe"

您将看到如下所示的输出:

Streaming response from agent <AGENT_ID>:

{'model_version': 'gemini-3-flash-preview', 'content': {'parts': [{'text': 'Here is a comprehensive
...
...
...

9. 清理

为避免系统向您的 Google Cloud 账号持续收取费用,请删除本 Codelab 中创建的资源。

删除部署创建的 Cloud Run 服务:

python main.py delete --agent-id ${AGENT_ID}

如果您已将地图 API 密钥存储在 Secret Manager 中,请删除相应 Secret:

gcloud secrets delete maps-api-key --project=$PROJECT_ID

如果您为此 Codelab 创建了新的 Google Cloud 云项目,可以删除整个项目,以移除与其关联的所有资源和 API:

gcloud projects delete $PROJECT_ID

10. 恭喜

恭喜!您已使用 ADK 构建了一个复杂的马拉松规划器代理。

您学到的内容

  • 初始化智能体开发套件 (ADK) 项目
  • 利用 PromptBuilder 实现模块化系统提示
  • 使用 MCP 工具和 ApiRegistry 集成地图功能
  • 使用 SkillToolset 有条件地加载技能
  • 在本地进行测试并部署到 Agent Engine

参考文档