ツール呼び出し
ツール呼び出し(function calling)は、言語モデルがアプリケーションを通して外部コードを使う仕組みです。会話とツールスキーマを送り、モデルが名前と引数の構造化要求を返します。アプリケーションが実行し、結果を追加して再びモデルを呼びます。本例はクライアント側で実行するツールです。
手紙で相談する相手を考えます。質問、必要な履歴、頼める作業の一覧を送り、相手は回答か作業依頼を返します。get_weather の依頼を受けても、実行して結果を知らせるのは送り手です。呼び出しの記述と関数実行を分けてください。
ツール呼び出しの仕組み
モデル、アプリケーション、ツールの間にアプリケーションが立ちます。API でモデルと話し、実行器で def get_weather(city): ... のような関数を呼びます。モデルからローカル関数へ直接つながる経路はありません。提供者が実行するサーバーツールは別構成です。
以下は教材用の擬似コードです。
def ask(question: str) -> str:
messages = [{"role": "user", "content": question}]
while True:
resp = claude.create(messages=messages, tools=TOOL_SCHEMAS,
tool_choice=CHOICE)
messages.append(assistant(resp.content))
if resp.stop_reason != "tool_use":
return text_of(resp)
results = []
for call in tool_uses_of(resp):
try:
results.append(TOOLS[call.name](**call.input))
except Exception as e:
results.append(f"error: {e}")
messages.append(tool_results(results))
TOOL_SCHEMAS は実装ではなく、名前、説明、引数仕様です。モデルは説明とスキーマ、他の文脈を使って選ぶため、用途と制約を明記します。
本例の stop_reason: "end_turn" は回答、"tool_use" は未実行の要求を示します。このクライアントツール方式ではモデル応答が終わり、アプリケーションへ制御が移ります。実装は max_tokens など他の停止理由も区別し、すべての非 tool_use を完全な成功とは扱いません。
TOOLS[call.name] は名前から関数を引く表です。ツールを追加しても、共通ループへ名前別の分岐を増やす必要はありません。ただし実装、スキーマ、検証、権限規則は必要です。
結果は tool_result ブロックとして user-role メッセージへ入れます。外界からの入力という位置付けです。次の要求は元の質問、assistant の tool_use、対応する結果を含みます。本例の Messages API はクライアントが履歴を管理します。他の API やホストは会話状態を保持でき、HTTP 自体がそれを禁止するわけではありません。
ReAct ループは、この基盤に Thought → Action → Observation を組み立てます。本課はツール分配の箱を開きます。
ツール呼び出しのステップ
初期質問は What's the weather in Tokyo right now?、提供するのは get_weather(city)。天気は固定表であり、現在の実天気ではありません。
- 準備。 messages は質問 1 件、TOOL_SCHEMAS は get_weather です。
- 要求 1。 1 メッセージとツール定義を組み立てます。
- 往復 1。 録画したモデルが天気ツールを選びます。学習済み知識だけでは現在の天気を確かめられません。
- 作業依頼。 抜粋は
{"name": "get_weather", "input": {"city": "Tokyo"}}、停止理由は tool_use。実ブロックの type、id などは表示から省いています。関数はまだ実行されません。 - 記録。 assistant の tool_use を履歴へ追加します。
- 停止理由を確認。
if resp.stop_reason != "tool_use"は偽なので、return せず実行側へ進みます。 - 解析。 name と input から
get_weather(city="Tokyo")を組みます。実行前に検証と認可が必要です。 - 実行。 アプリケーションが関数を呼びます。この間モデルを動かす必要はありません。
- 結果。 固定表から
18°C · rainが返ります。 - 結果を記録。 要求 ID に対応する user-role の tool_result を追加し、質問、依頼、結果の履歴になります。
- 要求 2。 3 メッセージとツール定義を送ります。
- 往復 2。 同じエンドポイントと形で、内容が増えます。
- 回答。 録画回答は東京が今 18°C で雨と述べて傘を勧め、
stop_reason: "end_turn"。温度は関数結果に由来します。 - 記録して終了。 条件が真になり、
return text_of(resp)を実行します。 - 回数。 この 1 ツールの仕事は モデル API 2 回、ツール実行 1 回です。
この例が 2 往復する理由
クライアントツールのプロトコルは tool_use の応答を終え、アプリケーションが結果を次の要求で返します。そのため本例の時間は 2 モデル呼び出しとツール実行が順につながります。すべての HTTP や提供者側ツールに同じ制約があるという意味ではありません。
保持履歴とスキーマは各要求へ入り、入力を増やします。プロンプトキャッシュは重複費用を軽減できます。復旧は往復を増やし、サービスが Springfield, Missouri しか受け付けないのに Springfield を出した例では、モデル呼び出しが 2 回から 3 回になります。
is_error: true の失敗も入力です。録画のエラー本文が有効な名前を列挙し、モデルは次に Springfield, Missouri をそのまま使います。今回の復旧経路の証拠であり、毎回正しく直せる保証ではありません。
境界条件
- ツール不要。
What does HTTP stand for?に天気ツールを付けても、auto の録画は最初から end_turn。API 1 回、ツール 0 回です。 - 関数が例外を出す。 捕捉して処理した tool_result を返し、
is_error: trueと対応 ID を保ちます。機密のスタックをそのまま出さず、失敗も隠しません。本例はエラーの有効キーが修正を助けます。 - UI の
tool_choice: "required"。 デモの統一ラベルです。Anthropic の任意ツール強制はネイティブには{"type":"any"}で、この文字列ではありません。HTTP の意味を問うだけでも要求が生まれ、不要な天気実行を示します。毎回強制すると、毎回ツール呼び出ししか許されず、直接回答できません。デモは初回後に auto へ戻します。強制に頼る前にモデルを確認します。Claude の最新モデル(Opus 5.5、Sonnet 5.5、Fable 5.1)は{"type":"any"}と{"type":"tool"}を 400 エラーで拒否し、Opus 5、Fable 5、OpenAI の"required"はまだ強制します。新しいモデルでは auto と呼び出し指示を使い、スキーマどおりの入力が必要ならstrict: trueを付けます。本課は claude-opus-5-5 を録画したため、強制ラウンドは模擬です。録画スクリプトがプロンプトで、テキストだけの応答は許されないと伝えています。本物の強制より弱く、録画した 3 サンプルのうち 1 つはテキストで答えました。強制するか、特定ツールを選ぶかは目的で決めます。 - 複数要求のまとめ出力。 東京と San Francisco の録画は 2 tool_use を 1 応答で返します。2 回実行し、id を合わせた 2 tool_result を1 user メッセージへ入れるので、追加モデル往復は 1 回です。まとめ出力と並列実行は別で、例の for は順次実行します。
- 存在しない名前や無効引数。 実行前に検証して拒否し、エラーとして返します。モデルの要求を任意コードのように実行しません。
- 無制限ループ。 教材の
while Trueに対し、本番は回数、時間、費用の上限を置き、未完了を明示します。
よくある間違い
- API がローカル関数を実行したと思う。 モデルは要求しただけで、検証、認可、分配はアプリケーションです。
- 依頼履歴や ID を落とす。 assistant の tool_use と結果の順序・対応を契約どおりに保ちます。対応する要求なしに結果だけを送るとエラーになります。
- 前の往復をモデルが勝手に覚えると思う。 この方式はクライアント管理なので、必要履歴を渡します。孤立した結果だけでは質問の文脈がありません。
- 結果の role を間違える。 Anthropic Messages は user が tool_result を運びます。API ごとの形式を混ぜないでください。
- 説明に入力制約がない。 「天気取得」だけでは、サービスの厳密な都市キーが必要だと分かりません。
Springfield, Missouriの例や合法値 enum をスキーマへ示します。
モデルの簡略化
選択、引数、最終回答は、リポジトリにある claude-opus-5-5 の実行記録で、各シナリオの原文 1 件を使います。このモデルは強制 tool_choice を拒否するため、required のセルはプロンプトの制約で強制を模擬しています。再生中はモデルを呼びません。get_weather は 3 都市の表を読みますが、ローカルで実行し、エラーを含む結果を作ります。
コードは擬似コードです。補助関数は呼び出し ID とエラーフラグを保持し、本番は他の stop_reason、検証、権限、予算を扱います。CHOICE は初回後の required → auto 切り替えを展開していません。複数ツール種別、ストリーミング、キャッシュも省きます。ここで示す停止、構造化要求、実行、結果返却、履歴再送はクライアントツールの流れで、全 API 唯一の形式ではありません。
続けて学ぶ
同じ手法につながるレッスンや、次の概念への入口です。
鍵マークのあるレッスンの操作には有料アクセスが必要です。解説はすべて無料で読めます。
誤りや気になる点を見つけましたか? フィードバックを送る。