Next ‘26 デベロッパー 基調講演: スキルとツールを使用した ADK エージェントの構築

1. はじめに

この Codelab では、Agent Development Kit(ADK)を使用して高度なマラソン プランナー エージェントを構築します。構造化されたシステム プロンプトから、動的なスキル読み込みと MCP ツールのマッピングまで、エージェントの機能を段階的に確認します。最後に、エージェントをローカルでテストし、Agent Runtime(Agent Engine)にデプロイします。

演習内容

  • 新しい ADK エージェント プロジェクトを初期化する
  • 構造化ビルダーを使用して堅牢なシステム プロンプトを作成する
  • 現実世界の場所のコンテキストに Google Maps 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 Maps API キーを作成する

Google Maps MCP ツールを使用するには、Maps 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. Maps API キーを設定します。アプリケーションは環境変数から読み取ります。
export GOOGLE_MAPS_API_KEY="<YOUR_MAPS_API_KEY>"

環境変数を構成する

Simulator Agent は、構成に .env ファイルを使用します。サンプル ファイルをコピーし、プロジェクト ID で更新します。

  1. サンプル環境ファイルをコピーします。
cp planner_agent/sample.env planner_agent/.env
  1. planner_agent/.env を開き、GOOGLE_CLOUD_PROJECT フィールドを実際の Google Cloud プロジェクト ID で更新し、GOOGLE_MAPS_API_KEY フィールドを作成した Google Maps API キーで更新します。

ファイルの内容は次のようになります。

GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID>
GOOGLE_CLOUD_LOCATION=us-west1
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 クラスを使用して初期化されます。基盤となるモデルと ID 名を指定し、他のモジュールで定義された手順とツールを取り込みます。

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 通信を抽象化するため、エージェントの動作に集中できます。

現時点では、エージェントは非常に一般的です。他の 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. システム プロンプトを作成する

システム プロンプト(指示)は、エージェントの動作を決定します。このプロジェクトでは、1 つの巨大な文字列ではなく、PromptBuilderplanner_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 を含むセクションを見つけて、次の 2 行をコメント化解除します。コードは次のようになります。

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. ブラウザを開き、ターミナルに表示された URL(通常は http://localhost:8000)に移動します。
  2. 左上のプルダウンで planner_agent を選択します。
  3. チャット ウィンドウで、次のプロンプトを送信します。
Plan a marathon for 10000 participants in Las Vegas on April 24, 2027 in the
evening timeframe

スキルが読み込まれ、ツールが呼び出されていることがわかります。しばらくすると、エージェントがマラソン プランを生成します。

UI は次のようになります。

ADK ウェブ UI

8. エージェントをデプロイする

エージェントのローカルでのパフォーマンスに問題がなければ、Agent Engine にデプロイできます。Agent Engine は、Cloud Run でエージェントを安全にホストします。

エージェントをデプロイするには、ADK CLI デプロイ コマンドを使用します。

uv run adk deploy agent_engine \
  --env_file planner_agent/.env \
  planner_agent

デプロイが完了すると、CLI はエージェントの安全にホストされたエンドポイントを出力します。このエンドポイントをフロントエンド アプリケーション、チャットボット、その他のバックエンド システムに統合できるようになりました。Agent Runtime 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_PROJECT フィールドを実際の Google Cloud プロジェクト ID で更新します。

ファイルを開くと、下のように表示されます。

GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID>
GOOGLE_CLOUD_LOCATION=us-west1
  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}

Maps API キーを Secret Manager に保存した場合は、シークレットを削除します。

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

この Codelab 用に新しい Google Cloud プロジェクトを作成した場合は、プロジェクト全体を削除して、関連付けられているすべてのリソースと API を削除できます。

gcloud projects delete $PROJECT_ID

10. 完了

おめでとうございます!ADK を使用して、高度なマラソン プランナー エージェントを構築しました。

学習した内容

  • Agent Development Kit(ADK)プロジェクトを初期化する
  • モジュラー システム プロンプトに PromptBuilder を活用する
  • MCP ツールと ApiRegistry を使用したマッピング機能の統合
  • SkillToolset を使用してスキルを条件付きで読み込む
  • ローカルでテストして Agent Engine にデプロイする

リファレンス ドキュメント