Gemini Thinking APIでエージェント推論を強化する実装ガイド

この記事の結論

Gemini 2.5 Flash/ProのThinking APIをエージェントの推論バックエンドとして使う実装ガイド。thinkingBudgetの設定からマルチステップ推論まで、Python SDKのコード例6本付きで解説。

Gemini Thinking APIでエージェント推論を強化する実装ガイド

「エージェントに複雑な判断をさせようとしたら、浅い推論しか返ってこない…」

マルチステップの意思決定や、条件が絡み合うワークフロー制御を実装するとき、よくぶつかる壁です。単純なLLM呼び出しでは、エージェントが「なんとなく」答えを出してしまい、推論の深さが足りない。かといって、プロンプトでひたすら「ステップバイステップで考えて」と誘導するのも限界がある。

この問題に対して、Gemini 2.5 Flash / ProのThinking APIは有効な選択肢です。モデルが回答を出力する前に内部で思考プロセスを走らせ、その推論の深さをAPIパラメータで制御できる。この記事では、Thinking APIの仕組みから、エージェントの推論バックエンドとして組み込む実装パターンまで、コピペ可能なPythonコードとともに解説します。

AIエージェントの基本設計については、PythonでAIエージェントを構築する完全ガイドもあわせて参照してください。

まず5分で動かす:Thinking APIの最小実装

まずは最小構成で動かしてみましょう。以下はGemini 2.5 FlashのThinking APIを使った基本的な呼び出しです。


# 動作環境: Python 3.11+, google-genai>=1.0
# インストール: pip install google-genai

import google.genai as genai
import os

# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="あるEC事業者が、在庫不足・価格競争・配送遅延という3つの問題を同時に抱えています。優先順位をつけて解決策を提案してください。",
    config=genai.types.GenerateContentConfig(
        thinking_config=genai.types.ThinkingConfig(
            thinking_budget=8192  # 思考に使えるトークン上限(0〜24576)
        )
    )
)

print(response.text)
# thinking_tokensの使用量も確認できる
print(f"思考トークン数: {response.usage_metadata.thoughts_token_count}")

ポイントを整理します。

  • thinking_budget:モデルが思考に使えるトークン数の上限。0で思考オフ、-1でモデル自動判断、最大24576(2.5 Flash)
  • thoughts_token_count:実際に使われた思考トークン数。コスト管理に活用
  • モデルは「必要な分だけ」思考する設計なので、上限を高く設定しても必ず使い切るわけではない

Thinking APIの仕組みと設計思想

Gemini 2.5系のThinking機能は、2025年に正式に一般提供が始まりました。モデルが最終回答を出力する前に「内部推論」フェーズを持つアーキテクチャで、数学・コーディング・複合的な意思決定タスクで特に効果が出ます。

Gemini 2.5 vs Gemini 3のThinking設定

バージョンによってパラメータ体系が異なります。

モデル系列 パラメータ 設定値 特徴
Gemini 2.5 Flash thinking_budget 0〜24576トークン コスト効率重視、高速
Gemini 2.5 Pro thinking_budget 0〜32768トークン 高精度、深い推論
Gemini 3系 thinkingLevel minimal / low / medium / high 段階的制御、シンプルなAPI

Gemini 3系ではthinkingLevelという抽象化されたパラメータになり、highがデフォルト(動的に最大限思考)です。エージェント組み込みで現実的なのは、コスト面でGemini 2.5 Flashのthinking_budget調整が使いやすいでしょう。

エージェント推論バックエンドとしての実装パターン3選

パターン1:タスク難易度に応じてthinking_budgetを動的調整

すべてのタスクに同じthinking_budgetを使うのは非効率です。単純な情報取得には小さい予算、複雑な判断には大きい予算を割り当てるルーティングを実装してみましょう。


# 動作環境: Python 3.11+, google-genai>=1.0

import google.genai as genai
import os

client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

def classify_task_complexity(task: str) -> str:
    """タスクの複雑度を判定する(軽量な分類ロジック)"""
    complex_keywords = ["最適化", "戦略", "比較", "設計", "判断", "優先順位", "複数の要素"]
    medium_keywords = ["分析", "提案", "評価", "計画"]

    for kw in complex_keywords:
        if kw in task:
            return "high"
    for kw in medium_keywords:
        if kw in task:
            return "medium"
    return "low"

