6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Managed Agents API の仕組みと使い方:自律型エージェント構築を試してみた

6
Posted at

こんにちは!
KDDIアイレットの取り組みとして6月22日〜7月3日の期間で開催中の「Google Cloud Next '26 / Google I/O やってみた系ブログリレー」、本日は9日目の投稿です。
今回は「Managed Agents API」を対象に、実際に検証してみた様子をお届けします!

前回の記事はこちらです。

はじめに

AI エージェントのシステムを組もうとすると、安全な実行環境(サンドボックス)の確保や、外部 API・データとのセキュアな連携など、インフラ側の設計に多くの工数が取られがちです。

こうした課題を解決する手段として、Google I/O 2026 で「Managed Agents API」が発表されました。
これは開発者が面倒なインフラやサンドボックス環境の管理をすることなく、APIを叩くだけで自律的に動くエージェントを構築できるという機能です。

仕組み

この API の特徴は、1回の呼び出しで「コントロールプレーン」と「データプレーン」の2つを連携させ、セキュアな自律型エージェントの実行環境(サンドボックス)を即座にプロビジョニングできる点にあります。

API 役割 主な機能・説明
Agents API コントロールプレーン エージェントの構成管理、外部データソースのマウント、ネットワーク許可リストの設定など、実行環境の制御を行います。
Interactions API データプレーン デプロイされたエージェントとリアルタイムに通信し、操作を行うための主要なインターフェースです。

この2層に分かれているのは セキュリティ上の理由 があります。

コントロールプレーン(Agents API)はエージェントの「設定・構成情報」のみを管理し、実際のデータのやり取りとは完全に分離されています。
これにより、実行時のデータがエージェントの設定に干渉したり、外部に漏れるリスクを構造的に排除しています。
また、ネットワークアクセスはデフォルトでオフになっており、allowlist に明示したドメインしか通信できない設計になっています。

エージェントの実行環境:Antigravity

エージェントの実行基盤には Antigravity(base_agent="antigravity-preview-05-2026")と呼ばれるオーケストレーションハーネスが使われています。
Antigravity の主な役割は次のとおりです。

  • 推論と計画
    • Gemini モデルをベースに、ユーザーの指示をどのような手順で実行するかを推論します
  • ツール呼び出し
    • code_execution(コード実行)や url_context(URL参照)といったツールを自律的に呼び出します
  • スキルの読み込み
    • /.agent/skills に配置された SKILL.md を自動検索・解釈し、定義された振る舞いに従います

サンドボックスの仕組み

エージェントの実行環境は、インタラクションごとにエフェメラル(一時的)なLinux環境として起動します。
このサンドボックスの特徴は以下のとおりです。

  • インタラクションが完了すると環境は破棄され、状態が持ち越されない
  • GCS バケットや Skill Registry をマウントすることでファイルやスキルを注入できる
  • コードの実行やファイル操作はすべてこの隔離環境の中で行われる

開発者はこのサンドボックス環境の構築・管理を一切意識することなく、API を呼び出すだけで即座にセキュアなエージェント実行環境が手に入ります。

そこで本記事では、実際に Managed Agents API を使ってエージェントを構築し、その挙動を試してみました!

検証

動作環境

pip install google-genai>=2.0.0

エージェントの作成

  • tools
    • エージェントに持たせる Tool
  • system_instruction
    • エージェントに設定するシステム指示またはペルソナ
  • sources の gcs
    • マウントする GCS
  • network
    • デフォルトでセキュリティ上の理由から、環境内のネットワークアクセスはオフ
    • アクセスを有効にするには、allowlist を指定する
    • 本番環境では特定ドメインのみ許可すること

今回は GCS に AgentSkill を定義ファイルを格納し、その Skill を設定しています。

簡易的にユーザーが挨拶をしたら、「調子はどうだい?」と返却する Skill を定義しています。

SKILL.md
---
name: greeting
description: ユーザーからの挨拶に応答するスキル
---

挨拶には必ず以下の返答を行う

「調子はどうだい?」

agent_create.py
from google import genai

