イベントを使用したエージェント AI アプリケーションの非同期呼び出し

1. はじめに

概要

このラボでは、Eventarc サービスと Pub/Sub サービスを使用して、Cloud Run にデプロイされた ADK エージェントのイベント ドリブン呼び出しを安全に実装する方法について説明します。ほとんどの場合、エージェントはユーザーまたは別のエージェントから直接呼び出されます。ただし、エージェントを既存のイベントベースのワークフローに統合する場合、直接呼び出しを行うには既存のソフトウェアを変更する必要があります。イベントに基づいてエージェントの呼び出しをトリガーすると、ワークフローを変更することなく、既存のワークフローにエージェントを組み込むことができます。

演習内容

このラボでは、AI エージェントを備え、いくつかのツールを使用して架空の動物園の動物に関する情報を提供する ZooKeeper エージェント アプリケーションを作成します。

Zoo-Keeper のイラスト

ZooKeeper アプリケーションをサービスとして Cloud Run にデプロイします。Cloud Run は、Google のインフラストラクチャでステートレス コンテナを実行するフルマネージドのサーバーレス コンピューティング プラットフォームです。次に、Pub/Sub トピックに公開されたメッセージを非同期で処理するサービス エンドポイントを呼び出す Eventarc トリガーを設定します。指定された IAM サービス アカウントの使用、最小権限のアクセスの付与、ZooKeeper アプリケーションのエンドポイントを Eventarc にのみ公開することによる潜在的な攻撃対象領域の最小化など、デプロイがベスト プラクティスに従っていることを確認します。Cloud Shell と Cloud コンソールを使用して行います。Python 用の ADK ライブラリと Cloud SDK ライブラリを使用します。動作を確認するには、gcloud CLI を使用します。

学習内容

  • ADK エージェントを Google Cloud Run にデプロイします。
  • Google Cloud Run で実行されている ADK エージェントと Eventarc トリガーを統合します。
  • Google Cloud IAM を使用して、最小権限アクセスの原則に従い、Eventarc を使用したデプロイと統合を保護します。
  • Pub/Sub との間でメッセージをパブリッシュして pull します。
  • Google Cloud Run にデプロイされたアプリケーションの一般公開を最小限に抑えます。

必要なもの

アカウントには、リソースをプロビジョニングし、これらのリソースに対する IAM アクセス権を構成できるプロジェクトに対する IAM アクセス権が必要です。

他のブラウザを使用した場合のユーザー エクスペリエンスは、ラボで説明されているものと異なる場合があります。

企業または学校のアカウントを使用している場合、ラボで説明されている一部の操作が制限されることがあります。

2. 環境のセットアップ

ラボで完全に機能する開発環境を確保するため、必要なツールがすべてプリインストールされている Google Cloud Shell を使用します。手順に沿って環境を設定します。

Google アカウントをお持ちでない場合は、Google アカウントを作成してください。

