The tool search tool lets Claude work with hundreds or thousands of tools by discovering and loading them on demand. Instead of loading all tool definitions into the context window up front, Claude searches your tool catalog (including tool names, descriptions, argument names, and argument descriptions) and loads only the tools it needs.
Loading every tool definition up front causes two problems as a tool library grows:
Tool search is generally available on the Claude API. For supported models, see Model compatibility.
For background on the scaling challenges that tool search solves, see Advanced tool use. Tool search's on-demand loading is also an instance of the broader just-in-time retrieval principle described in Effective context engineering.
Tool search runs as a server-side tool, but you can also implement your own client-side tool search. See Custom tool search implementation for details.
Share feedback on this feature through the feedback form.
This feature is eligible for Zero Data Retention (ZDR). When your organization has a ZDR arrangement, data sent through this feature is not stored after the API response is returned.
On Amazon Bedrock, server-side tool search is available only through the InvokeModel API, not the Converse API.
On Claude Platform on AWS, server-side tool search works identically to the Claude API. Claude Platform on AWS uses the Anthropic Messages API directly, so there is no InvokeModel or Converse distinction.
Both tool search variants are available on the following models:
| Model | Tool versions |
|---|---|
| Claude Fable 5 (claude-fable-5) | tool_search_tool_regex_20251119, tool_search_tool_bm25_20251119 |
| Claude Mythos 5 (claude-mythos-5) | tool_search_tool_regex_20251119, tool_search_tool_bm25_20251119 |
| Claude Opus 4.8 (claude-opus-4-8) | tool_search_tool_regex_20251119, tool_search_tool_bm25_20251119 |
| Claude Opus 4.7 (claude-opus-4-7) | tool_search_tool_regex_20251119, tool_search_tool_bm25_20251119 |
| Claude Opus 4.6 (claude-opus-4-6) | tool_search_tool_regex_20251119, tool_search_tool_bm25_20251119 |
| Claude Sonnet 4.6 (claude-sonnet-4-6) | tool_search_tool_regex_20251119, tool_search_tool_bm25_20251119 |
| Claude Opus 4.5 (claude-opus-4-5-20251101) | tool_search_tool_regex_20251119, tool_search_tool_bm25_20251119 |
| Claude Sonnet 4.5 (claude-sonnet-4-5-20250929) | tool_search_tool_regex_20251119, tool_search_tool_bm25_20251119 |
| Claude Haiku 4.5 (claude-haiku-4-5-20251001) | tool_search_tool_regex_20251119, tool_search_tool_bm25_20251119 |
Claude Opus 4.1 and earlier models don't support the tool search tool.
There are two tool search variants:
tool_search_tool_regex_20251119): Claude constructs regex patterns to search for tools.tool_search_tool_bm25_20251119): Claude uses natural language queries to search for tools.When you enable the tool search tool:
tool_search_tool_regex_20251119 or tool_search_tool_bm25_20251119) in your tools list.tools array and set defer_loading: true on the tools that shouldn't load up front. At least one tool, normally the tool search tool itself, must stay non-deferred.tool_reference blocks (up to 5 by default).The following example includes the tool search tool and two deferred tools:
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
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,
},
{
"name": "search_files",
"description": "Search through files in the workspace",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"},
"file_types": {"type": "array", "items": {"type": "string"}},
},
"required": ["query"],
},
"defer_loading": True,
},
],
)
print(response)Claude searches the catalog, discovers get_weather, and calls it. The response ends with stop_reason: "tool_use". Execute the discovered tool and return a tool_result as in Handle tool calls. Response format shows the blocks you get back and what to send next.
The tool search tool has two variants:
{
"type": "tool_search_tool_regex_20251119",
"name": "tool_search_tool_regex"
}{
"type": "tool_search_tool_bm25_20251119",
"name": "tool_search_tool_bm25"
}Regex variant query format: Python regex, not natural language
With tool_search_tool_regex_20251119, Claude writes Python re.search() patterns, not natural language queries. Matching is case-insensitive. Common patterns include the following:
"weather": matches tool names and descriptions containing "weather""get_.*_data": matches tools such as get_user_data and get_weather_data"database.*query|query.*database": matches either word orderMaximum pattern length: 200 characters
BM25 variant query format: natural language
With tool_search_tool_bm25_20251119, Claude searches with natural language queries. Maximum query length: 500 characters.
Mark tools for on-demand loading by adding defer_loading: true:
{
"name": "get_weather",
"description": "Get current weather for a location",
"input_schema": {
"type": "object",
"properties": {
"location": { "type": "string" },
"unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
},
"required": ["location"]
},
"defer_loading": true
}defer_loading controls what enters the context window, not what you send in the request:
tools array on every request, including the deferred ones. The API needs them server-side to run the search and expand tool_reference blocks.defer_loading load into context immediately.defer_loading: true load only when Claude discovers them through search.defer_loading: true on the tool search tool itself.Both tool search variants (regex and bm25) search tool names, descriptions, argument names, and argument descriptions.
Internally, the API excludes deferred tools from the system-prompt prefix. When Claude discovers a deferred tool through tool search, the API appends a tool_reference block inline in the conversation, then expands it into the full tool definition before passing it to Claude. The prefix is untouched, so prompt caching is preserved. The grammar for strict mode (the rules that constrain tool-call output to match your schemas) builds from the full toolset, so defer_loading and strict mode compose without grammar recompilation.
When Claude uses the tool search tool, the response includes the following block types:
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll search for tools to help with the weather information."
},
{
"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": "text",
"text": "I found a weather tool. Let me get the weather for San Francisco."
},
{
"type": "tool_use",
"id": "toolu_01XYZ789",
"name": "get_weather",
"input": { "location": "San Francisco", "unit": "fahrenheit" }
}
],
"stop_reason": "tool_use"
}server_tool_use: Claude's call to the tool search tool. The search runs on Anthropic's servers. Never return a tool_result for its srvtoolu_... ID.tool_search_tool_result: the search results, in a nested tool_search_tool_search_result object. Keep it in the message history as is.tool_references: an array of tool_reference objects pointing to discovered tools. The API expands these for Claude. You never expand them yourself.tool_use: Claude's call to a discovered tool. Execute it and return a tool_result exactly as in standard tool use.The API automatically expands tool_reference blocks into full tool definitions before showing them to Claude. You don't need to handle this expansion yourself, as long as you provide all matching tool definitions in the tools parameter.
On the next request, pass the assistant's content back unchanged, including the server_tool_use and tool_search_tool_result blocks. Add your tool_result for the discovered tool in a user message, and send the same tools array: the search tool plus every deferred definition. Don't return a tool_result for the srvtoolu_... ID: the API rejects the request. The API expands tool_reference blocks throughout the conversation history, so Claude can reuse discovered tools in later turns without re-searching. A search that matches nothing returns a tool_search_tool_search_result with an empty tool_references array, not an error.
If your tools come from MCP servers through the MCP connector, you don't set defer_loading on individual tool definitions. Instead, set it once on the mcp_toolset entry's default_config for the whole server, or per tool in its configs. See MCP toolset configuration.
You can implement your own tool search logic (for example, using embeddings or semantic search) by returning tool_reference blocks from a custom tool. When Claude calls your custom search tool, return a standard tool_result with tool_reference blocks in the content array:
{
"type": "tool_result",
"tool_use_id": "toolu_your_tool_id",
"content": [{ "type": "tool_reference", "tool_name": "discovered_tool_name" }]
}Every tool referenced must have a corresponding tool definition in the top-level tools parameter, normally with defer_loading: true. This lets you use search methods the built-in variants don't provide, such as embedding-based retrieval, and the API expands the returned tool_reference blocks the same way.
The tool_search_tool_result format shown in the Response format section is the server-side format used internally by Anthropic's built-in tool search. For custom client-side implementations, always use the standard tool_result format with tool_reference content blocks as shown in the preceding example.
For a complete example using embeddings, see the tool search with embeddings recipe.
Tool use examples
work with tool search: when Claude discovers a deferred tool, the API expands
its input_examples along with its definition.
These errors prevent the API from processing the request:
All tools deferred:
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "At least one tool must have defer_loading=false. All tools cannot be deferred."
}
}Missing tool definition:
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "Tool reference 'unknown_tool' not found in available tools"
}
}When a tool search operation fails during execution, the API returns a 200 response with the error in the body:
{
"type": "tool_search_tool_result",
"tool_use_id": "srvtoolu_01ABC123",
"content": {
"type": "tool_search_tool_result_error",
"error_code": "invalid_tool_input",
"error_message": "Invalid regular expression pattern: missing ) at position 1"
}
}The error_code field has four possible values:
invalid_tool_input: the search input was invalid, for example a malformed regex pattern or a pattern over the 200-character limitunavailable: the search couldn't run, for example because it timed out or the service was unavailabletoo_many_requests: rate limit exceeded for tool search operationsexecution_time_exceeded: the search exceeded its execution time limitFor how defer_loading preserves prompt caching, see Tool use with prompt caching.
A tool with defer_loading: true can't also carry cache_control: the API returns a 400. Put the cache breakpoint on a non-deferred tool.
With streaming enabled, you'll receive tool search events as part of the stream:
event: content_block_start
data: {"type": "content_block_start", "index": 1, "content_block": {"type": "server_tool_use", "id": "srvtoolu_xyz789", "name": "tool_search_tool_regex"}}
// Search pattern streamed
event: content_block_delta
data: {"type": "content_block_delta", "index": 1, "delta": {"type": "input_json_delta", "partial_json": "{\"pattern\":\"weather\"}"}}
// Pause while search executes
// Search results streamed
event: content_block_start
data: {"type": "content_block_start", "index": 2, "content_block": {"type": "tool_search_tool_result", "tool_use_id": "srvtoolu_xyz789", "content": {"type": "tool_search_tool_search_result", "tool_references": [{"type": "tool_reference", "tool_name": "get_weather"}]}}}
// Claude continues with discovered toolsYou can include the tool search tool in the Messages Batches API.
defer_loading: true per requestUse tool search when any of the following apply:
Standard tool calling, without tool search, is a better fit when you have fewer than 10 tools, every tool is used in every request, or your tool definitions are small (less than 100 tokens total).
github_, slack_) so one search matches the whole group.Tool search isn't metered as a separate server tool. The response's usage.server_tool_use object has no tool search field, and the tool definitions that search loads into context count as input tokens like any other tool definition.
Let Claude store and retrieve information across conversations by implementing the memory tool's file operations in your application.
Directory of Anthropic-provided tools and reference for optional tool definition properties.
Configure MCP toolsets with deferred loading.
Cache tool definitions across turns and understand what invalidates your cache.
Specify tool schemas, write effective descriptions, and control when Claude calls your tools.
Was this page helpful?