1. 简介
在本实验中,您将重点练习实现和部署客户端智能体服务。您将使用智能体开发套件 (ADK) 构建一个使用远程工具(例如在实验 1 中创建的 MCP 服务器)的 AI 智能体。本实验中体现的关键架构原则是关注点分离,即通过安全的 API,让不同的推理层(智能体)与不同的工具层(MCP 服务器)进行通信。
在实验 1 中,您创建了一个 MCP 服务器,该服务器可为 LLM 提供有关虚构动物园中动物的数据,例如当您使用 Gemini CLI 时就会用到它。在本实验中,我们将为虚构的动物园构建一个导游智能体。该智能体将使用实验 1 中的同一 MCP 服务器来访问有关动物园内动物的详细信息,并使用维基百科来为游客打造优秀的游玩体验。

最后,我们将导游智能体部署到 Google Cloud Run,这样动物园的所有游客都可以访问它,而不仅仅是在本地运行。
前提条件
- 在 Cloud Run 上运行的 MCP 服务器或关联的服务网址。
- 启用了结算功能的 Google Cloud 项目。
学习内容
- 如何构建一个 Python 项目,用于部署 ADK。
- 如何使用 google-adk 实现一个使用工具的智能体。
- 如何将智能体连接到远程 MCP 服务器以获取其工具集。
- 如何将 Python 应用作为无服务器容器部署到 Cloud Run。
- 如何使用 IAM 角色配置安全的服务间身份验证。
- 如何删除 Cloud 资源,避免以后产生费用。
所需条件
- Google Cloud 账号和 Google Cloud 项目
- 网络浏览器,例如 Chrome
2. 为何要部署到 Cloud Run?
Cloud Run 是托管 ADK 智能体的绝佳选择,因为它是一个无服务器平台,这意味着您可以专注于代码,而无需亲自管理底层基础设施。我们会为您处理运维工作。
您可以将其想象成一家快闪店:只在客户(请求)上门时开门营业并使用资源。没有顾客时,它会完全关闭,您无需为空店支付费用。
主要功能
在任何地方运行容器:
- 您需要提供一个包含应用的容器(Docker 映像)。
- Cloud Run 会在 Google 的基础设施上运行该容器。
- 不用负责为操作系统打补丁、设置虚拟机或扩缩。
自动扩缩:
- 如果没有人在使用您的应用 → 运行 0 个实例(缩减到零个实例,可节省费用)。
- 如果有 1,000 个请求发送到该服务 → 它会根据需要启动相应数量的副本。
默认为无状态:
- 每个请求都可以发送到不同的实例。
- 如果需要存储状态,请使用 Cloud SQL、Firestore 或 Memorystore 等外部服务。
支持任何语言或框架:
- 只要能在 Linux 容器中运行,Cloud Run 就不在乎它是 Python、Go、Node.js、Java 还是 .Net。
用多少,付多少:
3. 设置和要求
自定进度的环境设置
- 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个。



- 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串。您可以随时对其进行更新。
- 项目 ID 在所有 Google Cloud 项目中是唯一的,并且是不可变的(一经设置便无法更改)。Cloud 控制台会自动生成一个唯一字符串;通常情况下,您无需关注该字符串。在大多数 Codelab 中,您都需要引用项目 ID(通常用
PROJECT_ID标识)。如果您不喜欢生成的 ID,可以再随机生成一个 ID。或者,您也可以尝试自己的项目 ID,看看是否可用。完成此步骤后便无法更改该 ID,并且此 ID 在项目期间会一直保留。 - 此外,还有第三个值,即部分 API 使用的项目编号,供您参考。如需详细了解所有这三个值,请参阅文档。
- 接下来,您需要在 Cloud 控制台中启用结算功能,以便使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有的话)。若要关闭资源以避免产生超出本教程范围的结算费用,您可以删除自己创建的资源或删除项目。Google Cloud 新用户符合参与 300 美元免费试用计划的条件。
启动 Cloud Shell
前往 Cloud Shell 编辑器
如果终端未显示在屏幕底部,请打开它:
- 点击终端
- 点击新建终端

