ツールの利用 / 関数呼び出し
ツールの利用により、Claude はあなたが定義した関数——検索、計算機、あなたのデータベース、任意の API——を呼び出して、その結果を使えます。これはあらゆるエージェントの基盤です。
ほとんどのツール利用チュートリアルは、4ステップのループで話を終えます。ループは簡単な部分です。本番の連携を実際に壊すのは、もっと狭くて語られにくいところです:400 を返すメッセージの形、Claude が謝る代わりに回復できるようにするエラーフィールド、そして最新の Claude モデルではツール呼び出しの強制がもう効かないという事実。このページではそのすべてを扱います。
- 4ステップのエージェント型ループが、ツール定義から最終的な答えまでどう動くか
- ツール定義の書き方——そして Claude がいつ呼ぶかを実際に左右する説明の書き方
- 400 を返す3つのメッセージ形状ルールと、どれを破ったのか教えてくれるエラーテキスト
- tool_choice の "any" と "tool" が最新モデルで失敗するようになった理由と、2つの代替手段
- strict: true でスキーマ準拠のツール入力を保証する方法
- ツール結果が、プロンプトインジェクションがあなたのエージェントに到達する最も可能性の高い場所である理由
ループ
ツールの利用は単一の呼び出しではなく会話です。あなたが Claude にツールのメニューを渡し、Claude が1つを選んで一時停止し、あなたが実行して報告し、Claude がその結果を答えに織り込む——必要に応じて繰り返します。
- ツール定義のリストを含めます——それぞれに名前、説明、JSON-Schema 入力があります。
- Claude が1つを使うと決めると、レスポンスは stop_reason "tool_use" と、1つ以上の tool_use ブロック(それぞれ id、name、input オブジェクトを持つ)とともに返ってきます。
- あなた自身がツールを実行し、その出力を tool_use の id を参照する tool_result として返します。
- Claude は、通常の stop_reason で答えるまで、場合によってはさらにツールを呼び出しながら続行します。
ステップ2の複数形に注意してください:Claude は1回のレスポンスで複数の tool_use ブロックを返せます。content[0] を決め打ちせず、各ブロックの type フィールドで振り分けてください——レスポンスは通常 text ブロックで始まり、最新モデルでは代わりに thinking ブロックで始まることもあります。
ツールを定義する
ツール定義は、名前、平易な言葉の説明、そして入力の JSON Schema です。
| フィールド | 必須 | 補足 |
|---|---|---|
name | はい | 正規表現 ^[a-zA-Z0-9_-]{1,128}$ に一致する必要があります |
description | はい | 何をするか、いつ使うか、いつ使わないか。最低でも3〜4文を目指します |
input_schema | はい | パラメータを記述する JSON Schema オブジェクト |
input_examples | いいえ | 例となる入力オブジェクトの配列。それぞれがスキーマに対して有効であること |
strict | いいえ | true にするとスキーマ準拠の入力を強制します——下記参照 |
cache_control | いいえ | ターンをまたいで定義をキャッシュします(プロンプトキャッシュを参照) |
get_weather ツール + 最初の呼び出し(Python)
tools = [{
"name": "get_weather",
"description": (
"Get the current weather for a city. Use this when the user asks about "
"present conditions or temperature in a named place. Returns temperature "
"in the requested unit plus a one-word sky condition. It does NOT return "
"forecasts — use get_forecast for anything in the future."
),
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City and region, e.g. 'Rome, IT'"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["city"],
"additionalProperties": False,
},
}]
msg = client.messages.create(
model="claude-opus-5-5", max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "What's the weather in Rome?"}],
)
if msg.stop_reason == "tool_use":
for block in msg.content: # iterate — never index content[0]
if block.type == "tool_use":
result = run_tool(block.name, block.input)
# send back a tool_result carrying block.id説明はプロンプト
description フィールドは、ツール利用の品質に対して圧倒的に最も強いレバーです——これを読むのはチームメイトではなくモデルです。何が良い説明を分けるのかについて、Anthropic 自身のガイダンスは明快です:
- いつ使わないかを書く。 選択ミスの多くは、隣接するツールが担う仕事のためにそのツールが呼ばれるケースです。
- 増やすのではなく統合する。
create_pr、review_pr、merge_prの代わりに、actionパラメータを持つ1つのツールを出荷しましょう。少なく広いツールのほうが選択の曖昧さを減らします。 - サービスをまたいで名前空間を付ける。 ツールの面が広がれば、
github_list_prsとslack_send_messageのほうがlist_prsとsend_messageに勝ります。 - シグナルの高い結果を返す。 安定した意味のある識別子(slug、UUID)と、Claude が次のステップを選ぶのに必要なフィールドだけ。膨れたツール出力はコンテキストを焼き、シグナルを埋もれさせます。
- 扱いが面倒な入力には
input_examplesを足す。 スキーマ検証される例は、単純なオブジェクトなら1つあたりおよそ 20〜50 トークン、複雑にネストしたものなら 100〜200 トークンかかり、無効な例は 400 を返します。
レスポンスを処理する:400 を返す3つのルール
動いていたコードが壊れるのは、たいていここです。tool_result はごく普通の user メッセージですが、3つの配置ルールが API によって強制されます。
- assistant の tool_use メッセージとあなたの tool_result メッセージの間には、どんなメッセージも入れられません。これを破ると API はこう報告します:tool_use ids were found without tool_result blocks immediately after。
- あなたが足すテキストは、すべての tool_result のあとに来なければなりません。tool_result より前の text ブロックは 400 です。
- 同じ assistant のターンが、まだ結果のないサーバーツールも呼んでいた場合、末尾にテキストを足すとターンが早く終わってしまい、リクエストは未解決のサーバーツール名を挙げた 400 で失敗します。
// ❌ 400 — text before tool_result
{"role": "user", "content": [
{"type": "text", "text": "Here are the results:"},
{"type": "tool_result", "tool_use_id": "toolu_01", "content": "15 degrees"}
]}
// ✅ correct — results first, text after (client tools only)
{"role": "user", "content": [
{"type": "tool_result", "tool_use_id": "toolu_01", "content": "15 degrees"},
{"type": "text", "text": "What should I do next?"}
]}
tool_result の content は、プレーンな文字列でも、text・image・document・search_result ブロックのリストでもかまいません。何も返さないツールなら、完全に省略することもできます。
失敗は例外ではなく結果として返す
ツールが例外を投げたとき、ループを中断しないでください——is_error で失敗を返しましょう:
{"role": "user", "content": [{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "Rate limit exceeded. Retry after 60 seconds.",
"is_error": true
}]}
メッセージは、次に何をするか決めなければならない読み手に向けて書いてください。"failed" は Claude に何も伝えませんが、"Rate limit exceeded. Retry after 60 seconds." は即座に再試行するのではなく待つように伝えます。ツール呼び出しが無効だったりパラメータが欠けていたりすると、Claude は通常2〜3回、修正しながら再試行してから諦めてユーザーに謝ります——つまり、指示的なエラーが回復と行き止まりの分かれ目になることがよくあります。
スキーマ準拠の入力を保証する:strict: true
ツール定義に strict: true を設定すると、モデルのトークンサンプリングがスキーマ準拠の出力に制約されます(文法制約付きサンプリング)。これにより、すべての tool_use ブロックの input はあなたの input_schema に一致することが証明でき、name は常に実在するツールになります——2 が必要なところに "2" が来ることも、必須フィールドの欠落も、検証して再試行する層も、もうありません。
strict なツール定義
{
"name": "search_flights",
"description": "Search bookable flights for a route and date.",
"strict": true,
"input_schema": {
"type": "object",
"properties": {
"destination": {"type": "string"},
"departure_date": {"type": "string", "format": "date"},
"passengers": {"type": "integer", "enum": [1, 2, 3, 4, 5, 6]}
},
"required": ["destination", "departure_date"],
"additionalProperties": false
}
}どこでも有効にする前に、知っておく価値のある3つの注意点:
- スキーマは、サポートされている JSON Schema のサブセット内に収めなければなりません——構造化出力が使うものと同じサブセットです。
- コンピュータ利用とブラウザ利用のツールセットエントリは
strict: trueを受け付けません。どちらかに設定したリクエストは拒否されます。 - コンパイルされたスキーマは、メッセージ内容とは別に最大24時間キャッシュされます。Anthropic のガイダンスは明示的です:保護対象保健情報をスキーマに入れないでください——プロパティ名、
enumの値、constの値、patternの正規表現のいずれにも。PHI はメッセージ内容に置くべきであり、そこにはキャッシュされたスキーマにはない HIPAA の保護措置が効いています。
tool_choice ——そしてツールの強制がいま失敗する理由
tool_choice は、Claude がツールを呼ぶことができるのか、しなければならないのか、できないのかを制御します。4つの値を取ります:
| 値 | 意味 |
|---|---|
auto | Claude が決めます。tools がある場合のデフォルト |
any | Claude はあなたのツールのいずれかを必ず呼びますが、どれを呼ぶかは自分で選びます |
tool | Claude は指定された名前のツールを必ず呼びます |
none | Claude はどのツールも呼べません。tools がない場合のデフォルト |
ここが、他のどのツール利用ガイドも今のところ取り落としている部分です。any と tool はどこでもサポートされているわけではなく、最新モデルでは 400 を返します。
| モデルまたは設定 | 制限 | 代わりに使うもの |
|---|---|---|
手動の拡張思考(thinking の type が enabled) | any と tool がエラーになります | auto または none。適応的思考はそれ単体ではツール呼び出しの強制を妨げません |
| Claude Opus 5.5、Sonnet 5.5、Fable 5.1、Mythos 5.1 | 思考の設定にかかわらず any と tool が 400 を返します | auto + strict: true、または構造化出力。none は引き続き動きます |
エラーは明示的です:
tool_choice: type "tool" and "any" are not supported for this model.
同じ検証はトークンカウントのエンドポイントにも適用されるので、トークンカウントを通ったリクエストがあとで驚かせることはありません。
代わりにどうするか
2つの動機を切り分ければ移行は明らかになります。というのも、ツール呼び出しの強制は無関係な2つの仕事をしていたからです:
- 「スキーマ準拠の JSON が必要だ」 これは実のところ、呼び出しを強制する話ではありませんでした。
tool_choiceをautoのままにしてstrict: trueを設定するか、呼び出しではなくレスポンスが欲しいならスキーマを構造化出力に移しましょう。 - 「おしゃべりではなく、ツールを呼んでほしい」 それをプロンプトで言ってください。そのツールがいつ当てはまるかを明記すること——「現在の状況に関する質問には
get_weatherを使うこと」——は、autoがどのツールを選ぶかを今も左右します。
ツール呼び出しの強制を手放すことには、おまけもあります:any と tool は assistant メッセージをプリフィルすることで動いていたため、tool_use ブロックの前の自然言語の前置きが抑制されていました。auto のもとでは、Claude はこれから何をしようとしているのかを説明できます——ユーザーに見えるエージェントでは、たいていそれが望ましい挙動です。
会話の途中で tool_choice を変更すると、キャッシュされたメッセージブロックが無効化されます。ツール定義とシステムプロンプトはキャッシュされたままですが、メッセージ内容は再処理が必要になります。ターンごとに tool_choice を切り替えていたなら、それは静かにコストを生んでいました——プロンプトキャッシュを参照。
クライアントツール vs. サーバーツール
すべてのツールに、あなたのコードベース内のハンドラが必要なわけではありません。
- クライアントツール——あなたのもの。あなたがスキーマを定義し、実行し、
tool_resultを返します。上のループです。 - Anthropic スキーマのクライアントツール——bash、テキストエディタ、メモリ。スキーマはあらかじめ定義されていますが、実行するのは依然としてあなたのアプリです。
- サーバーツール——ウェブ検索、ウェブ取得、コード実行、ツール検索。あなた側にハンドラのコードなしで Anthropic のインフラ上で実行され、エラーは透過的に処理されます:サーバーツールに対して
is_errorを返すことは決してありません。 - クライアントツールセット——コンピュータ利用とブラウザ利用は、
nameを持たない単一のエントリで、固定のメンバーツール群を宣言します。それらのtool_useブロックには追加のtoolset_nameフィールド("computer"または"browser")が付き、nameは呼ばれているメンバー(screenshotやnavigateなど)になります。両方のフィールドで振り分け、結果にはtoolset_nameを返し返してください——これを省いたメンバー結果は拒否されます。
よくある間違い
content[0]をインデックス参照する——反復処理してtypeで分岐する代わりに。レスポンスはよくtextブロックで始まり、最新モデルではthinkingブロックで始まります。- 1レスポンスにつき
tool_useを1つしか処理しない。 Claude は1ターンで複数のツールを呼べます。最初の1つに答えて残りを捨てるループは、tool_useの id を結果なしで残し、それは次のリクエストで 400 になります。 - あなたのコメントを結果より前に置く。
tool_resultブロックは常に先です。 - ツールの例外を飲み込む。 ハンドラ内の例外はループを終わらせます。
is_errorの結果は Claude に適応させます。 - 習慣で
tool_choice: "any"に手を伸ばす。 現在のフラッグシップモデルではそれは 400 です——そしてどちらにせよstrict: trueのほうが良い答えでした。 - ツール出力を信頼できるものとして扱う。 下記を参照。
ツール結果には、あなたが制御できないコンテンツが日常的に入ってきます:ウェブページ、受信メール、ユーザーのアップロード、サードパーティ API。そのいずれかに影響を与えられる攻撃者は、あなたのモデルを狙った命令を埋め込めます——間接プロンプトインジェクションです。信頼できないコンテンツは、必ず tool_result ブロックの中に留め、system プロンプトやプレーンなユーザーの text ブロックに継ぎ足すことは決してせず、プロンプトインジェクションとエージェントとツールのセキュリティ確保を読んでください。実際のアクションを取るツールは、セキュリティモデルも引き継ぎます:最小権限、そして取り返しのつかないことには人の介在を。
理解度チェック
0/4- ツールの利用はループ:ツール定義を送り、Claude が1つ以上の tool_use ブロックを返して停止し、あなたが実行して tool_result を返し、Claude が続ける。content ブロックは type で反復処理する——決して content[0] をインデックス参照しない。
- 400 の大半は3つの配置ルールが原因:結果は対応する tool_use の直後に来なければならない、tool_result ブロックは content 配列の先頭に来る、未解決のサーバーツール呼び出しがあるなら結果のみを送る。
- 最新モデルではツール呼び出しの強制がなくなった:tool_choice の "any" と "tool" は Opus 5.5、Sonnet 5.5、Fable 5.1、Mythos 5.1 で 400 を返す。auto と strict: true を使うか構造化出力を使い、ツールの選択はプロンプトから誘導する。
- strict: true は文法制約付きサンプリングでスキーマ準拠の入力を保証する——ただし PHI はスキーマに入れず、computer/browser のツールセットエントリには設定しない。
- 失敗は is_error と指示的なメッセージを付けた tool_result として返し、Claude が謝る代わりに適応できるようにする。
- ツール結果は、間接プロンプトインジェクションがあなたのエージェントに到達する最も可能性の高い経路——信頼できないコンテンツはその中に留め、最小権限を適用し、取り返しのつかないアクションには人のゲートを置く。
次へ
- プログラマティックツール呼び出し — サンドボックス内の Python から Claude に同じツールを呼ばせ、往復回数を削り、中間結果をコンテキストの外に保つ
- 構造化出力 — ツール呼び出しの強制の置き換えのもう半分。呼び出しではなく JSON のレスポンスが欲しいとき
- API でエージェントを構築する — このループを本物のエージェントで包む
- Claude Opus 5.5: フィールドガイド — ツール呼び出しの強制が削除された背景にある移行の全体像
- MCP & ツールへの接続 — 自分で定義する代わりにサーバーからツールを取得する