Claude Media
Claudeのstrict tool useが保証すること・しないこと

Claudeのstrict tool useが保証すること・しないこと

strict: trueが保証するのはinput_schema準拠とツール名の妥当性だけです。additionalProperties:false必須化とpatternの部分対応、複雑さ上限まで仕様で確認します。

背景 — ツール呼び出しに「保証」が必要になった理由

Claudeにツールを呼ばせるとき、通常のツール定義はモデルの推論任せです。passengersint型のパラメータでも、Claudeが"2"という文字列や"two"という単語を返すことがあります。型が合わなければ、呼び出し側のコードは実行時エラーで落ちるか、余分なバリデーションと再試行のロジックを挟むことになります。

ツール定義にstrict: trueを1つ足すと、この不確実性が構造的に消えます。グラマー制約サンプリング(grammar-constrained sampling)という技術で、モデルのトークンサンプリング自体をスキーマに適合する出力だけに絞り込む仕組みです。プロンプトで「型を守ってください」と頼むのではなく、スキーマ違反のトークン列がそもそも生成され得ないところまで踏み込みます。

この技術は、Claude APIの構造化出力(output_config.format)が応答全体に使っているグラマーコンパイルの仕組みと同じ基盤を共有しています。Agent SDKの構造化出力がエージェントの最終応答全体をスキーマに固定するのに対し、strict tool useは個々のツール呼び出しの入力だけをスキーマに固定します。適用範囲が違うだけで、対応するJSON Schemaのサブセットや複雑さの上限は共通です。Claude Codeの--json-schemaフラグでスキーマが複雑すぎるときに出るschema too largeという診断も、この複雑さ制約と同じ性質の症状に見えます。ネストと$refの再利用を減らすと解消する点まで、両者は共通しています。

strict: trueの使い方 — 3ステップ

手順はシンプルです。

  1. input_schemaを、サポート対象のJSON Schemaサブセットで書く
  2. ツール定義のトップレベルに"strict": trueを追加する(namedescriptioninput_schemaと同じ階層)
  3. 返ってくるtool_useブロックのinputをそのまま使う(バリデーションと再試行のコードが不要になる)
curl https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-opus-5",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "What is the weather in San Francisco?"}],
    "tools": [{
      "name": "get_weather",
      "description": "Get the current weather in a given location",
      "strict": true,
      "input_schema": {
        "type": "object",
        "properties": {
          "location": {"type": "string"},
          "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
        },
        "required": ["location"],
        "additionalProperties": false
      }
    }]
  }'

保証されること

公式ドキュメントが明言している保証は2つだけです。

  • ツールのinputが、input_schemaに厳密に従う
  • ツールのnameが、常に妥当な値になる(渡したツール一覧またはサーバーツールの中から)

型が一致しない・必須フィールドが欠ける・スキーマに無いプロパティが混ざる、といった不整合はこの2点で構造的に防がれます。バリデーションと再試行のコードを書かずに済むのは、この2つの保証が実行時エラーの主な原因を潰しているからです。冒頭のpassengers: intの例で言えば、strict tool useを有効にした時点でresponse.content[x].input.passengersは必ず整数として返ります。文字列や単語が混ざる余地は、構造的になくなります。

保証されないこと — 保証の輪郭

「厳密に守る」という言葉は強く聞こえますが、保証が及ぶ範囲はツールのinputnameの2つだけです。それ以外の場面では、非対応スキーマや通常の応答生成と同じ落とし穴が残ります。

  • 拒否(refusal): Claudeが安全性の観点でリクエストを拒否すると、stop_reasonrefusalになります。200ステータスで返り、生成されたトークン分の課金も発生しますが、出力はスキーマに従いません。拒否メッセージがスキーマ制約より優先されるためです
  • max_tokens到達による打ち切り: stop_reasonmax_tokensになった場合、出力は途中で切れており、スキーマに一致しない可能性があります。完全な出力を得るにはmax_tokensを増やして再試行します
  • enumの大文字小文字: enumconstの値は、スキーマに書いた表記と大文字小文字だけが違う値が返ることがあります(単語の先頭文字など)。エラーにはならず、200で正常終了します。enumの値は大文字小文字を無視して比較する設計にしておく必要があります