def get_thinking_budget(complexity: str) -> int:
    """複雑度に応じたthinking_budgetを返す"""
    budgets = {
        "low": 0,       # 思考なし(高速・低コスト)
        "medium": 4096, # 中程度の思考
        "high": 16384   # 深い思考
    }
    return budgets.get(complexity, 4096)

def reasoning_agent(task: str) -> dict:
    """推論エージェント:複雑度に応じて思考深度を切り替える"""
    complexity = classify_task_complexity(task)
    budget = get_thinking_budget(complexity)

    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=task,
        config=genai.types.GenerateContentConfig(
            thinking_config=genai.types.ThinkingConfig(
                thinking_budget=budget
            )
        )
    )

    return {
        "result": response.text,
        "complexity": complexity,
        "thinking_tokens_used": response.usage_metadata.thoughts_token_count,
        "budget": budget
    }

# 使用例
result = reasoning_agent("新規プロダクトの価格戦略を、競合他社3社のポジショニングを考慮しながら提案してください")
print(f"複雑度: {result['complexity']}")
print(f"思考トークン: {result['thinking_tokens_used']} / 予算: {result['budget']}")
print(result['result'])

パターン2:マルチステップ推論チェーン(思考サマリーの活用)

Thinking APIにはinclude_thoughts=Trueオプションがあり、モデルの推論過程のサマリーを取得できます。これをエージェントの次のステップの入力として使う「チェーン推論」が実装できます。


# 動作環境: Python 3.11+, google-genai>=1.0
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

import google.genai as genai
import os

client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

def chain_reasoning(problem: str, steps: list[str]) -> list[dict]:
    """
    段階的な推論チェーンを実行する。
    各ステップの思考サマリーを次のステップのコンテキストとして渡す。
    """
    results = []
    accumulated_context = f"問題: {problem}nn"

    for i, step in enumerate(steps):
        prompt = accumulated_context + f"ステップ{i+1}: {step}"

        response = client.models.generate_content(
            model="gemini-2.5-flash",
            contents=prompt,
            config=genai.types.GenerateContentConfig(
                thinking_config=genai.types.ThinkingConfig(
                    thinking_budget=8192,
                    include_thoughts=True  # 思考サマリーを取得
                )
            )
        )

        # 思考サマリーと最終回答を分離
        thought_summary = ""
        final_answer = ""
        for part in response.candidates[0].content.parts:
            if hasattr(part, "thought") and part.thought:
                thought_summary = part.text
            else:
                final_answer = part.text

        results.append({
            "step": step,
            "thought_summary": thought_summary[:500],  # 要約のみ保持
            "answer": final_answer
        })

        # 次ステップのコンテキストに推論結果を追加
        accumulated_context += f"nステップ{i+1}の結論: {final_answer}n"

    return results

# 使用例:事業計画の段階的分析
results = chain_reasoning(
    problem="新しいSaaSプロダクトの市場投入戦略を立案する",
    steps=[
        "市場規模と競合環境を評価してください",
        "ターゲット顧客セグメントを特定してください",
        "上記の分析を踏まえて、Go-to-Marketの優先施策を3つ提案してください"
    ]
)

for r in results:
    print(f"n【{r['step']}】")
    print(r['answer'])

パターン3:関数呼び出し(Function Calling)と組み合わせた推論エージェント

Thinking APIはFunction Callingと組み合わせて使えます。エージェントが「どのツールをいつ使うか」を深く推論した上で、適切な関数を呼び出す設計です。


# 動作環境: Python 3.11+, google-genai>=1.0
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

import google.genai as genai
from google.genai import types
import os, json

client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

# ツール定義
search_tool = types.Tool(
    function_declarations=[
        types.FunctionDeclaration(
            name="search_database",
            description="社内データベースから製品情報を検索する",
            parameters=types.Schema(
                type=types.Type.OBJECT,
                properties={
                    "query": types.Schema(type=types.Type.STRING, description="検索クエリ"),
                    "category": types.Schema(type=types.Type.STRING, description="カテゴリ(product/customer/sales)")
                },
                required=["query"]
            )
        )
    ]
)

