ADK × Cloud Run で、気軽にAIエージェントを開発&デプロイする

ADK × Cloud Run で、気軽にAIエージェントを開発&デプロイする

2025.12.03

こんにちは、すらぼです。

この記事は クラスメソッド Google Cloud Advent Calendar 2025 3日目の記事です。

今回は自作の AI チャットを作って、Cloud Run にデプロイする方法について紹介してみます。「AIチャットってそんな簡単に作れるの?」というイメージの方も多いと思います。筆者も実際に試してみるまではそう思っていましたが、いざやってみるとすんなり作成〜デプロイまでできました。
様々なツールが出てきていますが、今回は Google 社が出している Agent Development Kit (ADK) を使用し、開発からデプロイまでこのツールでやってみます。

ちなみに、ADK の中身に関する解説は、アドベントカレンダー2日目の 渡邉 光 さんの記事がとてもわかりやすいのでぜひ読んでみてください。

https://dev.classmethod.jp/articles/getting-started-with-adk-local-setup/

今回の私の記事では、実際にデプロイするまでの流れや設定について紹介していきます。

今回作るリソース

今回は、以下のリソースを作成します。

  • GitHub API を呼び出すエージェント(ローカル)
  • Cloud Run サービス(デプロイ後)
    • Secret Manager(API キー保存用)

前提条件

  • Python 3.11以上
  • uv がインストール済み
  • Google Cloud プロジェクトが作成済み
  • gcloud CLI がインストール済み

やってみる

今回は大きく2つの手順に分けて試してみます。

  1. ローカルで動くアプリケーションを作る
  2. Cloud Run にデプロイしてみる

では、早速作っていきましょう。

1. ローカルで動くアプリケーションを作る

まずはデプロイするアプリケーションをローカルで作って、動作確認してみます。

1-1. プロジェクトの初期化

プロジェクトディレクトリを作成し、uv で初期化します。

mkdir adk-app
cd adk-app
uv init

1-2. 必要なパッケージのインストール

ADK と requests をインストールします。

uv add google-adk requests

1-3. API キーの取得

ADK で LLM を呼び出す方法は、大きく以下の2通りがあります。

  • Google AI Studio(API キー)
  • Google Cloud Vertex AI(ADC、サービスアカウント認証)

今回は、API キーを Google AI Studio から取得して認証してみます。

Google AI Studio - APIキー にアクセスします。

https://aistudio.google.com/api-keys

「APIキーの作成」をクリックすると、以下のような画面が表示されます。
キーの名前は適当なものを入力し、プロジェクトを選択します。ただ、プロジェクトが存在しない場合は「プロジェクトをインポート」から請求が有効な Google Cloud プロジェクトを選択して AI Studio にインポートする必要があります。

CleanShot 2025-12-01 at 18.00.38@2x.png

キーが作成できたら、コピーボタンから API キーをコピーします。

CleanShot 2025-12-02 at 22.18.16@2x.png

コピーできたら、次の手順に進みます。

1-4. エージェントの作成

adk create コマンドでエージェントを作成します。

uv run adk create github_agent

以下のような対話UIが表示されます。

CleanShot 2025-12-02 at 22.48.42@2x.png

ここでは、 1(gemini-2.5-flash) → 1(Google AI) を選択しています。
また、先ほど取得した API キーを最後にペーストします。

設定が完了すると、以下の構造でフォルダ/ファイルが生成されます。

adk-app/
├── github_agent/
│   ├── __init__.py
│   ├── .env
│   └── agent.py
├── pyproject.toml
└── ...

実はもうこれだけで、 uv run adk web . コマンドで Web UI が立ち上がります。あっという間ですね。

試しに起動して、挨拶してみました。ちゃんと回答も返ってきていて、チャットが成立していることが確認できます。

CleanShot 2025-12-02 at 23.00.23.png

1-5. GitHub API ツール・エージェントの実装

では、今度はエージェントが「ユーザーの要望に沿って必要な情報を取得する」というシチュエーションを想定して、外部APIから情報を取得できるようにしてみます。今回は、GitHub API から人気のリポジトリを取得するエージェントを作ってみます。

github_agent/agent.py を以下の内容に書き換えます。
※長いので折りたたんでいます。開いてコピーしてください。

github_agent/agent.py
github_agent/agent.py
import requests
from typing import Optional
from google.adk.agents.llm_agent import Agent