保証は「スキーマに従った形」に閉じており、「必ず成功する」「必ず呼び出しに到達する」という意味ではありません。拒否と打ち切りは、strict tool useを使っていても消えない例外です。実装側では、stop_reasontool_useだけでなくrefusalmax_tokensも含めて分岐させる必要があります。後者2つでは、inputをスキーマ準拠として扱わない防御的な作りにしておきます。

対応スキーマの範囲 — additionalProperties: falseは必須、patternは部分対応

strict tool useが受け付けるのは、標準のJSON Schemaのうち一部のサブセットです。構造化出力(JSON outputs)と同じグラマー変換の仕組みを共有しているため、対応範囲もこの2機能で共通です。

対応するのは次の要素です。

  • 基本型 — object / array / string / integer / number / boolean / null
  • enum(文字列・数値・真偽値・nullのみ)とconst
  • anyOf / allOf(ただしallOf$refの組み合わせは不可)
  • $ref / $def / definitions(同一ドキュメント内に限る)
  • 全型のdefaultrequiredadditionalProperties(false固定)
  • 文字列フォーマット — date-time / time / date / duration / email / hostname / uri / ipv4 / ipv6 / uuid
  • 配列のminItems(0と1のみ)

対応しないのは次の要素です。

  • 再帰スキーマ、enum内の複合型、外部$ref
  • 数値制約 — minimum / maximum / multipleOf
  • 文字列長制約 — minLength / maxLength
  • minItemsの0・1以外の配列制約
  • additionalPropertiesfalse以外にする指定

additionalPropertiesはオブジェクトにfalseを明示しないと通りません。省略もtrueも非対応です。グラマー制約サンプリングは「このスキーマに一致する出力だけを生成できる状態」をあらかじめコンパイルしておく仕組みです。プロパティの集合が実行時に増減する余地があると、コンパイル対象の形が定まりません。additionalProperties: falseを全オブジェクトに書き切ることが、保証を成立させるための前提条件になっています。既存のスキーマにstrict tool useを後付けするときは、ネストしたオブジェクトも含めてadditionalProperties: falseが抜けていないかを1つずつ確認する必要があります。抜けが1箇所でもあれば、その箇所だけ400エラーになります。

外部$refが非対応な点も見落としやすい制約です。同一ドキュメント内の$def / definitionsを指す$refは使えますが、別ファイルやURLを指す$refはコンパイルできません。複数ツールでスキーマの一部を共有したい場合、外部ファイル分割ではなく同一スキーマ内の$defにまとめる設計が必要です。

pattern(正規表現)は、よくある誤解と違って完全非対応ではありません。対応する機能と対応しない機能が分かれています。

pattern内容
対応内容完全一致・部分一致(^...$)、量指定子(* + ?、単純な{n,m})、文字クラス([] . \d \w \s)、グループ((...))
非対応内容後方参照(\1など)、先読み・後読み((?=...) (?!...))、単語境界(\b \B)、大きな範囲の複雑な{n,m}

対応外の機能を使うと400エラーで詳細メッセージが返ります。実際のエラーメッセージはUnsupported regex feature in pattern field: ...という形式で、どの機能が引っかかったかが本文に含まれます。シンプルな正規表現は通り、複雑な正規表現ほど400エラーのリスクが上がる、という理解が実務的です。メールアドレスや郵便番号のような単純な形式チェックなら問題なく書けますが、「特定の単語を含まない」ような後方参照・先読みに頼る正規表現は、strict tool useの外で検証するしかありません。

スキーマの複雑さ上限

