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日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-04-06中級

Gemini Function Calling が呼び出されない — 5つの症状から原因を特定する

Gemini APIのFunction Calling(ツール呼び出し)が動かない・エラーになる問題を症状別に整理。スキーマ定義ミス・モデル選択・レスポンス解析など原因別に解決手順をコード例付きで紹介します。

troubleshooting57error14fix10function-calling20gemini-api279

ツールが呼ばれないとき、どこを疑うか

スキーマを定義してリクエストを投げたのに、モデルは普通のテキストを返してくるだけ。レスポンスに function_call は現れず、エラーも出ません。Function Calling でつまずくときの多くは、こうした「何も起きない」状態から始まります。

原因はスキーマの書き方、モデルの選択、レスポンスの読み取り方など複数の層に分かれており、エラーメッセージだけでは切り分けが進みません。実際に遭遇しやすい5つの症状を入り口に、それぞれの原因と対処を順に確認します。


Function Callingの基本的な仕組みを確認する

トラブルシューティングの前に、動作の流れを整理しておきます。

  1. アプリがツール定義(スキーマ)とユーザーメッセージをAPIに送信する
  2. モデルがツールを呼び出すべきと判断すると、function_call を含むレスポンスを返す
  3. アプリがツールを実行し、結果を function_response としてAPIに送り返す
  4. モデルがツール結果を踏まえて最終的な回答を生成する

この4ステップのどこかに問題があることがほとんどです。以下の症状ごとに確認していきましょう。


症状1: ツールが一切呼び出されない

原因の分析

モデルがツールをまったく使わない場合、以下の原因が考えられます。

  • ツール説明文が曖昧: モデルはツールの description を読んで使用判断をするため、説明が不明確だと使われません
  • ユーザーメッセージとツールの関係が薄い: 質問とツールの用途が合致していないケース
  • モデルが対応していない: Function Callingは全モデルで使えるわけではありません
  • tool_choice の設定漏れ: 必ずツールを呼ぶよう強制する設定ができます

解決手順

まずツールの description を改善します。悪い例と良い例を比較してみましょう。

import google.generativeai as genai
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
 
# ❌ 悪い例:説明が抽象的すぎてモデルが使用タイミングを判断できない
bad_tool = {
    "name": "get_weather",
    "description": "天気を取得する",
    "parameters": {
        "type": "object",
        "properties": {
            "location": {"type": "string"}
        },
        "required": ["location"]
    }
}
 
# ✅ 良い例:いつ・どこで使うかが明確
good_tool = {
    "name": "get_weather",
    "description": (
        "指定した都市または地域の現在の天気情報を取得します。"
        "ユーザーが天気、気温、降水確率、風速など気象情報を尋ねたときに使用してください。"
        "例: 東京の天気、大阪の明日の気温"
    ),
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "都市名または地域名(例: 東京、大阪、北海道)"
            }
        },
        "required": ["location"]
    }
}
 
# tool_choice で強制的にツールを使わせる(デバッグに有効)
model = genai.GenerativeModel(
    model_name="gemini-2.5-pro",
    tools=[good_tool],
    tool_config={"function_calling_config": {"mode": "ANY"}}  # 必ずツールを使う
)
 
response = model.generate_content("東京の今日の天気を教えてください")
print(response.candidates[0].content.parts)
# 期待する出力: [function_call { name: "get_weather", args: { location: "東京" } }]

tool_configmode には3種類あります。

  • AUTO(デフォルト): モデルが判断してツールを使う
  • ANY: 必ずいずれかのツールを使う
  • NONE: ツールを使わない

症状2: スキーマ定義エラーが発生する

原因の分析

400 Bad RequestInvalid argument エラーが出る場合、ツールのスキーマ定義に問題があります。よくあるミスは以下の通りです。

  • required フィールドにプロパティ名のタイポ
  • サポートされていない型(例: integer の代わりに int
  • ネストしたオブジェクトの型定義漏れ
  • enum の値を properties に入れ忘れ

解決手順

スキーマを構造化して明示的に定義するのが確実です。

import google.generativeai as genai
from google.ai.generativelanguage_v1beta import FunctionDeclaration, Schema, Type
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
 
# ✅ 型安全にスキーマを定義する方法(ネストオブジェクト対応)
search_products_tool = FunctionDeclaration(
    name="search_products",
    description="商品データベースを検索し、条件に合う商品一覧を返します",
    parameters=Schema(
        type=Type.OBJECT,
        properties={
            "query": Schema(
                type=Type.STRING,
                description="検索キーワード"
            ),
            "category": Schema(
                type=Type.STRING,
                description="商品カテゴリ",
                enum=["electronics", "clothing", "food", "books"]  # enumはここで指定
            ),
            "price_range": Schema(
                type=Type.OBJECT,
                description="価格範囲",
                properties={
                    "min": Schema(type=Type.NUMBER, description="最低価格(円)"),
                    "max": Schema(type=Type.NUMBER, description="最高価格(円)")
                }
                # ネストオブジェクトはrequiredなし = すべてオプション
            ),
            "limit": Schema(
                type=Type.INTEGER,  # int ではなく INTEGER
                description="取得件数の上限(デフォルト: 10)"
            )
        },
        required=["query"]  # プロパティ名のスペルを必ず確認
    )
)
 
model = genai.GenerativeModel(
    model_name="gemini-2.5-pro",
    tools=[search_products_tool]
)
 
response = model.generate_content("電子機器で1万円以下の商品を5件探して")
print(response.candidates[0].content.parts)
# 期待する出力:
# function_call {
#   name: "search_products"
#   args { fields { key: "query" value { string_value: "電子機器" } }
#          fields { key: "category" value { string_value: "electronics" } }
#          fields { key: "price_range" value { struct_value { ... max: 10000 } } }
#          fields { key: "limit" value { number_value: 5 } } }
# }

症状3: function_callレスポンスのパースに失敗する

原因の分析

AttributeError: 'Part' object has no attribute 'function_call'KeyError が出る場合、レスポンスの構造を正しく理解していない可能性があります。

解決手順

レスポンスの構造を確認し、安全にパースする関数を作りましょう。

import google.generativeai as genai
import json
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
 
def safe_parse_function_call(response):
    """
    Function Callingのレスポンスを安全にパースするユーティリティ関数
    戻り値: (tool_name, tool_args) のタプル。ツール呼び出しでない場合は (None, None)
    """
    if not response.candidates:
        print("⚠️ candidatesが空です")
        return None, None
 
    candidate = response.candidates[0]
 
    # finish_reasonを確認(STOP以外は異常)
    print(f"finish_reason: {candidate.finish_reason}")
 
    for part in candidate.content.parts:
        # function_callがあるかチェック
        if hasattr(part, "function_call") and part.function_call:
            fc = part.function_call
            tool_name = fc.name
            # argsはMapCompositで直接dict変換できる
            tool_args = dict(fc.args)
            print(f"✅ ツール呼び出し検出: {tool_name}({tool_args})")
            return tool_name, tool_args
        elif hasattr(part, "text") and part.text:
            print(f"📝 テキストレスポンス: {part.text}")
 
    return None, None
 
# マルチターン会話でFunction Callingを実装する例
def run_weather_chat():
    get_weather_tool = {
        "name": "get_weather",
        "description": "指定した都市の現在の天気を取得します",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "都市名"}
            },
            "required": ["city"]
        }
    }
 
    model = genai.GenerativeModel(
        model_name="gemini-2.5-pro",
        tools=[get_weather_tool]
    )
    chat = model.start_chat()
 
    # ユーザーメッセージを送信
    response = chat.send_message("大阪の天気を教えてください")
    tool_name, tool_args = safe_parse_function_call(response)
 
    if tool_name == "get_weather":
        # 実際のツール実行(ここでは仮のデータを返す)
        weather_result = {
            "city": tool_args.get("city", "大阪"),
            "temperature": 22,
            "condition": "晴れ",
            "humidity": 55
        }
        print(f"🔧 ツール実行結果: {weather_result}")
 
        # ツール結果をモデルに返す
        final_response = chat.send_message(
            genai.protos.Content(
                parts=[genai.protos.Part(
                    function_response=genai.protos.FunctionResponse(
                        name=tool_name,
                        response={"result": weather_result}
                    )
                )]
            )
        )
        print(f"🤖 最終回答: {final_response.text}")
 
