読み込み中

厳格なツール使用:自分自身の呼び出しの拒否をやめる

レッスン 210 分
読み込み中

厳格なツール使用:自分自身の呼び出しの拒否をやめる

要約トランスクリプト

バックエンドがClaude自身が生成したツール呼び出しを拒否する場合、厳格なツール使用が解決策になります。この動画では、架空のエンジニアリングコンサルティング会社Meridianで1つのツールに対してこの機能をオンにし、同じ100件のリクエストをオンとオフの両方で実行します。

この動画のデモは2026年9月に収録されました。使用したモデルはClaude Haiku 4.5(claude-haiku-4-5)です。新しいモデルでは結果が異なる場合があります。

Claudeは通常ツールのinput_schemaに従いますが、デフォルトではそれを強制する仕組みはありません。そのため、バックエンドがClaudeが行ったツール呼び出しを拒否することがあります。これは、呼び出しの入力に次のいずれかが含まれている場合に起こります。

  • 整数2の代わりに文字列"2"
  • 必須フィールドの欠落

厳格なツール使用はこれを解決します。strict: trueという1つのフラグだけで、Claudeが書く入力がスキーマと一致するようになります。

Meridianでは、アシスタントがqueue_stamp_requestツールを使って、図面セットを免許を持つエンジニアの押印に回すためのキューに登録します。Meridianのバリデータとは、すべてのツール呼び出しをチェックするコードのことです。厳格モードをオフにすると、100件中79件が拒否されます。バリデータから生成したスキーマで厳格モードをオンにすると、拒否件数はゼロになります。

厳格なツール使用の仕組み

strict: trueを指定すると、APIはまずJSON Schemaを文法(grammar)にコンパイルします。文法とは、入力の各時点でどのトークンが次に来てよいかを示す一連のルールです。 その後、Claudeがツール呼び出しの次のトークンを選ぶたびに、その文法が許すトークンしか選べなくなります。これは文法制約付きサンプリングと呼ばれます。

スキーマでは revision は整数と定められており、Claude は "revision": まで書き終えています。strict なしでは、次のトークンとして 3、"3"、three、3.0、null の5つを選べます。strict: true では 3 だけを選べ、ほかの4つには取り消し線が引かれています。

strict: trueを指定すると、スキーマが許すトークンしか選べなくなるため、整数フィールドには整数が入ります。

以下はMeridianのツール定義を短縮したものです。厳格モードにはそのうちの2行、フラグとそのフラグが必要とする設定が必要です。

json
{
  "name": "queue_stamp_request",
  "description": "Queues a drawing set for a professional engineer's stamp.",
  "strict": true,
  "input_schema": {
    "type": "object",
    "properties": {
      "drawing_set_id": {"type": "string"},
      "revision": {"type": "integer"}
    },
    "required": ["drawing_set_id", "revision"],
    "additionalProperties": false
  }
}
  • "strict": trueがそのフラグです。これはname、description、input_schemaと並んでトップレベルに置かれ、スキーマの外にあります。
  • "additionalProperties": falseがその設定です。これは、入力にスキーマが名前を挙げていないフィールドを含められないことを意味し、厳格モードではすべてのオブジェクトに対してこれが必須です。

バリデータからスキーマを構築する

厳格なツール使用は、Claudeが書く入力をスキーマと一致させる仕組みなので、スキーマはバリデータが言っていることと一致している必要があります。スキーマを手書きすると、この2つはずれていきます。すると、ツール呼び出しがスキーマには一致していても拒否されることがあります。 Meridianでは、手書きのスキーマによって免許番号がパターンなしの単純な文字列になっていました。そのため、"PE 46196"はスキーマを通過しましたが、PE-に続く5桁の数字を要求するバリデータでは失敗しました。

ルールはバリデータの中で一度だけ書き、そこからスキーマを生成してください。Pythonではバリデータは通常Pydanticクラスです。TypeScriptでは通常Zodで書かれます。

以下はMeridianのPydanticクラスStampRequestと、それを使うコード、そしてStampRequest.model_json_schema()が返すスキーマです。それぞれの# ...は表示されていないコードを表し、スキーマは免許番号の部分のみを示しています。