strict tool useには、コンパイル時間を守るための明示的な上限があります。output_config.format(構造化出力)を使うリクエストにも同じ上限がかかります。

上限内容
strictなツール数20内容strict: trueを設定したツールの上限。strictを設定しないツールはカウント対象外
省略可能パラメータ数24内容strictなツールスキーマと構造化出力スキーマ全体の合計。requiredに無いパラメータはすべてカウント
union型パラメータ数16内容anyOf"type": ["string", "null"]のような型配列を使うパラメータの合計

これらはリクエスト単位の合計値です。4つのstrictなツールにそれぞれ省略可能パラメータが6個あれば、個々のツールは単純に見えても合計24に達し、上限に触れます。1つのツールだけを見て「複雑ではない」と判断しても、リクエスト全体で見ると上限を超えているケースが実務では起きやすいところです。上限を超えるか、超えなくてもコンパイル後のグラマーが大きすぎる場合は400エラーでSchema is too complex for compilationというメッセージが返ります。この上限は表の3つの数値だけで決まる単純な計算ではありません。省略可能パラメータ・union型・ネストしたオブジェクト・ツール数が互いに掛け合わさって大きくなるため、表の数値をすべて満たしていても、内部のグラマーサイズ上限に触れて失敗することがあります。コンパイルには180秒のタイムアウトも設定されており、この時間を超えても失敗扱いです。

複雑さを削る優先順は、①本当に重要なツールだけをstrict: trueにする、②省略可能パラメータを減らしてrequiredに寄せる、③ネストしたオブジェクトを浅くする、④リクエストを複数に分割する、の順です。

strict: trueとinput_examplesの使い分け

strict: trueと、ツール定義に呼び出し例を添えるinput_examplesは、どちらも「Claudeの呼び出し精度を上げる」という同じ目的を持ちながら、効く場面が違います。トラブルシューティングガイドは、パラメータの型が合わない・スキーマに無いパラメータが混ざる、という症状に対して両方を候補として並べています。

スキーマが対応サブセットに収まるならstrict: trueのほうが確実です。構造的に保証されるため、再試行やバリデーションのコードが要りません。スキーマが対応サブセット外(数値の範囲制約が必須、複雑な正規表現が必要、など)なら、strict: trueは使えないか400エラーの原因になります。この場合は具体的な入力例を渡すinput_examplesが代替になります。保証はありませんが、対応サブセットの制約を受けません。両者は排他的な選択肢ではなく、同じツールに両方設定することもできます。

Tool Search ToolやProgrammatic Tool Callingと合わせてAdvanced Tool Useとしてまとめて語られることもあります。ただしstrict tool useが応える課題は別です。呼び出し件数の多さやコンテキスト圧迫ではなく、単発の呼び出しの型安全性に効く機能だからです。

forced tool use(tool_choiceで特定のツールの使用を強制する設定)が使えないモデル・設定もあります。この場合は代わりにautostrict: trueを組み合わせ、実質的に同じ確実性を得る、という使い分けも公式ドキュメントが案内しています。

まとめ

strict: trueが保証するのは、ツールのinputinput_schemaに従うことと、nameが常に妥当であることの2点だけです。拒否・max_tokens打ち切り・enumの大文字小文字は保証の外にあります。対応スキーマはJSON Schemaの一部サブセットに限られ、additionalProperties: falseは必須、patternは単純な正規表現だけが対応、数値・文字列長の制約は非対応です。さらにstrictなツール20個・省略可能パラメータ24個・union型パラメータ16個という複雑さ上限があり、超えると400エラーになります。スキーマがこの範囲に収まるかどうかが、strict: trueを選ぶかinput_examplesで代替するかの分かれ目です。既存のツール定義に後付けするときは、まずadditionalProperties: falseの抜けと外部$refの有無を確認します。次に、複雑さ上限に触れていないかをリクエスト単位で数えます。この順番で当たると手戻りが少なくなります。

この記事を共有:XはてブLinkedIn