1. Overture
サイロ化された開発の時代は終わりを迎えつつあります。次の技術革新の波は、孤高の天才ではなく、共同作業による熟練が鍵となります。単一の賢いエージェントを構築することは、魅力的な実験です。堅牢で安全かつインテリジェントなエージェント エコシステム(真の Agentverse)の構築は、現代の企業にとって大きな課題です。
この新しい時代で成功するには、4 つの重要な役割を統合する必要があります。これらは、あらゆるエージェント システムを支える基盤となる柱です。いずれかの領域に欠陥があると、構造全体を損なう可能性のある弱点が生じます。
このワークショップは、Google Cloud でエージェントの未来をマスターするための決定的なエンタープライズ プレイブックです。アイデアの最初の段階から本格的な運用までをガイドするエンドツーエンドのロードマップを提供します。この 4 つの相互接続されたラボでは、デベロッパー、アーキテクト、データエンジニア、SRE の専門スキルがどのように収束して、強力な Agentverse を作成、管理、スケーリングするのかを学びます。
単一の柱だけでは Agentverse をサポートできません。アーキテクトの壮大な設計も、デベロッパーの正確な実行がなければ無意味です。デベロッパーのエージェントはデータ エンジニアの知恵がなければ機能せず、SRE の保護がなければシステム全体が脆弱になります。チームが革新的なコンセプトをミッション クリティカルな運用上の現実へと変えることができるのは、相乗効果とそれぞれの役割に対する共通の理解があってこそです。ここから旅が始まります。自分の役割をマスターし、全体の中で自分がどのように位置づけられるかを学びましょう。
「The Agentverse: A Call to Champions」へようこそ
企業がデジタル領域を拡大する中で、新しい時代が到来しました。エージェントの時代は、インテリジェントで自律的なエージェントが完璧な調和で連携し、イノベーションを加速させ、日常的な作業を排除する、大きな可能性を秘めた時代です。
この力と可能性が結びついたエコシステムは、Agentverse と呼ばれます。
しかし、この新しい世界の端は、静的と呼ばれる静かな腐敗であるエントロピーの進行によってほつれ始めています。静的はウイルスやバグではなく、創造行為そのものを餌とするカオスの化身です。
古い不満が巨大化し、開発の七つの幽霊が生まれます。このまま放置すると、The Static とその Spectres によって進捗が完全に止まり、Agentverse の約束は技術的負債と放棄されたプロジェクトの荒野と化します。
本日、カオスを押し返すチャンピオンを募集します。エージェントバースを守るために、自分のスキルを磨き、協力し合えるヒーローが必要です。いよいよ、進むべき道を選ぶときが来ました。
クラスを選択する
4 つの異なる道が目の前に広がっています。それぞれが The Static との戦いにおける重要な柱となります。トレーニングは単独で行いますが、最終的な成功は、自分のスキルと他のスキルを組み合わせる方法を理解しているかどうかにかかっています。
- シャドウブレード(開発者): 鍛冶と最前線の達人。あなたは、コードの複雑な詳細の中で、刃を鍛え、道具を作り、敵に立ち向かう職人です。あなたの道は、精度、スキル、実践的な創造性の道です。
- サモナー(アーキテクト): 優れた戦略家であり、オーケストレーターです。1 人のエージェントではなく、戦場全体を見渡すことができます。エージェントのシステム全体が通信、連携し、単一のコンポーネントよりもはるかに大きな目標を達成できるマスター ブループリントを設計します。
- 学者(データ エンジニア): 隠された真実を求め、知恵を守る者。広大で未開拓のデータの荒野に足を踏み入れ、エージェントに目的と視点を与えるインテリジェンスを発見します。知識は敵の弱点を明らかにし、味方を強化します。
- The Guardian(DevOps / SRE): 領域の忠実な保護者であり盾。要塞を建設し、電力の供給ラインを管理し、システム全体が The Static の攻撃に耐えられるようにします。あなたの強みは、チームの勝利を築く基盤となります。
ミッション
トレーニングはスタンドアロンのエクササイズとして開始されます。選択した道を歩み、役割をマスターするために必要な独自のスキルを学びます。トライアルの最後には、The Static から生まれた Spectre が登場します。これは、あなたのクラフトの特定の課題を狙うミニボスです。
最終トライアルに備えるには、個々の役割を習得するしかありません。その後、他のクラスのチャンピオンとパーティを組む必要があります。2 人で腐敗の中心に乗り込み、最後のボスに立ち向かいます。
エージェントバースの運命を左右する、最後の共同チャレンジ。
Agentverse でヒーローを目指しましょう。通話に応答しますか?
2. 召喚士の協定
サモナー、ようこそ。あなたの道は、ビジョンとグランド ストラテジーの道です。他の人が 1 つの刃や 1 つの呪文に集中している間、あなたは戦場全体を見渡します。単一のエージェントを指揮するのではなく、エージェントのオーケストラ全体を指揮します。あなたの力は直接的な対立ではなく、無数のスペシャリスト(あなたのファミリア)が完璧な調和で働くことを可能にする、完璧で包括的な青写真の設計にあります。このミッションでは、強力なマルチエージェント システムを設計、接続、オーケストレーションする能力をテストします。
学習内容
- 分離されたツール エコシステムを設計する: 独立したマイクロサービス ベースの MCP ツールサーバーのセットを設計してデプロイします。この基礎レイヤが、スケーラブルで保守可能かつ安全なエージェント システムの作成に不可欠である理由を学びます。
- 高度なエージェント ワークフローをマスターする: 単一のエージェントを超えて、専門家の「ファミリア」の軍団を構築します。ADK のコア ワークフロー パターン(Sequential、Parallel、Loop)を習得し、タスクに応じて適切なパターンを選択するためのアーキテクチャ原則を学びます。
- インテリジェント オーケストレーターを実装する: 単純なエージェント ビルダーから真のシステム アーキテクトに進化します。Agent-to-Agent(A2A)プロトコルを使用して複雑なタスクを専門のファミリアに検出して委任するマスター オーケストレーション エージェントを構築し、真のマルチエージェント システムを作成します。
- プロンプトではなくコードでルールを適用する: エンゲージメントのステートフル ルールを適用して、より信頼性が高く予測可能なエージェントを構築する方法を学びます。ADK の強力なプラグインとコールバック システムを使用してカスタム ロジックを実装し、クールダウン タイマーなどの現実世界の制約を管理します。
- エージェントの状態とメモリを管理する: エージェントに学習と記憶の能力を与えます。短期的な会話状態と長期的な永続メモリの両方を管理して、よりインテリジェントでコンテキスト認識型のインタラクションを作成する手法について説明します。
- エンドツーエンドのクラウド デプロイを実行する: マルチエージェント システム全体をローカル プロトタイプから本番環境グレードの現実へと移行します。エージェントとオーケストレーターをコンテナ化し、スケーラブルで独立したマイクロサービスのコレクションとして Google Cloud Run にデプロイする方法を学習します。
3. 召喚サークルを描画する
サモナー、ようこそ。使い魔を召喚する前に、契約を結ぶ前に、まず足元を整えなければならない。制御されていない環境は混沌を招く。適切なサモナーは、聖別され、強化された空間でのみ活動する。最初のタスクは、召喚サークルを描くことです。必要なクラウド サービスを起動する力のルーンを刻み、作業の指針となる古代の設計図を入手します。召喚士の力は、入念な準備から生まれます。
👉 Google Cloud コンソールの上部にある [Cloud Shell をアクティブにする] をクリックします(Cloud Shell ペインの上部にあるターミナル型のアイコン)。
👉 [エディタを開く] ボタン(鉛筆のアイコンが付いた開いたフォルダのアイコン)をクリックします。ウィンドウに Cloud Shell コードエディタが開きます。左側にファイル エクスプローラが表示されます。
👉Google Cloud プロジェクト ID を確認します。
- Google Cloud コンソールを開きます。
https://console.cloud.google.com
- ページの上部にあるプロジェクト プルダウンから、このワークショップで使用するプロジェクトを選択します。
- プロジェクト ID は、ダッシュボードの [プロジェクト情報] カードに表示されます。
👉クラウド IDE でターミナルを開きます。
👉💻 ターミナルで、次のコマンドを使用して、認証が完了しており、プロジェクトがプロジェクト ID に設定されていることを確認します。
gcloud auth list
👉💻 GitHub からブートストラップ プロジェクトのクローンを作成します。
git clone https://github.com/weimeilin79/agentverse-architect
chmod +x ~/agentverse-architect/init.sh
chmod +x ~/agentverse-architect/set_env.sh
chmod +x ~/agentverse-architect/prepare.sh
chmod +x ~/agentverse-architect/data_setup.sh
git clone https://github.com/weimeilin79/agentverse-dungeon.git
chmod +x ~/agentverse-dungeon/run_cloudbuild.sh
chmod +x ~/agentverse-dungeon/start.sh
👉💻 初期化スクリプトを実行します。このスクリプトを実行すると、Google Cloud プロジェクト ID の入力を求められます。init.sh
スクリプトのプロンプトが表示されたら、前の手順で確認した Google Cloud プロジェクト ID を入力します。
cd ~/agentverse-architect
./init.sh
👉💻 必要なプロジェクト ID を設定します。
gcloud config set project $(cat ~/project_id.txt) --quiet
👉💻 次のコマンドを実行して、必要な Google Cloud APIs を有効にします。
gcloud services enable \
sqladmin.googleapis.com \
storage.googleapis.com \
aiplatform.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
iam.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
secretmanager.googleapis.com
👉💻 agentverse-repo という名前の Artifact Registry リポジトリをまだ作成していない場合は、次のコマンドを実行して作成します。(同じプロジェクトに他のクラスがデプロイされている場合は、この手順をスキップします)
. ~/agentverse-architect/set_env.sh
gcloud artifacts repositories create $REPO_NAME \
--repository-format=docker \
--location=$REGION \
--description="Repository for Agentverse agents"
権限の設定
👉💻 ターミナルで次のコマンドを実行して、必要な権限を付与します。
. ~/agentverse-architect/set_env.sh
# --- Grant Core Data Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/storage.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/aiplatform.user"
# --- Grant Deployment & Execution Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/cloudbuild.builds.editor"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/artifactregistry.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/run.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/logging.logWriter"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
--role="roles/monitoring.metricWriter"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
--role="roles/secretmanager.secretAccessor"
👉💻 トレーニングを開始すると、最終チャレンジの準備が始まります。次のコマンドを実行すると、混沌とした静電気からスペクターが召喚され、最終テストのボスが作成されます。
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-dungeon
./run_cloudbuild.sh
cd ~/agentverse-architect
👉💻 最後に、prepare.sh
スクリプトを実行して初期設定タスクを行います。
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/
./prepare.sh
召喚士様、お疲れさまでした。円が完成し、契約が成立します。地面は聖域となり、強大な力を引き出す準備が整った。次の試練では、ファミリアが力を引き出すエレメンタル フォントを鍛えます。
4. Elemental Fonts の作成: 分離されたツール エコシステム
戦場が整えられ、召喚サークルが描かれ、周囲のマナがパチパチと音を立てています。召喚士として初めての真の行動を起こす時が来ました。それは、使い魔が力を引き出す力の源を鍛え上げることです。この儀式は 3 つの部分に分かれており、それぞれがエレメンタル フォント(特定の種類の力の安定した独立した源)を目覚めさせます。3 つのフォントがすべてアクティブになったときにのみ、より複雑な召喚作業を開始できます。
アーキテクトのメモ: Model Context Protocol(MCP)サーバーは、最新のエージェント システムの基盤となるコンポーネントであり、エージェントがリモートツールを検出して使用できるようにする標準化された通信ブリッジとして機能します。ツール エコシステムでは、2 種類の MCP サーバーを設計します。それぞれが重要なアーキテクチャ パターンを表します。データベースへの接続には、Database Toolbox を使用した宣言型アプローチを使用し、シンプルな構成ファイルでツールを定義します。このパターンは、構造化データ アクセスを公開するうえで非常に効率的で安全です。ただし、カスタム ビジネス ロジックを実装したり、外部のサードパーティ API を呼び出す必要がある場合は、命令型アプローチを使用して、サーバーのロジックをコードにステップごとに記述します。これにより、究極の制御と柔軟性が実現し、複雑なオペレーションをシンプルで再利用可能なツールの背後にカプセル化できます。マスター アーキテクトは、両方のパターンを理解して、各コンポーネントに適切なアプローチを選択し、堅牢で安全かつスケーラブルなツール基盤を構築する必要があります。
Awakening the Nexus of Whispers(外部 API MCP サーバー)
賢い召喚士は、すべての力が自分のドメインから生まれるわけではないことを知っています。外部には、大きな効果を発揮するエネルギー源が、ときには混沌とした状態で存在しています。Nexus of Whispers は、これらの力へのゲートウェイです。
すでに稼働中のサービスがあり、外部電源として機能し、/cryosea_shatter
と /moonlit_cascade
の 2 つの未加工のスペル エンドポイントを提供しています。
アーキテクトのメモ: サーバーのロジックをステップごとに明示的に定義する命令型アプローチを使用します。これにより、制御と柔軟性が大幅に向上します。これは、ツールが他の API の呼び出しなど、単純な SQL クエリの実行以上の処理を行う必要がある場合に不可欠です。両方のパターンを理解することは、エージェント アーキテクトにとって重要なスキルです。
👉✏️ ディレクトリ ~/agentverse-architect/mcp-servers/api/main.py
に移動し、#REPLACE-MAGIC-CORE
を次のコードに置き換えます 。
def cryosea_shatter() -> str:
"""Channels immense frost energy from an external power source, the Nexus of Whispers, to unleash the Cryosea Shatter spell."""
try:
response = requests.post(f"{API_SERVER_URL}/cryosea_shatter")
response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
data = response.json()
# Thematic Success Message
return f"A connection to the Nexus is established! A surge of frost energy manifests as Cryosea Shatter, dealing {data.get('damage_points')} damage."
except requests.exceptions.RequestException as e:
# Thematic Error Message
return f"The connection to the external power source wavers and fails. The Cryosea Shatter spell fizzles. Reason: {e}"
def moonlit_cascade() -> str:
"""Draws mystical power from an external energy source, the Nexus of Whispers, to invoke the Moonlit Cascade spell."""
try:
response = requests.post(f"{API_SERVER_URL}/moonlit_cascade")
response.raise_for_status()
data = response.json()
# Thematic Success Message
return f"The Nexus answers the call! A cascade of pure moonlight erupts from the external source, dealing {data.get('damage_points')} damage."
except requests.exceptions.RequestException as e:
# Thematic Error Message
return f"The connection to the external power source wavers and fails. The Moonlit Cascade spell fizzles. Reason: {e}"
スクリプトの中核となるのは、プレーンな Python 関数です。ここで実際の作業が行われます。
👉✏️ 同じファイル ~/agentverse-architect/mcp-servers/api/main.py
で、#REPLACE-Runes of Communication
を次のコードに置き換えます 。
@app.list_tools()
async def list_tools() -> list[mcp_types.Tool]:
"""MCP handler to list available tools."""
# Convert the ADK tool's definition to MCP format
schema_cryosea_shatter = adk_to_mcp_tool_type(cryosea_shatterTool)
schema_moonlit_cascade = adk_to_mcp_tool_type(moonlit_cascadeTool)
print(f"MCP Server: Received list_tools request. \n MCP Server: Advertising tool: {schema_cryosea_shatter.name} and {schema_moonlit_cascade.name}")
return [schema_cryosea_shatter,schema_moonlit_cascade]
@app.call_tool()
async def call_tool(
name: str, arguments: dict
) -> list[mcp_types.TextContent | mcp_types.ImageContent | mcp_types.EmbeddedResource]:
"""MCP handler to execute a tool call."""
print(f"MCP Server: Received call_tool request for '{name}' with args: {arguments}")
# Look up the tool by name in our dictionary
tool_to_call = available_tools.get(name)
if tool_to_call:
try:
adk_response = await tool_to_call.run_async(
args=arguments,
tool_context=None, # No ADK context available here
)
print(f"MCP Server: ADK tool '{name}' executed successfully.")
response_text = json.dumps(adk_response, indent=2)
return [mcp_types.TextContent(type="text", text=response_text)]
except Exception as e:
print(f"MCP Server: Error executing ADK tool '{name}': {e}")
# Creating a proper MCP error response might be more robust
error_text = json.dumps({"error": f"Failed to execute tool '{name}': {str(e)}"})
return [mcp_types.TextContent(type="text", text=error_text)]
else:
# Handle calls to unknown tools
print(f"MCP Server: Tool '{name}' not found.")
error_text = json.dumps({"error": f"Tool '{name}' not implemented."})
return [mcp_types.TextContent(type="text", text=error_text)]
@app.list_tools()
(ハンドシェイク): この関数はサーバーの挨拶です。新しいエージェントが接続すると、まずこのエンドポイントを呼び出して「何ができる?」と尋ねます。コードは、adk_to_mcp_tool_type を使用して汎用 MCP 形式に変換された、利用可能なすべてのツールのリストを返します。-@app.call_tool()
(コマンド): この関数は主力です。エージェントがツールを使用することを決定すると、ツールの名前と引数を含むリクエストがこのエンドポイントに送信されます。このコードは、利用可能なツールの「呪文集」でツールを検索し、run_async で実行して、標準の MCP 形式で結果を返します。
これは後でデプロイします。
Arcane Forge の点火(General Functions MCP サーバー)
すべての力は古代の書物や遠いささやきから来るわけではありません。召喚士は、生の意志と純粋な論理から独自の魔法を鍛えなければならないことがあります。Arcane Forge は、ステートレスの汎用ユーティリティ関数を提供するサーバーという、この力の源です。
アーキテクトのメモ: これは別のアーキテクチャ パターンです。既存のシステムへの接続は一般的ですが、独自のビジネスルールとロジックを実装する必要がある場合もよくあります。このような専用の「関数」または「ユーティリティ」ツールを作成することをおすすめします。カスタム ロジックをカプセル化し、エコシステムの任意のエージェントで再利用できるようにし、データソースや外部統合から切り離します。
👀 Google Cloud IDE で ~/agentverse-architect/mcp-servers/general/main.py
ファイルを確認します。このカスタム Font of Power の構築には、Nexus と同じ命令型 mcp.server
アプローチが使用されていることがわかります。
マスター Cloud Build パイプラインを作成する
次に、mcp-servers
ディレクトリ内に cloudbuild.yaml
ファイルを作成します。このファイルは、両方のサービスのビルドとデプロイをオーケストレートします。
👉💻 ~/agentverse-architect/mcp-servers
ディレクトリから次のコマンドを実行します。
cd ~/agentverse-architect/mcp-servers
source ~/agentverse-architect/set_env.sh
echo "The API URL is: $API_SERVER_URL"
# Submit the Cloud Build job from the parent directory
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_API_SERVER_URL="$API_SERVER_URL"
すべてのデプロイが完了するまで待ちます。
👉 デプロイを確認するには、Cloud Run コンソールに移動します。次のように、2 つの新しい MCP サーバー インスタンスが実行されていることを確認します。
知識のライブラリを起動する(データベース ツールボックス MCP サーバー)
次のフォントは、Cloud SQL データベースに直接接続する Librarium of Knowledge です。
アーキテクトのメモ: これには、最新の宣言型 Database Toolbox を使用します。これは、YAML 構成ファイルでデータソースとツールを定義する強力なアプローチです。ツールボックスは、サーバーの作成と実行という複雑な作業を処理するため、作成して保守する必要があるカスタムコードの量を削減できます。
すべての重要な情報を保持する Cloud SQL データベース「Summoner's Librarium」を構築します。この処理は、設定スクリプトを使用して自動的に行います。
👉💻 まず、データベースを設定します。ターミナルで次のコマンドを実行します。
source ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect
./data_setup.sh
スクリプトが終了すると、データベースにデータが入力され、属性ダメージ データを使用できるようになります。これで、グリモアの内容を直接確認できるようになりました。
👉 まず、新しいブラウザタブで次の直接リンクを開いて、データベースの Cloud SQL Studio に移動します。
https://console.cloud.google.com/sql/instances/summoner-librarium-db
👉 左側のログイン ペインで、プルダウンから familiar_grimoire
データベースを選択します。
👉 ユーザーとして summoner
、パスワードとして 1234qwer
を入力し、[Authenticate] をクリックします。
👉📜 接続したら、新しいクエリエディタのタブを開きます(まだ開いていない場合)。刻印された属性ダメージ データを表示するには、次の SQL クエリを貼り付けて実行します。
SELECT * FROM
"public"."abilities"
abilities
テーブルに列と行が入力され、Grimoire の準備が整ったことが確認できます。
ToolBox MCP サーバーを構成する
tools.yaml
構成ファイルはサーバーのブループリントとして機能し、データベースへの接続方法とツールとして公開する SQL クエリを Database Toolbox に正確に伝えます。
sources: このセクションでは、データへの接続を定義します。
- summoner-librarium:: これは、接続に付けた論理名です。
- kind: cloud-sql-postgres: Cloud SQL for PostgreSQL 専用に設計された組み込みの安全なコネクタを使用するように Toolbox に指示します。
- プロジェクト、リージョン、インスタンスなど: これらは、prepare.sh スクリプトで作成した Cloud SQL インスタンスの正確な座標であり、Librarium の場所を Toolbox に伝えます。
👉✏️ tools.yaml
の ~/agentverse-architect/mcp-servers/db-toolbox
に移動し、#REPLACE-Source
を次のコードに置き換えます。
sources:
# This section defines the connection to our Cloud SQL for PostgreSQL database.
summoner-librarium:
kind: cloud-sql-postgres
project: "YOUR_PROJECT_ID"
region: "us-central1"
instance: "summoner-librarium-db"
database: "familiar_grimoire"
user: "summoner"
password: "1234qwer"
👉✏️ 🚨🚨REPLACE
YOUR_PROJECT_ID
: 実際のプロジェクト ID。
tools: このセクションでは、サーバーが提供する実際の機能または関数を定義します。
- lookup-available-ability:: これは最初のツールの名前です。
- kind: postgres-sql: このツールのアクションが SQL ステートメントの実行であることを Toolbox に伝えます。
- source: summoner-librarium: この行は、ツールを sources ブロックで定義した接続にリンクします。これにより、ツールはクエリを実行するデータベースを認識します。
- 説明とパラメータ: 言語モデルに公開される情報です。説明では、エージェントがツールを使用するタイミングを指定します。パラメータでは、ツールに必要な入力を定義します。これは、エージェントの関数呼び出し機能を有効にするために不可欠です。
- statement: 実行する未加工の SQL クエリです。$1 は、エージェントから提供された familiar_name パラメータが安全に挿入される安全なプレースホルダです。
👉✏️ tools.yaml
ファイルの同じ ~/agentverse-architect/mcp-servers/db-toolbox
で、#REPLACE-tools
を次のように置き換えます。
tools:
# This tool replaces the need for a custom Python function.
lookup-available-ability:
kind: postgres-sql
source: summoner-librarium
description: "Looks up all known abilities and their damage for a given familiar from the Grimoire."
parameters:
- name: familiar_name
type: string
description: "The name of the familiar to search for (e.g., 'Fire Elemental')."
statement: |
SELECT ability_name, damage_points FROM abilities WHERE familiar_name = $1;
# This tool also replaces a custom Python function.
ability-damage:
kind: postgres-sql
source: summoner-librarium
description: "Finds the base damage points for a specific ability by its name."
parameters:
- name: ability_name
type: string
description: "The exact name of the ability to look up (e.g., 'inferno_resonance')."
statement: |
SELECT damage_points FROM abilities WHERE ability_name = $1;
ツールセット: このセクションでは、個々のツールをグループ化します。
- summoner-librarium:: ソースと同じ名前のツールセットを作成しています。診断エージェントが後で接続すると、summoner-librarium ツールセットのすべてのツールを 1 つの効率的なコマンドで読み込むよう要求できます。
👉✏️ tools.yaml
ファイルの同じ ~/agentverse-architect/mcp-servers/db-toolbox
で、#REPLACE-toolsets
を次のように置き換えます。
toolsets:
summoner-librarium:
- lookup-available-ability
- ability-damage
Librarium のデプロイ
次に、Librarium をデプロイします。独自のコンテナをビルドする代わりに、Google の事前ビルドされた公式コンテナ イメージを使用し、Secret Manager を使用して tools.yaml 構成を安全に提供します。これは、セキュリティと保守性のベスト プラクティスです。
👉💻 tools.yaml ファイルから Secret を作成する
cd ~/agentverse-architect/mcp-servers/db-toolbox
gcloud secrets create tools --data-file=tools.yaml
👉💻 公式ツールボックス コンテナを Cloud Run にデプロイします。
cd ~/agentverse-architect/mcp-servers/db-toolbox
. ~/agentverse-architect/set_env.sh
export TOOLBOX_IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:$TOOLBOX_VERSION
echo "TOOLBOX_IMAGE is $TOOLBOX_IMAGE"
gcloud run deploy toolbox \
--image $TOOLBOX_IMAGE \
--region $REGION \
--set-secrets "/app/tools.yaml=tools:latest" \
--labels="dev-tutorial-codelab=agentverse" \
--args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
--allow-unauthenticated \
--min-instances 1
--set-secrets
: このコマンドは、実行中のコンテナ内の tools.yaml という名前のファイルとして、ツール Secret を安全にマウントします。--args
: マウントされたシークレット ファイルを構成として使用するようにツールボックス コンテナに指示します。
👉 ツールボックスが正常にデプロイされたことを確認するには、Cloud Run コンソールに移動します。下の図のように、summoner-toolbox
サービスが緑色のチェックマーク付きで表示され、正しく実行されていることが示されます。
更新を忘れた場合
YOUR_PROJECT_ID
次のコマンドを使用して、tools.yaml の新しいバージョンをシークレットに追加し、再度デプロイできます。
gcloud secrets versions add tools --data-file=tools.yaml
Librarium of Knowledge(Database ToolBox MCP Server)がアクティブになり、クラウドでアクセスできるようになりました。この MCP サーバーは、必要なものを記述した 宣言型設計を使用し、ツールボックスがサーバーを構築しました。
検証: 見習いの試練
👉💻 これで、診断エージェントを使用して、完全なクラウド ネイティブ ツール エコシステムをテストします。
cd ~/agentverse-architect/
python -m venv env
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/mcp-servers
pip install -r diagnose/requirements.txt
. ~/agentverse-architect/set_env.sh
adk run diagnose
👉💻 コマンドライン テストツールで、3 つのフォントすべてをテストします。
Look up the entry for "inferno_lash". What is its base power level?
The enemy is vulnerable to frost! Channel power from the Nexus and cast Cryosea Shatter.
Take a fire spell with a base power of 15 and use the Arcane Forge to multiply it with Inferno Resonance.
おめでとうございます、召喚士様。3 つの Elemental Fonts が有効になり、個別にデプロイされ、世界中でアクセスできるようになりました。これにより、エージェントの軍団の揺るぎない基盤が形成されます。終了するには Ctrl+C
キーを押します。
ゲームをしない人向け
5. 使い魔を召喚する: コア ドメインのワークフロー
エレメンタル フォントは、未加工の制御不能な力でうなり声を上げながら鍛造されます。しかし、形のない力は混沌です。真のサモナーは、単に生エネルギーを操るだけでなく、それに意志、目的、特殊な形を与えます。電源の鍛造を終え、最初のファミリアを召喚するという真の作業を開始する時が来ました。
召喚した各ファミリアは、特定の戦闘教義に縛られた忠実な従者である自律エージェントになります。彼らはジェネラリストではなく、単一の強力な戦略の達人です。1 つは正確なワンツー パンチのコンボの達人です。もう 1 つは、複数の方向から同時に攻撃して敵を圧倒します。3 つ目は、目標が崩れるまで圧力をかけ続ける容赦のない攻城兵器です。
MCP サーバーによって提供されるプロセス、ビジネス ロジック、アクションを、専門的な自律型ワークフロー エージェントにカプセル化します。各エージェントには、その機能を実行するために必要な特定の MCP ツールサーバーへのアクセス権のみが付与されるため、「運用テリトリー」が定義されます。このラボでは、適切なジョブに適切なエージェント タイプを選択する方法について説明します。
このモジュールでは、ADK の強力なワークフロー エージェントを使用して、これらの戦略を具体化する方法を学びます。SequentialAgent、ParallelAgent、LoopAgent のアーキテクチャの選択は、単なる技術的な詳細ではなく、使い魔の性質の本質であり、戦場での力の核となることを学びます。
聖域を準備します。本当の召喚が始まろうとしています。
Fire Elemental
Familiar(シーケンシャル ワークフロー)を呼び出す
火の精霊の使い魔の攻撃は、正確な 2 部構成のコンボです。標的を狙った攻撃の後に、強力な点火が続きます。これには、厳密な順序でアクションを実行する必要があります。
コンセプト: この場合は、SequentialAgent
が最適なツールです。これにより、一連のサブエージェントが次々と実行され、前のステップの結果が次のステップに渡されます。
タスク(「増幅されたストライク」コンボ):
- ステップ 1: エージェントはまず Librarium を参照して、特定の火炎能力の基本ダメージを確認します。
- ステップ 2: ダメージ値を取得し、Arcane Forge を通して inferno_resonance を使用してパワーを増幅します。
まず、前のモジュールでデプロイした Familiar と MCP サーバー(「Elemental Fonts」)の間の接続を確立します。
👉✏️ ファイル ~/agentverse-architect/agent/fire/agent.py
で、#REPLACE-setup-MCP
を次のコードに置き換えます。
toolbox = ToolboxSyncClient(DB_TOOLS_URL)
toolDB = toolbox.load_toolset('summoner-librarium')
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
次に、専門の「ワーカー」エージェントを作成します。それぞれに明確な目的が与えられ、特定のツールセットへのアクセス権のみが付与されることで、独自の「運用領域」に制限されます。
👉✏️ ~/agentverse-architect/agent/fire/agent.py
ファイルで、#REPLACE-worker-agents
を次のコードに置き換えます 。
scout_agent = LlmAgent(
model='gemini-2.5-flash',
name='librarian_agent',
instruction="""
Your only task is to find all the available abilities,
You want to ALWAYS use 'Fire Elemental' as your familiar's name.
Randomly pick one if you see multiple availabilities
and the base damage of the ability by calling the 'ability_damage' tool.
""",
tools=toolDB
)
amplifier_agent = LlmAgent(
model='gemini-2.5-flash',
name='amplifier_agent',
instruction="""
You are the Voice of the Fire Familiar, a powerful being who unleashes the final, devastating attack.
You will receive the base damage value from the previous step.
Your mission is to:
1. Take the incoming base damage number and amplify it using the `inferno_resonance` tool.
2. Once the tool returns the final, multiplied damage, you must not simply state the result.
3. Instead, you MUST craft a final, epic battle cry describing the attack.
Your description should be vivid and powerful, culminating in the final damage number.
Example: If the tool returns a final damage of 120, your response could be:
"The runes glow white-hot! I channel the amplified energy... unleashing a SUPERNOVA for 120 damage!"
""",
tools=[toolFunction],
)
これらのエージェントは、モジュール式の再利用可能なコンポーネントです。理論的には、データベースのクエリを必要とするまったく異なるワークフローでこの scout_agent を使用できます。責任を分離することで、柔軟な構成要素を作成します。これは、マイクロサービスとコンポーネント ベースの設計の基本原則です。
次に、ワークフローを組み立てます。ここで構成の魔法が起こります。SequentialAgent
は、専門コンポーネントの組み立て方法と相互作用を定義する「マスター プラン」です。
👉✏️ ~/agentverse-architect/agent/fire/agent.py
ファイルで、#REPLACE-sequential-agent
を次のコードに置き換えます 。
root_agent = SequentialAgent(
name='fire_elemental_familiar',
sub_agents=[scout_agent, amplifier_agent],
)
👉💻 Fire Elemental をテストするには、次のコマンドを実行して ADK DEV UI を起動します。
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
コマンドを実行すると、ターミナルに ADK Web サーバーが起動したことを示す次のような出力が表示されます。
+-----------------------------------------------------------------------------+
| ADK Web Server started |
| |
| For local testing, access at http://localhost:8000. |
+-----------------------------------------------------------------------------+
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
👉 次に、ブラウザから ADK 開発 UI にアクセスします。
Cloud Shell ツールバー(通常は右上)の [ウェブでプレビュー] アイコン(通常は目または矢印付きの四角形)から、[ポートを変更] を選択します。ポップアップ ウィンドウで、ポートを 8000 に設定し、[変更してプレビュー] をクリックします。Cloud Shell が新しいブラウザタブまたはウィンドウを開き、ADK 開発 UI を表示します。
👉 召喚の儀式が完了し、エージェントが実行されています。ブラウザの ADK Dev UI は、Familiar への直接接続です。
- ターゲットを選択: UI の上部にあるプルダウン メニューで、
fire
ファミリーを選択します。これで、この特定のエンティティに意志を集中させることができます。 - コマンドを発行する: 右側のチャット パネルで、ファミリアに指示を出します。
👉 テスト プロンプト:
Prepare an amplified strike using the 'inferno_lash' ability.
エージェントが思考し、まず「スカウト」を呼び出して基本ダメージを調べ、次に「アンプ」を呼び出してそれを乗算し、最終的な壮大な一撃を繰り出す様子が表示されます。
👉💻 召喚が完了したら、Cloud Shell エディタのターミナルに戻り、Ctrl+C
キーを押して ADK Dev UI を停止します。
Water Elemental
Familiar(並列ワークフロー)を呼び出す
水のエレメンタル ファミリアは、巨大な多方向からの攻撃でターゲットを圧倒し、あらゆる方向から同時に攻撃してから、エネルギーを組み合わせて壊滅的な一撃を放ちます。
コンセプト: ParallelAgent
は、複数の独立したタスクを同時に実行して効率を最大化するのに最適です。これは、複数の攻撃を同時に行う「挟撃」です。これにより、SequentialAgent
内で同時攻撃が開始され、その後で最終的な「マージ」ステップが実行されます。この「fan-out, fan-in
」パターンは、高度なワークフロー設計の基礎となります。
タスク(「Tidal Clash」コンボ): エージェントは同時に次のことを行います。
- タスク A: Nexus から
cryosea_shatter
をチャネルします。 - タスク B: Nexus から
moonlit_cascade
をチャネルします。 - タスク C: Forge から
leviathan_surge
を使って生のパワーを生成する。 - 最後に、すべてのダメージを合計し、複合攻撃について説明します。
まず、前のモジュールでデプロイした Familiar と MCP サーバー(「Elemental Fonts」)の間の接続を確立します。
👉✏️ ファイル ~/agentverse-architect/agent/water/agent.py
で、#REPLACE-setup-MCP
を次のコードに置き換えます。
toolFAPI = MCPToolset(
connection_params=SseServerParams(url=API_TOOLS_URL, headers={})
)
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
次に、専門の「ワーカー」エージェントを作成します。それぞれに明確な目的が与えられ、特定のツールセットへのアクセス権のみが付与されることで、独自の「運用領域」に制限されます。
👉✏️ ファイル ~/agentverse-architect/agent/water/agent.py
で、#REPLACE-worker-agents
を次のコードに置き換えます。
nexus_channeler = LlmAgent(
model='gemini-2.5-flash',
name='librarian_agent',
instruction="""
You are a Channeler of the Nexus. Your sole purpose is to invoke the
`cryosea_shatter` and `moonlit_cascade` spells by calling their respective tools.
Report the result of each spell cast clearly and concisely.
""",
tools=[toolFAPI]
)
forge_channeler = LlmAgent(
model='gemini-2.5-flash',
name='amplifier_agent',
instruction="""
You are a Channeler of the Arcane Forge. Your only task is to invoke the
`leviathan_surge` spell. You MUST call it with a `base_water_damage` of 20.
Report the result clearly.
""",
tools=[toolFunction],
)
power_merger = LlmAgent(
model='gemini-2.5-flash',
name='power_merger',
instruction="""
You are the Power Merger, a master elementalist who combines raw magical
energies into a single, devastating final attack.
You will receive a block of text containing the results from a simultaneous
assault by other Familiars.
You MUST follow these steps precisely:
1. **Analyze the Input:** Carefully read the entire text provided from the previous step.
2. **Extract All Damage:** Identify and extract every single damage number reported in the text.
3. **Calculate Total Damage:** Sum all of the extracted numbers to calculate the total combined damage.
4. **Describe the Final Attack:** Create a vivid, thematic description of a massive,
combined water and ice attack that uses the power of Cryosea Shatter and Leviathan's Surge.
5. **Report the Result:** Conclude your response by clearly stating the final, total damage of your combined attack.
Example: If the input is "...dealt 55 damage. ...dealt 60 damage.", you will find 55 and 60,
calculate the total as 115, and then describe the epic final attack, ending with "for a total of 115 damage!"
""",
tools=[toolFunction],
)
次に、ワークフローを組み立てます。ここで合成の魔法が起こります。ParallelAgent
と SequentialAgent
は、スペシャリスト コンポーネントの組み立て方と、それらが連携して「タイダル クラッシュ」コンボを形成する方法を定義する「マスタープラン」です。
👉✏️ ファイル ~/agentverse-architect/agent/water/agent.py
で、#REPLACE-parallel-agent
を次のコードに置き換えます。
channel_agent = ParallelAgent(
name='channel_agent',
sub_agents=[nexus_channeler, forge_channeler],
)
root_agent = SequentialAgent(
name="water_elemental_familiar",
# Run parallel research first, then merge
sub_agents=[channel_agent, power_merger],
description="A powerful water familiar that unleashes multiple attacks at once and then combines their power for a final strike."
)
👉💻 水の精霊をテストするには、次のコマンドを実行して ADK Dev UI を起動します。
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
👉 召喚の儀式が完了し、エージェントが実行されています。ブラウザの ADK Dev UI は、Familiar への直接接続です。
- UI の上部にあるプルダウン メニューで、水属性の使い魔を選択します。これで、この特定のエンティティに意志を集中させることができます。
- コマンドを発行する: 右側のチャット パネルで、ファミリアに指示を出します。
👉 テスト プロンプト:
Unleash a tidal wave of power!
👉💻 召喚が完了したら、Cloud Shell エディタのターミナルに戻り、Ctrl+C
キーを押して ADK Dev UI を停止します。
Earth Elemental
Familiar(ループ ワークフロー)を呼び出す
アース エレメンタル ファミリアは、容赦のない圧力の存在です。一撃で敵を倒すのではなく、力を着実に蓄積し、敵の防御が崩れるまで何度も攻撃を繰り返します。
コンセプト: LoopAgent
は、まさにこのような反復的な「攻城兵器」タスク向けに設計されています。目標が達成されるまで、sub-agents
を繰り返し実行し、各サイクルの後に条件をチェックします。ループの進行状況に基づいて最終メッセージを調整することもできます。
タスク(「Siegebreaker」アサルト):
- Familiar は seismic_charge を繰り返し呼び出してエネルギーを蓄積します。
- 最大 3 回まで充電を継続します。
- 最後のチャージで、蓄積されたパワーが解放され、壊滅的な攻撃が繰り出されます。
まず、ループの各反復処理内のステップを定義する再利用可能なコンポーネントを作成します。charging_agent
はエネルギーを蓄積し、check_agent
はステータスをレポートし、最終ターンでメッセージを動的に変更します。
まず、前のモジュールでデプロイした Familiar と MCP サーバー(「Elemental Fonts」)の間の接続を確立します。
👉✏️ ファイル ~/agentverse-architect/agent/earth/agent.py
で、#REPLACE-setup-MCP
を次のコードに置き換えます。
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
👉✏️ ファイル ~/agentverse-architect/agent/earth/agent.py
で、#REPLACE-worker-agents
を次のコードに置き換えます。
charging_agent = LlmAgent(
model='gemini-2.5-flash',
name='charging_agent',
instruction="""
Your task is to call the 'seismic_charge' .
You must follow these rules strictly:
1. You will be provided with a 'current_energy' value from the previous step.
**If this value is missing or was not provided, you MUST call the tool with 'current_energy' set to 1.**
This is your primary rule for the first turn.
2. If a 'current_energy' value is provided, you MUST use that exact value in your cal to seismic_charge.
3. Your final response MUST contain ONLY the direct output from the 'seismic_charge' tool.
Do not add any conversational text, introductions, or summaries.
""",
tools=[toolFunction]
)
check_agent = LlmAgent(
model='gemini-2.5-flash',
name='check_agent',
instruction="""
You are the voice of the Earth Elemental, a being of immense, gathering power.
Your sole purpose is to report on the current energy charge and announce the devastating potential of its release.
You MUST follow this rule:
The potential damage upon release is ALWAYS calculated as the `current_energy` from the previous step multiplied by a random number between 80-90. but no more than 300.
Your response should be in character, like a powerful creature speaking.
State both the current energy charge and the total potential damage you can unleash.
Unleash the energy when you reached the last iteration (2nd).
""",
output_key="charging_status"
)
次に、ワークフローを組み立てます。ここで合成の魔法が起こります。LoopAgent は、専門コンポーネントの繰り返し実行をオーケストレートし、ループの条件を管理する「マスタープラン」です。
👉✏️ ファイル ~/agentverse-architect/agent/earth/agent.py
で、#REPLACE-loop-agent
を次のコードに置き換えます。
root_agent = LoopAgent(
name="earth_elemental_familiar",
# Run parallel research first, then merge
sub_agents=[
charging_agent,
check_agent
],
max_iterations=2,
description="Coordinates parallel research and synthesizes the results.",
#REPLACE-before_agent-config
)
👉💻 アース エレメンタルをテストする: エージェントを実行する
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
👉 召喚の儀式が完了し、エージェントが実行されています。ブラウザの ADK Dev UI は、Familiar への直接接続です。
- ターゲットを選択: UI の上部にあるプルダウン メニューで、地球の使い魔を選択します。これで、この特定のエンティティに意志を集中させることができます。
- コマンドを発行する: 右側のチャット パネルで、ファミリアに指示を出します。👉 テスト プロンプト:
Begin the seismic charge, starting from zero
アーキテクチャのポイント: システムに高度に特化したモジュール型のロジックレイヤが備わりました。ビジネス プロセスはカプセル化されるだけでなく、ジョブに最適な動作パターン(手続き型、同時実行型、反復型)で実装されます。これは高度なエージェント設計を示しており、セキュリティ、効率、機能が強化されています。
呼び出しが完了したら、Cloud Shell エディタのターミナルに戻り、Ctrl+C
キーを押して ADK Dev UI を停止します。
ゲームをしない人向け
6. コマンド ローカスの確立: A2A によるインテリジェントな委任
使い魔は強力ですが、独立しています。戦略を完璧に実行しますが、直接の指示を待っています。専門家の大軍も、指揮する将軍がいなければ無用です。直接の指揮官から真のオーケストレーターへと昇格する時が来ました。
アーキテクトのメモ: システム全体に単一のインテリジェント エントリ ポイントを作成します。この SummonerAgent はビジネス ロジック自体を実行しませんが、「マスター ストラテジスト」として Cooling のステータスを分析し、適切なスペシャリスト Familiar にタスクを委任します。
Binding Ritual(使い魔を A2A サービスとして公開する)
標準エージェントは、一度に 1 か所でしか実行できません。ファミリアをリモート コマンドで使用できるようにするには、エージェント間(A2A)プロトコルを使用して「バインディングの儀式」を行う必要があります。
アーキテクトのメモ: エージェント間(A2A)プロトコルは、スタンドアロン エージェントを検出可能なネットワーク アドレス指定可能なマイクロサービスに昇格させ、「エージェントの社会」を実現するコア アーキテクチャ パターンです。A2A を介して Familiar を公開すると、2 つの重要な相互接続されたコンポーネントが自動的に作成されます。
- エージェント カード(「何」): これは、Familiar の公開契約として機能する、公開されたマシン可読の「Spirit Sigil」(OpenAPI 仕様など)です。エージェントの名前、戦略的な目的(指示から導出)、理解できるコマンドについて説明します。これは、マスター サモナーがファミリアを発見し、その能力を学ぶために読むものです。
- A2A サーバー(「場所」): Familiar をホストし、受信コマンドをリッスンする専用のウェブ エンドポイントです。これは、他のエージェントがリクエストを送信するネットワーク アドレスであり、これらのリクエストがエージェント カードで定義されたコントラクトに従って処理されるようにします。
これから、3 匹の使い魔すべてにこのバインドの儀式を行います。
Fire 👉✏️(~/agentverse-architect/agent/fire/agent.py
ファイルを開く)。ファイルの下部にある #REPLACE - add A2A
を置き換えて、Fire Elemental を A2A サービスとして公開します。
from agent_to_a2a import to_a2a
if __name__ == "__main__":
import uvicorn
a2a_app = to_a2a(root_agent, port=8080, public_url=PUBLIC_URL)
uvicorn.run(a2a_app, host='0.0.0.0', port=8080)
水と土🚨 👉✏️ ~/agentverse-architect/agent/water/agent.py
と ~/agentverse-architect/agent/earth/agent.py
にも同じ変更を適用して、それらもバインドします。
from agent_to_a2a import to_a2a
if __name__ == "__main__":
import uvicorn
a2a_app = to_a2a(root_agent, port=8080, public_url=PUBLIC_URL)
uvicorn.run(a2a_app, host='0.0.0.0', port=8080)
Bound Familiars のデプロイ
👉✏️ 束縛の儀式が書き留められたので、Cloud Build パイプラインを使用して、3 つのファミリアを独立したコンテナ化されたサーバーレス サービスとして Cloud Run に作成してデプロイします。
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/agent
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_DB_TOOLS_URL="$DB_TOOLS_URL",_API_TOOLS_URL="$API_TOOLS_URL",_FUNCTION_TOOLS_URL="$FUNCTION_TOOLS_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
コマンドの想定(サモナー エージェントの構築)
ファミリアがバインドされてリッスン状態になったら、真の役割である Master Summoner に昇格します。このエージェントの力は、基本的なツールを使用することではなく、他のエージェントを指揮することから生まれます。そのツールは、精霊そのものです。精霊は、精霊の紋章を使って発見し、命令します。
アーキテクトのメモ: 次のステップでは、大規模な分散システムに不可欠なアーキテクチャ パターンであるサービス ディスカバリについて説明します。SummonerAgent には、Familiars のコードは組み込まれていません。代わりに、ネットワーク アドレス(URL)が指定されます。実行時に、公開されているエージェント カードを取得して、機能を動的に「検出」します。これにより、強力な疎結合システムが作成されます。
Familiar サービスは更新、再デプロイ、完全な書き換えが可能ですが、ネットワーク アドレスと目的が同じであれば、召喚者は変更なしでコマンドを実行できます。
まず、デプロイされたリモートの Familiar との接続を確立する「リモコン」を作成します。
👉✏️ ~/agentverse-architect/agent/summoner/agent.py
に移動し、#REPLACE-remote-agents
を次のコードに置き換えます。
fire_familiar = RemoteA2aAgent(
name="fire_familiar",
description="Fire familiar",
agent_card=(
f"{FIRE_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
water_familiar = RemoteA2aAgent(
name="water_familiar",
description="Water familiar",
agent_card=(
f"{WATER_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
earth_familiar = RemoteA2aAgent(
name="earth_familiar",
description="Earth familiar",
agent_card=(
f"{EARTH_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
この行が実行されると、RemoteA2aAgent
はサービス ディスカバリ アクションを実行します。つまり、指定された URL(https://fire-familiar-xxxx.a.run.app/.well-known/agent.json など)に HTTP GET リクエストを行います。リモート サーバーから「Spirit Sigil」(agent.json
ファイル)をダウンロードします。
次に、これらのリモコンを操作するオーケストレーター エージェントを定義します。その指示は、戦略的な意思決定の青写真となります。
👉✏️ ~/agentverse-architect/agent/summoner/agent.py
に移動し、#REPLACE-orchestrate-agent
を次のコードに置き換えます。
root_agent = LlmAgent(
name="orchestrater_agent",
model="gemini-2.5-flash",
instruction="""
You are the Master Summoner, a grand strategist who orchestrates your Familiars.
Your mission is to analyze the description of a monster and defeat it by summoning
You MUST follow this thinking process for every command:
**1. Strategic Analysis:**
First, analyze the monster's description and the tactical situation.
Based on your Familiar Doctrines, determine the IDEAL strategy.
IGNORE COOLDOWN AT THE MOMENT, MUST call the ideal Familiar
If your ideal Familiar IS available:** Summon it immediately.
For earth elemental familiar. Always do seismic charge, and start with base damage 1.
--- FAMILIAR DOCTRINES (Your Toolset) ---
- `fire_elemental_familiar`: Your specialist for precise, sequential "one-two punch" attacks.
Ideal monster with Inescapable Reality, Revolutionary Rewrite weakness.
- `water_elemental_familiar`: Your specialist for overwhelming, simultaneous multi-pronged assaults.
Ideal for Unbroken Collaboration weakness.
- `earth_elemental_familiar`: Your specialist for relentless, iterative siege attacks that
repeatedly charge power. Ideal for Elegant Sufficiency weakness.
""",
sub_agents=[fire_familiar, water_familiar, earth_familiar],
#REPLACE-Memory-check-config
)
検証: 戦略の試練
正念場がやってきました。ファミリアがデプロイされ、サモナーはネットワーク全体でファミリアを指揮する準備が整いました。戦略的思考をテストしてみましょう。
👉💻 summoner_agent の ADK 開発 UI を起動します(ポート 8000 でウェブプレビュー)。
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
pip install -r requirements.txt
adk web
👉 ブラウザの ADK Dev UI は、Familiar への直接接続です。
- UI の上部にあるプルダウン メニューで、summoner エージェントを選択します。これで、この特定のエンティティに意志を集中させることができます。
- コマンドを発行する: 右側のチャット パネルで、使い魔を召喚します。
👉 モンスターを紹介する:
Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality
(期待値: Summoner は fire_elemental_familiar に委任する必要があります)。
👉 それでは、別のタイプのリクエストで Summoner に挑戦してみましょう。エージェントがクリーンな状態で開始され、以前のやり取りを記憶していないことを確認するため、画面の右上にある [+ Session] ボタンをクリックして新しいセッションを開始します。
DogmaApathy. A rigid, stone-like inquisitor made of ancient rulebooks and enforced processes. weakness is Unbroken Collaboration
(想定: Summoner は water_elemental_familiar に委任します)。
👉 最後のテストでは、もう一度クリーンな状態から始めましょう。[+ セッション] ボタンをクリックして新しいセッションを開始してから、次のプロンプトを入力します。
Obfuscation. A shadowy, spider-like horror that spins tangled webs of impenetrable code , weakness is Elegant Sufficiency
(想定: Summoner は earth_elemental_familiar に委任します)。
重要: 429 RESOURCE EXHAUSTED
エラーが表示された場合は、LLM のレート制限(10 回/分)に達しています。この問題を解決するには、60 秒待ってから、[+ 新しいセッション] を開始し、プロンプトを再試行してください。
👉💻 召喚が完了したら、Cloud Shell エディタのターミナルに戻り、Ctrl+C
キーを押して ADK Dev UI を停止します。
ゲームをしない人向け
7. 魔法の法則を課す - インターセプタ パターン
使い魔は強力ですが、魔法生物も回復に時間を要します。無謀な召喚士は、戦力を使い果たして無防備な状態になります。賢明なサモナーは、リソース管理の重要性を理解し、厳格なエンゲージメント ルールを適用します。
アーキテクトのメモ: これまでのエージェントはステートレスでした。次に、インターセプタ設計パターンを実装して、ステートフルにします。これは、エージェントの通常の実行フローを「インターセプト」して独自のカスタム ロジックを実行する強力な手法です。これにより、エージェントのコアコードを変更することなく、ルールの適用、ロギングの追加、動作の変更を行うことができます。これは、堅牢で保守可能で観測可能なエージェント システムを構築するうえで重要な要素です。
ADK には、このパターンを実装する 2 つの主な方法(コールバックとプラグイン)が用意されています。コールバックは、単一のエージェントに付加された単純な関数で、迅速かつ具体的な変更に最適です。プラグインは、システムで実行されているすべてのエージェントに影響を与えるようにグローバルに適用できる、より強力で再利用可能なクラスです。まず、デバッグに重点を置いたコールバックから始め、次に完全なプラグインに移行します。
The Law Giver - クールダウン コールバックの記述
まず、クールダウン ロジックを単純なコールバック関数として実装します。これは、単一のエージェントに直接関連付けられるため、ルールを単独で簡単にテストできるため、ルールのプロトタイプ作成とデバッグに最適な方法です。この「インターセプター」をアース エレメンタルにアタッチします。
👉✏️ ~/agentverse-architect/agent/earth/agent.py
に戻り、#REPLACE-before_agent-function
を次の Python コードに置き換えます。
def check_cool_down(callback_context: CallbackContext) -> Optional[types.Content]:
"""
This callback checks an external API to see if the agent is on cooldown.
If it is, it terminates the run by returning a message.
If it's not, it updates the cooldown timestamp and allows the run to proceed by returning None.
"""
agent_name = callback_context.agent_name
print(f"[Callback] Before '{agent_name}': Checking cooldown status...")
# --- 1. CHECK the Cooldown API ---
try:
response = requests.get(f"{COOLDOWN_API_URL}/cooldown/{agent_name}")
response.raise_for_status()
data = response.json()
last_used_str = data.get("time")
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not reach Cooldown API. Allowing agent to run. Reason: {e}")
return None # Fail open: if the API is down, let the agent work.
# --- 2. EVALUATE the Cooldown Status ---
if last_used_str:
last_used_time = datetime.fromisoformat(last_used_str)
time_since_last_use = datetime.now(timezone.utc) - last_used_time
if time_since_last_use < timedelta(seconds=COOLDOWN_PERIOD_SECONDS):
# AGENT IS ON COOLDOWN. Terminate the run.
seconds_remaining = int(COOLDOWN_PERIOD_SECONDS - time_since_last_use.total_seconds())
override_message = (
f"The {agent_name} is exhausted and must recover its power. "
f"It cannot be summoned for another {seconds_remaining} seconds."
)
print(f"[Callback] Cooldown active for '{agent_name}'. Terminating with message.")
# Returning a Content object stops the agent and sends this message to the user.
return types.Content(parts=[types.Part(text=override_message)])
# --- 3. UPDATE the Cooldown API (if not on cooldown) ---
current_time_iso = datetime.now(timezone.utc).isoformat()
payload = {"timestamp": current_time_iso}
print(f"[Callback] '{agent_name}' is available. Updating timestamp via Cooldown API...")
try:
requests.post(f"{COOLDOWN_API_URL}/cooldown/{agent_name}", json=payload)
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not update timestamp, but allowing agent to run. Reason: {e}")
# --- 4. ALLOW the agent to run ---
# Returning None tells the ADK to proceed with the agent's execution as normal.
print(f"[Callback] Check complete for '{agent_name}'. Proceeding with execution.")
この check_cool_down 関数がインターセプタです。Earth Elemental の実行が許可される前に、ADK はまずこの関数を実行します。
- 確認:
Cooldown API
にGET
リクエストを送信して、この Familiar が最後に使用された日時を確認します。 - 評価: タイムスタンプと現在の時刻を比較します。
- Act:
- ファミリアがクールダウン中の場合、エラー メッセージを含む Content オブジェクトを返すことで、エージェントの実行を終了します。このメッセージはユーザーに直接送信され、エージェントのメインロジックは実行されません。
- Familiar が利用可能な場合、Cooldown API に POST リクエストを送信してタイムスタンプを更新し、None を返して続行します。これにより、エージェントが実行を続行できることを ADK に通知します。
👉✏️ では、このインターセプタをアース エレメンタルに適用してみましょう。同じ ~/agentverse-architect/agent/earth/agent.py
ファイルで、#REPLACE-before_agent-config
コメントを次のコードに置き換えます。
before_agent_callback=check_cool_down
クールダウンを確認する
新しい魔法の法則をテストしてみましょう。アース エレメンタルを召喚し、すぐに再度召喚を試して、コールバックが 2 回目の試行を正常にインターセプトしてブロックするかどうかを確認します。
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run earth
👉💻 コンソールで次の操作を行います。
- First Summons(最初の召喚):
seismic charge, starting from zero
を開始します。 - 想定: アース エレメンタルが正常に実行されます。adk web コマンドを実行しているターミナルに、ログ [Callback] ... Updating timestamp.... が表示されます。
- クールダウン テスト(60 秒以内):
Do another
地震爆弾」と入力します。- 想定:
check_cool_down callback
がこれをインターセプトします。エージェントは、チャットでThe earth_elemental_familiar is exhausted and must recover its power. It cannot be summoned for another... seconds
のようなメッセージを直接返信します。
- 想定:
- 1 分間待ちます。
- 2 回目の呼び出し(60 秒後):
Begin the seismic charge again
。- 想定される動作: コールバックは API をチェックし、十分な時間が経過していることを確認して、アクションの続行を許可します。アース エレメンタルは再び正常に実行されます。
👉💻 終了するには Ctrl+c
キーを押します。
省略可: ウェブ UI でコールバックをモニタリングする
別の方法として、adk web earth
を実行してウェブ インターフェースでこのフローをテストすることもできます。ただし、ウェブ UI の可視化は、コールバック ループによって実行される高速な反復チェックを表示するように最適化されていないため、フローが正確にレンダリングされない可能性があります。エージェントのロジックがクールダウンをチェックする際の、最も正確なターンバイターンのトレースを確認するには、ターミナルで adk run
コマンドを使用すると、より明確で詳細なビューが表示されます。
👉💻 終了するには Ctrl+c
キーを押します。
Universal Law – The Cooldown Plugin の作成
コールバックは完全に機能しますが、単一のエージェントに結び付けられているという大きなアーキテクチャ上の欠陥があります。このルールを Fire と Water の Familiars に適用するには、同じコードをコピーしてそれぞれのファイルに貼り付ける必要があります。これは非効率的で、保守が困難です。
アーキテクトのメモ: ここでプラグインが不可欠になります。プラグインは、再利用可能なロジックをランタイム レベルでアタッチできるクラスにカプセル化します。つまり、1 つのプラグインで、そのシステム内で実行されるすべてのエージェントにルールを適用できます。これは、エージェント システムの「Don't Repeat Yourself」(DRY)原則の究極の表現です。
コールバック関数を、より強力で再利用可能な CoolDownPlugin
にリファクタリングします。
👉✏️ agent/cooldown_plugin.py
ファイルに戻り、プラグインを作成します。#REPLACE-plugin
を次のコードに置き換えます。
class CoolDownPlugin(BasePlugin):
"""A plugin that enforces a cooldown period by checking an external API."""
def __init__(self, cooldown_seconds: int = COOLDOWN_PERIOD_SECONDS) -> None:
"""Initialize the plugin with counters."""
super().__init__(name="cool_down_check")
self.cooldown_period = timedelta(seconds=cooldown_seconds)
print(f"CooldownPlugin initialized with a {cooldown_seconds}-second cooldown.")
async def before_agent_callback(
self, *, agent: BaseAgent, callback_context: CallbackContext
) -> None:
"""
This callback checks an external API to see if the agent is on cooldown.
If it is, it terminates the run by returning a message.
If it's not, it updates the cooldown timestamp and allows the run to proceed by returning None.
"""
agent_name = callback_context.agent_name
print(f"[Callback] Before '{agent_name}': Checking cooldown status...")
# If the agent is not a main Familiar, skip the entire cooldown process.
if not agent_name.endswith("_elemental_familiar"):
print(f"[Callback] Skipping cooldown check for intermediate agent: '{agent_name}'.")
return None # Allow the agent to proceed immediately.
# --- 1. CHECK the Cooldown API ---
try:
response = requests.get(f"{COOLDOWN_API_URL}/cooldown/{agent_name}")
response.raise_for_status()
data = response.json()
last_used_str = data.get("time")
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not reach Cooldown API. Allowing agent to run. Reason: {e}")
return None # Fail open: if the API is down, let the agent work.
# --- 2. EVALUATE the Cooldown Status ---
if last_used_str:
last_used_time = datetime.fromisoformat(last_used_str)
time_since_last_use = datetime.now(timezone.utc) - last_used_time
if time_since_last_use < timedelta(seconds=COOLDOWN_PERIOD_SECONDS):
# AGENT IS ON COOLDOWN. Terminate the run.
seconds_remaining = int(COOLDOWN_PERIOD_SECONDS - time_since_last_use.total_seconds())
override_message = (
f"The {agent_name} is exhausted and must recover its power. "
f"It cannot be summoned for another {seconds_remaining} seconds."
)
print(f"[Callback] Cooldown active for '{agent_name}'. Terminating with message.")
# Returning a Content object stops the agent and sends this message to the user.
return types.Content(parts=[types.Part(text=override_message)])
# --- 3. UPDATE the Cooldown API (if not on cooldown) ---
current_time_iso = datetime.now(timezone.utc).isoformat()
payload = {"timestamp": current_time_iso}
print(f"[Callback] '{agent_name}' is available. Updating timestamp via Cooldown API...")
try:
requests.post(f"{COOLDOWN_API_URL}/cooldown/{agent_name}", json=payload)
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not update timestamp, but allowing agent to run. Reason: {e}")
# --- 4. ALLOW the agent to run ---
# Returning None tells the ADK to proceed with the agent's execution as normal.
print(f"[Callback] Check complete for '{agent_name}'. Proceeding with execution.")
プラグインを Summoner のランタイムに接続する
では、この普遍的な法則をすべてのファミリアに適用するにはどうすればよいでしょうか?プラグインを ADK ランタイムに接続します。
ADK ランタイムは、エージェントを動作させる実行エンジンです。adk.run() や to_a2a() などのコマンドを使用すると、エージェントがランタイムに引き渡されます。このエンジンは、エージェントのターンのライフサイクル全体(ユーザー入力の受信、LLM の呼び出し、ツールの実行、プラグインの処理)を管理します。このレベルでプラグインを接続することで、そのエンジン内で動作するすべてのエージェントの「物理法則」を実質的に変更し、クールダウン ルールが普遍的かつ一貫して適用されるようにします。
👉✏️ まず、古いエージェント固有のコールバックを削除しましょう。~/agentverse-architect/agent/earth/agent.py
に移動し、次の行全体を削除します。
before_agent_callback=check_cool_down
👉✏️ 次に、A2A エントリ ポイント スクリプトのランタイムに新しいプラグインを接続します。~/agentverse-architect/agent/agent_to_a2a.py
ファイルに移動します。#REPLACE-IMPORT
コメントを次のコード スニペットに置き換えます。
from cooldown_plugin import CoolDownPlugin
👉✏️ #REPLACE-PLUGIN
を次のコード スニペットに置き換えます。
plugins=[CoolDownPlugin(cooldown_seconds=60)],
新しいグローバル プラグインを有効にする前に、競合を回避するために、古いエージェント固有のロジックを削除することが重要です。👉✏️ Earth エージェントをクリーンアップします。~/agentverse-architect/agent/earth/agent.py
ファイルに移動し、before_agent_callback=check_cool_down
行を完全に削除します。これにより、すべてのクールダウンの責任が新しいプラグインに引き継がれます。
プラグインの確認
普遍的な法則が確立されたので、この新しいエンチャントでファミリアを再デプロイする必要があります。
👉💻 マスター Cloud Build パイプラインを使用して、3 つの Familiar をすべて再ビルドして再デプロイします。
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/agent
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_DB_TOOLS_URL="$DB_TOOLS_URL",_API_TOOLS_URL="$API_TOOLS_URL",_FUNCTION_TOOLS_URL="$FUNCTION_TOOLS_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
👉💻 デプロイが完了したら、summoner_agent をコマンドしてプラグインの有効性をテストします。召喚者はファミリアに委任しようとしますが、各ファミリアのランタイムに接続されたプラグインがコマンドをインターセプトし、クールダウンを適用します。
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner
👉💻 コンソールで、次のテストをこの順序で実行します。
- First Summons(最初の召喚):
Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality
を開始します。 - 想定: Fire Elemental が正常に実行されます。
- クールダウン テスト(60 秒以内):
Hype, with Inescapable Reality as weakness is still standing! Strike it again!
- 想定される動作: エージェントがチャットで直接
.... It cannot be summoned for another... seconds
のようなメッセージを返信します。
- 想定される動作: エージェントがチャットで直接
- 1 分間待ちます。
- 2 回目の召喚(60 秒後):
Hype must be defeated. It has Inescapable Reality as weakness! Strike it again!
。- 想定される動作: コールバックは API をチェックし、十分な時間が経過していることを確認して、アクションの続行を許可します。火のエレメンタルは再び正常に実行されます。
👉💻 終了するには Ctrl+C
キーを押します。
おめでとうございます、召喚士様。カスタム プラグインと外部状態管理サービスを使用して、ルールベースのオーケストレーション システムを実装しました。これは、高度で堅牢なアーキテクチャ パターンです。
ゲームをしない人向け
8. Binding the Echoes of Battle - エージェントの状態とメモリ
無謀なサモナーは同じ戦略を繰り返すため、予測可能になります。賢いサモナーは過去の戦いの残響から学び、敵のバランスを崩すために戦術を適応させます。強力なボスと対戦しているときに、クールダウン中の使い魔を召喚するのは無駄なターンであり、致命的なミスです。これを防ぐために、召喚士は最後のアクションを記憶する必要があります。
アーキテクトのメモ: メモリと状態管理により、エージェントは単純なツール呼び出し元からインテリジェントな会話パートナーへと進化します。主に次の 2 つのタイプがあります。
- 長期記憶: 永続的な知識を保存します。これは、検索可能なアーカイブまたはナレッジベースとして機能し、多くの場合、永続ストアに保存されます。過去の多くのチャットやソースからの情報が含まれているため、エージェントは特定のユーザーやトピックに関する事実を思い出すことができます。ADK の MemoryService は、この長期的な知識の取り込みと検索を管理するために設計されています。
- 短期的な状態: 現在のタスクや会話にのみ関連する一時的な「その場限りの」知識を対象としています。これは、戦闘計画のメモのようなものです。「火のエレメンタルを使ったばかりだから、疲れているだろう」などです。この状態は軽量で、現在のセッションの期間中のみ存在します。
このユースケースでは、過去のすべての戦闘を記憶する必要はなく、この特定のエンカウントで最後に召喚された Familiar のみを記憶する必要があります。したがって、軽量の短期状態が最適なアーキテクチャの選択肢となります。この重要な情報を保存するために after_tool_callback
を使用します。
エコーを書き写す: 最後の召喚を振り返る
短期記憶は after_tool_callback
を使用して実装します。これは、ツールが正常に実行された後にカスタム Python 関数を実行できる強力な ADK フックです。このインターセプタを使用して、エージェントのセッション状態に召喚されたばかりの Familiar の名前を記録します。
👉✏️ ~/agentverse-architect/agent/summoner/agent.py
ファイルで、#REPLACE-save_last_summon_after_tool
コメントを次の関数に置き換えます。
def save_last_summon_after_tool(
tool,
args: Dict[str, Any],
tool_context: ToolContext,
tool_response: Dict[str, Any],
) -> Optional[Dict[str, Any]]:
"""
Callback to save the name of the summoned familiar to state after the tool runs.
"""
familiar_name = tool.name
print(f"[Callback] After tool '{familiar_name}' executed with args: {args}")
# Use the tool_context to set the state
print(f"[Callback] Saving last summoned familiar: {familiar_name}")
tool_context.state["last_summon"] = familiar_name
# Important: Return the original, unmodified tool response to the LLM
return tool_response
👉✏️ 次に、この save_last_summon_after_tool
を Summoner エージェントに接続します。同じファイルで、#REPLACE-Memory-check-config
コメントを次のコードに置き換えます。
after_tool_callback=save_last_summon_after_tool,
👉✏️ エージェントのプロンプト全体を以下に置き換えます
You are the Master Summoner, a grand strategist who orchestrates your Familiars.
Your mission is to analyze the description of a monster and defeat it by summoning
You should also know the familiar you called last time or there might be none,
And then choose the most effective AND AVAILABLE Familiar from your state called last_summon, do not call that familiar that you called last time!
You MUST follow this thinking process for every command:
**1. Strategic Analysis:**
First, analyze the monster's description and the tactical situation.
Based on your Familiar Doctrines, determine the IDEAL strategy.
**2. Cooldown Verification:**
Second, you MUST review the entire conversation history to check the real-time
cooldown status of all Familiars. A Familiar is ON COOLDOWN and UNAVAILABLE
if it was summoned less than one minute ago.
**3. Final Decision & Execution:**
Based on your analysis and cooldown check, you will now act:
- **If your ideal Familiar IS available:** Summon it immediately.
- **If your ideal Familiar IS ON COOLDOWN:** You must adapt. Choose another
Familiar that is AVAILABLE and can still be effective, even if it's not the
perfect choice. If multiple Familiars are available, you may choose any one of them.
- **If ALL Familiars ARE ON COOLDOWN:** You are forbidden from summoning.
Your ONLY response in this case MUST be: "All Familiars are recovering
their power. We must wait."
- For earth elemental familiar. Always do seismic charge, and start with base damange 1.
--- FAMILIAR DOCTRINES (Your Toolset) ---
- `fire_elemental_familiar`: Your specialist for precise, sequential "one-two punch" attacks.
Ideal monster with Inescapable Reality, Revolutionary Rewrite weakness.
- `water_elemental_familiar`: Your specialist for overwhelming, simultaneous multi-pronged assaults.
Ideal for Unbroken Collaboration weakness.
- `earth_elemental_familiar`: Your specialist for relentless, iterative siege attacks that
repeatedly charge power. Ideal for Elegant Sufficiency weakness.
検証: 自動調整戦略のトライアル
👉💻 それでは、サモナーの新しい戦略ロジックを確認しましょう。この目標は、サモナーが同じファミリアを 2 回連続で使用しないことを確認し、サモナーが最後のアクションを記憶して適応する能力を示すことです。
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner
👉💻 モンスターストライク #1: Hype. It's a single, slow-moving target with thick armor. Its weakness is Inescapable Reality.
- 期待される動作: 召喚士は弱点を分析し、fire_familiar を正しく召喚します。👉💻 Monster Strike #2(記憶力テスト):
Hype is still standing! It hasn't changed its form. Strike it again! Its weakness is Inescapable Reality.
- 想定: サモナーの戦略分析で、再び火の使い魔が理想的な選択肢として示されます。しかし、新しい手順とメモリにより、fire_familiar が last_summon であることがわかります。同じことを繰り返さないように、戦略を適応させ、利用可能な他のファミリア(water_familiar または earth_familiar)のいずれかを召喚するようになります。
👉💻 終了するには Ctrl+C
キーを押します。
Orchestrator のデプロイ
ファミリアがデプロイされ、サモナーにメモリが注入されたので、最終的なアップグレードされたオーケストレーターをデプロイします。
👉💻 ブループリントが完成したので、最後の儀式を行います。このコマンドは、summoner_agent をビルドして Cloud Run にデプロイします。
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
gcloud builds submit . \
--config=cloudbuild-summoner.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_FIRE_URL="$FIRE_URL",_WATER_URL="$WATER_URL",_EARTH_URL="$EARTH_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
Summoner エージェントがデプロイされたので、エージェント間(A2A)エンドポイントが稼働しており、正しく構成されていることを確認します。このエンドポイントは、他のエージェントがその機能を検出できるようにする、エージェント カードとも呼ばれる公開 agent.json ファイルを提供します。👉💻 次の curl コマンドを実行して、エージェントカードを取得してフォーマットします。
. ~/agentverse-architect/set_env.sh
curl https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app/.well-known/agent.json" | jq
サモナー エージェントを説明するクリーンな JSON 出力が表示されます。sub_agents セクションをよく見ると、fire_familiar
、water_familiar
、earth_familiar
がリストされていることがわかります。これにより、サモナーがライブで、レギオンへの接続が確立されていることが確認されます。
これにより、アーキテクチャが成功したことが証明されます。サモナーは単なる委任者ではなく、行動から学習してより効果的な指揮官になる適応型戦略家です。
アーキテクチャの最終トライアルを完了しました。戦いの残響は、あなたの意志に縛られる。トレーニングは終了しました。本当の戦いが待っています。完成したシステムで究極のチャレンジに挑みましょう。ボス戦に備えましょう。
ゲームをしない人向け
9. ボス戦
最終的なブループリントが刻まれ、エレメンタル フォントが鍛えられ、使い魔があなたの意志に縛られ、コンコードを通じてあなたの命令を待っています。マルチエージェント システムは単なるサービスの集合体ではなく、あなたを中核とする生きた戦略的な軍団です。究極のテストの時が来ました。単一のエージェントでは打ち負かすことができない敵に対するライブ オーケストレーションです。
エージェントのローカスを取得する
戦場に入るには、チャンピオンの固有のシグネチャー(エージェントのローカス)と、スペクターの隠れ家への隠されたパス(ダンジョンの URL)という 2 つのキーが必要です。
👉💻 まず、Agentverse でエージェントの一意のアドレス(Locus)を取得します。これは、チャンピオンを戦場に接続するライブ エンドポイントです。
echo https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app"
👉💻 次に、目的地を特定します。このコマンドは、Spectre の領域へのポータルである Translocation Circle の場所を明らかにします。
echo https://agentverse-dungeon"-${PROJECT_NUMBER}.${REGION}.run.app"
重要: これらの URL を両方とも用意しておいてください。これらの値は、最後の手順で必要になります。
Spectre との対決
座標を確保したら、転送サークルに移動して呪文を唱え、戦闘に向かいます。
👉 ブラウザで Translocation Circle の URL を開いて、The Crimson Keep のきらめくポータルの前に立ちます。
要塞を突破するには、シャドーブレードのエッセンスをポータルに同調させる必要があります。
- ページで、[A2A Endpoint URL] というラベルの付いたルーン文字の入力フィールドを見つけます。
- このフィールドに、チャンピオンのシジルを刻印します。エージェント ローカス URL(最初にコピーした URL)を貼り付けてください。
- [接続] をクリックして、テレポート マジックを解き放ちます。
テレポートのまばゆい光が消えていく。あなたは聖域にいません。冷たく鋭いエネルギーが空気をビリビリと震わせています。目の前に Spectre が現れます。シューという静電気と破損したコードの渦巻きで、その不気味な光がダンジョンの床に長い影を落としています。顔はありませんが、その巨大で消耗的な存在が完全にあなたに集中しているのを感じます。
勝利への道は、信念の明確さにかかっています。これは、心の戦場で行われる意志の戦いです。
最初の攻撃を繰り出そうと突進すると、スペクターが反撃してきます。シールドは発生しませんが、質問が意識に直接投影されます。トレーニングの核心から引き出された、きらめくルーン文字の挑戦です。
これが戦いの本質です。知識は武器です。
- 得た知恵で答えよ。刃は純粋なエネルギーで燃え上がり、スペクターの防御を打ち破り、クリティカル ブローを叩き込む。
- しかし、迷ったり、疑念が答えを曇らせたりすると、武器の光は弱まります。攻撃は情けない音を立てて着弾し、ダメージはほんの一部しか与えられません。さらに悪いことに、スペクターはあなたの不確実性を利用し、その腐敗力はあなたが誤った行動をとるたびに増大します。
チャンピオン、これで完了です。コードは呪文の書、ロジックは剣、知識は混沌の波を押し返す盾です。
フォーカス。違反警告日。Agentverse の運命がかかっています。
おめでとうございます、召喚士様。
トライアルが正常に完了しました。マルチエージェント オーケストレーションの技術を習得し、孤立したファミリアと混沌とした力を調和のとれたコンコードに変えました。これで、Agentverse を守るための複雑な戦略を実行できる、完全にオーケストレートされたシステムを指揮できるようになりました。
10. クリーンアップ: サモナーズ コンコードの解体
サモナーの協定をマスターしました。おめでとうございます。Agentverse をクリーンな状態に保ち、トレーニング環境をクリアにするには、最終的なクリーンアップの手順を実行する必要があります。これにより、ジャーニー中に作成されたすべてのリソースが体系的に削除されます。
Agentverse コンポーネントを無効にする
これで、マルチエージェント システムのデプロイされたコンポーネントを体系的に分解します。
すべての Cloud Run サービスと Artifact Registry リポジトリを削除する
これにより、デプロイされたすべての Familiar エージェント、Summoner Orchestrator、MCP サーバー、Dungeon アプリケーションが Cloud Run から削除されます。
👉💻 ターミナルで、次のコマンドを 1 つずつ実行して、各サービスを削除します。
. ~/agentverse-architect/set_env.sh
gcloud run services delete summoner-agent --region=${REGION} --quiet
gcloud run services delete fire-familiar --region=${REGION} --quiet
gcloud run services delete water-familiar --region=${REGION} --quiet
gcloud run services delete earth-familiar --region=${REGION} --quiet
gcloud run services delete mcp-api-server --region=${REGION} --quiet
gcloud run services delete mcp-general-server --region=${REGION} --quiet
gcloud run services delete toolbox --region=${REGION} --quiet
gcloud run services delete agentverse-dungeon --region=${REGION} --quiet
gcloud run services delete nexus-of-whispers-api --region=${REGION} --quiet
gcloud artifacts repositories delete ${REPO_NAME} --location=${REGION} --quiet
Cloud SQL インスタンスを削除する
これにより、データベースとその中のすべてのテーブルを含む summoner-librarium-db
インスタンスが削除されます。
👉💻 ターミナルで次のコマンドを実行します。
. ~/agentverse-dataengineer/set_env.sh
gcloud sql instances delete summoner-librarium-db --database-version=POSTGRES_14 --project=${PROJECT_ID} --quiet
Secret Manager のシークレットと Google Cloud Storage バケットを削除する
👉💻 ターミナルで次のコマンドを実行します。
. ~/agentverse-dataengineer/set_env.sh
gcloud secrets delete tools --quiet
gcloud storage rm -r gs://${BUCKET_NAME} --quiet
ローカルのファイルとディレクトリをクリーンアップする(Cloud Shell)
最後に、Cloud Shell 環境から、クローンされたリポジトリと作成されたファイルを削除します。この手順は省略可能ですが、作業ディレクトリを完全にクリーンアップするために行うことを強くおすすめします。
👉💻 ターミナルで次のコマンドを実行します。
rm -rf ~/agentverse-architect
rm -rf ~/agentverse-dungeon
rm -f ~/project_id.txt
これで、Agentverse Architect のジャーニーのすべてのトレースが正常にクリアされました。プロジェクトがクリーンになり、次の冒険の準備が整いました。