一行要約

導入判断の目安は明確 — ツールが10個以上、定義が10kトークン超、または MCP サーバを複数集約しているなら使う。30〜50個を超えるとツール選択の精度自体が落ち始めるので、context 削減だけの話ではない。

要点

2つの問題を同時に解く

  • context 肥大 — 典型的な複数サーバ構成(GitHub / Slack / Sentry / Grafana / Splunk)で作業前に約 55k トークン。tool search は85% 超削減し、そのリクエストに必要な 3〜5 個だけをロードする
  • ツール選択の精度利用可能なツールが 30〜50 個を超えると、正しいツールを選ぶ能力が劣化する。 絞った集合だけをロードするので、数千個あっても精度が保たれる

2つの variant

variantクエリ形式上限
tool_search_tool_regex_20251119Python の re.search() パターン(自然言語ではない)。大文字小文字を区別しない200 文字
tool_search_tool_bm25_20251119自然言語クエリ500 文字

どちらも、ツール名・説明・引数名・引数の説明を検索する。

動作の流れ

  1. tools に tool search ツールを含める
  2. 全ツールの定義を tools 配列に入れ、先読みさせないものに defer_loading: true を付ける。最低1つ(通常は tool search ツール自身)は非 deferred でなければならない
  3. 最初は tool search ツールと非 deferred のツールだけが context に入る
  4. Claude が検索する
  5. API が検索を実行し、**tool_reference ブロック(既定で最大5件)**を返す
  6. API が自動的にそれを完全なツール定義に展開する
  7. Claude が発見したツールを呼ぶ

defer_loading の意味(誤解しやすい点)

defer_loading controls what enters the context window, not what you send in the request. defer_loading が制御するのは、context window に何が入るかであって、リクエストで何を送るかではない

  • deferred なものも含め、毎リクエストで全ツールの完全な定義を送る。 API がサーバ側で検索と展開に使うため
  • tool search ツール自身に defer_loading: true を付けてはいけない
  • 最頻出の 3〜5 個は非 deferred のままにする(検索せずに呼べるように)

prompt caching は保たれる。 API は内部的に deferred なツールを system prompt の prefix から除外し、発見時に会話内へ tool_reference ブロックを追記して展開する。prefix は触られない。

defer_loading: true のツールに cache_control は付けられない(400 になる)。キャッシュの breakpoint は非 deferred のツールに置く。

レスポンスの扱い

ブロック扱い
server_tool_useClaude の検索呼び出し。Anthropic のサーバで走る。この srvtoolu_... ID に tool_result を返してはいけない(API がリクエストを拒否する)
tool_search_tool_result検索結果。そのままメッセージ履歴に残す
tool_references発見したツールへの参照。API が展開する。自分で展開しない
tool_use発見したツールへの呼び出し。通常のツール使用と同じく実行して tool_result を返す

マッチしなかった検索は、空の tool_references を持つ結果を返す。エラーではない。

上限

項目
deferred ツールの最大数1リクエストあたり 10,000
1回の検索が返す結果既定で最大 5 件
パターン長regex 200 文字 / BM25 500 文字

いつ使うか / 使わないか

使う: ツールが10個以上 / 定義が 10k トークン超 / ツール増加で選択精度が落ちている / 複数の MCP サーバを集約している(200個以上) / ツール群が時間とともに増える。

使わない: 10個未満 / 毎リクエストで全ツールを使う / 定義が合計 100 トークン未満

最適化のコツ

  • 最頻出の 3〜5 個は非 deferred に保つ
  • ツール名に一貫した namespace を使うgithub_slack_)— 1回の検索でグループ全体がマッチする
  • ユーザーがタスクを説明する言葉に合うキーワードを description に入れる
  • system prompt にツールのカテゴリを書く — “You can search for tools to interact with Slack, GitHub, and Jira.”

エラー

400(リクエスト自体が処理されない):

  • At least one tool must have defer_loading=false. All tools cannot be deferred.
  • Tool reference 'unknown_tool' not found in available tools

200(実行時のエラーはボディに入る)error_codeinvalid_tool_input / unavailable / too_many_requests / execution_time_exceeded

課金

Tool search isn’t metered as a separate server tool. The tool definitions that search loads into context count as input tokens like any other tool definition. tool search は別建てのサーバツールとして課金されるわけではない。search が context にロードしたツール定義は、他のツール定義と同じように入力トークンとして数えられる

そのまま使える具体例

最小構成:

response = client.messages.create(
    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,
        },
    ],
)

2つの variant:

{"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"}
{"type": "tool_search_tool_bm25_20251119",  "name": "tool_search_tool_bm25"}

regex variant が書くパターンの例(Claude は ".*weather.*" のような広いパターンを使う):

"weather"                            名前や説明に weather を含むもの
"get_.*_data"                        get_user_data, get_weather_data
"database.*query|query.*database"    どちらの語順でも

パターンのデバッグ:

import re; re.search(r"your_pattern", "tool_name", re.IGNORECASE)

独自の検索(埋め込みなど)を実装する — 通常の tool_resulttool_reference を入れて返す:

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

MCP 経由のツールは個別に defer_loading を付けず、mcp_toolsetdefault_config かツール別の configs で設定する。

原典で言及されている関連文書

未取得の派生リンク