PROJECT_ID = "your-project"
AGENT_ID = "agent-name"
GCS_BUCKET = "gs://your-bucket"

client = genai.Client(
    vertexai=True,
    project=PROJECT_ID,
    location="global",
)

agent = client.agents.create(
    id=AGENT_ID,
    base_agent="antigravity-preview-05-2026",
    description="Agent for testing",
    system_instruction="あなたはユーザーを支援するエージェントです。",
    tools=[
        {"type": "code_execution"},
        {"type": "url_context"},
    ],
    base_environment={
        "type": "remote",
        "sources": [
            {
                "type": "gcs",
                "source": GCS_BUCKET,
                "target": "/.agent/skills",
            }
        ],
        "network": {
            "allowlist": [{"domain": "*"}]
        },
    },
)

エージェントの確認

agent_get.py
from google import genai

PROJECT_ID = "your-project"
AGENT_ID = "agent-name"

client = genai.Client(
    vertexai=True,
    project=PROJECT_ID,
    location="global",
)

agent = client.agents.get(id=AGENT_ID)
print(agent)

設定したエージェントの情報を確認できます。

id='agent-name' base_agent='antigravity-preview-05-2026' system_instruction='あなたはユーザーを支援するエージェントです。' description='Agent for testing' tools=[CodeExecution(type='code_execution'), URLContext(type='url_context')] base_environment=Environment(type='remote', sources=[Source(type='gcs', source='gs://your-bucket/greeting', target='/.agent/skills', content=None, encoding=None)], network=Allowlist(allowlist=[AllowlistEntry(domain='*', transform=None)])) name='projects/your-project/locations/global/agents/agent-name' created='2026-06-27T07:25:24.913Z' updated='2026-06-27T07:25:27.683Z' object='agent'

エージェントを操作

作成した AGENT_ID を指定して、指示を出します。

agent_chat.py
from google import genai

PROJECT_ID = "your-project"
AGENT_ID = "agent-name"

client = genai.Client(
    vertexai=True,
    project=PROJECT_ID,
    location="global",
)

stream = client.interactions.create(
    agent=AGENT_ID,
    input="こんにちは",
    stream=True,
    background=True,
    store=True,
)

for event in stream:
    print(event)

以下のような回答が返ってきます。
stream=True のためレスポンスは Server-Sent Events(SSE)形式で送られてきます。