run_weather_chat()
# 期待する出力:
# finish_reason: FinishReason.STOP
# ✅ ツール呼び出し検出: get_weather({'city': '大阪'})
# 🔧 ツール実行結果: {'city': '大阪', 'temperature': 22, 'condition': '晴れ', 'humidity': 55}
# 🤖 最終回答: 大阪の現在の天気は晴れで、気温は22℃、湿度は55%です。...

症状4: 複数ツールで意図しないツールが選ばれる

原因の分析

複数のツールを定義すると、モデルが誤ったツールを選択することがあります。

  • ツール名・説明が似すぎている
  • 呼び出してほしいツールの説明が具体的でない
  • allowed_function_names で制限していない

解決手順

import google.generativeai as genai
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
 
# 複数ツールのうち特定のツールだけ使わせる
tools = [
    {
        "name": "search_database",
        "description": "社内データベースから顧客情報を検索します",
        "parameters": {
            "type": "object",
            "properties": {"customer_id": {"type": "string"}},
            "required": ["customer_id"]
        }
    },
    {
        "name": "search_web",
        "description": "インターネット上の一般的な情報を検索します",
        "parameters": {
            "type": "object",
            "properties": {"query": {"type": "string"}},
            "required": ["query"]
        }
    }
]
 
# allowed_function_names で使えるツールを限定する
model = genai.GenerativeModel(
    model_name="gemini-2.5-pro",
    tools=tools,
    tool_config={
        "function_calling_config": {
            "mode": "ANY",
            "allowed_function_names": ["search_database"]  # これだけ使う
        }
    }
)
 
response = model.generate_content("顧客ID C-12345 の情報を調べて")
print(response.candidates[0].content.parts)
# 期待する出力: search_database が呼ばれる(search_web は呼ばれない)

症状5: JavaScriptでFunction Callingがうまくいかない

原因の分析

Python以外のSDKでは、APIの呼び出し方や型指定が異なります。Node.js(Google AI SDK)でのよくあるミスを確認しましょう。

import { GoogleGenerativeAI } from "@google/generative-ai";
 
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
 
// ✅ JavaScript での正しいFunction Calling実装
const getStockPriceTool = {
  functionDeclarations: [
    {
      name: "get_stock_price",
      description: "指定した銘柄コードの現在の株価を取得します",
      parameters: {
        type: "OBJECT",  // JavaScriptでは大文字
        properties: {
          symbol: {
            type: "STRING",  // 大文字
            description: "銘柄コード(例: GOOGL, AAPL)"
          }
        },
        required: ["symbol"]
      }
    }
  ]
};
 
async function runFunctionCalling() {
  const model = genAI.getGenerativeModel({
    model: "gemini-2.5-pro",
    tools: [getStockPriceTool]
  });
 
  const chat = model.startChat();
  const result = await chat.sendMessage("Googleの株価を教えて");
 
  // レスポンスのパース
  const response = result.response;
  const candidate = response.candidates[0];
 
  for (const part of candidate.content.parts) {
    if (part.functionCall) {
      const { name, args } = part.functionCall;
      console.log(`✅ ツール呼び出し: ${name}`, args);
 
      // ツール実行
      const toolResult = { price: 175.42, currency: "USD" };
 
      // ツール結果を返す
      const followUp = await chat.sendMessage([{
        functionResponse: {
          name: name,
          response: { result: toolResult }
        }
      }]);
 
      console.log("🤖 最終回答:", followUp.response.text());
    }
  }
}
 
runFunctionCalling();
// 期待する出力:
// ✅ ツール呼び出し: get_stock_price { symbol: 'GOOGL' }
// 🤖 最終回答: Googleの現在の株価は175.42ドルです。

確認方法: 解決できたか検証する

以下のチェックリストで動作を確認しましょう。

import google.generativeai as genai
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
 