def search_github_repos(query: str, limit: int = 5) -> str:
    """
    キーワードでGitHubリポジトリを検索し、スター数順に並べ替えた上位結果を返す関数。

    Args:
        query: 検索キーワード (例: "python machine learning", "rust web framework")
        limit: 返す結果の数 (デフォルト: 5件, 最大: 10件)

    Returns:
        リポジトリ情報(名前、説明、スター数、URLを含む)を格納したフォーマット済み文字列。
    """
    try:
        limit = min(limit, 10)
        url = "https://api.github.com/search/repositories"
        params = {
            "q": query,
            "sort": "stars",
            "order": "desc",
            "per_page": limit
        }

        response = requests.get(url, params=params, timeout=10)
        response.raise_for_status()

        data = response.json()
        repos = data.get("items", [])

        if not repos:
            return f"No repositories found for query: '{query}'"

        result_lines = [f"Found {len(repos)} top repositories for '{query}':\n"]

        for i, repo in enumerate(repos, 1):
            name = repo.get("full_name", "N/A")
            description = repo.get("description", "No description")
            stars = repo.get("stargazers_count", 0)
            url = repo.get("html_url", "")
            language = repo.get("language", "Unknown")

            result_lines.append(
                f"{i}. **{name}** ⭐ {stars:,}\n"
                f"   Language: {language}\n"
                f"   Description: {description}\n"
                f"   URL: {url}\n"
            )

        return "\n".join(result_lines)

    except requests.exceptions.RequestException as e:
        return f"Error calling GitHub API: {str(e)}"
    except Exception as e:
        return f"Unexpected error: {str(e)}"

root_agent = Agent(
    model='gemini-2.5-flash',
    name='github_assistant',
    description='A helpful assistant that can search GitHub repositories and answer questions.',
    instruction="""You are a helpful assistant with access to GitHub repository data.

When users ask about GitHub repositories, programming projects, or popular open source tools,
use the search_github_repos tool to find relevant repositories.

Always provide context and explain what makes the repositories interesting or relevant to the user's question.
Be conversational and helpful in your responses.""",
    tools=[search_github_repos],
)

大事な部分だけ解説します。

search_github_repos() はAPIを実際に呼び出す処理を定義している部分ですが、APIリクエストとレスポンスの処理を行なっているだけなので、今回は割愛します。
注目して欲しいのは以下の部分です。この部分で実際に、LLM が API を適切に扱うために必要な情報を渡してあげています。

root_agent = Agent(
    model='gemini-2.5-flash',
    name='github_assistant',
    description='A helpful assistant that can search GitHub repositories and answer questions.',
    instruction="""You are a helpful assistant with access to GitHub repository data.

When users ask about GitHub repositories, programming projects, or popular open source tools,
use the search_github_repos tool to find relevant repositories.

Always provide context and explain what makes the repositories interesting or relevant to the user's question.
Be conversational and helpful in your responses.""",
    tools=[search_github_repos],
)

特に descriptioninstruction が重要で、それぞれ以下のような役割を持っています。

  • description: エージェントが「このエージェントがユーザーへの回答に適切かどうか」を判断するための材料。
  • instruction: エージェントがこのエージェントを実際に使うときのプロンプト。

また、 model などもエージェントごとに指定することができます。複雑な処理が求められるエージェントと簡単な処理をこなすエージェントでモデルを使い分けることも可能です。処理費用やレスポンススピードの最適化を行う場合は、重要な調整ポイントになります。

1-6. ローカルでの動作確認

では、一通りの設定が完了したのでローカルで動作を確認しましょう。
以下のコマンドで Web UI を起動します。

# /adk-app で実行
uv run adk web .

ブラウザで http://localhost:8000/ にアクセスすると、先ほどと同様に画面が確認できます。

1-7. エージェントのテスト

Web UI で以下のような質問を試してみましょう。

  • 「GitHub 上で、TypeScript で人気のリポジトリを教えて」
  • 「Rustのwebフレームワークでおすすめは?」
  • 「機械学習のライブラリ探してる」

CleanShot 2025-12-02 at 23.05.30.png

すると、エージェントが GitHub API を呼び出し、リポジトリ情報を返すことが確認できました。

また、実際にどのようなツールの使い方をしたのかもトレースすることができます。
以下のスクリーンショットでは、今回の質問で使ったクエリは TypeScript であることがわかります。

CleanShot 2025-12-02 at 23.08.26.png

たったこれだけで、外部APIから情報を取得して回答するエージェントができました。デバッグも容易で、非常に便利ですね。

2. Cloud Run にデプロイしてみる

では、これをさらにデプロイして自分以外の人も使えるようにしてみます。

デプロイ先の筆頭候補は Agent Engine ですが、検証レベルでは少しお値段が高めです。今回は検証を目的としており、コールドスタートなども許容できるので Cloud Run を選択し、極力コストを抑える方向で進めてみます。

2-1. Google Cloud の初期設定

まず、プロジェクトとリージョンを設定します。今後のコマンドでも度々使うので、一時的なシェル環境変数としてセットして使います。

PROJECT_ID には、ご自身のデプロイ先プロジェクトIDを設定してください。

export PROJECT_ID="your-project-id"
export REGION="asia-northeast1"

gcloud config set project $PROJECT_ID
gcloud config set run/region $REGION

必要な API を有効化します。

gcloud services enable run.googleapis.com
gcloud services enable artifactregistry.googleapis.com
gcloud services enable cloudbuild.googleapis.com
gcloud services enable secretmanager.googleapis.com

2-2. Secret Manager に API キーを保存

先ほど AI Studio で取得した API キーを Secret Manager に保存します。また、Cloud Run がキーにアクセスするための権限も付与しておきます。

echo -n "your-api-key-here" | gcloud secrets create google-api-key --data-file=-

export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)")

gcloud secrets add-iam-policy-binding google-api-key \
    --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"

2-3. adk deploy でデプロイ

adk にはデプロイコマンドが標準で用意されているので、これを使うとサクッとデプロイできます。Dockerfile を書いたりしなくて良いので非常に楽です。

ということで、以下のコマンドを実行します。

※ 以下のコマンドでは、パブリックにアプリケーションが公開されます。注意してください。

# /adk-app で実行
uv run adk deploy cloud_run \
    --project=$PROJECT_ID \
    --region=$REGION \
    --with_ui \
    --service_name=adk-app \
    --port=8080 \
    github_agent \
    -- --allow-unauthenticated --set-secrets=GOOGLE_API_KEY=google-api-key:latest

デプロイが完了すると、以下のようなログが出力されます。

Done. 
Service [adk-app] revision [adk-app-00001-d5n] has been deployed and is serving 100 percent of traffic.
Service URL: https://adk-app-XXXXXXXXXX.asia-northeast1.run.app

このURLにデプロイが成功しています。実際に確認してみましょう!

2-5. Cloud Run 上での動作確認

先ほどと同じように、質問を投げかけてみます。

CleanShot 2025-12-03 at 00.01.25.png

ローカルで試した時と同様、ツールを使った上できちんと回答が返ってきていますね!

2-6. (オプション) Identity-Aware Proxy での保護

Identity-Aware Proxy (IAP) を使って、Cloud Run を直接保護することができます。
ただ、本機能はプレビューのため、 adk deploy コマンドではまだ対応していないようです。

そのため、Cloud Run 直接保護を行いたい場合は以下のようにブラウザ操作から設定する必要があります。

Identity-Aware Proxy にチェックを入れ、「ポリシーの編集」をクリック

CleanShot 2025-12-03 at 01.07.20.png

プリンシパルに自身のメールアドレス(もしくは IAM グループ)を設定

CleanShot 2025-12-03 at 01.07.58.png

コマンドでの設定方法に関して気になる方は、以下のブログをご参照ください。

https://dev.classmethod.jp/articles/iap-for-cloud-run-googlecloudnext/

なお、ブラウザで設定したあとにデプロイした場合でも --allow-unauthenticated オプション無しでデプロイすることでこの設定は維持されます。もしこの方法が難しい場合は、NEGの作成など別の対応を行う必要があります。

まとめ

ADK を使って GitHub API を呼び出すエージェントを作成し、Cloud Run にデプロイしてみました。
adk コマンドが非常に強力で、エージェントの作成からデプロイまで非常に簡単に行えることが伝わったかと思います。実際に触る中で、コードを全く書かなくても UI 付きの AI チャットが起動してすぐに会話が始められるのはとてもワクワクしました。
また、デプロイ先が Cloud Run なので、費用も抑えつつ、Identity-Aware Proxy などで認証をかけることもできるのは嬉しいポイントです。

今回は GitHub API で試してみましたが、これを応用すればさまざまな外部 API にアクセスすることも可能です。また、 BigQuery などのデータにもアクセスできるので、データに対する調査用エージェントとしての活躍も期待できます。

色々な可能性がある ADK へのワクワクが少しでも伝われば嬉しいです!
以上、すらぼでした!

参考リンク

https://google.github.io/adk-docs/

https://github.com/google/adk-python

https://docs.github.com/ja/rest

この記事をシェアする

FacebookHatena blogX

関連記事