python
class StampRequest(BaseModel):
    model_config = {"extra": "forbid"}
    # ...
    pe_license_number: str | None = Field(pattern=r"^PE-\d{5}$")
    # ...
stamp_tool = {
    # ...
    "input_schema": StampRequest.model_json_schema(),
    "strict": True,
}
stamp_request = StampRequest.model_validate(call.input)
json
{
  "additionalProperties": false,
  "properties": {
    "pe_license_number": {
      "anyOf": [
        {"pattern": "^PE-\\d{5}$", "type": "string"},
        {"type": "null"}
      ],
      "title": "Pe License Number"
    }
  }
}
  • "extra": "forbid"は、厳格モードが要求する設定である"additionalProperties": falseになります。
  • str | NoneはanyOfになり、免許番号はそのpatternを持つ文字列、またはnullになります。
  • model_validate()は、Claudeが書いた入力であるcall.inputを、同じクラスに対してチェックします。

厳格モードのオフとオンで実行結果を比較する

Meridianのテストでは、queue_stamp_requestツールを使ってClaude Haiku 4.5に100件の平易な言葉による押印リクエストを送り、StampRequestがすべてのツール呼び出しを検証します。同じ100件のリクエストを2回実行します。まずは手書きのスキーマで厳格モードをオフにして、次に生成したスキーマで厳格モードをオンにして実行します。

下記で両方の実行を再現してみてください。

読み込み中

スキーマのpatternは許される形式を示しており、厳格モードはClaudeにそれを守らせます。

厳格モードは入力の形を制御しますが、リクエストに一度も含まれていない事実を補うことはできません。100件のリクエストのうち28件は免許について一度も言及していません。生成したスキーマでは免許番号にnullを許可しており、その28件すべてがnullとして返ってきました。

厳格なツール使用の限界

2026年10月時点で知っておくべき6つのことを紹介します。

  1. 保護対象保健情報(PHI)を含めないでください。 コンパイルされたスキーマは、プロンプトやレスポンスと同じPHI保護を受けません。そのため、プロパティ名、enumの値、constの値、patternの式にPHIを含めないでください。
  2. 境界値はサポートされていません。 スキーマでminimum、maximum、minLength、またはmaxLengthを使用しているリクエストは400エラーを返します。境界値はPydanticの@field_validatorのようなバリデータ関数でチェックし、そのフィールドの説明文の中に明記してください。
  3. 制限はツール全体で積み上がります。 1件のリクエストに含められる厳格なツールは最大20個です。それらのツール全体で、任意パラメータは最大24個まで含められます。また、anyOfまたは型配列(str | Noneのようなnullable可能なフィールドが生成するもの)を使うパラメータは最大16個まで含められます。
  4. 入力がスキーマに一致しないこともあります。 これは拒否の後や、レスポンスがmax_tokensで打ち切られたとき、あるいはenumやconstの文字列が異なる大文字・小文字で返ってきたときに起こります。
  5. 一部のモデルは強制されたツール呼び出しを拒否します。 tool_choiceをanyまたはtoolに設定すると、ツール呼び出しが強制されます。Claude Opus 5.5、Claude Sonnet 5.5、Claude Fable 5.1、Claude Mythos 5.1では、これが400エラーを返します。これらのモデルでは、tool_choiceをデフォルトのautoのままにしてください。
  6. プログラムによるツール呼び出しでは厳格なツールを使用できません。 プログラムによるツール呼び出しでは、Claudeがツールを呼び出すコードを書きます。これについてはレッスン8で扱います。

重要なポイント

  • strict: trueは、拒否の後や打ち切られたレスポンスの後、あるいはenumやconstの文字列の大文字・小文字が変わった場合を除き、ツールの入力をスキーマに一致させます。
  • Pydanticクラスのようなバリデータからスキーマを生成してください。
  • 境界値はスキーマから外し、ツール、任意パラメータ、nullable可能なパラメータはリクエスト全体を通してカウントしてください。