Claude Media
Tool Search Toolのregex版とBM25版はクエリの書き方が全く違う

Tool Search Toolのregex版とBM25版はクエリの書き方が全く違う

Tool Search Toolのregex版はPython正規表現(200字上限)、BM25版は自然文(500字上限)でクエリを書きます。defer_loadingの仕様も含めて実装差を扱います。

このTipsでできること

Advanced Tool Useの3機能の1つであるAnthropic APIのTool Search Toolには、tool_search_tool_regex_20251119tool_search_tool_bm25_20251119という2つの変種があり、Claudeが書くクエリの形式がまったく違います。regex版はPythonの正規表現、BM25版は自然文です。この記事では、2つの変種の使い分け、defer_loadingによるツール読み込みの仕組み、実装時に400エラーになりやすい落とし穴、そしてAgent SDKが提供する同名機能との違いをまとめます。

regex版とBM25版 — クエリの書式が違う2つの変種

Tool Search Toolは、数百から数千のツールをカタログとして持たせ、Claudeが必要なツールだけをその場で発見して読み込む仕組みです。ツール名・説明・引数名・引数の説明をまとめて検索対象にします。変種は2つあり、tools配列にどちらか一方(または両方)を含めて有効にします。

変種typeの値クエリの書式上限
regex版typeの値tool_search_tool_regex_20251119クエリの書式Pythonのre.search()パターン上限200字
BM25版typeの値tool_search_tool_bm25_20251119クエリの書式自然文上限500字
{ "type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex" }
{ "type": "tool_search_tool_bm25_20251119", "name": "tool_search_tool_bm25" }

マッチングはどちらの変種も大文字小文字を区別しません。ツール名・説明・引数名・引数の説明のすべてが検索対象になる点も共通です。

regex版 — Claudeが書くのは自然言語のクエリではない

regex版で誤解しやすいのは、Claudeが渡すpatternが自然言語の検索語ではなく、Pythonの正規表現そのものだという点です。単純な単語だけでなく、次のようなパターンをClaudeが自分で組み立てます。

  • "weather": ツール名・説明に"weather"を含むものにマッチ
  • "get_.*_data": get_user_dataget_weather_dataのようなツールにマッチ
  • "database.*query|query.*database": 語順のどちらにもマッチ

パターン長の上限は200字です。デバッグに詰まったら、import re; re.search(r"your_pattern", "tool_name", re.IGNORECASE)のようにローカルで実際にパターンを試すのが、公式が挙げているデバッグ手順です。Claudeが期待したツールを見つけられない場合の原因は、多くがツール名・説明・引数の記述にキーワードが不足していることなので、まずツール定義側の説明文を見直すのが定石です。

BM25版 — Claudeが書くのは自然文

BM25版では、Claudeは正規表現ではなく自然文のクエリを書きます。上限は500字で、regex版の200字より緩やかです。BM25(情報検索で使われるランキングアルゴリズムの一種)という名前が付いていますが、実装側がクエリの書式を意識する必要はなく、Claudeが自然文で検索語を組み立てる点だけを押さえておけば十分です。

regex版とBM25版は、どちらもツール名の一貫した命名規則(github_slack_のようなサービス名プレフィックス)や、利用者が実際に使う言葉に寄せた説明文があるほど、検索の的中率が上がります。書式こそ違いますが、検索対象のインデックス設計そのものはどちらの変種でも同じです。

defer_loadingは「送るかどうか」ではなく「文脈に載せるかどうか」

Tool Search Toolを使う場合、検索対象にしたいツールにはdefer_loading: trueを付けます。ここで押さえておくべきなのは、defer_loadingが制御するのはClaudeの文脈に最初から載るかどうかであって、APIに送信するデータそのものではないという点です。defer_loading: trueを付けたツールも、その完全な定義を毎リクエストのtools配列に含めて送る必要があります。APIがサーバー側で検索を実行し、見つかったtool_referenceを展開するために、定義そのものをサーバー側で保持しておく必要があるからです。

よく使う3〜5個のツールはdefer_loadingを付けずに残しておくのが基本パターンです。これらは最初からClaudeの文脈に載るため、検索を挟まずに直接呼び出せます。

regex版とBM25版の使い分け早見表

状況regex版が向くBM25版が向く
ツール名に命名規則の一貫性がある(github_*等)regex版が向く◎ 前方一致・語順パターンで確実に絞れるBM25版が向く
ツールの説明が長い自然文で書かれているregex版が向くBM25版が向く◎ 自然文クエリとの相性が良い
複数の言い回しでツールを探させたいregex版が向く△ 正規表現を複数の言い回し分書く必要があるBM25版が向く◎ 自然文なら言い換えを吸収しやすい
実装側でクエリの挙動を厳密に予測したいregex版が向く◎ パターンマッチは決定的BM25版が向く△ ランキングアルゴリズムの挙動

どちらか一方を選ぶ必要はなく、両方をtools配列に含めて併用することもできます。

実装時に詰まりやすい3つのミス

公式ドキュメントが挙げている典型的な失敗は3つあります。

  1. 全ツールがdeferredになっている: Tool Search Tool自体にまでdefer_loading: trueを付けてしまうケース。修正は、Tool Search Toolの定義からdefer_loadingを外すこと
  2. ツール定義が足りない: tool_referenceが指すツール名がtools配列に存在しないケース。発見されうるすべてのツールについて、完全な定義を用意しておく必要がある
  3. 期待したツールが見つからない: 正規表現やクエリがツール名・説明・引数名・引数の説明のどれにもマッチしていないケース。ツールの説明文にキーワードを足すのが対処法

このほか、defer_loading: trueを付けたツールにはcache_controlを同時に設定できず、設定すると400エラーになります。プロンプトキャッシュのブレークポイントは、deferされていないツールの側に置く必要があります。

エラーコードは4種類

検索の実行自体が失敗した場合は、HTTPステータスは200のまま、tool_search_tool_resultの中にtool_search_tool_result_errorとしてエラーが返ります。

error_code意味
invalid_tool_input意味検索の入力が不正(不正な正規表現、200字超のパターン等)
unavailable意味検索処理がタイムアウトした、またはサービスが一時的に利用できない
too_many_requests意味検索操作のレート制限を超過した
execution_time_exceeded意味検索の実行時間が上限を超えた

一致するツールが1件も無い検索そのものはエラーではなく、tool_referencesが空配列のtool_search_tool_search_resultとして返ります。「見つからない」と「検索に失敗した」は別の応答形として区別されています。

発見したツールは会話の後のターンでも使い回せる

検索で見つかったツールは、そのターンだけの一時的な扱いではありません。APIは会話履歴の中に現れるtool_referenceブロックを毎回展開するため、一度発見したツールは後続のターンでも再検索なしにそのまま呼び出せます。継続リクエストを組み立てるときは、アシスタントのserver_tool_useブロックとtool_search_tool_resultブロックをそのまま履歴に残し、tools配列にはTool Search Toolと全deferred定義を毎回含めて送ります。srvtoolu_...というIDを持つTool Search Tool自体の呼び出しに対してtool_resultを返す必要はなく、返そうとするとAPIに拒否されます。

自前の検索ロジックを実装することもできる

組み込みのregex版・BM25版以外に、埋め込みベクトルによる意味検索のような独自の検索ロジックを使いたい場合は、通常のカスタムツールとして検索ツールを自作し、そのtool_resultとしてtool_referenceブロックを返す形で同じ仕組みに乗せられます。

{
  "type": "tool_result",
  "tool_use_id": "toolu_your_tool_id",
  "content": [{ "type": "tool_reference", "tool_name": "discovered_tool_name" }]
}

参照するツール名は、組み込み変種を使う場合と同じくtools配列に完全な定義(通常はdefer_loading: true付き)を持っておく必要があります。組み込みのtool_search_tool_resultはサーバー内部の応答形式であり、自前実装では標準のtool_resulttool_referenceブロックの組み合わせを使う点だけが違います。

ストリーミングでレスポンスを受け取る場合も、識別方法は変わりません。server_tool_useブロックとしてTool Search Toolの呼び出しが流れ、検索の実行中は一旦ストリームが止まり、結果がtool_search_tool_resultとして届きます。Tool Search ToolはMessages Batches APIにも組み込めます。

上限と、いつ使うべきか

defer_loading: trueを付けられるツールは1リクエストあたり最大10,000個です。検索結果の件数は既定で5件ですが、Claude自身がlimitを指定でき、1から10,000までの任意の整数を設定できます。

Tool Search Toolを使うべき目安は、ツールが10個以上ある、ツール定義の合計が10,000トークンを超える、ツール選択の精度が構成の拡大とともに落ちている、複数のMCPサーバーを束ねていて200個を超えるツールがある、といった条件のいずれかに当てはまるときです。逆に、ツールが10個未満で毎回すべてを使い、ツール定義の合計が100トークン未満のような小規模な構成では、Tool Search Toolを使わない通常のツール呼び出しのほうが向いています。ツール設計そのもの(命名・粒度・説明文の書き方)の指針はエージェント向けツール設計の原則にまとめてあります。

Agent SDKのTool Searchとは別の仕組み

Agent SDK Tool SearchENABLE_TOOL_SEARCHという環境変数でオン・オフや閾値を制御する、SDK側の抽象化された機能です。本記事で扱ったregex版・BM25版のツール定義そのものは、Messages APIを直接呼ぶ実装で使う低レベルの仕様です。SDK側のENABLE_TOOL_SEARCHが有効なとき、内部的にどちらの変種を使っているかや、defer_loadingをどう組み立てているかは、SDKが引き受ける実装詳細であり、SDK利用者がtool_search_tool_regex_20251119tool_search_tool_bm25_20251119をtools配列に書き分ける必要はありません。逆に、Messages APIを直接叩く実装、あるいはSDKが対応していないモデルやプロキシ経由の構成では、本記事で扱った低レベルの仕様を自分で組み立てる必要があります。どちらの層で実装するかによって、参照すべき仕様が変わる点が、この2つの記事の役割の違いです。

Tool Search Toolが見つけたツールの定義には、input_examplesを設定していればその内容も一緒に展開されます。deferされているからといって、入力例による精度向上の恩恵が失われるわけではありません。

まとめ

Tool Search Toolのregex版はPythonの正規表現(200字上限)、BM25版は自然文(500字上限)でクエリを書くという違いがあります。defer_loadingは文脈に最初から載せるかどうかを制御するだけで、ツール定義自体は毎回送信する必要がある点、Tool Search Tool自体をdeferしてはいけない点、defer_loadingcache_controlは同居できない点が実装時の主な落とし穴です。Agent SDKのENABLE_TOOL_SEARCHはこれらをSDK側で肩代わりする別レイヤーの機能なので、Messages APIを直接扱う実装かどうかで参照すべき仕様が変わります。

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