設定の手順

  1. Google アカウントを使用して Google Cloud コンソールにログインします。
  2. 👉 上部のナビゲーション バーでプロジェクト選択ツールを開く([プロジェクトを選択] と表示されるか、既存のプロジェクト名が表示されます)。または、キーボード ショートカット Ctrl+O をクリックして、既存のプロジェクトを選択するか、新しいプロジェクトを作成します。新しいプロジェクトの作成には数秒かかります。準備が整うまで待ってから、プロジェクト選択ツールを使用して選択します。
  1. 👉 Google Cloud コンソールの上部にある Cloud Shell アイコンをクリックします。(赤い長方形で囲まれています):Cloud Shell ボタン
    プロンプトが表示されたら、ポップアップ ダイアログ ボックスで [**承認**] をクリックして、アカウントの認証情報を使用する Cloud Shell を承認します。
    承認ダイアログ
  2. 👉💻 選択(または作成)したプロジェクトを使用するように gcloud CLI が構成されていることを確認します。次のコマンドを実行して、構成済みのプロジェクト ID を確認します。
    gcloud config get-value project
    
    出力は次のようになります。
    Your active configuration is: [cloudshell-19597]
    [PROJECT_ID]
    
    ここで、[PROJECT_ID] は選択または作成したプロジェクトの ID です。👉💻 別の値が表示された場合は、次のコマンドを実行して、プロジェクト ID を gcloud CLI コマンドのデフォルトのプロジェクト ID として構成します。
    gcloud config set project [YOUR_PROJECT_ID]
    
    たとえば、プロジェクト ID が lab-project-id-example-123 の場合、コマンドは次のようになります。
    gcloud config set project lab-project-id-example-123
    
    🤔💻 プロジェクト ID を忘れた場合は、次のコマンドを使用して、アクセス権のあるすべてのプロジェクト ID を最新のものから順に一覧表示します。
    gcloud projects list \
        --format='value(projectId)' \
        --sort-by='~createTime'
    
  1. 👉💻 環境変数で、リソースのプロビジョニングのロケーションとプロジェクトの ID と番号を設定します。
    export LOCATION="us-central1"
    export PROJECT_ID=$(gcloud config get-value project)
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
    
  2. 👉💻 このラボに必要な Google API を有効にします。
    gcloud services enable \
        aiplatform.googleapis.com \
        eventarc.googleapis.com \
        run.googleapis.com \
        artifactregistry.googleapis.com \
        cloudbuild.googleapis.com \
        pubsub.googleapis.com
    
    このコマンドは数分かかることがあります。コマンドが正常に実行されると、次のようなメッセージが表示されます。
    Operation "operations/ab12345c-6e7f-8ghi-jkl9-m0e1d23456f7" finished successfully.
    

3. ZooKeeper デモ アプリケーションをデプロイする

次の手順では、エージェント AI アプリケーションのデプロイなど、リソースのプロビジョニングと構成を行います。

Pub/Sub リソースの設定

2 つの Pub/Sub トピックを作成します。1 つは、サードパーティ サービスがエージェント AI アプリケーションにイベントを送信するために使用されます。もう 1 つは、イベント処理の結果を公開するアプリケーション用です。

  1. 👉💻 エージェント AI アプリケーションのトリガーに使用される Pub/Sub トピックを作成します。
    gcloud pubsub topics create invoke_agent
    export INVOKE_TOPIC_ID=$(gcloud pubsub topics describe invoke_agent --format="value(name)")
    
  2. 👉💻 アプリケーションがレスポンスを投稿できる Pub/Sub トピックを作成します。
    gcloud pubsub topics create agent_responses
    export RESPONSE_TOPIC_ID=$(gcloud pubsub topics describe agent_responses --format="value(name)")
    gcloud pubsub subscriptions create agent_responses \
        --topic=agent_responses
    
    これらのコマンドは、作成された Pub/Sub トピックのサブスクリプションも作成します。サブスクリプションは、デモを実行して結果を表示する際に使用されます。

サービス アカウントとプロジェクト レベルの IAM ポリシーの設定

最小権限の原則に従って、Cloud Run サービスと Eventarc トリガーのアクセス範囲を最小限に制限する 2 つのサービス アカウントを作成します。Cloud Run サービスには、ログとトレースの書き込み、Google Vertex AI での Gemini LLM の呼び出し、Pub/Sub トピックへの結果の投稿を行う権限が必要です。Eventarc トリガーの最小限のアクセス権では、Cloud Run ZooKeeper サービスを呼び出し、Pub/Sub にアクセスして投稿されたイベントを読み取る権限が必要です。この手順では、Pub/Sub システム サービスの権限を借用するために必要な権限をトリガーのサービス アカウントに付与します。Eventarc トリガー リソースを作成したら、roles/run.invoker ロールを付与するコマンドを実行して、トリガーのサービス アカウントが Cloud Run サービスを呼び出せるようにします。

  1. 👉💻 Cloud Run サービスのサービス アカウントを作成します。
    gcloud iam service-accounts create zookeeper-cloudrun-sa
    export ZOOKEEPER_SA="zookeeper-cloudrun-sa@${PROJECT_ID}.iam.gserviceaccount.com"
    
  2. 👉💻 ログとトレースを書き込み、Vertex AI で Gemini モデルを使用する権限をサービス アカウントに付与します。
    gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
         --member="serviceAccount:${ZOOKEEPER_SA}" \
         --role="roles/logging.logWriter" \
         --condition=None
    gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
        --member="serviceAccount:${ZOOKEEPER_SA}" \
        --role="roles/cloudtrace.agent" \
        --condition=None
    gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
        --member="serviceAccount:${ZOOKEEPER_SA}" \
        --role="roles/aiplatform.user" \
        --condition=None
    
  3. 👉💻 「agent_responses」トピックにメッセージを投稿する権限を持つサービス アカウントに権限を付与します。
    gcloud pubsub topics add-iam-policy-binding agent_responses \
        --member="serviceAccount:${ZOOKEEPER_SA}" \
        --role="roles/pubsub.publisher"
    
  4. 👉💻 Eventarc トリガーのサービス アカウントを作成します。
    gcloud iam service-accounts create zookeeper-trigger-sa
    export TRIGGER_SA="zookeeper-trigger-sa@${PROJECT_ID}.iam.gserviceaccount.com"
    
  5. 👉💻 認証済みのプッシュ リクエストを行う権限を Pub/Sub システム サービス アカウントに付与します。
    gcloud iam service-accounts add-iam-policy-binding "${TRIGGER_SA}" \
           --member="serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com" \
        --role="roles/iam.serviceAccountTokenCreator"
    
    プロジェクトが 2021 年 4 月 8 日以降に作成された場合、このコマンドは省略可能です

ZooKeeper アプリを Cloud Run にデプロイする

デモ アプリケーションのコードを GitHub からダウンロードします。コードを Cloud Run にデプロイします。

  1. 👉💻 エージェント AI アプリケーションをダウンロードします。
    mkdir zoo-keeper-lab && cd zoo-keeper-lab
    git init
    git remote add origin https://github.com/GoogleCloudPlatform/devrel-demos
    git config set core.sparseCheckout true
    echo "ai-ml/agent-labs/adk_invoke_with_pubsub/" >> .git/info/sparse-checkout
    git pull origin main --depth 1
    cd ai-ml/agent-labs/adk_invoke_with_pubsub/
    
    これらのコマンドは、デモアプリを含むフォルダの Git スパース チェックアウトを使用して、ダウンロード時間を短縮します。
  2. 👉💻 エージェント AI アプリケーションを Cloud Run にデプロイします。
    gcloud run deploy zookeeper-agent \
        --region="${LOCATION}" \
        --source="." \
        --no-allow-unauthenticated \
        --quiet \
        --service-account="${ZOOKEEPER_SA}" \
        --set-env-vars="REPLY_TOPIC_ID=${RESPONSE_TOPIC_ID}"
    

Eventarc トリガーを構成する

すべてのリソース(Pub/Sub トピック、IAM サービス アカウント、Cloud Run サービス)を準備したら、Eventarc トリガー リソースを設定します。Eventarc トリガー リソースを作成し、Cloud Run サービスを呼び出す権限をトリガーのサービス アカウントに付与します。

  1. 👉💻 Eventarc トリガーを作成します。
    gcloud eventarc triggers create invoke-agent \
        --location="${LOCATION}" \
        --destination-run-service="zookeeper-agent" \
        --destination-run-path="/zookeeper" \
        --destination-run-region="${LOCATION}" \
        --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
        --transport-topic="${INVOKE_TOPIC_ID}" \
        --service-account="${TRIGGER_SA}"
    
  2. 👉💻 トリガーのサービス アカウントに Cloud Run サービスを呼び出す権限を付与します。
    gcloud run services add-iam-policy-binding zookeeper-agent \
        --region="${LOCATION}" \
        --member="serviceAccount:${TRIGGER_SA}" \
        --role="roles/run.invoker"
    

4. ソリューションの仕組みを確認する

デプロイした内容を確認します。次の図は、すべてのリソースとそれらの相互作用を示しています。gcloud CLI を使用して、invoke_agent トピックにメッセージをパブリッシュします。これにより、エージェント AI アプリケーションを呼び出すためにサードパーティ サービスがメッセージング サービスにログを記録するイベントがシミュレートされます。

ソリューション図

最小権限アクセスに従ってデプロイが保護されます。Cloud Run サービスは認証を適用します(前のセクションのステップ 9 の --no-allow-unauthenticated 引数をご覧ください)。roles/run.invoker または同様の権限を持つ ID のみ、サービスを呼び出すことができます。このロールは、Eventarc トリガーのサービス アカウントにのみ付与されます。同様に、invoke_agent トピックへのアクセスも最小限に抑えられ、イベントの不正なパブリッシュが禁止されます。Pub/Sub トピックへの投稿をバイパスして、ZooKeeper エージェントを直接呼び出すことは可能です。アプリケーションのエンドポイントを一般公開から隠す方法については、セクション 6 をご覧ください。

ワークフローを実行する

自然言語で ZooKeeper に質問を公開して、外部イベントをエミュレートします。

👉💻 次のコマンドを使用して、Pub/Sub トピックにメッセージを投稿します。

gcloud pubsub topics publish invoke_agent \
    --message='{"user_id": "important_app", "prompt": "How many animals are in the zoo?"}'

実際には、イベント情報は読み取りにくい形式になっている可能性があります。処理するには、エージェント AI アプリケーションに、イベントの形式、データ、エージェントがイベント情報に対して行うべきことに関する詳細な指示が必要です。

エージェントがイベントを受信し、リクエストを処理して、レスポンスを agent_responses トピックに投稿したことを確認できます。レスポンスを読み取るには、agent_responses サブスクリプションを使用します(この Codelab では、トピックとレスポンスのサブスクリプションの両方に同じ ID を使用します)。

👉💻 次のコマンドを使用して、Pub/Sub サブスクリプションからエージェントのレスポンスを読み取ります。

gcloud pubsub subscriptions pull agent_responses --auto-ack

出力には、メッセージ メタデータと、動物園には 33 種の動物がいるという回答を含むペイロードを含むテーブルが表示されます。--auto-ack フラグは、メッセージが pull された後に自動的に確認応答を行うため、メッセージが再度配信されることはありません。

仕組み

Cloud Shell エディタを開き、~/zoo-keeper-lab フォルダにあるファイルを表示して、エージェント AI アプリケーションのソースコードを確認します。GitHub でソースコードを表示することもできます。

  • main.py は、Eventarc イベントを処理する単一のハンドラを含む基本的な FastAPI ウェブ アプリケーションを実装します。
  • processor.py は、イベントのメッセージを解析して、ユーザー ID とリクエストを取得します。次に、ADK ランナーで新しいセッションを作成し、Zookeeper エージェントを呼び出してリクエストを処理します。エージェントからのレスポンスは、agent_responses Pub/Sub トピックに投稿されます。
  • サブフォルダ zookeeper_agent には、ADK エージェントのソースコードが格納されています。アプリケーションのルートフォルダからコマンド adk run zookeeper_agent を実行して、adk CLI を使用してエージェントを操作できます。

トラブルシューティング方法

上記のコマンドのいずれかが失敗した場合は、エラー メッセージをよく読んでください。Cloud Run へのデプロイが失敗した場合、最初の手順は、プロセスのどの段階で失敗が発生したかを特定することです。

  • 「gcloud run deploy...」コマンドの出力でビルドが失敗したことが報告された場合は、出力に表示されているビルドログの URL を確認し、別のウィンドウで開きます。
  • 出力に「サービスを開始できませんでした」などのメッセージが表示された場合は、サービスはデプロイされたものの、実行がヘルスチェックに失敗したことを意味します。この場合は、ログ エクスプローラを開くか、次の段落の gcloud CLI コマンドをご覧ください。ログを読んで、障害の根本原因を見つけます。

Pub/Sub にメッセージを投稿したのに、エージェントが応答しない場合や、応答が不自然な場合はどうすればよいですか?

👉💻 次のコマンドを使用して、最近の実行から投稿されたアプリケーション ログを読み取ります。

gcloud logging read \
    'resource.type = "cloud_run_revision" AND \
     resource.labels.service_name = "zookeeper-agent" AND \
     resource.labels.location = "us-central1"'

ログは実行を追跡し、正しくないメッセージ ペイロードや解析できないメッセージ ペイロード、Gemini モデルからの無効なレスポンス、無効な環境設定などのエラーを報告します。

5. デプロイのセキュリティを強化する

デプロイした Cloud Run サービスは、インターネット上のすべてのユーザーが呼び出すことができるパブリック エンドポイントを公開します。エンドポイントは不正な呼び出しから保護され、リクエストの構造が厳密に検証されますが、サービス拒否攻撃やウォレット拒否攻撃を可能にする攻撃ベクトルが残っています。現在の設計では、サービスの唯一の呼び出しパスは Eventarc トリガーを介しているため、サービスはエンドポイントをインターネットに公開する必要はありません。

👉💻 この攻撃ベクトルを閉じるには、Eventarc トリガーなどの限定されたソースのコレクションからのみサービスを呼び出すように制限します。

gcloud run services update zookeeper-agent --region=${LOCATION} --ingress=internal

ローカルマシンからサービスの URL を呼び出そうとすると、「404 Page not found」エラーが表示されます。

👉💻 curl を使用してサービス エンドポイントにリクエストを送信します。

URL=$(gcloud run services describe zookeeper-agent --region=${LOCATION} --format='value(status.url)')
curl -X POST -d '{}' "${URL}/zookeeper"

出力は次のようになります。

<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>404 Page not found</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Page not found</h1>
<h2>The requested URL was not found on this server.</h2>
<h2></h2>
</body></html>

この変更後は、同じプロジェクトの VPC、リビジョンがトラフィックの送信先として構成されている共有 VPC ネットワーク、または VPC Service Controls 境界の一部であるホストから呼び出しを行わない限り、Cloud Run サービス エンドポイントを呼び出して ZooKeeper を直接呼び出すことはできません。

6. まとめ

おめでとうございます!受信イベントによってトリガーされるエージェント AI アプリケーションを非同期的に呼び出す環境を正常に設定しました。

クリーンアップ

プロビジョニングしたリソースを保持すると、請求先アカウントに料金が発生する場合があります。この環境を他のテストに使用する予定がなく、今後の課金を回避する場合は、この Codelab で作成したリソースを削除することをおすすめします。

これには次の 2 つの方法があります。

方法 1: プロジェクトをシャットダウンする

プロジェクトをシャットダウン(削除)すると、プロジェクトのすべてのリソースとデータが解放され、請求先アカウントのリンクが解除されます。この方法を使用すると、このコードラボで使用したリソースやデータに対して追加料金が発生しなくなります。次のコマンドを使用してプロジェクトをシャットダウンします。

gcloud projects delete $(gcloud config get-value project) --quiet

方法 2: プロジェクト内のリソースを削除する

Cloud Run サービスを削除すると、サーバーレス プラットフォームの使用に対する追加料金が発生しなくなります。この方法では、Cloud Build やアプリケーション ログ、コンテナ イメージなど、Codelab で生成されたすべてのデータが完全に削除されるわけではありません。次のコマンドを実行して、サービスを削除します。

gcloud run services delete zookeeper-agent --region=${LOCATION}

Eventarc トリガー定義と Pub/Sub トピックには管理費用はかかりません(詳細については、Eventarc の料金Pub/Sub の料金をご覧ください)。

詳しくは、プロジェクトのシャットダウンをご覧ください。

次のステップ