1. はじめに
このラボでは、クライアント エージェント サービスの実装とデプロイに焦点を当てます。エージェント開発キット(ADK)を使用して、ラボ 1 で作成した MCP サーバーなどのリモートツールを使用する AI エージェントを構築します。ここで示されている主なアーキテクチャ原則は、懸念事項の分離です。明確な推論レイヤ(エージェント)が、安全な API を介して明確なツールレイヤ(MCP サーバー)と通信します。
ラボ 1 では、架空の動物園の動物に関するデータを LLM に提供する MCP サーバーを作成しました(Gemini CLI の使用時など)。このラボでは、架空の動物園のツアーガイド エージェントを構築します。エージェントは、ラボ 1 の同じ MCP サーバーを使用して動物園の動物の詳細にアクセスし、Wikipedia を使用して最高のツアーガイド エクスペリエンスを作成します。
最後に、ツアーガイド エージェントを Google Cloud Run にデプロイして、ローカルで実行するだけでなく、動物園のすべての来園者がアクセスできるようにします。
前提条件
- Cloud Run で実行中の MCP サーバーまたは関連付けられたサービス URL。
- 課金を有効にした Google Cloud プロジェクト
学習内容
- ADK デプロイ用に Python プロジェクトを構成する方法。
- google-adk を使用してツールを使用するエージェントを実装する方法。
- ツールセットのエージェントをリモート MCP サーバーに接続する方法。
- Python アプリケーションをサーバーレス コンテナとして Cloud Run にデプロイする方法。
- IAM ロールを使用して安全なサービス間認証を構成する方法。
- 将来の費用が発生しないように Cloud リソースを削除する方法。
必要なもの
- Google Cloud アカウントと Google Cloud プロジェクト
- ウェブブラウザ(Chrome など)
2. Cloud Run にデプロイする理由
Cloud Run はサーバーレス プラットフォームであるため、ADK エージェントのホスティングに最適です。基盤となるインフラストラクチャの管理ではなく、コードに集中できます。運用作業は Google が行います。
ポップアップ ショップのように、顧客(リクエスト)が到着したときにのみリソースを開いて使用します。顧客がいない場合は完全に閉店するため、空の店舗の料金を支払う必要はありません。
主な機能
どこでもコンテナを実行:
- アプリを含むコンテナ(Docker イメージ)を用意します。
- Cloud Run は、Google のインフラストラクチャで実行します。
- OS のパッチ適用、VM の設定、スケーリングの煩わしさから解放されます。
自動スケーリング:
- アプリを使用しているユーザーが 0 人の場合 → 0 インスタンスが実行されます(アイドル状態のときは $0 を支払います)。
- 1,000 件のリクエストがヒットした場合 → 必要に応じてコピーが作成されます。
デフォルトでステートレス:
- 各リクエストは異なるインスタンスに送信できます。
- 状態を保存する必要がある場合は、Cloud SQL、Firestore、Redis などの外部サービスを使用します。
任意の言語またはフレームワークをサポート:
- Linux コンテナで実行される限り、Cloud Run は Python、Go、Node.js、Java、.Net のいずれであるかを問いません。
従量課金制:
- リクエストごと + コンピューティング時間(100 ミリ秒単位)。
- 従来の VM のように、アイドル状態のリソースに対して料金を支払う必要はありません。
3. 設定と要件
セルフペース型の環境設定
- Google Cloud Console にログインして、プロジェクトを新規作成するか、既存のプロジェクトを再利用します。Gmail アカウントも Google Workspace アカウントもまだお持ちでない場合は、アカウントを作成してください。
- プロジェクト名は、このプロジェクトの参加者に表示される名称です。Google API では使用されない文字列です。いつでも更新できます。
- プロジェクト ID は、すべての Google Cloud プロジェクトにおいて一意でなければならず、不変です(設定後は変更できません)。Cloud コンソールでは一意の文字列が自動生成されます。通常は、この内容を意識する必要はありません。ほとんどの Codelab では、プロジェクト ID(通常は
PROJECT_ID
と識別されます)を参照する必要があります。生成された ID が好みではない場合は、ランダムに別の ID を生成できます。または、ご自身で試して、利用可能かどうかを確認することもできます。このステップ以降は変更できず、プロジェクトを通して同じ ID になります。 - なお、3 つ目の値として、一部の API が使用するプロジェクト番号があります。これら 3 つの値について詳しくは、こちらのドキュメントをご覧ください。
- 次に、Cloud のリソースや API を使用するために、Cloud コンソールで課金を有効にする必要があります。この Codelab の操作をすべて行って、費用が生じたとしても、少額です。このチュートリアルの終了後に請求が発生しないようにリソースをシャットダウンするには、作成したリソースを削除するか、プロジェクトを削除します。Google Cloud の新規ユーザーは、300 米ドル分の無料トライアル プログラムをご利用いただけます。
Cloud Shell の起動
Cloud Shell エディタに移動します。
ターミナルが画面の下部に表示されない場合は、開きます。
- [Terminal] をクリックします。
- [New Terminal] をクリックします。
ターミナルで、次のコマンドを使用してプロジェクトを設定します。ラボ 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.
Vertex AI エンベディング モデルを使用するようにデフォルトのリージョンを構成します。Vertex AI で利用可能なロケーションの詳細を確認する。この例では、europe-west1 リージョンを使用しています。
gcloud config set compute/region europe-west1
5. ADK をダウンロードしてインストールし、プロジェクト フォルダを作成します。
プロジェクト ディレクトリを作成します。
このコマンドは、エージェントのソースコードのラボ用のメイン フォルダを作成します。
cd && mkdir zoo_guide_agent && cd zoo_guide_agent
仮想環境を作成します。
python3 -m venv .venv
仮想環境をアクティブにします。
source .venv/bin/activate
requirements.txt
ファイルを作成します。このファイルには、エージェントに必要な Python ライブラリがリストされています。次のコマンドは、ファイルを作成してデータを入力します。
cloudshell edit requirements.txt
google-adk==1.12.0
langchain-community
wikipedia
コマンドは、メイン プロジェクト ディレクトリ zoo_guide_agent
から実行する必要があります。
pip install -r requirements.txt
現在のプロジェクト、リージョン、ユーザーの変数を設定します。これは、これらのコマンドを実行するより堅牢な方法です。
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_REGION=$(gcloud config get-value compute/region)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
export SERVICE_ACCOUNT="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
zoo_guide_agent
ディレクトリに .env
ファイルを作成して開き、エージェントを認証します。
cloudshell edit .env
cloudshell edit コマンドを実行すると、ターミナルの上のエディタで .env
ファイルが開きます。.env
ファイルに以下を入力して、ターミナルに戻ります。
MODEL="gemini-2.5-flash"
SERVICE_ACCOUNT="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
MCP サーバーの URL を追加します。ラボ 1 を完了している場合は、次の手順に沿って、ラボ 1 で作成した MCP サーバーを使用します。
- Cloud Run サービス ID にリモート MCP サーバーを呼び出す権限を付与する
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT" \
--role="roles/run.invoker"
- ラボ 1 の MCP サーバー URL を環境変数に保存します。
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 ファイルを作成します。このファイルは、zoo_guide_agent ディレクトリがパッケージであることを Python に伝えます。
cloudshell edit __init__.py
上記のコマンドを実行すると、コードエディタが開きます。__init__.py
に次のコードを追加します。
from . import agent
メインの agent.py ファイルを作成する
メインの agent.py ファイルを作成します。このコマンドは、Python ファイルを作成し、マルチエージェント システムの完全なコードを貼り付けます。
cloudshell edit agent.py
ステップ 1: インポートと初期設定
最初のブロックでは、ADK と Google Cloud から必要なライブラリをすべて取り込みます。また、ロギングを設定し、.env
ファイルから環境変数を読み込みます。これは、モデルとサーバーの URL にアクセスするために不可欠です。
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 ツール、Wikipedia ツールなど、エージェントが持つすべての機能を定義します。
次のコードを 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())
)
3 つのツールについて
add_prompt_to_state
📝
このツールは、動物園の来園者が尋ねた内容を記憶します。「ライオンはどこにいますか?」という質問が来ると、このツールはその質問をエージェントのメモリに保存し、ワークフロー内の他のエージェントが何を調査すべきかを把握できるようにします。
方法: 共有の tool_context.state
辞書に訪問者のプロンプトを書き込む Python 関数です。このツール コンテキストは、1 回の会話におけるエージェントの短期記憶を表します。1 つのエージェントによって State に保存されたデータは、ワークフローの次のエージェントが読み取ることができます。
MCPToolset
🦁
これは、ツアーガイド エージェントをラボ 1 で作成した動物園 MCP サーバーに接続するために使用されます。このサーバーには、動物の名前、年齢、囲いなど、動物に関する特定の情報を検索するための特別なツールがあります。
方法: 動物園のプライベート サーバーの URL に安全に接続します。get_id_token
を使用して、ID を証明してアクセス権を取得するための安全な「キーカード」(サービス アカウント ID トークン)を自動的に取得します。
LangchainTool
🌍
これにより、ツアーガイド エージェントは一般的な世界に関する知識を得ることができます。「野生のライオンは何を食べるの?」など、動物園のデータベースにない質問が来場者から寄せられた場合、このツールを使用すると、エージェントは Wikipedia で回答を検索できます。
方法: アダプタとして機能し、エージェントが LangChain ライブラリの事前構築済み WikipediaQueryRun ツールを使用できるようにします。
リソース:
ステップ 3: スペシャリスト エージェントを定義する
次に、リサーチャー エージェントとレスポンス フォーマッタ エージェントを定義します。リサーチャー エージェントは、オペレーションの「頭脳」です。このエージェントは、共有 State
からユーザーのプロンプトを取得し、強力なツール(Zoo の MCP サーバーツールと Wikipedia ツール)を調べて、回答を見つけるために使用するツールを決定します。
レスポンス フォーマッタ エージェントの役割はプレゼンテーションです。新しい情報を探すためにツールを使用することはありません。代わりに、リサーチャー エージェントによって収集された生データ(State 経由で渡される)を取得し、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: ワークフロー エージェント
ワークフロー エージェントは、動物園ツアーの「バックオフィス」マネージャーとして機能します。この関数は、調査リクエストを受け取り、上記の 2 つのエージェントが正しい順序でジョブを実行するようにします。つまり、最初に調査を行い、次にフォーマットを行います。これにより、訪問者の質問に答えるための予測可能で信頼性の高いプロセスが作成されます。
方法: 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 プロジェクトを準備します。これには、エージェントのファイル構造がデプロイ コマンドと互換性があることを確認するための最終チェックが含まれます。さらに重要なのは、デプロイされた Cloud Run サービスがユーザーに代わって Vertex AI モデルを呼び出すことができるようにする重要な IAM 権限を構成することです。この手順を完了すると、クラウド環境でエージェントを正常に実行できるようになります。
source コマンドを実行して、変数をシェル セッションに読み込みます。
source .env
サービス アカウントに Vertex AI ユーザーロールを付与します。これにより、予測を行い、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 に push され、Cloud Run でサービスが起動してウェブでアクセスできるようになります。
.gcloudignore ファイルを作成する
デプロイ時間を短縮するために、.gcloudignore
ファイルを作成します。次のコマンドを実行して、エージェントをデプロイします。
cloudshell edit .gcloudignore
cloudshell edit コマンドを実行すると、ターミナルの上のエディタで .gcloudignore
ファイルが開きます。ファイルに次の内容を記述して保存します。次に、ターミナルに戻り、次のセクションでデプロイ コマンドを実行します。
.venv/
導入
次のコマンドを実行して、エージェントをデプロイします。
# Run the deployment command
adk deploy cloud_run \
--project=$PROJECT_ID \
--region=europe-west1 \
--service_name=zoo-tour-guide \
--with_ui \
.
gcloud run services update zoo-tour-guide \
--region=europe-west1 \
--update-labels=dev-tutorial=codelab-adk
プロンプトを受け入れる
次のようなメッセージが表示されることがあります。
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 サービスの URL が返されます。(https://zoo-tour-guide-123456789.europe-west1.run.app のようになります)。次のタスクのためにこの URL をコピーします。
9. デプロイされたエージェントをテストする
エージェントが Cloud Run で稼働したので、デプロイが成功し、エージェントが想定どおりに動作していることを確認するテストを行います。パブリック サービス URL(https://zoo-tour-guide-123456789.europe-west1.run.app/ など)を使用して、ADK のウェブ インターフェースにアクセスし、エージェントを操作します。
ウェブブラウザで一般公開の Cloud Run サービス URL を開きます。--with_ui flag
を使用したため、ADK デベロッパー UI が表示されます。
右上にある Token Streaming
をオンにします。
これで、Zoo エージェントを操作できるようになりました。
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?"
エージェント フローの説明
システムはインテリジェントなマルチエージェント チームとして動作します。このプロセスは明確なシーケンスで管理され、ユーザーの質問から最終的な詳細な回答までがスムーズかつ効率的に行われます。
1. 動物園の受付係(ウェルカム デスク)
プロセス全体は、グリーター エージェントから始まります。
役割: 会話を始める。ユーザーに挨拶し、どの動物について知りたいかを尋ねるように指示されています。
ツール: ユーザーが返信すると、Greeter は add_prompt_to_state ツールを使用して、ユーザーの言葉を正確にキャプチャします(例: 「ライオンについて教えて」)をシステムメモリに保存します。
ハンドオフ: プロンプトを保存すると、すぐにサブエージェントである tour_guide_workflow に制御が渡されます。
2. 包括的なリサーチャー(スーパー リサーチャー)
これはメイン ワークフローの最初のステップであり、オペレーションの「頭脳」です。大規模なチームではなく、利用可能なすべての情報にアクセスできる 1 人の熟練したエージェントが対応します。
役割: ユーザーの質問を分析し、インテリジェントなプランを作成します。言語モデルの強力なツール使用機能を使用して、次のものが必要かどうかを判断します。
- 動物園の記録からの内部データ(MCP サーバー経由)。
- ウェブからの一般的な知識(Wikipedia API 経由)。
- 複雑な質問の場合は、両方を使用します。
アクション: 必要なツールを実行して、必要なすべての生データを収集します。たとえば、「ライオンの年齢と野生での食事を教えて」と質問された場合、年齢については MCP サーバーを呼び出し、食事については Wikipedia ツールを呼び出します。
3. レスポンス フォーマッタ(プレゼンター)
包括的な調査担当者がすべての事実を収集したら、最後に実行するエージェントです。
役割: 動物園ツアーガイドの親しみやすい声として機能します。元データ(1 つまたは両方のソースから取得)を加工します。
アクション: すべての情報を 1 つのまとまりのある魅力的な回答に統合します。指示に従って、まず動物園の具体的な情報を提示し、次に興味深い一般的な事実を追加します。
最終結果: このエージェントによって生成されたテキストは、ユーザーがチャット ウィンドウで確認できる完全で詳細な回答です。
エージェントの作成についてさらに詳しく知りたい場合は、次のリソースをご覧ください。
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 は完了です。
学習した内容
- ADK コマンドライン インターフェースでデプロイするための Python プロジェクトの構造化方法。
- SequentialAgent と ParallelAgent を使用してマルチエージェント ワークフローを実装する方法。
- MCPToolset を使用してリモート MCP サーバーに接続し、そのツールを使用する方法。
- Wikipedia API などの外部ツールを統合して内部データを補強する方法。
- adk deploy コマンドを使用して、エージェントをサーバーレス コンテナとして Cloud Run にデプロイする方法。
12. アンケート
出力: