Use Tool Search
When the Tool Catalog Is Larger Than the Conversation
Every tool in a request is described to Claude, with its name, its description, and its input schema. Those definitions are input tokens, and they are sent with every request in the conversation. For an application with a handful of tools, the cost is small. For a platform with hundreds of integrations, each with several operations, the definitions alone can outweigh the conversation they serve. They also crowd the context, so the model has more to consider on every turn than the task requires.
Tool search addresses that problem. Instead of loading every definition up front, the application marks most tools as deferred, and gives Claude a search capability. When a request needs a tool, Claude searches the catalog, and only the matching definitions are loaded for that step. The rest of the catalog stays out of the request until it is needed.
This lesson explains the pattern, its effect on cost and on the cache, and how to design a catalog so search finds the right tool. A simulation at the end shows the selection step on a catalog of three hundred tools.
Deferred and Loaded Tools
Tools fall into two states in this pattern:
| State | What is sent | When it applies |
|---|---|---|
| Loaded | The full definition: name, description, and schema | Tools the application always needs, and tools the search has selected |
| Deferred | Only enough to be found by search | The rest of the catalog |
The documentation describes marking tools for deferred loading with a defer_loading setting on each tool definition. A deferred tool is not usable until it is loaded, and loading happens through the search mechanism. The distinction is important for cost, and for the cache: a catalog that changes on every request invalidates the cached tool prefix, while a stable catalog with deferred loading keeps the prefix steady, as Lesson 128 showed for tool definitions.
The exact field names and the search tool's type identifier are defined in the tool search documentation, and they should be copied from there rather than from memory. The pattern itself is the important part, and it is the same regardless of the exact spelling.
What Search Needs
Search can only find a tool whose description tells it what the tool is for. A tool named op_4417 with no description will never be selected, however useful it is. Good catalog design for search therefore follows rules that also help the model choose tools directly:
| Element | Guidance |
|---|---|
| Name | Descriptive and consistent, such as billing_refund_order |
| Description | Says what the tool does, the domain it belongs to, and when to use it |
| Vocabulary | Uses the words users actually say: refund, cancel, track, not only internal codes |
| Grouping | Related tools share a domain word, so search can find the family |
Lesson 93 described tool docstrings in depth. The same content serves search, because the search matches against the same text Claude reads.
When Tool Search Pays Off
Tool search adds a step, and that step has a cost of its own. It is worth using when the definitions of the tools that are not needed would be a large share of the request. A rough test is to estimate the tokens of the full catalog, and compare them with the tokens a typical request actually needs. When the full catalog dominates, deferral pays. When the catalog is small, the overhead of searching can exceed the saving, and loading everything is simpler.
The estimate can be rough. Tokens are usually a fixed multiple of characters, so the length of the serialized definitions gives an order of magnitude, and count_tokens() (Lesson 158) gives the exact figure for a specific request.
Simulating Selection
The simulation below builds a catalog of three hundred tools in five domains. It selects the tools whose description or name matches the words in a request, the way a search would, and it reports how little of the catalog was needed. The matching is deliberately simple, so the behavior is easy to follow:
"""tool_search_sim.py: select a few relevant tools from a large catalog, by word matching."""
import re
DOMAINS = ["billing", "shipping", "inventory", "support", "analytics"]
CATALOG = [
{
"name": f"{domain}_action_{number}",
"description": f"Performs {domain} action {number} for the store team. "
"Accepts record identifiers and returns status details.",
}
for domain in DOMAINS
for number in range(60)
]
def words(text: str) -> set[str]:
return set(re.findall(r"[a-z]+", text.lower()))
def search(query: str, catalog: list[dict], limit: int = 5) -> list[dict]:
query_words = words(query)
scored = []
for tool in catalog:
score = len(query_words & words(tool["name"] + " " + tool["description"]))
if score:
scored.append((score, tool))
scored.sort(key=lambda pair: (-pair[0], pair[1]["name"]))
return [tool for _, tool in scored[:limit]]
if __name__ == "__main__":
chosen = search("Refund the billing charge for this customer", CATALOG)
print("catalog size:", len(CATALOG))
print("loaded:", [tool["name"] for tool in chosen])
print(f"share of catalog loaded: {len(chosen) / len(CATALOG):.1%}")
Output:
catalog size: 300
loaded: ['billing_action_0', 'billing_action_1', 'billing_action_10', 'billing_action_11', 'billing_action_12']
share of catalog loaded: 1.7%
How It Works
- The catalog is built from domains. Five domains of sixty tools each give three hundred tools, and every tool carries its domain word in its description, as good catalog design requires.
words()reduces text to lowercase words, so matching ignores case and punctuation. The query "Refund the billing charge for this customer" contributes the wordbilling, along with other words no tool uses.search()scores each tool by shared words, and ignores tools with no match. Every billing tool scores the same, so the tie is broken by name, which makes the output reproducible.- Only five tools are loaded, which is 1.7% of the catalog. Sending the other 295 definitions would have cost far more, for tools this request cannot use.
- The ordering is alphabetical among ties. A real search ranks by relevance, which is usually better, but the simulation keeps the example exact.
Note: a real tool search is driven by Claude's own query, not by the user's raw wording, and it matches against richer signals than shared words. The simulation shows the principle that a good catalog makes selection possible, not the matching algorithm.
Keeping the Cache Stable
The cache interaction is one of the main reasons to design this carefully. A tool definition change invalidates the tool cache and everything after it (Lesson 127). A catalog that is edited frequently, or that loads a different set of definitions on every request, rewrites the cached prefix each time. Deferred loading keeps the always-loaded definitions stable, and the searched definitions arrive in the conversation as results, after the cached prefix. The design goal is a stable core and a variable periphery.
Validating Search Quality
A search that loads the wrong tool is worse than one that loads too many, because the model then reasons from the wrong definition. Quality should be checked with test queries that have known correct tools, in the same way Lesson 39 checked prompts. A set of fifty requests, each paired with the tool it should load, shows which descriptions are failing. The failures usually point to a description that lacks the words users use, which is an easy fix.
Summary
Tool search keeps a large catalog out of the request until it is needed. Deferred tools are found through search, and only the relevant definitions are loaded for each step. Its value depends on the size of the catalog and on the quality of the descriptions, since search can only find what the text describes. Stable catalogs with deferred loading also protect the cache. The next lesson covers the web search tool, a server-side capability that searches the internet for the model.