Tool Search Tool defer_loading Parameters Cheatsheet
Quick reference for configuring the Tool Search Tool: which type string to declare, what defer_loading does on an individual tool, and the constraints that will 400 your request if you get them wrong.
How to Use This Cheatsheet
- Look up the exact
typestring for the search variant you want before writing thetoolsarray - a typo in the date suffix is a common source of "unknown tool type" errors. - Check the constraints table before deploying - the two hard failure modes (deferring the search tool itself, deferring every tool) are both silent-until-request-time.
- Use the decision table to pick regex vs BM25 based on how your tool library is organized.
- Revisit the token-savings note when your tool count grows past a few dozen -
defer_loadingonly pays off once schema bulk becomes the bottleneck.
Tool Search Tool Variants
type | name | Discovery method | Best for |
|---|---|---|---|
tool_search_tool_regex_20251119 | tool_search_tool_regex | Regex pattern matching over tool names and descriptions | Tool libraries with predictable naming conventions (e.g. crm_get_*, crm_update_*) |
tool_search_tool_bm25_20251119 | tool_search_tool_bm25 | BM25 keyword-relevance ranking | Large, loosely-related tool catalogs where Claude needs to match natural-language intent to tool descriptions |
Both are server-side tools - you declare them in the tools array like any other tool, but Anthropic runs the search itself. Neither takes an input_schema; Claude calls them the same way it calls any tool, and you never implement a handler for them.
tools = [
{"type": "tool_search_tool_bm25_20251119", "name": "tool_search_tool_bm25"},
# ...your other tool definitions...
]defer_loading Reference
| Field | Type | Default | Effect |
|---|---|---|---|
defer_loading | boolean | false | When true on a tool definition, its full schema is left out of the initial request context. Claude discovers the tool by calling the search tool, and the matched schema is loaded into context on demand. |
{
"name": "get_weather",
"description": "Get current weather for a location.",
"input_schema": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"],
},
"defer_loading": True,
}defer_loading is the mechanism behind the token savings: on a library of hundreds of tools, deferring the rarely-used majority and keeping only a handful always-loaded can cut ~85% of the tokens that would otherwise be spent re-sending every tool schema on every request.
Constraints and Gotchas
| Constraint | What happens if you violate it |
|---|---|
The search tool itself (tool_search_tool_regex / tool_search_tool_bm25) must never have defer_loading: true. | The search tool has to be visible to Claude from the first turn - deferring it would mean nothing could ever discover it. |
| At least one tool in the request must remain non-deferred. | An all-deferred tools array returns 400: All tools have defer_loading set. |
| Discovered schemas are appended to the request, not swapped in. | This is a feature, not a gotcha - it means the prompt-cache prefix for tools and system stays intact across a search call, so you don't pay a full cache-miss cost every time Claude searches. |
Search results arrive as a tool_search_tool_result content block. | Code that only checks for tool_use / text block types will silently ignore search results - branch on tool_search_tool_result explicitly if you're inspecting response content. |
| Mixing always-loaded and deferred tools in one request is supported and expected. | Keep frequently-used, small-schema tools always-loaded; defer rarely-used tools or tools that are part of a large catalog. |
Minimal Request Shape
{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"tools": [
{"type": "tool_search_tool_bm25_20251119", "name": "tool_search_tool_bm25"},
{"name": "get_weather", "description": "...", "input_schema": {"type": "object", "properties": {}}, "defer_loading": true}
],
"messages": [{"role": "user", "content": "..."}]
}Equivalent Python, using the official anthropic SDK:
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
tools=[
{"type": "tool_search_tool_bm25_20251119", "name": "tool_search_tool_bm25"},
{
"name": "get_weather",
"description": "Get current weather for a location.",
"input_schema": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"],
},
"defer_loading": True,
},
],
messages=[{"role": "user", "content": "What's the weather in Boston?"}],
)Choosing Regex vs BM25
| If your tool library... | Use |
|---|---|
| Follows a consistent naming/prefix convention you can express as a pattern | tool_search_tool_regex_20251119 |
| Is large, loosely organized, or matched best by natural-language intent rather than naming structure | tool_search_tool_bm25_20251119 |
| Is small enough that all schemas fit comfortably in context | Neither - skip Tool Search Tool entirely and load every tool normally |
FAQs
What does defer_loading actually save?
- It keeps the full JSON schema of a tool out of the initial request payload.
- Claude only sees the tool's name and description (via the search tool) until it decides the tool is relevant.
- On large tool libraries this is where the ~85% token savings comes from - you stop paying to re-send hundreds of unused schemas on every turn.
Can I set defer_loading: true on every tool in my tools array?
No. At least one tool must remain non-deferred, or the request returns 400: All tools have defer_loading set. In practice this means the search tool itself plus at least one other tool.
Can the search tool itself be deferred?
No. tool_search_tool_regex and tool_search_tool_bm25 must never have defer_loading: true - Claude needs the search tool visible from the start in order to discover anything else.
How do I know when Claude used the search tool?
Look for a tool_search_tool_result content block in the response. This is a distinct block type from tool_use and text - code that only checks those two will miss it.
Does calling the search tool break prompt caching?
No. Discovered tool schemas are appended to the request rather than swapping the existing tools array, so the cached prefix for tools and system is preserved across the search call.
Should I defer every tool that isn't in the current request's obvious path?
Not necessarily. Keep frequently-used, small-schema tools always-loaded so common requests don't need a search round trip. Reserve defer_loading for tools that are rarely used or part of a large catalog where the schema bulk is the actual problem.
Do I need a beta header to use Tool Search Tool?
Declare the tool by its versioned type string (tool_search_tool_regex_20251119 or tool_search_tool_bm25_20251119) in the tools array like any other server-side tool. Check current platform documentation for header requirements, since beta status can change between SDK releases.
How do I pass defer_loading in the Python SDK?
Add "defer_loading": True as a key inside the tool's dict in the tools list you pass to client.messages.create(...). It sits alongside name, description, and input_schema on the same tool definition.
What's the difference between regex and BM25 discovery?
- Regex (
tool_search_tool_regex_20251119) matches tool names and descriptions against a pattern - good when your tools follow a predictable naming convention. - BM25 (
tool_search_tool_bm25_20251119) ranks tools by keyword relevance - better when tool names don't cleanly encode intent and Claude needs to match natural language to descriptions.
Can I mix deferred and always-loaded tools in the same request?
Yes, and this is the expected usage pattern. Keep a small set of frequently-used tools always-loaded, and defer the rest of a large catalog.
What model should I use in example requests?
claude-sonnet-5 is the current default Claude model and works well for tool-use-heavy workloads. Any current model that supports tool use can use Tool Search Tool.
Is defer_loading worth using on a small tool library?
Generally no. If all your tool schemas already fit comfortably in context without noticeable token overhead, skip Tool Search Tool entirely - the search round trip adds latency you don't need to pay for.
Related
- Scaling to Hundreds of Tools with the Tool Search Tool - the full walkthrough this cheatsheet summarizes.
- Connecting to Remote Tools via the MCP Connector - another way to scale a large tool surface.
- Tool Choice Options Reference - controlling when and which tools Claude calls.
- Best Practices - broader tool-use guidance this cheatsheet fits into.
Stack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5 - and the official
anthropicPython SDK (latest 0.x release). Model names, SDK versions, and pricing move quickly - verify current specifics at platform.claude.com/docs before relying on them.