ツール検索ツールで数百のツールを扱う

Claude.ai エンジニアリング 9分で読めます

ツールの数が増えると、ツール定義そのものがコンテキストウィンドウを食いつぶし、Claude のツール選択精度も落ちていきます。ツール検索ツール(tool search tool)は、すべての定義を先に読み込むのをやめ、必要なツールだけをその都度探して読み込むことでこの2つの問題を同時に解きます。この記事では公式ドキュメントに沿って、仕組み・書き方・使いどころを解説します。

なぜツール検索が必要か

ツールをすべて事前に読み込む方式は、ツールライブラリが育つと2つの形で破綻します。

1つ目はコンテキストの圧迫です。 公式ドキュメントは具体的な数字を挙げています。GitHub・Slack・Sentry・Grafana・Splunk という典型的な複数サーバー構成では、Claude が何か仕事を始める前の時点でツール定義だけで約55,000トークンを消費します。ツール検索を使うと、実際に必要な3〜5個だけを読み込むため、この消費を85パーセント以上削減できるとされています。

2つ目はツール選択の精度です。 利用可能なツールが30〜50個を超えると、Claude が正しいツールを選ぶ能力は落ちていきます。ツール検索は、その都度絞り込まれたツール群だけを読み込むため、ツールが数千個あっても選択精度が保たれます

この機能は Claude API で一般提供(GA)されています。サーバーサイドのツールとして動きますが、後述するとおり自前の検索ロジックを実装することもできます。

2つの検索方式

ツール検索ツールには2つの方式があり、Claude が検索クエリをどう書くかが違います。

方式typeClaude が書くもの長さの上限
正規表現tool_search_tool_regex_20251119Python の re.search() パターン200文字
BM25tool_search_tool_bm25_20251119自然言語のクエリ500文字

ここは誤解しやすい点です。regex 版で Claude が書くのは自然言語ではなく正規表現です。マッチングは大文字小文字を区別しません。公式が挙げている典型的なパターンは次のようなものです。

どちらの方式も、検索対象はツール名・説明文・引数名・引数の説明の4つです。ツールが見つからないときは、まずこの4つのどこかに検索語が入っているかを確認してください。

対応モデルは Claude Fable 5 / Mythos 5 / Opus 5 / Opus 4.8 / Opus 4.7 / Opus 4.6 / Sonnet 4.6 / Opus 4.5 / Sonnet 4.5 / Haiku 4.5 です。Claude Opus 4.1 以前のモデルは対応していません。

defer_loading の指定方法

使い方は3ステップです。ツール検索ツールを tools に加え、遅延読み込みしたいツールに defer_loading: true を付けるだけです。

{
  "model": "claude-opus-5",
  "max_tokens": 2048,
  "messages": [
    { "role": "user", "content": "What is the weather in San Francisco?" }
  ],
  "tools": [
    {
      "type": "tool_search_tool_regex_20251119",
      "name": "tool_search_tool_regex"
    },
    {
      "name": "get_weather",
      "description": "Get the weather at a specific location",
      "input_schema": {
        "type": "object",
        "properties": {
          "location": { "type": "string" },
          "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
        },
        "required": ["location"]
      },
      "defer_loading": true
    }
  ]
}

ここで最も重要な仕様は次の一点です。defer_loading が制御するのは「コンテキストウィンドウに何が入るか」であって、「リクエストに何を送るか」ではありません。

つまり、遅延読み込みにしたツールも含めて、毎回すべてのツール定義を tools 配列で送る必要があります。API がサーバー側で検索を実行し、参照を完全な定義へ展開するために必要だからです。「送る量が減る」のではなく「モデルが読む量が減る」と理解してください。

あわせて次の3つを守ります。

プロンプトキャッシュとの関係も押さえておく価値があります。API は遅延ツールをシステムプロンプトの接頭辞から除外し、見つかったツールは会話の中に tool_reference ブロックとして差し込みます。接頭辞が変わらないので、プロンプトキャッシュは壊れません。

レスポンスの読み方

Claude がツール検索を使うと、レスポンスには次のブロックが順に現れます。

{
  "role": "assistant",
  "content": [
    { "type": "text", "text": "I'll search for tools to help..." },
    {
      "type": "server_tool_use",
      "id": "srvtoolu_01ABC123",
      "name": "tool_search_tool_regex",
      "input": { "pattern": "weather" }
    },
    {
      "type": "tool_search_tool_result",
      "tool_use_id": "srvtoolu_01ABC123",
      "content": {
        "type": "tool_search_tool_search_result",
        "tool_references": [
          { "type": "tool_reference", "tool_name": "get_weather" }
        ]
      }
    },
    {
      "type": "tool_use",
      "id": "toolu_01XYZ789",
      "name": "get_weather",
      "input": { "location": "San Francisco", "unit": "fahrenheit" }
    }
  ],
  "stop_reason": "tool_use"
}

読み方の要点は次のとおりです。

会話を続けるときは、アシスタントの content をそのまま返し、見つかったツールの tool_result をユーザーメッセージとして追加し、同じ tools 配列(検索ツール+全遅延定義)を送ります。API は履歴全体の tool_reference を展開するので、2回目以降のターンでは再検索なしに同じツールを使えます

検索が何にもマッチしなかった場合はエラーではなく、tool_references が空配列の結果が返ります。実行時のエラーも HTTP 200 で本文に入り、error_codeinvalid_tool_input / unavailable / too_many_requests / execution_time_exceeded の4種類です。

使いどころと注意点

公式が挙げる導入の目安は次のとおりです。1つでも当てはまれば検討する価値があります。

逆に、ツールが10個未満、毎回すべてのツールを使う、定義の合計が100トークン未満といった場合は、検索を挟まない通常のツール呼び出しのほうが適しています。検索という1往復が純粋な遅延になるためです。

精度を上げるコツも公式にまとまっています。ツール名に github_ / slack_ のようなサービス単位の接頭辞を付けて名前空間を揃えると、1回の検索でそのサービスのツール群がまとめてヒットします。説明文には、利用者がタスクを説明するときに使う語を入れておきます。システムプロンプトに「Slack・GitHub・Jira を操作するツールを検索できます」といったカテゴリの見取り図を書いておくのも効果的です。

制限は、遅延ツールが1リクエストあたり最大10,000個、1回の検索が返すのは既定で最大5件です。

ツールが MCP コネクタ経由で来ている場合は、個々のツール定義に defer_loading を書きません。MCPToolset の default_config にサーバー単位で指定するか、configs でツールごとに指定します。

課金についても明記があります。ツール検索はサーバーツールとして別途課金されません。 検索によってコンテキストに読み込まれたツール定義が、他のツール定義と同じく入力トークンとして数えられるだけです。