def handle_function_call(name: str, args: dict) -> str:
    """実際のツール実行(ダミー実装)"""
    if name == "search_database":
        return json.dumps({"results": [{"id": 1, "name": "サンプル製品", "price": 9800}]})
    return "{}"

def tool_reasoning_agent(user_query: str) -> str:
    """思考+ツール呼び出しを統合したエージェント"""
    messages = [{"role": "user", "parts": [{"text": user_query}]}]

    for _ in range(5):  # 最大5ターン
        response = client.models.generate_content(
            model="gemini-2.5-flash",
            contents=messages,
            config=types.GenerateContentConfig(
                tools=[search_tool],
                thinking_config=types.ThinkingConfig(thinking_budget=4096)
            )
        )

        candidate = response.candidates[0]

        # Function Callがあれば実行
        function_calls = [p for p in candidate.content.parts if hasattr(p, "function_call") and p.function_call]
        if function_calls:
            messages.append({"role": "model", "parts": candidate.content.parts})
            tool_results = []
            for part in function_calls:
                fc = part.function_call
                result = handle_function_call(fc.name, dict(fc.args))
                tool_results.append(
                    types.Part.from_function_response(name=fc.name, response={"result": result})
                )
            messages.append({"role": "user", "parts": tool_results})
        else:
            # 最終回答
            return response.text

    return "最大ターン数に達しました"

result = tool_reasoning_agent("当社で最も売れている製品の価格帯を教えてください")
print(result)

コスト最適化:thinking_budgetの設定指針

Thinking APIはトークンコストが加算されるため、闇雲に高い予算を設定するのは禁物です。実務で使えるガイドラインを整理しました。

タスクタイプ 推奨 thinking_budget 根拠 コスト影響
情報抽出・分類 0(無効) 推論不要、高速応答優先 なし
要約・翻訳 0〜1024 軽度の文脈把握のみ必要
質問応答・分析 4096〜8192 複数観点の整理が必要
意思決定・戦略立案 8192〜16384 トレードオフ分析が必要
コード生成・数学 16384〜24576 厳密な推論ステップが必要 最高

コスト管理のベストプラクティスとして、usage_metadata.thoughts_token_countを記録して実際の使用量をモニタリングし、予算設定を継続的にチューニングすることが重要です。


# 動作環境: Python 3.11+, google-genai>=1.0
# コスト追跡ユーティリティ

import google.genai as genai
import os

client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

class ThinkingCostTracker:
    def __init__(self):
        self.total_thinking_tokens = 0
        self.total_output_tokens = 0
        self.request_count = 0

    def generate(self, model: str, contents, thinking_budget: int = 4096):
        response = client.models.generate_content(
            model=model,
            contents=contents,
            config=genai.types.GenerateContentConfig(
                thinking_config=genai.types.ThinkingConfig(
                    thinking_budget=thinking_budget
                )
            )
        )

        # コスト追跡
        thinking_tokens = response.usage_metadata.thoughts_token_count or 0
        output_tokens = response.usage_metadata.candidates_token_count or 0

        self.total_thinking_tokens += thinking_tokens
        self.total_output_tokens += output_tokens
        self.request_count += 1

        return response

    def report(self):
        print(f"リクエスト数: {self.request_count}")
        print(f"思考トークン合計: {self.total_thinking_tokens:,}")
        print(f"出力トークン合計: {self.total_output_tokens:,}")
        print(f"思考/出力 比率: {self.total_thinking_tokens / max(self.total_output_tokens, 1):.1f}x")

# 使用例
tracker = ThinkingCostTracker()
tracker.generate("gemini-2.5-flash", "AIエージェントのメモリ設計における3つの主要パターンを解説してください", thinking_budget=8192)
tracker.report()

【要注意】Thinking API実装でよくある失敗パターン

失敗1:thinking_budget=0にしたのに思考が走ってしまう

thinking_budget=0を設定しても、モデルのバージョンによっては最低限の思考が入る場合があります。

⭕ コスト削減が目的なら、プレビュー版ではなく安定版モデルを使い、挙動をusage_metadataで必ず確認する。

なぜ重要か:プレビュー期間中はthinking_budget=0の挙動が安定していないケースがGoogleのフォーラムで報告されています(2025年時点)。