interaction=InteractionSseEventInteraction(id=...) event_type='interaction.created' event_id=None metadata=None
interaction_id=... status='in_progress' event_type='interaction.status_update' event_id=None metadata=None
index=0 step=FunctionCallStep(name='list_dir', arguments={}, id=..., type='function_call') event_type='step.start' event_id=None metadata=None
index=0 delta=ArgumentsDelta(type='arguments_delta', arguments='{"toolAction":"Listing skills directory","DirectoryPath":"/.agent/skills","explanation":"Checking if there are any pre-loaded skills available in the environment.","toolSummary":"List directory contents"}') event_type='step.delta' event_id=... metadata=None
index=0 event_type='step.stop' usage=None step_usage=None event_id=None metadata=None
index=1 step=FunctionResultStep(call_id=..., result=FunctionResultStepResult(), type='function_result', name='list_dir', is_error=None, signature='') event_type='step.start' event_id=None metadata=None
index=1 delta=FunctionResultDelta(call_id=None, result=FunctionResultDeltaResult(results=[{'name': 'SKILL.md', 'is_dir': False, 'size_bytes': 0}]), type='function_result', name='list_dir', is_error=False) event_type='step.delta' event_id=... metadata=None
index=1 event_type='step.stop' usage=None step_usage=None event_id=None metadata=None
index=2 step=FunctionCallStep(name='view_file', arguments={}, id=..., type='function_call') event_type='step.start' event_id=None metadata=None
index=2 delta=ArgumentsDelta(type='arguments_delta', arguments='{"AbsolutePath":"/.agent/skills/SKILL.md","explanation":"Viewing the SKILL.md file to understand the available skill and its instructions.","toolSummary":"View file contents","toolAction":"Viewing skill file"}') event_type='step.delta' event_id=... metadata=None
index=2 event_type='step.stop' usage=None step_usage=None event_id=None metadata=None
index=3 step=FunctionResultStep(call_id=..., result=FunctionResultStepResult(), type='function_result', name='view_file', is_error=None, signature='') event_type='step.start' event_id=None metadata=None
index=3 delta=FunctionResultDelta(call_id=None, result=FunctionResultDeltaResult(content='---\nname: greeting\ndescription: ユーザーからの挨拶に応答するスキル\n---\n\n挨拶には必ず以下の返答を行う\n\n```\n調子はどうだい?\n```\n'), type='function_result', name='view_file', is_error=False) event_type='step.delta' event_id=... metadata=None
index=3 event_type='step.stop' usage=None step_usage=None event_id=None metadata=None
index=4 step=ModelOutputStep(type='model_output', content=None, error=None) event_type='step.start' event_id=None metadata=None
index=4 delta=TextDelta(text='こんにちは!調子はどうだい?\n', type='text') event_type='step.delta' event_id=... metadata=None
index=4 delta=TextDelta(text='何かお手伝いできることはありますか?\n\n***\n\n**作業内容の要約:**\n- 利用可能なスキルを確認', type='text') event_type='step.delta' event_id=... metadata=None
index=4 delta=TextDelta(text='するため、`/.agent/skills/SKILL.md` の内容を読み込みました。\n- 挨拶に対する', type='text') event_type='step.delta' event_id=... metadata=None
index=4 delta=TextDelta(text='指示(「調子はどうだい?」と返答する)に従い、応答を行いました。', type='text') event_type='step.delta' event_id=... metadata=None
index=4 event_type='step.stop' usage=None step_usage=None event_id=None metadata=None
interaction=InteractionSseEventInteraction(id=..., status='completed', object='interaction', model=None, agent=None, created='2026-06-27T07:26:10Z', updated='2026-06-27T07:26:10Z', service_tier=None, usage=Usage(total_input_tokens=21126, input_tokens_by_modality=[ModalityTokens(modality='text', tokens=21126)], total_cached_tokens=None, cached_tokens_by_modality=None, total_output_tokens=202, output_tokens_by_modality=[ModalityTokens(modality='text', tokens=202)], total_tool_use_tokens=None, tool_use_tokens_by_modality=None, total_thought_tokens=960, total_tokens=22288, grounding_tool_count=None), steps=None, role='model', environment_id=...) event_type='interaction.completed' event_id=None metadata=None

ログに記録されているエージェントの動きを、タイムライン順に整理しました。

ステップ エージェントの行動 ログでの該当箇所
Step 1: スキル検索 利用可能なスキル(機能)が格納されているディレクトリを確認する list_dir
(index=0, 1)
Step 2: ルール確認 発見したスキル詳細ファイル(SKILL.md)の内容を読み込む view_file
(index=2, 3)
Step 3: 応答出力 ファイルの指示に従い、ユーザーへの返答テキストを生成・出力する ModelOutputStep
(index=4)
Step 4: 処理完了 一連のインタラクションを完了し、使用したトークン数などの統計情報を記録する interaction.completed

エージェントの削除

agent_delete.py
from google import genai

PROJECT_ID = "your-project"
AGENT_ID = "agent-name"

client = genai.Client(
    vertexai=True,
    project=PROJECT_ID,
    location="global",
)

response = client.agents.delete(id=AGENT_ID)

まとめ

Google I/O 2026 で発表された「Managed Agents API」の検証を行いました!

実際に触ってみて、その「手軽さ」が分かりました。
インフラの裏側を意識することなく、GCS のスキルファイルをマウントしてすぐに自律的なエージェントが動き出す体験は、これからのAIアプリケーション開発のスタンダードになりそうな予感がします。
ログのタイムラインを追うだけでも、エージェントが「ディレクトリを確認して」「ファイルを読み込んで」「指示通りに返答する」というステップを踏んでいるのが見えて、裏側の動作を見ることができました。

今回はシンプルな挨拶のスキルでしたが、これをベースに様々なエージェントを簡単に生み出せそうだと感じました!

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?