← ブログに戻る
コラム

Function calling(ツール呼び出し)とは?仕組みと実装の流れ

FastMetal

光の線でつながる六角形の金属ノードのイラスト。Function calling(ツール呼び出し)を表しています

この記事の要点

  • Function calling(tool calling)は、LLMが呼ぶべき関数と引数を返し、アプリのコードが実行する仕組みです。
  • OpenAI形式では tools を送り、tool_calls を受け取り、結果を role: "tool" で返します。往復は最低2回です。
  • 並列呼び出しで複数の依頼が届いたら、全件の結果をそろえてから次を送ります。
  • 出力の形をそろえるだけなら構造化出力、外部の処理を動かすならツール呼び出しを使います。
  • 入力トークンの消費はモデルごとに違い、同じリクエストで約8倍の差が出ました(実測)。

LLMは、今日の在庫数や注文の配送状況を知りません。そこでアプリの関数を道具としてモデルに渡し、必要なときに呼び出しを依頼させます。これがFunction calling(ツール呼び出し)です。コードはFastMetalで実際に動かして確認しました。LLM APIの基本はLLM APIとはで解説しています。

Function calling(ツール呼び出し)とは

Function callingは、LLMが文章の代わりに「この関数を、この引数で呼んでください」という依頼を返す機能です。役割は次のように分かれます。

  • モデル:どの関数をどの引数で呼ぶかを決める
  • アプリ:関数を実行し、結果をモデルに返す
  • モデル:結果を踏まえて回答を書く

データベースの検索や在庫の確認など、モデル単体では届かない処理をつなぐ入口です。検索を関数として渡せば、RAGもこの仕組みで組めます。

function calling、tool calling、tool useの違い

指している仕組みは同じです。OpenAIは2023年にfunction callingとして公開し、のちにパラメータを functions から tools に改めたため、tool callingとも呼ばれます。AnthropicはTool useと呼んでいます。古い記事の functions と function_call は旧形式です。

リクエストからレスポンスまでの流れ

OpenAI形式(Chat Completions)では、次の4段階で進みます。

  1. アプリが質問と tools(使える関数の一覧)を送る
  2. モデルが tool_calls(関数名と引数)を返す
  3. アプリが関数を実行し、結果を role: "tool" で会話に加える
  4. 会話全体を送り直し、モデルが最終的な回答を返す

OpenAIのResponses APIは形式が異なるため、ここではChat Completions形式で説明します。

リクエスト:tools と tool_choice

関数はJSON Schemaで定義します。description はモデルが呼ぶかどうかを判断する材料なので、用途がはっきり伝わる文にします。呼び出し方は tool_choice で指定できます。

値動き
"auto"必要なときだけ関数を呼ぶ(既定)
"none"関数を呼ばずに文章で答える
"required"少なくとも1つの関数を必ず呼ぶ
{"type": "function", "function": {"name": "..."}}指定した関数を必ず呼ぶ

レスポンス:finish_reason と tool_calls

関数を使うと判断したモデルは、finish_reason を "tool_calls" にして、呼び出しの一覧を返します。

"tool_calls": [{
  "id": "call_...",
  "type": "function",
  "function": {
    "name": "get_order_status",
    "arguments": "{\"order_id\": \"A-1001\"}"
  }
}]
  • arguments はJSON形式の文字列なので、json.loads() で辞書に変換してから使います。
  • id は結果との照合に使います。実測では call_、tooluse_、chatcmpl-tool- で始まる値が返り、形式はモデルごとに違いました。受け取った値をそのまま使います。
  • finish_reason が "stop" なら、モデルは関数を使わずに回答しています。

結果を返す:role: "tool" と tool_call_id

tool_calls を含むassistantメッセージを履歴に戻し、続けて結果を role: "tool" で加えます。tool_call_id に対応する id を入れ、会話をもう一度送ります。

Pythonでの実装例

FastMetalはOpenAI互換APIに対応しているため、OpenAIの公式SDKで base_url を差し替えるだけで呼び出せます。注文の配送状況を調べる関数を1つ渡す例です。

import json
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["FASTMETAL_API_KEY"],
    base_url="https://api.fastmetal.ai/v1",
)
MODEL = "gemini-flash-lite-free"

def get_order_status(order_id: str) -> dict:
    # 実際には社内の注文データベースやAPIを参照します
    return {"order_id": order_id, "status": "発送済み"}

tools = [{
    "type": "function",
    "function": {
        "name": "get_order_status",
        "description": "注文番号から、その注文の配送状況を調べる",
        "parameters": {
            "type": "object",
            "properties": {
                "order_id": {"type": "string", "description": "注文番号(例:A-1001)"},
            },
            "required": ["order_id"],
        },
    },
}]

messages = [{"role": "user", "content": "注文A-1001とA-1002の状況を教えて"}]

# 1回目:どの関数を、どの引数で呼ぶかをモデルに決めてもらう
first = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
msg = first.choices[0].message

if msg.tool_calls:
    messages.append(msg)  # tool_calls を含む assistant メッセージを履歴に戻す
    for call in msg.tool_calls:  # 並列呼び出しでは複数件が入る
        args = json.loads(call.function.arguments)  # JSON文字列を辞書に変換
        if call.function.name == "get_order_status":
            result = get_order_status(args["order_id"])
        else:
            result = {"error": "unknown function"}
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps(result, ensure_ascii=False),
        })
    # 2回目:実行結果を踏まえた回答を受け取る
    final = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
    print(final.choices[0].message.content)
else:
    print(msg.content)

2026年10月6日に、このコードを gemini-flash-lite-free、deepseek-v4-flash、anthropic-claude-haiku-4-5 で実行し、3モデルとも1回目で2件の呼び出しを、2回目で回答を返しました。ループ化までの手順はツール呼び出しの実装チュートリアル、APIキーの発行はAPIの始め方で解説しています。

並列呼び出し(parallel tool calls)

上の例のように、1回の応答で複数の呼び出しが返ることを並列呼び出しといいます。互いに依存しない処理を、往復を増やさずにまとめて依頼できます。

  • tool_calls は複数ある前提で、ループで処理する
  • すべての呼び出しに、tool_call_id 付きの結果を返す
  • 全件の結果をそろえてから、次のリクエストを送る

結果が1件でも欠けると、エラーを返すモデルがあります。順番が大事な処理では parallel_tool_calls を false にすると、1回に呼ぶ関数を0件か1件に絞れます(効くかどうかはモデルによります)。

構造化出力とツール呼び出しの使い分け

どちらもJSONを扱いますが、目的が違います。

構造化出力ツール呼び出し
指定するものresponse_format にJSON Schematools に関数の定義
返ってくるものスキーマに沿った回答そのもの呼びたい関数名と引数
往復1回2回以上
向いている場面抽出、分類、要約の形をそろえる検索、データベース参照、外部APIの実行

JSONで項目を受け取りたいだけなら、往復が1回で済む構造化出力が簡単です。外部の情報の取得や処理の実行には、ツール呼び出しを使います。書き方は構造化出力(JSON)のチュートリアルにまとめています。

対応状況とトークン消費はモデルごとに違う

FastMetalはOpenAI形式のツール呼び出しと構造化出力に対応しており、model を差し替えるだけで各社のモデルを試せます。ただし対応や精度はモデルごとに異なるため、モデル一覧から各モデルのページを開き、「サポートされているパラメータ」に tools があるかを確認してください。

関数の定義は毎回プロンプトに含まれ、入力トークンとして課金されます。上のコードの1回目のリクエストで、入力トークン数をモデルごとに比べました。

モデル入力トークン(prompt_tokens)
gemini-flash-lite-free91
deepseek-v4-flash319
anthropic-claude-haiku-4-5706

2026年10月6日にFastMetal経由で実測しました。条件は同じでも、定義をプロンプトに組み込む方法がモデルごとに違うため、約8倍の差が出ています。料金は100万トークンあたりの従量課金なので、ツールを多用するアプリではモデル選びがコストに響き、コンテキストウィンドウの消費も増えます。

model に "auto" を指定すると、ツールなどの要件を満たすモデルのうち最も安いものにFastMetalが振り分けます。課金は選ばれたモデルの料金です。

次のステップ:エージェントとMCP

ツール呼び出しを、モデルが関数を呼ばなくなるまで繰り返すと、エージェントの基本形になります。Claude Codeのようなコーディングエージェントもこの仕組みで動き、1つのタスクで数十回から数百回、会話を送り直しながらモデルを呼ぶため、コストの大半は入力トークンです。

MCP(Model Context Protocol)は、ツールの公開と接続の方法をそろえた共通の規格です。MCPサーバーのツールは、クライアントを通じて最終的に tools としてモデルに渡されます。詳しくはMCPとはをご覧ください。

FastMetalの組み込みMCPサーバー(https://mcp.fastmetal.ai/mcp)を使えば、他のモデルへの質問や画像生成などのツールを、Claude Codeなどにコマンド1つで追加できます。設定方法はMCPガイドにあります。

よくある失敗

arguments を文字列のまま使う

json.loads() を通さずに辞書として扱うと、その場でエラーになります。

assistantメッセージを履歴に戻し忘れる

結果より先に、tool_calls を含むassistantメッセージを履歴に入れます。独自の情報を添えるモデルもあるため、組み立て直さずにそのまま戻します。

ループに上限を付けない

同じ呼び出しが繰り返され、課金が積み上がることがあります。往復回数には上限を設けます。FastMetalならAPIキーごとに残高の上限も設定できます。

引数を検証しない

存在しない関数名や、必須項目の欠けた引数が返ることがあります。ユーザーの入力と同じように検証し、送金や削除のような処理には人の確認を挟みます。渡す関数も、その場面で必要なものに絞ると選び間違いが減ります。

よくある質問

モデルが関数を実行するのですか

いいえ。モデルが返すのは「どの関数を、どの引数で呼ぶか」という依頼だけです。実行するのはアプリ側のコードで、その結果を返すと、モデルが最終的な回答をまとめます。

RAGとFunction callingの違いは何ですか

RAGは、関連する文書を検索してプロンプトに加え、回答させる手法です。Function callingは、モデルが関数の実行を依頼する仕組みです。検索を関数として渡せば、RAGをFunction callingで組むこともできます。

Function callingとMCPはどう違いますか

Function callingは、モデルとアプリが関数の呼び出しをやり取りするAPIの仕組みです。MCPは、ツールの公開と接続を標準化したプロトコルで、MCPでつないだツールも最終的にはtoolsとしてモデルに渡されます。

無料で試せますか

アカウントの作成は無料で、gemini-flash-lite-freeなどの無料モデルは¥0で使えます。この記事のコードも同じモデルで確認しました。有料モデルは¥500から購入できるクレジットによる従量課金です。


FastMetalで試す

FastMetalは、95以上のLLM・生成AIモデルをOpenAI互換APIで呼び出せる、日本のAIゲートウェイです。同じツール呼び出しのコードのまま、各社のモデルを比べられます。円建てのプリペイドで、クレジット購入ごとに適格請求書を発行します。

無料でアカウントを作成 | 料金を見る | OpenAI互換APIとは

参考リンク

最新のAIモデルを今すぐ試す

最新のAIモデルはFastMetalのAPIキー1つで利用できます。ブラウザですぐに試す、またはOpenAI SDKからそのまま呼び出せます。