失敗2:思考サマリーと最終回答を混同する

response.textだけを取ると、思考サマリーが混入することがある。

include_thoughts=Trueを使う場合は、part.thought属性で思考か回答かを判定してから処理する。

失敗3:長い会話履歴に思考署名(thought signatures)を混入させる

❌ マルチターン会話で思考署名ありのレスポンスをそのまま次のリクエストに渡すと、入力トークンコストが急増する。

⭕ 思考署名は会話の最終ターン以外は除外し、最終回答テキストのみを履歴に保持する。

失敗4:すべてのタスクに同じ予算を設定する

❌ 単純な情報抽出にもthinking_budget=16384を設定して不要なコストを発生させる。

⭕ タスク分類→予算マッピングの仕組みを実装し、タスク難易度に応じて動的に設定する(パターン1参照)。

GPT-5.4 Thinkingとの性能比較(2026年3月時点)

正直にお伝えすると、「どのThinking APIが最強か」という答えは現時点では出せません。ベンチマーク環境・タスク設定によって結果が大きく変わるからです。

現在公開されているデータを整理すると:

モデル ARC-AGI-2スコア 思考トークン上限 API公開状況
Gemini 3 Deep Think 45.1%(with code exec) thinkingLevel: high Gemini API(2026年)
Gemini 2.5 Pro 4.9% 32768トークン GA済み
Gemini 2.5 Flash 24576トークン GA済み
GPT-5.2 Thinking 約53% OpenAI API(2026年)

ARC-AGI-2は汎用知能の抽象的推論を測るベンチマークであり、実務エージェントの性能を直接反映するものではありません。実際のタスクで使いやすさを評価したほうが、選定の判断に直結します。

(ベンチマーク情報は各社公式発表に基づきます。最終確認: 2026-03-27)

セキュリティと運用のポイント

Thinking APIをエージェントに組み込む際の本番運用チェックリストです。


# 動作環境: Python 3.11+, google-genai>=1.0
# セキュリティ設定例

import google.genai as genai
from google.genai import types
import os

# ✅ APIキーは環境変数から取得(ハードコード禁止)
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

# ✅ ユーザー入力のサニタイゼーション
def sanitize_input(user_input: str, max_length: int = 2000) -> str:
    """プロンプトインジェクション対策の基本処理"""
    # 長さ制限
    if len(user_input) > max_length:
        raise ValueError(f"入力が{max_length}文字を超えています")

    # システムプロンプトに影響するパターンを検出
    injection_patterns = ["ignore previous", "ignore all", "you are now", "new instructions"]
    lower_input = user_input.lower()
    for pattern in injection_patterns:
        if pattern in lower_input:
            raise ValueError("不正な入力パターンを検出しました")

    return user_input.strip()

# ✅ 使用量の上限設定
MAX_THINKING_TOKENS_PER_REQUEST = 16384
MAX_REQUESTS_PER_HOUR = 100

def safe_agent_call(user_input: str, thinking_budget: int = 4096) -> str:
    """セキュリティチェックを含む安全なエージェント呼び出し"""
    clean_input = sanitize_input(user_input)
    actual_budget = min(thinking_budget, MAX_THINKING_TOKENS_PER_REQUEST)

    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=clean_input,
        config=types.GenerateContentConfig(
            thinking_config=types.ThinkingConfig(thinking_budget=actual_budget),
            safety_settings=[
                types.SafetySetting(
                    category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
                    threshold=types.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE
                )
            ]
        )
    )
    return response.text

参考・出典

まとめ:今日から始める3つのアクション

  1. 今日やること:パターン1のコードをローカルで動かして、タスク別のthinking_token使用量を計測する。コスト感覚をつかむのが先決
  2. 今週中:既存のエージェントで「推論精度が低い」と感じているステップにThinking APIを適用。thinking_budget 8192からスタートして調整する
  3. 今月中:ThinkingCostTrackerを本番に組み込み、タスク種別×コスト×精度のデータを蓄積。データに基づいてbudgetポリシーを最適化する

あわせて読みたい:


この記事はAIgent Lab編集部がお届けしました。

AIエージェントの設計・導入に関するご相談は、株式会社Uravation(お問い合わせフォーム)からお気軽にどうぞ。

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年3月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事