def verify_function_calling():
    """Function Callingが正しく動作するか確認するテスト"""
    test_tool = {
        "name": "add_numbers",
        "description": "2つの数値を足し算します。数値計算が必要な場合に使用してください。",
        "parameters": {
            "type": "object",
            "properties": {
                "a": {"type": "number", "description": "1つ目の数値"},
                "b": {"type": "number", "description": "2つ目の数値"}
            },
            "required": ["a", "b"]
        }
    }
 
    model = genai.GenerativeModel(
        model_name="gemini-2.5-pro",
        tools=[test_tool],
        tool_config={"function_calling_config": {"mode": "ANY"}}
    )
 
    response = model.generate_content("3 + 5 を計算して")
    part = response.candidates[0].content.parts[0]
 
    assert hasattr(part, "function_call"), "❌ function_callが含まれていません"
    assert part.function_call.name == "add_numbers", "❌ ツール名が正しくありません"
    args = dict(part.function_call.args)
    assert "a" in args and "b" in args, "❌ 引数が正しくありません"
 
    print(f"✅ テスト成功: add_numbers(a={args['a']}, b={args['b']})")
    print(f"   期待する計算結果: {args['a'] + args['b']}")
 
verify_function_calling()

予防策: 再発防止のベストプラクティス

トラブルを未然に防ぐために、以下の点を実装に組み込みましょう。

1. ツール定義のバリデーション: スキーマを一元管理してテストを書く

def validate_tool_schema(tool: dict) -> bool:
    """ツールスキーマの基本チェック"""
    required_keys = ["name", "description", "parameters"]
    for key in required_keys:
        if key not in tool:
            print(f"❌ '{key}' が必要です")
            return False
 
    params = tool["parameters"]
    if "required" in params:
        props = params.get("properties", {})
        for req_field in params["required"]:
            if req_field not in props:
                print(f"❌ required フィールド '{req_field}' が properties に存在しません")
                return False
 
    print(f"✅ ツール '{tool['name']}' のスキーマは正常です")
    return True

2. finish_reason の監視: MAX_TOKENSSAFETY で打ち切られていないか確認する

3. 再試行ロジック: ツールが呼ばれなかった場合はメッセージを具体化して再試行する

4. ログ記録: すべてのfunction_callとfunction_responseを記録して異常検知に使う


まとめ

Gemini APIのFunction Callingトラブルは、多くの場合以下のいずれかが原因です。

  • ツールの description が不明確で、モデルが使用を判断できない
  • スキーマの型名やフィールド名にタイポがある
  • レスポンスのパース方法がAPIの構造と合っていない
  • 複数ツールの競合を allowed_function_names で解決していない

デバッグの際は tool_configmode: ANY でツール呼び出しを強制し、スキーマが正しく渡っているかを確認するのが最短の道です。問題が解消しない場合は、最小限のシンプルなツールで再現確認してから複雑な実装に戻りましょう。

Function Callingのさらなる活用法については、Gemini APIのFunction Calling完全ガイドも合わせてご覧ください。

本記事の実装

シェア

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

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

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

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

関連記事

API / SDK2026-05-31
Gemini APIで「Unsupported MIME type」エラーが出るときの原因と対処
画像や音声をGemini APIに渡したときに発生する『Unsupported MIME type』エラーを、MIMEタイプの綴り間違い・octet-stream問題・非対応フォーマットの3つの観点から切り分けて、確実に動くコードで解決します。
API / SDK2026-05-30
Gemini 2.5 Pro で thinkingBudget を 0 にすると INVALID_ARGUMENT になる原因と対処
Gemini 2.5 Pro で thinkingBudget を 0 にすると 400 INVALID_ARGUMENT が返る原因を、モデルごとの思考予算レンジの違いから解説します。Pro でレイテンシを抑える正しい書き方と Flash への切り替え判断を Python・JavaScript のコード付きで紹介します。
API / SDK2026-04-14
Veo API で動画生成がうまくいかないとき — エラーと詰まりポイントの完全対処法
Veo API の動画生成でよく起きるエラーを徹底解説。ポーリング実装の落とし穴、セーフティフィルター拒否、クォータ超過、動画ファイル取得失敗など、実際に詰まりやすいポイントと解決策をコード付きで紹介します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →