GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/高度な活用
高度な活用/2026-06-13上級

Gemini で自律エージェントを動かす最小構成 — ツールループ設計で学んだこと

google-genai SDK の自動 Function Calling で自律エージェントを最小構成から作る手順。ステップ上限・ツール許可リスト・再試行の設計判断を、ブログ運用の自動化で得た実体験とともにまとめます。

Gemini API191エージェント14Function Calling16自律型AI

個人開発のかたわら複数のブログを並行運用するようになってから、毎朝の定型作業が静かに積み上がっていきました。アクセス状況の確認、更新キューの整理、画像アセットの振り分け。一つひとつは数分でも、サイトが増えるたびに朝の時間が削られていきます。

「判断はモデルに任せて、手は道具に任せる」。そう割り切って Gemini にツールを持たせる構成へ移行したのが、私にとっての自律エージェント開発の始まりでした。

最初に断っておくと、エージェントは魔法ではありません。実体は「モデルがツール呼び出しを提案し、コードが実行し、結果をモデルに返す」というループの反復です。この構造を自分の手で一度書いておくと、フレームワークやマネージドサービスを選ぶときの判断軸が一気に明確になります。ここでは、その最小構成と、運用して初めて見えた設計判断をまとめます。

自動 Function Calling だけで動く最小エージェント

現行の Python SDK は google-genai です(pip install google-genai)。旧 google-generativeai のサンプルが検索上位に残っていますが、クラス構成が異なるため混ぜると動きません。私自身、移行直後に旧 SDK の GenerativeModel を探して時間を溶かしました。

新 SDK の大きな利点は、Python 関数をそのまま渡すと自動 Function Calling が働くことです。docstring と型ヒントから関数宣言が生成され、モデルが必要と判断すれば SDK が関数を実行し、結果を踏まえた最終応答まで返してくれます。

from google import genai
from google.genai import types
 
# GEMINI_API_KEY 環境変数を自動で読み込みます
client = genai.Client()
 
def get_article_stats(slug: str) -> dict:
    """指定したスラッグの記事の直近7日間の閲覧数とクリック数を返します。"""
    # 実際には GA4 / Search Console のデータストアを引きます
    return {"slug": slug, "views": 1280, "clicks": 96}
 
def list_pending_drafts() -> list[str]:
    """公開待ちの下書きスラッグ一覧を返します。"""
    return ["gemini-batch-api-notes", "image-asset-pipeline"]
 
response = client.models.generate_content(
    model="gemini-3.5-flash",
    contents="公開待ちの下書きを確認して、直近の人気記事の傾向と合わせて公開順の提案をしてください。",
    config=types.GenerateContentConfig(
        tools=[get_article_stats, list_pending_drafts],
    ),
)
 
print(response.text)

このコードだけで、モデルは list_pending_drafts を呼び、必要に応じて get_article_stats を複数回呼び、結果を統合した提案文を返します。ループを自分で書いていないのに複数ステップの実行が成立するのは、SDK が内部でツールループを回しているためです。

つまずきやすいのは docstring の書き方です。自動 Function Calling では docstring がそのままモデルへの説明になるため、「何を返すか」を曖昧に書くと呼び出し判断がぶれます。引数の意味と戻り値の中身を一文ずつ明記する。それだけで呼び出しの安定感が目に見えて変わりました。

手動ループに切り替える判断基準

自動実行は便利ですが、私は本番のパイプラインでは手動ループに切り替えています。理由は二つあります。実行前にツール呼び出しの内容を検査したいこと、そしてステップ数の上限を自分で握りたいことです。

from google import genai
from google.genai import types
 
client = genai.Client()
 
publish_tool = types.Tool(function_declarations=[
    types.FunctionDeclaration(
        name="publish_article",
        description="指定スラッグの記事を公開します。破壊的操作のため確認が必要です。",
        parameters=types.Schema(
            type=types.Type.OBJECT,
            properties={"slug": types.Schema(type=types.Type.STRING)},
            required=["slug"],
        ),
    ),
])
 
config = types.GenerateContentConfig(
    tools=[publish_tool],
    # 自動実行を止めて、呼び出し提案だけ受け取ります
    automatic_function_calling=types.AutomaticFunctionCallingConfig(disable=True),
)
 
contents = [
    types.Content(role="user", parts=[
        types.Part(text="レビュー済みの記事を公開してください。対象: gemini-batch-api-notes"),
    ]),
]
 
MAX_STEPS = 6  # 暴走防止。経験上、定型運用タスクは6ステップで収まります
 
for step in range(MAX_STEPS):
    response = client.models.generate_content(
        model="gemini-3.5-flash", contents=contents, config=config,
    )
    part = response.candidates[0].content.parts[0]
 
    if not part.function_call:
        print(response.text)  # ツール提案がなくなったら完了
        break
 
    call = part.function_call
    # ここで呼び出し内容を検査してから実行します
    result = execute_with_allowlist(call.name, dict(call.args))
 
    contents.append(response.candidates[0].content)
    contents.append(types.Content(role="user", parts=[
        types.Part.from_function_response(name=call.name, response={"result": result}),
    ]))

ポイントは MAX_STEPS です。初期の実装でこれを入れておらず、ツールがエラー文字列を返し続ける状況でモデルが同じ呼び出しを繰り返し、無駄な API 課金だけが積み上がったことがあります。ループの上限は「保険」ではなく必須の部品だと考えるようになりました。

ツールは読み取り系と破壊系で分ける

運用して最も効いた設計判断は、ツールを「読み取り系」と「破壊系」に分けたことです。

統計の取得や下書き一覧の参照は、モデルが何度呼んでも実害がありません。一方で「公開する」「削除する」「外部に投稿する」は、一度実行すると取り消せません。私の実装では、破壊系ツールは許可リスト方式にして、ループ内で実行する前に引数を検証しています。

READ_TOOLS = {"get_article_stats", "list_pending_drafts"}
WRITE_TOOLS = {"publish_article"}
 
def execute_with_allowlist(name: str, args: dict) -> str:
    if name in READ_TOOLS:
        return run_tool(name, args)
    if name in WRITE_TOOLS:
        # 破壊系は対象の実在確認を挟んでから実行します
        if not draft_exists(args.get("slug", "")):
            return f"対象 {args.get('slug')} が見つからないため中止しました"
        return run_tool(name, args)
    return f"ツール {name} は許可されていません"

「存在しない対象への破壊的操作はツール側で握りつぶす」。この一段を入れてから、モデルの判断ミスがそのまま事故になる経路が塞がれました。モデルの賢さに頼るのではなく、ツールの設計で安全側に倒す。エージェント開発の品質は、実はツール側のコードで決まる部分が大きいと感じています。

マルチエージェントの前に、1エージェント+良いツール

エージェント関連の記事では複数エージェントの協調がよく語られます。私も一度、「分析役」「執筆役」「レビュー役」と分けた構成を試しました。結論として、個人開発の規模では維持コストに見合いませんでした。

役割間の受け渡しプロンプトが増えるほどデバッグが難しくなり、どこで判断が崩れたのか追跡するだけで時間が消えます。同じ成果は「1つのエージェントに、責務の明確なツールを揃える」ほうが安定して出せました。マルチエージェントが活きるのは、役割ごとに必要なコンテキストが本当に分離している場合に限られる、というのが現時点での私の判断です。

なお、ループの実行環境ごと Google 側に任せたい場合は、Managed Agents(公開プレビュー)という選択肢もあります。隔離されたサンドボックスで計画からコード実行までを担ってくれますが、上で書いたような「破壊系ツールの検証を自分のコードで握る」構成とはトレードオフになります。私はまず自前ループで運用の勘所を掴んでから、移せる部分だけを移す段階移行を取っています。

運用で毎月見ている数字

エージェントを回し続けるかどうかは、感覚ではなく数字で判断するようにしています。私が月初に確認しているのは三つです。

ツール呼び出しの成功率(直近は 96% 前後で、低下したら docstring か引数スキーマを疑います)。1タスクあたりの平均ステップ数(2〜3 で安定していれば健全、上振れしたらプロンプトの目標設定が曖昧になっています)。そして usage_metadata から合計したトークン消費です。自動化で浮いた作業時間とこの費用を並べたとき、見合わなくなった機能は畳む。この基準を持っておくと、エージェントを「動いているから残す」ではなく「効いているから残す」で運用できます。

次に試すこと

まずは読み取り系ツールを2つだけ持つ最小エージェントを、自動 Function Calling で動かしてみてください。docstring を一文直すだけで挙動が変わる感覚を掴めたら、手動ループ化とステップ上限の導入に進むのが近道です。

ツール定義をさらに細かく制御したくなったら、Gemini API の Function Calling 活用法が次の一歩になります。基本の呼び出しに不安があれば Gemini APIクイックスタートから固めるのも良い順序です。

同じように日々の運用を少しずつ自動化している方の参考になれば幸いです。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

高度な活用2026-07-04
Gemini 3 × Function Calling + Built-in Tools + Context Circulation: プロダクション向けマルチツールエージェント設計と実装
Gemini 3の最新ツール機能を深掘り。Built-in ToolsとFunction Callingの組み合わせ、Context Circulation、並列ツール呼び出しIDによる本番エージェント設計を、実測とつまずきの記録を交えて解説します。
高度な活用2026-07-03
ツール結果が会話を静かに食いつぶす — Gemini Function Calling の巨大レスポンスをハンドル渡しで軽くする設計
Function Calling のツール結果が会話履歴に滞留し、入力トークンを複利で膨らませる問題を分解します。トークン予算つき圧縮とハンドル渡しの2実装で、実測で入力を約1/8に抑えた手順と落とし穴をまとめます。
高度な活用2026-07-01
Managed Agents の隔離サンドボックスから成果物を安全に持ち出す — スコープ限定クレデンシャルと egress の設計
Gemini API の Managed Agents はGoogleホストの隔離サンドボックスで動きます。生成した成果物をそこから自分のリポジトリへ安全に戻すための、短命・最小権限クレデンシャルとegress境界の実装をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →