ツール使用(Function Calling):LLMに外部世界を触らせる
テキストを書くだけのLLMを、検索やAPI呼び出しまでこなす実行主体へ引き上げるのがFunction Callingだ。関数スキーマを渡すとモデルが呼び出しをJSONで指示し、ホストが実行して結果を戻す。この一往復の設計を理解できる。
- ツール使用(Function Calling)は、実行可能な関数の名前・説明・引数の型をスキーマとしてLLMに渡し、モデルが「どの関数をどの引数で呼ぶか」をJSONで返すパターンだ。モデル自身は関数を実行せず、実行はあくまでホスト側が担う。
- 基本はツール定義の提示→モデルが呼び出しを出力→ホストが実行→tool_resultを返却、の往復だ。モデルは結果から回答するか次のツールを呼び、独立した複数ツールなら並列化もできる。
- 呼び出しの精度は、ツールの説明文と引数スキーマの明快さでほぼ決まる。曖昧な説明は誤ったツール選択や引数の欠落を招く。実行時のエラーやツールの不在も想定し、失敗を構造化してモデルへ戻す設計が、堅牢なエージェントの前提になる。
横にスクロール
どんなパターンか
大規模言語モデル(LLM)は、本来テキストを受け取ってテキストを返すだけの存在だ。学習した知識の範囲でしか答えられず、いまの天気も、社内データベースの在庫数も、電卓のように正確な計算結果も、モデル単体では知り得ない。だが現実のアプリケーションでは、モデルに外部の情報を参照させ、あるいは外部へ働きかけてほしい場面が大半を占める。
ツール使用(tool use)、別名Function Callingは、この隔たりを埋める設計パターンだ。ホスト側のアプリケーションが「呼び出せる関数(ツール)」の一覧を、名前・説明・引数の形式を記したスキーマとしてモデルに渡す。するとモデルは、ユーザーの要求を満たすために「どのツールを、どんな引数で呼ぶべきか」を判断し、その指示を構造化されたJSONで返す。関数を実際に実行するのはホストであり、モデルはあくまで「呼び出しの意図」を出力するだけだ。
この役割分担が要点である。モデルは自然言語の理解と判断に徹し、実行という副作用を伴う操作はホストが握る。こうしてLLMは、検索・計算・API呼び出し・データベース参照といった手段を通じて、初めて外部世界に手を伸ばせる。ツール使用は、単なるテキスト生成器を「行動するエージェント」へ引き上げる、最も基礎的な一歩だ。
裏を返せば、ツールを与えなければモデルは知らないことを推測で埋め、もっともらしい誤りを述べかねない。ツール使用は、その推測を実データの参照や確実な計算へ置き換える仕組みでもある。事実に基づく回答が要るほど、この置き換えの価値は大きくなる。
仕組み
ツールの定義(スキーマ)
出発点は、ツールをスキーマとして記述することだ。最低限必要なのは、ツールの名前、何をするかの説明、そして受け取る引数の型である。次は「都市の天気を取得するツール」の定義例だ。
{
"name": "get_weather",
"description": "指定した都市の現在の天気を取得する。ユーザーが天気・気温・降水を尋ねたときに使う。",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "都市名。例: Tokyo, Osaka"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "気温の単位。既定はcelsius。"
}
},
"required": ["city"]
}
}
引数の型はJSON Schemaで記述するのが一般的で、必須の引数、列挙できる値、既定値などを表現できる。ここで決定的に重要なのが説明文(description)だ。モデルはこの説明を読んで、どのツールがいまの状況に適合するかを選ぶ。つまり説明文は、モデルに対する小さなプロンプトそのものであり、その良し悪しが呼び出しの精度を直接左右する。
モデルはツールの説明文だけを手がかりに、そのツールをいつ呼ぶかを決める。「何をするツールか」に加えて「どんなときに使い、どんなときは使わないか」まで書くほど、選択の精度は上がる。引数の一つ一つにも短い説明を添えるとよい。
呼び出しから結果返却までの一往復
ツールを定義したら、実際のやり取りは次の流れをたどる。
1. ホスト → モデル : ユーザーの質問 + ツール定義の一覧
2. モデル → ホスト : tool_use(呼ぶツール名と引数のJSON)
3. ホスト : 引数を検証し、対応する関数を実行
4. ホスト → モデル : tool_result(実行結果、または is_error)
5. モデル → ホスト : 最終回答、あるいは次の tool_use
ユーザーが「東京の天気を知りたい」と伝えたとする。モデルはget_weatherが適切だと判断し、次のような呼び出しを返す。実行はまだ行われていない点に注意したい。これは「このツールをこの引数で呼んでほしい」という要求にすぎない。
{
"type": "tool_use",
"id": "toolu_01A09q90qw",
"name": "get_weather",
"input": { "city": "Tokyo", "unit": "celsius" }
}
ホストはこのJSONを受け取り、引数を検証したうえで、対応する関数を実行する。得られた結果は、同じ呼び出しを指し示すtool_use_idを添えて、tool_resultという形でモデルに戻す。
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw",
"content": "{\"temp_c\": 22, \"condition\": \"晴れ\"}"
}
モデルはこの結果を読み、「東京は晴れ、気温は22度だ」といった最終的な自然言語の回答を組み立てる。ここまでが基本の一往復である。結果を見たモデルが、さらに別のツールを続けて呼ぶこともある。
実装上は、モデルのtool_use出力もホストが戻すtool_resultも、そのまま会話履歴に積み重なっていく。ホストは、モデルがツールをもう呼ばなくなる——通常のテキスト応答で終わる——まで、この往復をループで回す。つまりツール使用の一回一回は独立した魔法ではなく、履歴を育てながら進む対話の一部だ。
並列呼び出しとエラーの扱い
一度の応答で複数のツールをまとめて要求する並列ツール呼び出しにも、多くのモデルが対応する。「東京と大阪の天気」を同時に求められれば、モデルは2つの呼び出しを一度に返し、ホストはそれぞれ実行して2つの結果を戻せる。往復の回数を減らせるため、応答が速くなる。
実行は必ず失敗しうる。都市が見つからない、外部APIがタイムアウトする、引数が不正だ——こうした失敗は、握りつぶさずに構造化してモデルへ返すのがよい。
{
"type": "tool_result",
"tool_use_id": "toolu_01B77x12de",
"is_error": true,
"content": "CityNotFound: 指定された都市が見つからない"
}
is_errorを立てて理由を伝えれば、モデルは引数を直して呼び直したり、別の手段に切り替えたりと、回復に向けて振る舞える。モデルとホストの責任分担を整理すると次のようになる。
| 段階 | モデル(LLM) | ホスト(アプリ) |
|---|---|---|
| ツールの提示 | スキーマを読む | 定義を渡す |
| 呼び出しの決定 | ツール名と引数をJSONで返す | — |
| 実行 | — | 関数を実際に走らせる |
| 結果の受け取り | tool_resultを解釈し次を判断 | 結果を構造化して返す |
使いどころと注意
ツール使用が生きるのは、モデル内部の知識だけでは答えが閉じない場面だ。代表的なのは、最新情報の取得(天気・在庫・料金)、社内データベースやドキュメントの検索(いわゆるRAGの検索部分)、正確さが要る計算、そして外部システムへの操作——チケットの起票やメールの下書き作成といったアクションである。いずれも「モデルが判断し、ツールが現実を担う」構図に落ちる。
設計上の注意点はいくつかある。
第一に、説明文と引数スキーマの質がすべてに優先する。曖昧な説明は、誤ったツール選択や引数の取り違え、必須引数の欠落を招く。ツール名は動詞+目的語で具体的に、説明文には「いつ使うか」「いつ使わないか」まで書くと精度が上がる。
第二に、ツールの数を絞る。候補が多すぎるとモデルは選択を誤りやすい。関連するツールだけを、その時々の文脈に応じて渡すのが定石だ。
第三に、副作用を伴うツール——課金・送信・削除など——は、実行前の確認や権限チェックといった歯止めと組み合わせる。この観点はガードレールで扱う、エージェント設計の独立した論点である。
モデルが返す引数は、外部から来た未検証の入力と同じ扱いをする。型・範囲・権限をホスト側で必ず確かめ、確認を通らない呼び出しは実行しない。この一線が、ツールに実行権限を与えるうえでの生命線になる。
そして、ツール使用は単発で完結するとは限らない。結果を見て次の手を考え、必要なら何度もツールを呼ぶ——こうした思考と行動の反復は、ReActパターンとして体系化されている。ツール使用は、その反復を支える「行動」の部品にあたる。
まとめ
ツール使用(Function Calling)は、LLMにツールのスキーマを渡し、モデルが呼び出しをJSONで指示し、ホストが実行して結果を戻す——この一往復を核とするパターンだ。モデルは判断に、ホストは実行に責任を持つという分担が、安全に外部世界へ手を伸ばすための土台になる。呼び出しの精度を決めるのは説明文の明快さであり、失敗を構造化して戻す設計が堅牢さを生む。ほかのエージェント設計パターンは設計パターン一覧から辿れる。
AIエージェント設計の記事ガイド
ツール使用(Function Calling):LLMに外部世界を触らせるを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
AIエージェント
比較で見る軸
難易度: advanced / カテゴリ: AIエージェント設計 / タグ数: 4
導入後に効く点
基本はツール定義の提示→モデルが呼び出しを出力→ホストが実行→tool_resultを返却、の往復だ。モデルは結果から回答するか次のツールを呼び、独立した複数ツールなら並列化もできる。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- AIエージェント設計
- タグ数
- 4
判断チェックリスト
- 自社の用途が「AIエージェント / LLM」に近いか確認する。
- 強みである「ツール使用(Function Calling)は、実行可能な関数の名前・説明・引数の型をスキーマとしてLLMに渡し、モデルが「どの関数をどの引数で呼ぶか」をJSONで返すパターンだ。モデル自身は関数を実行せず、実行はあくまでホスト側が担う。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。