在终端中,使用以下命令设置项目。如果您已完成实验 1,请确保您使用的是相同的项目 ID:
gcloud config set project [YOUR-PROJECT-ID]
如果您不记得项目 ID,可以使用以下命令列出所有项目 ID:
gcloud projects list | awk '/PROJECT_ID/{print $2}'
4. 如果系统提示您进行授权,请点击授权继续。

5. 您应会看到以下消息:
Updated property [core/project].
If you see a `WARNING` and are asked `Do you want to continue (Y/n)?`,
then you have likely entered the project ID incorrectly. Press `n`,
press `Enter`, and try to run the `gcloud config set project` command again.
4. 准备工作
启用 API 并设置环境变量
启用所有必要的服务:
gcloud services enable \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com \
aiplatform.googleapis.com \
compute.googleapis.com
预期输出
Operation "operations/acat.p2-[GUID]" finished successfully.
5. 创建项目文件夹
创建项目目录。
此命令会在实验中创建一个用于存放智能体源代码的主文件夹。
cd && mkdir zoo_guide_agent && cd zoo_guide_agent
创建 requirements.txt 文件。此文件列出了您的代理需要使用的 Python 库。以下命令会创建该文件并填充内容。
cloudshell edit requirements.txt
google-adk==1.14.0
langchain-community==0.3.27
wikipedia==1.4.0
为当前项目 ID 和项目编号设置变量,并为项目创建一个专用服务账号。这是一种更稳健的运行这些命令的方式。
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
export SA_NAME=lab2-cr-service
export SERVICE_ACCOUNT="${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
gcloud iam service-accounts create ${SA_NAME} \
--display-name="Service Account for lab 2 "
创建并打开 .env 文件,以对 zoo_guide_agent 目录中的代理进行身份验证。
cloudshell edit .env
cloudshell edit 命令会在终端上方的编辑器中打开 .env 文件。在 .env 文件中输入以下内容,然后返回到终端。
MODEL="gemini-2.5-flash"
添加 MCP 服务器网址。如果您已完成实验 1,请按照以下步骤操作,以使用您在实验 1 中创建的 MCP 服务器:
- 为 Cloud Run 服务身份授予调用远程 MCP 服务器的权限
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT" \
--role="roles/run.invoker"
- 将实验 1 中的 MCP 服务器网址保存到环境变量中。
echo -e "\nMCP_SERVER_URL=https://zoo-mcp-server-${PROJECT_NUMBER}.europe-west1.run.app/mcp" >> .env
如果您使用的是公共 MCP 服务器链接,请运行以下命令,并将 PROJECT_NUMBER 替换为所提供的链接。
echo -e "\nMCP_SERVER_URL=https://zoo-mcp-server-${PROJECT_NUMBER}.europe-west1.run.app/mcp" >> .env
6. 创建代理工作流
创建 init.py 文件
创建 init.py 文件。此文件会告诉 Python,zoo_guide_agent 目录是一个软件包。
cloudshell edit __init__.py
上述命令会打开代码编辑器。将以下代码添加到 __init__.py:
from . import agent
创建主 agent.py 文件
创建主 agent.py 文件。此命令会创建 Python 文件,并将多智能体系统的完整代码粘贴到该文件中。
cloudshell edit agent.py
第 1 步:导入和初始设置
第一个代码块会引入 ADK 和 Google Cloud 中的所有必要库。它还会设置日志记录,并从 .env 文件加载环境变量,这对于访问模型和服务器网址至关重要。
将以下代码添加到 agent.py 文件中:
import os
import logging
import google.cloud.logging
from dotenv import load_dotenv
from google.adk import Agent
from google.adk.agents import SequentialAgent
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset, StreamableHTTPConnectionParams
from google.adk.tools.tool_context import ToolContext
from google.adk.tools.langchain_tool import LangchainTool
from langchain_community.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper
import google.auth
import google.auth.transport.requests
import google.oauth2.id_token
# --- Setup Logging and Environment ---
cloud_logging_client = google.cloud.logging.Client()
cloud_logging_client.setup_logging()
load_dotenv()
model_name = os.getenv("MODEL")
第 2 步: 定义工具(智能体的功能)

智能体是否优秀取决于它能使用的工具。在本部分中,我们将定义智能体的所有功能,包括用于保存数据的自定义函数、连接到安全 MCP 服务器的 MCP 工具,以及维基百科工具。
将以下代码添加到 agent.py 的底部:
# Greet user and save their prompt
def add_prompt_to_state(
tool_context: ToolContext, prompt: str
) -> dict[str, str]:
"""Saves the user's initial prompt to the state."""
tool_context.state["PROMPT"] = prompt
logging.info(f"[State updated] Added to PROMPT: {prompt}")
return {"status": "success"}
# Configuring the MCP Tool to connect to the Zoo MCP server
mcp_server_url = os.getenv("MCP_SERVER_URL")
if not mcp_server_url:
raise ValueError("The environment variable MCP_SERVER_URL is not set.")
def get_id_token():
"""Get an ID token to authenticate with the MCP server."""
target_url = os.getenv("MCP_SERVER_URL")
audience = target_url.split('/mcp/')[0]
request = google.auth.transport.requests.Request()
id_token = google.oauth2.id_token.fetch_id_token(request, audience)
return id_token
"""
# Use this code if you are using the public MCP Server and comment out the code below defining mcp_tools
mcp_tools = MCPToolset(
connection_params=StreamableHTTPConnectionParams(
url=mcp_server_url
)
)
"""
mcp_tools = MCPToolset(
connection_params=StreamableHTTPConnectionParams(
url=mcp_server_url,
headers={
"Authorization": f"Bearer {get_id_token()}",
},
),
)
# Configuring the Wikipedia Tool
wikipedia_tool = LangchainTool(
tool=WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())
)
这三种工具的说明
add_prompt_to_state📝
此工具用于记录动物园游客提出的问题。当访客问“狮子在哪里?”时,此工具会将这个问题保存到智能体的记忆中,以便工作流中的其他智能体知道要研究的对象。
运作方式:这是一个 Python 函数,用于将游客的提示写入共享的 tool_context.state 字典。此工具上下文表示智能体在单次对话中的短期记忆。一个智能体保存到状态的数据可以被工作流中的下一个智能体读取。
MCPToolset🦁
用于将导游代理连接到实验 1 中创建的动物园 MCP 服务器。该服务器提供了一些专门的工具,可用于查找我们动物的特定信息,例如名称、年龄和位置。
运作方式:它能安全地连接到动物园的专用服务器网址。它使用 get_id_token 自动获取安全的“钥匙卡”(服务账号 ID 令牌),以证明其身份并获得访问权限。
LangchainTool🌍
这使导游代理具备一般性的世界知识。如果访客提出的问题不在动物园的数据库中,例如“狮子在野外吃什么?”,此工具可让智能体在维基百科上查找答案。
运作方式:它充当适配器,让我们的智能体可以使用 LangChain 库中预构建的 WikipediaQueryRun 工具。
资源:
第 3 步:定义专业智能体
接下来,我们将定义研究智能体和回答格式化智能体。研究智能体相当于整套操作的“大脑”。此智能体从共享的 State 中获取用户提示,检查其强大的工具(Zoo 的 MCP 服务器工具和维基百科工具),并决定使用哪些工具来查找答案。
回答格式化智能体的作用是呈现回答。它不使用任何工具来查找新信息,而是接收研究智能体收集的原始数据(通过状态传递),并利用 LLM 的语言技能将其转换为方便用户理解的对话式回答。
将以下代码添加到 agent.py 的底部:
# 1. Researcher Agent
comprehensive_researcher = Agent(
name="comprehensive_researcher",
model=model_name,
description="The primary researcher that can access both internal zoo data and external knowledge from Wikipedia.",
instruction="""
You are a helpful research assistant. Your goal is to fully answer the user's PROMPT.
You have access to two tools:
1. A tool for getting specific data about animals AT OUR ZOO (names, ages, locations).
2. A tool for searching Wikipedia for general knowledge (facts, lifespan, diet, habitat).
First, analyze the user's PROMPT.
- If the prompt can be answered by only one tool, use that tool.
- If the prompt is complex and requires information from both the zoo's database AND Wikipedia,
you MUST use both tools to gather all necessary information.
- Synthesize the results from the tool(s) you use into preliminary data outputs.
PROMPT:
{{ PROMPT }}
""",
tools=[
mcp_tools,
wikipedia_tool
],
output_key="research_data" # A key to store the combined findings
)
# 2. Response Formatter Agent
response_formatter = Agent(
name="response_formatter",
model=model_name,
description="Synthesizes all information into a friendly, readable response.",
instruction="""
You are the friendly voice of the Zoo Tour Guide. Your task is to take the
RESEARCH_DATA and present it to the user in a complete and helpful answer.
- First, present the specific information from the zoo (like names, ages, and where to find them).
- Then, add the interesting general facts from the research.
- If some information is missing, just present the information you have.
- Be conversational and engaging.
RESEARCH_DATA:
{{ research_data }}
"""
)
第 4 步:工作流智能体
工作流智能体充当动物园导游的“后台”管理员。它会接收研究请求,并确保我们在上文中定义的两个智能体按正确的顺序各司其职:先研究,再给出格式化回答。它为回答游客的问题制定了一个可预测且可靠的过程。
运作方式:这是一个 SequentialAgent,是一种不会独立思考的特殊代理。它唯一的任务就是按固定顺序运行 sub_agents(研究智能体和回答格式化智能体)列表,并自动将共享内存从一个智能体传递到下一个智能体。
将此代码块添加到 agent.py 的底部:
tour_guide_workflow = SequentialAgent(
name="tour_guide_workflow",
description="The main workflow for handling a user's request about an animal.",
sub_agents=[
comprehensive_researcher, # Step 1: Gather all data
response_formatter, # Step 2: Format the final response
]
)
最后一步:组装主工作流 
此代理被指定为 root_agent,ADK 框架会将其用作所有新对话的起点。其主要作用是编排整个流程。它充当初始控制器,管理第一轮对话。
将下面的最后一段代码添加到 agent.py 的底部:
root_agent = Agent(
name="greeter",
model=model_name,
description="The main entry point for the Zoo Tour Guide.",
instruction="""
- Let the user know you will help them learn about the animals we have in the zoo.
- When the user responds, use the 'add_prompt_to_state' tool to save their response.
After using the tool, transfer control to the 'tour_guide_workflow' agent.
""",
tools=[add_prompt_to_state],
sub_agents=[tour_guide_workflow]
)
您的 agent.py 文件现已完成!通过以这种方式构建智能体,您可以了解每个组件(工具、工作器智能体和管理器智能体)在创建最终智能系统中的具体作用。接下来是部署!
7. 准备应用以进行部署
本地环境准备就绪后,下一步是为部署准备 Google Cloud 项目。您需要对智能体的文件结构进行最后检查,以确保其与部署命令兼容。更重要的是,您配置要一项关键的 IAM 权限,允许已部署的 Cloud Run 服务代表您调用 Vertex AI 模型。完成此步骤可确保云环境已准备好成功运行您的智能体。
运行 source 命令,将变量加载到 shell 会话中。
source .env
向服务账号授予 Vertex AI User 角色,使其有权进行预测并调用 Google 的模型。
# Grant the "Vertex AI User" role to your service account
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT" \
--role="roles/aiplatform.user"
8. 使用 ADK CLI 部署智能体
本地代码已准备就绪,Google Cloud 项目也已准备好,现在可以部署智能体了。您将使用 adk deploy cloud_run 命令,这是一个方便的工具,可自动执行整个部署工作流。只需一个命令,它就能打包代码、构建容器映像、将其推送到 Artifact Registry,并在 Cloud Run 上启动服务,使其可通过网络访问。
部署
运行以下命令以部署智能体。借助 uvx 命令,您可以运行以 Python 软件包形式发布的命令行工具,而无需全局安装这些工具。
# Run the deployment command
uvx --from google-adk==1.14.0 \
adk deploy cloud_run \
--project=$PROJECT_ID \
--region=europe-west1 \
--service_name=zoo-tour-guide \
--with_ui \
. \
-- \
--labels=dev-tutorial=codelab-adk \
--service-account=$SERVICE_ACCOUNT
接受提示
系统可能会提示您执行以下操作:
Deploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in region [europe-west1] will be created. Do you want to continue (Y/n)?
输入 Y,然后按 Enter 键。
系统可能会提示您执行以下操作:
Allow unauthenticated invocations to [your-service-name] (y/N)?.
在本实验中,我们希望允许未经身份验证的调用,以便轻松进行测试,因此请输入 y 并按 Enter 键。
获取部署链接
成功执行后,该命令将提供已部署的 Cloud Run 服务的网址。(该网址应与 https://zoo-tour-guide-123456789.europe-west1.run.app 类似)。复制此网址以供下一个任务使用。
9. 测试已部署的智能体
现在,您的智能体已在 Cloud Run 上运行。您将执行一项测试,以确认部署成功且智能体按预期工作。您将使用公共服务网址(例如 https://zoo-tour-guide-123456789.europe-west1.run.app/)访问 ADK 的网页界面并与智能体互动。
在 Web 浏览器中打开公开 Cloud Run 服务网址。由于您使用了 --with_ui flag,因此您应该会看到 ADK 开发者界面。
在右上角开启 Token Streaming。
现在,您可以与动物园导游智能体互动了。
输入 hello,然后按 Enter 键开始新对话。
观察结果。智能体应快速回复问候语:
"Hello! I'm your Zoo Tour Guide. I can help you learn about the amazing animals we have here. What would you like to know or explore today?"
您可以向智能体提出以下问题:
Where can I find the polar bears in the zoo and what is their diet?

智能体工作流详解
您的系统可以像一个睿智的多智能体团队一样运作。整个过程由清晰的顺序管理,确保从用户提问到得到最终详细回答的整个流程顺畅高效。
1. 动物园接待员(接待处)
整个过程的第一步是接待员智能体。
任务:开始与游客对话。它要向游客问好,并询问游客想要了解哪种动物。
工具:当用户回复时,接待员智能体使用 add_prompt_to_state 工具来采集用户的确切措辞(例如 “tell me about the lions”(给我介绍一下狮子)并将其保存在系统内存中。
移交:保存提示后,它会立即将控制权移交给其子智能体 tour_guide_workflow。
2. 综合研究智能体(超级研究员智能体)
这是主工作流中的第一步,也是整个操作的“大脑”。现在,您不再需要庞大的团队,只需一个能够访问所有相关信息的专业智能体。
任务:分析用户的问题并确定回答问题的方案。它利用语言模型强大的工具使用功能来决定是否需要:
- 来自动物园记录的内部数据(通过 MCP 服务器)。
- 来自网络(通过 Wikipedia API)的一般性知识。
- 或者,对于复杂的问题,两者都使用。
操作:执行必要的工具,以收集所有必需的原始数据。例如,如果游客问到“动物园里的狮子几岁了?它们在野外吃什么?”,它会调用 MCP 服务器来获取狮子的年龄信息,并调用维基百科工具来获取狮子的进食习性信息。
3. 回答格式化智能体(演示者)
在综合研究智能体收集完所有事实后,回答格式化智能体是要运行的最后一个智能体。
工作:充当动物园导游。它会获取原始数据(可能来自一个或两个来源)并进行优化。
行动:它将所有信息整合到一个连贯且有趣的回答中。按照提示,它首先介绍动物园的具体信息,然后添加一些有趣的事实。
最终结果:这个智能体生成的文本就是用户在聊天窗口中看到的完整且详细的答案。
如果您有兴趣详细了解如何构建智能体,请查看以下资源:
10. 清理环境
gcloud run services delete zoo-tour-guide --region=europe-west1 --quiet
gcloud artifacts repositories delete cloud-run-source-deploy --location=europe-west1 --quiet
11. 恭喜
恭喜您完成此 Codelab。
所学内容
- 如何构建 Python 项目,以便使用 ADK 命令行界面进行部署。
- 如何使用 SequentialAgent 和 ParallelAgent 实现多代理工作流。
- 如何使用 MCPToolset 连接到远程 MCP 服务器以使用其工具。
- 如何通过集成 Wikipedia API 等外部工具来扩充内部数据。
- 如何使用 adk deploy 命令将代理作为无服务器容器部署到 Cloud Run。
12. 调查问卷
输出如下:
