
API
イベント
マガジン
技術ブログ
LINE アプリ開発に携わっている Hiraki と申します。普段は、LINE アプリにおけるアーキテクチャの統一を推進するプロジェクトのリードや、AI ネイティブな開発スタイルを業務に組み込むための...
セーフィー株式会社でサーバーサイドエンジニアを務めている尹です。 近年、AI エージェントやプロンプトエンジニアリングといった言葉が広く使われています。私自身、バックエンドの開発や社内ツールの自動化を進める中で、プロンプトの「使い捨て」に課題を感じていました。 通常、プロンプトはその場で書いて使い捨てるものとして扱われがちです。しかし、開発で繰り返し使う指示ほど、毎回ゼロから書き直すのは非効率で、書く人によって品質もばらつき、変更履歴も残りません。本来であれば再利用できるはずの指示が、資産として蓄積されずに失われてしまう――これが私の感じていた課題です。 本記事では、こうした使い捨てのプ
G-gen の佐々木です。当記事では、Agent Development Kit(以下 ADK と記載)で開発した AI エージェントを Cloud Run にデプロイし、Cloud Run のサンドボックス機能による Code Execution(LLM が生成したコードの安全な実行)を試します。 構成 当記事で使用するもの Cloud Run とは Cloud Run のサンドボックスとは サンドボックスの概要 sandbox コマンドラインツール 実行結果の取得とファイルの受け渡し Agent Development Kit(ADK)とは エージェントの開発 ディレクトリ構成 uv プロジェクトの作成 agent.py __init__.py main.py Dockerfile .dockerignore Google Cloud 側の準備 API の有効化 サービスアカウントの作成 デプロイ 動作確認 Web UI へのアクセス エージェントとの対話 ログの確認 構成 当記事では、ADK で開発した AI エージェントを、サンドボックス機能を有効化した Cloud Run サービスとしてデプロイします。 処理の流れは以下のとおりです。 ユーザーが ADK の Web UI からエージェントに質問する エージェントが質問への回答に必要なコードを生成し、サンドボックス内でコードを実行するためのカスタムツールを呼び出す ツールが Cloud Run の隔離されたサンドボックス内でコードを実行する エージェントが実行結果を元に回答を生成する LLM が生成したコードをアプリケーションのコンテナ内で直接実行すると、意図しないファイル操作や外部通信などのリスクがあります。Cloud Run のサンドボックス機能を使用すると、ホストコンテナから隔離された環境でコードを実行できます。 当記事で使用するもの Cloud Run とは Cloud Run は、Google Cloud のフルマネージドなサーバーレスコンテナ実行基盤です。コンテナイメージまたはソースコードをデプロイするだけで、リクエスト数に応じた自動スケーリングを備えた Web サービスを実行できます。 Cloud Run の詳細は、以下の記事で解説しています。 blog.g-gen.co.jp Cloud Run のサンドボックスとは サンドボックスの概要 Cloud Run の サンドボックス (Cloud Run sandboxes)は、信頼できないコードを高速・安全・隔離された環境で実行するための機能です。 Cloud Run サービスでサンドボックス機能を有効化すると、コンテナ内で sandbox コマンドラインツールが利用可能になり、任意のコマンドをサンドボックス内で実行できます。2026年7月現在、この機能は Preview 公開 です。 サンドボックスの主な特徴は以下のとおりです。 第2世代実行環境の Cloud Run でのみ使用可能 サンドボックスは必要に応じて瞬時に作成され、すぐにコマンドを実行できる サンドボックス内のプロセスは非 root ユーザーとして実行され、デフォルトでは親ワークロードや Cloud Run のメタデータサーバーにアクセスできない(プロセスレベルの分離) ホストコンテナの環境変数はサンドボックスに継承されず、API キーなどの機密情報が意図せず参照されることを防げる(渡す場合は --env フラグで明示的に指定する) 外部へのアウトバウンド通信はデフォルトでブロックされる( --allow-egress フラグで許可できる) サンドボックスから見えるルートファイルシステムは読み取り専用( --write フラグやバインドマウントで書き込みを許可できる) サンドボックスはホストコンテナと同一インスタンス内で動作し、CPU とメモリをホストコンテナと共有する サンドボックスの作成・削除などのライフサイクルイベントは Cloud Logging に自動的に記録される 参考 : Code execution in Cloud Run 参考 : Configure sandboxes for services sandbox コマンドラインツール sandbox コマンドラインツールには以下のサブコマンドがあります。 コマンド 説明 sandbox do 一時的なサンドボックスを作成してコマンドを実行し、終了後に破棄する sandbox run サンドボックスを起動する sandbox exec 実行中のサンドボックスでコマンドを実行する sandbox tar サンドボックスのファイルシステムのスナップショットを取得する sandbox delete サンドボックスを削除する 当記事では、単発のコード実行に適した sandbox do を使用します。 実行結果の取得とファイルの受け渡し サンドボックス内で実行したプロセスの標準出力・標準エラーは、呼び出し元のプロセスに直接返されます。後述のサンプルコードでは、この仕様を利用して subprocess モジュール経由でコードの実行結果を取得します。 サンドボックスのファイルシステムへの書き込みは、 --write フラグで許可した場合も一時的なもので、ホストコンテナからは参照できません。 実行結果としてファイルを取り出す場合は、サンドボックス内で変更されたファイルを tar アーカイブとして出力する --export-tar フラグ(取り込みは --import-tar 、双方向同期は --sync-tar )や、 --mount フラグによるバインドマウントを使用して、ホストコンテナとファイルを受け渡しします。 Agent Development Kit(ADK)とは Agent Development Kit (以下 ADK と記載)は、Google が開発するオープンソースのエージェント開発フレームワークです。 ADK は Python、TypeScript、Go、Java に対応しており、開発したエージェントはローカル環境のほか、Agent Runtime(旧称 Agent Engine)、Cloud Run、Google Kubernetes Engine(GKE)にデプロイできます。 当記事では Python 版の ADK( google-adk )を使用します。 参考 : Agent Development Kit 参考 : google/adk-python エージェントの開発 ディレクトリ構成 作成するプロジェクトのディレクトリ構成は以下のとおりです( uv init が生成する README.md や .python-version などは省略)。 sandbox-agent/ ├── .dockerignore ├── Dockerfile ├── main.py # FastAPI アプリのエントリーポイント ├── pyproject.toml ├── uv.lock └── sandbox_agent/ # ADK エージェントのパッケージ ├── __init__.py └── agent.py # エージェントとツールの定義 uv プロジェクトの作成 uv プロジェクトを初期化し、依存パッケージとして google-adk と uvicorn を追加します。 # uv のセットアップ $ uv init sandbox-agent --python 3 . 13 $ cd sandbox-agent # 依存パッケージのインストール $ uv add google-adk uvicorn # エージェントのパッケージディレクトリとファイルの作成 $ mkdir sandbox_agent $ touch sandbox_agent/__init__.py sandbox_agent/agent.py Dockerfile .dockerignore main.py は uv init によって生成されるため、ここでは作成せず、後の手順で内容を書き換えます。各ファイルの中身は以降の節で順に記述していきます。 pyproject.toml は以下のようになります。 [project] name = "sandbox-agent" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.13" dependencies = [ "google-adk>=2.4.0" , "uvicorn>=0.51.0" , ] agent.py エージェント本体とカスタムツールを sandbox_agent/agent.py に定義します。 import subprocess from google.adk.agents import Agent from google.adk.tools import FunctionTool SANDBOX_BIN = "/usr/local/gcp/bin/sandbox" PYTHON_BIN = "/usr/local/bin/python3" def execute_python_code (code: str ) -> dict : """Python コードをサンドボックス内で実行し、結果を返す。 Args: code: 実行する Python ソースコード。 Returns: stdout、stderr、returncode を含む dict。 """ result = subprocess.run( [SANDBOX_BIN, "do" , "--" , PYTHON_BIN, "-c" , code], capture_output= True , text= True , timeout= 60 , ) return { "stdout" : result.stdout, "stderr" : result.stderr, "returncode" : result.returncode, } root_agent = Agent( name= "sandbox_agent" , model= "gemini-2.5-flash" , description= "Python コードをサンドボックスで実行して回答するエージェント" , instruction=( "あなたはユーザーの質問に答えるアシスタントです。" "計算やデータ処理が必要な場合は、必ず Python コードを書いて" " execute_python_code ツールで実行し、その実行結果に基づいて回答してください。" "実行結果の stdout をそのまま引用し、コードの内容も簡単に説明してください。" ), tools=[FunctionTool(func=execute_python_code)], ) ポイントは以下のとおりです。 execute_python_code 関数を FunctionTool でラップしてエージェントのツールとして登録している。関数のドキュメンテーション文字列と型ヒントがツールの仕様として LLM に渡される ツール内では、サンドボックス機能の有効化時にコンテナへ配置されるバイナリ /usr/local/gcp/bin/sandbox を subprocess で呼び出し、 sandbox do -- /usr/local/bin/python3 -c <コード> の形式で LLM が生成した Python コードをサンドボックス内で実行している サンドボックスからはホストコンテナのルートファイルシステムが読み取り専用で参照できるため、コンテナイメージに含まれる Python ランタイムをサンドボックス内でも実行できる サンドボックスにはホストの環境変数が継承されず、実行するコマンドの PATH 解決も行われないため、コマンドは /usr/local/bin/python3 のような絶対パスで指定する必要がある __init__.py ADK がエージェントを認識できるように、 sandbox_agent/__init__.py で agent モジュールをインポートしておきます。 from . import agent main.py Cloud Run 上でエージェントを Web アプリケーションとして公開するため、ADK が提供する get_fast_api_app() で FastAPI アプリを作成します。 import os from google.adk.cli.fast_api import get_fast_api_app AGENTS_DIR = os.path.dirname(os.path.abspath(__file__)) app = get_fast_api_app( agents_dir=AGENTS_DIR, allow_origins=[ "http://localhost:8080" , "http://127.0.0.1:8080" ], web= True , ) if __name__ == "__main__" : import uvicorn uvicorn.run(app, host= "0.0.0.0" , port= int (os.environ.get( "PORT" , 8080 ))) get_fast_api_app() は、ADK の開発用 Web UI とエージェント実行用の REST API を含む FastAPI アプリを返します。 agents_dir にはエージェントのパッケージ(当記事では sandbox_agent/ )が置かれたディレクトリを指定し、 web=True で Web UI を有効化します。ポート番号は Cloud Run が設定する環境変数 PORT から取得します。 allow_origins には、後述の動作確認で gcloud run services proxy コマンド経由で Web UI にアクセスするときのオリジンを指定します。ADK の API サーバーは、セキュリティ対策として POST などの状態変更リクエストの Origin ヘッダーを検証します。プロキシ経由のアクセスでは Origin( http://127.0.0.1:8080 など)とリクエスト先( run.app ドメイン)が一致しないため、 allow_origins を指定していないと Web UI からの操作が403エラーになります。 Dockerfile uv を使用してコンテナイメージをビルドする Dockerfile を作成します。 FROM python:3.13-slim COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv WORKDIR /app COPY pyproject.toml uv.lock ./ RUN uv sync --frozen --no-dev COPY . . ENV PATH= "/app/.venv/bin:$PATH" CMD [ " python ", " main.py " ] .dockerignore .dockerignore に以下の内容を記述し、ローカルの .venv などをコンテナイメージのビルドコンテキストから除外します。 .venv __pycache__ *.pyc .git 後述のデプロイで使用する --source フラグは、カレントディレクトリ全体を Cloud Build にアップロードします。 .dockerignore で除外していない場合、 COPY . . の際にローカル環境用の .venv がコンテナ内に作成済みの .venv を上書きし、コンテナの起動に失敗するため注意してください。 Google Cloud 側の準備 API の有効化 使用する API を有効化します。ソースコードからのデプロイ( --source フラグ)では Cloud Build と Artifact Registry も使用されるため、あわせて有効化します。なお2026年7月現在、Gemini の呼び出しに使用する Agent Platform の API 名や IAM ロール ID には、旧称の Vertex AI に由来する aiplatform という名称が残っています。 $ gcloud services enable \ run.googleapis.com \ aiplatform.googleapis.com \ cloudbuild.googleapis.com \ artifactregistry.googleapis.com \ --project =< プロジェクトID > サービスアカウントの作成 Cloud Run サービスが使用するサービスアカウントを作成します。エージェントが Agent Platform の API 経由で Gemini を呼び出すため、Agent Platform ユーザー( roles/aiplatform.user )を付与します。 # サービスアカウントの作成 $ gcloud iam service-accounts create sandbox-agent \ --project =< プロジェクトID > # Agent Platform ユーザーの付与 $ gcloud projects add-iam-policy-binding < プロジェクトID > \ --member =" serviceAccount:sandbox-agent@<プロジェクトID>.iam.gserviceaccount.com " \ --role =" roles/aiplatform.user " デプロイ 作成したプロジェクトのディレクトリ( sandbox-agent/ )で、以下のコマンドを実行して Cloud Run にデプロイします。サンドボックス機能を有効化する --sandbox-launcher フラグは、2026年7月現在、 gcloud beta コマンドでのみ使用できます。 $ gcloud beta run deploy sandbox-agent \ --source . \ --project =< プロジェクトID > \ --region = asia-northeast1 \ --execution-environment = gen2 \ --sandbox-launcher \ --service-account = sandbox-agent@ < プロジェクトID > .iam.gserviceaccount.com \ --set-env-vars = GOOGLE_GENAI_USE_VERTEXAI =TRUE, GOOGLE_CLOUD_PROJECT = < プロジェクトID > , GOOGLE_CLOUD_LOCATION =asia-northeast1 \ --no-allow-unauthenticated 主なフラグの意味は以下のとおりです。 フラグ 説明 --source . カレントディレクトリのソースコードから Cloud Build でコンテナイメージをビルドしてデプロイする。 Dockerfile が存在する場合はそれが使用される --execution-environment=gen2 第2世代実行環境を指定する。サンドボックス機能の使用に必須 --sandbox-launcher サンドボックス機能を有効化する。コンテナ内に sandbox コマンドラインツールが配置される --service-account ランタイムサービスアカウントとして、前の手順で作成したサービスアカウントを指定する --set-env-vars ADK が Agent Platform 経由で Gemini を呼び出すための環境変数を設定する。 GOOGLE_GENAI_USE_VERTEXAI という変数名にも旧称に由来する名称が残っている --no-allow-unauthenticated 未認証のアクセスを拒否する 環境変数 GOOGLE_CLOUD_LOCATION は、Gemini を呼び出す Agent Platform 側のロケーションであり、Cloud Run サービスのリージョン( --region )とは独立しています。当記事では asia-northeast1 を指定し、東京リージョンのリージョンエンドポイント経由でモデルを呼び出します。 参考 : gcloud beta run deploy 動作確認 Web UI へのアクセス デプロイしたサービスは未認証アクセスを拒否しているため、 gcloud run services proxy コマンドで手元の端末からプロキシ経由でアクセスします。 $ gcloud run services proxy sandbox-agent \ --project =< プロジェクトID > \ --region = asia-northeast1 ブラウザで http://localhost:8080 を開くと、ADK の開発用 Web UI にアクセスできます。画面左上のプルダウンでエージェント sandbox_agent を選択します。 ADK の開発用 Web UI にアクセスし、sandbox_agent を選択する エージェントとの対話 エージェントに、コード実行が必要な質問を送信します。例として「1から100までの素数の合計を計算してください」と質問すると、エージェントは Python コードを生成して execute_python_code ツールを呼び出し、サンドボックス内での実行結果を元に回答します。 エージェントがコードを生成して実行している Web UI の Info ペインでは、ツール呼び出しの内容を確認できます。 Function Calls イベントにはエージェントが生成した Python コードが、 Function Responses イベントにはサンドボックスでの実行結果( stdout など)が記録されています。 Function Calls にエージェントが生成したコードが記録されている Function Responses にコードの実行結果が記録されている ログの確認 前述のとおり、サンドボックスのライフサイクルイベントは Cloud Logging に自動的に記録されます。サンドボックスの実行ログは、Cloud Run の標準ログ( stdout や requests )とは別の専用ログ run.googleapis.com//var/log/sandbox.log に出力されるため、ログエクスプローラで以下のクエリを実行して確認します。 resource.type="cloud_run_revision" resource.labels.service_name="sandbox-agent" logName="projects/<プロジェクトID>/logs/run.googleapis.com%2F%2Fvar%2Flog%2Fsandbox.log" sandbox do の実行1回につき [start] と [end] のペアが記録され、実行したコマンドの全文(LLM が生成した Python コードを含む)が残ります。以下は先ほどの対話で実際に記録されたログです( [end] のコマンド文字列は省略しています)。 [start] cwd=/app "/usr/local/gcp/bin/sandbox do -- /usr/local/bin/python3 -c def is_prime(n): if n < 2: return False for i in range(2, int(n**0.5) + 1): if n % i == 0: return False return True total_sum = 0 for number in range(2, 101): if is_prime(number): total_sum += number print(total_sum) " [end] exit_code=0 elapsed=541ms "/usr/local/gcp/bin/sandbox do -- /usr/local/bin/python3 -c ..." Cloud Run でサンドボックスが使用されたときのログを検索する [end] エントリには終了コード( exit_code )と実行時間( elapsed )が付くため、サンドボックスが実際に使用されたこと、どのようなコードが実行されたか、正常に終了したかどうかまで確認できます。今回の実行時間は約540ミリ秒で、サンドボックスの作成からコード実行、破棄までが高速に完了していることもわかります。 参考 : Code execution in Cloud Run 佐々木 駿太 (記事一覧) クラウドソリューション部 クラウドエンジニアリング1課 北海道在住 大学院まで社会心理学を専攻し、AI に興味を持ち IT 業界へ。2022年6月に G-gen にジョイン。Google Cloud Partner Top Engineer に選出(2024 / 2025 Fellow / 2026)。好きな Google Cloud プロダクトは Cloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。最近は法律の勉強にも目覚め、2級知的財産管理技能士を取得。 Follow @sasashun0805



















