Tool Search with Embeddings: Scaling Claude to Thousands of Tools
Building Claude applications with dozens of specialized tools quickly hits a wall: providing all tool definitions upfront consumes your context window, increases latency and costs, and makes it harder for Claude to find the right tool. Beyond ~100 tools, this approach becomes impractical.
Semantic tool search solves this by treating tools as discoverable resources. Instead of front-loading hundreds of definitions, you give Claude a single tool_search tool that returns relevant capabilities on demand, cutting context usage by 90%+ while enabling applications that scale to thousands of tools.
By the end of this cookbook, you'll be able to:
- Implement client-side tool search to scale Claude applications from dozens to thousands of tools
- Use semantic embeddings to dynamically discover relevant tools based on task context
- Apply this pattern to domain-specific tool libraries (APIs, databases, internal systems)
This pattern is used in production by teams managing large tool ecosystems where context efficiency is critical. While we'll demonstrate with a small set of tools for clarity, the same approach scales seamlessly to libraries with hundreds or thousands of tools.
Prerequisites
Before following this guide, ensure you have:
Required Knowledge
- Python fundamentals - comfortable with functions, dictionaries, and basic data structures
- Basic understanding of Claude tool use - we recommend reading the Tool Use Guide(opens in new tab) first
Required Tools
- Python 3.11 or higher
- Anthropic API key (get one here(opens in new tab))
Setup
First, install the required dependencies:
huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks... To disable this warning, you can either: - Avoid using `tokenizers` before the fork if possible - Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false) Note: you may need to restart the kernel to use updated packages.
Ensure your .env file contains:
Load your environment variables and configure the client:
Loading SentenceTransformer model... ✓ Clients initialized successfully
Define Tool Library
Before we can implement semantic search, we need tools to search through. We'll create a library of 8 tools across two categories: Weather and Finance.
In production applications, you might manage hundreds or thousands of tools across your internal APIs, database operations, or third-party integrations. The semantic search approach scales to these larger libraries without modification - we're using a small set here purely for demonstration clarity.
✓ Defined 8 tools in the library
Create Tool Embeddings
Semantic search works by comparing the meaning of text, rather than just searching for keywords. To enable this, we need to convert each tool definition into an embedding vector that captures its semantic meaning.
Since our tool definitions are structured JSON objects with names, descriptions, and parameters, we first convert each tool into a human-readable text representation, then generate embedding vectors using SentenceTransformer's all-MiniLM-L6-v2 model.
We picked this model because it is:
- Lightweight and fast (only 384 dimensions vs 768+ for larger models)
- Runs locally without requiring API calls
- Sufficient for tool search (you can experiment with larger models for better accuracy)
Let's start by creating a function that converts tool definitions into searchable text:
Sample tool text representation: Tool: get_weather Description: Get the current weather in a given location Parameters: location (string): The city and state, e.g. San Francisco, CA, unit (string): The unit of temperature
Now let's create embeddings for all our tools:
Creating embeddings for all tools... ✓ Created embeddings with shape: (8, 384) - 8 tools - 384 dimensions per embedding
Implement Tool Search
With our tools embedded as vectors, we can now implement semantic search. If two pieces of text have similar meanings, their embedding vectors will be close together in vector space. We measure this "closeness" using cosine similarity.
The search process:
- Embed the query: Convert Claude's natural language search request into the same vector space as our tools
- Calculate similarity: Compute cosine similarity between the query vector and each tool vector
- Rank and return: Sort tools by similarity score and return the top N matches
With semantic search, Claude can search using natural language like "I need to check the weather" or "calculate investment returns" rather than exact tool names.
Let's implement the search function and test it with a sample query:
Search query: 'I need to check the weather' Top 3 matching tools: 1. get_weather (similarity: 0.560) 2. get_forecast (similarity: 0.508) 3. get_air_quality (similarity: 0.401)
Define the tool_search Tool
Now we'll implement the meta-tool that allows Claude to discover other tools on demand. When Claude needs a capability it doesn't have, it searches for it using this tool_search tool, receives the tool definitions in the result, and can use those newly discovered tools immediately.
This is the only tool we provide to Claude initially:
✓ Tool search definition created
Now let's implement the handler that processes tool_search calls from Claude and returns discovered tools:
🔍 Tool search: 'stock market data'
Found 3 tools:
1. get_stock_price (similarity: 0.524)
2. get_market_news (similarity: 0.469)
3. calculate_compound_interest (similarity: 0.244)
Returned 3 tool references:
{'type': 'tool_reference', 'tool_name': 'get_stock_price'}
{'type': 'tool_reference', 'tool_name': 'get_market_news'}
{'type': 'tool_reference', 'tool_name': 'calculate_compound_interest'}Mock Tool Execution
For this demonstration, we'll create mock responses for tool executions. In a real application, these would call actual APIs or services:
✓ Mock tool execution function created
Implement Conversation Loop
Now let's put it all together! We'll create a conversation loop that handles the complete tool search workflow.
The conversation flow:
- Claude starts with only the
tool_searchtool available - When Claude calls
tool_search, we run semantic search and return matching tool definitions - Claude can then use the discovered tools immediately
- When Claude calls a discovered tool, we execute it (using mock responses for this demo)
- The loop continues until Claude has a final answer
✓ Conversation loop implemented
Example 1: Weather Query
Let's test with a simple weather question. Claude should:
- Call
tool_searchto find weather tools - Receive weather tool definitions in the result
- Use one of the discovered tools
================================================================================
USER: What's the weather like in Tokyo?
================================================================================
--- Turn 1 ---
🔧 Tool invocation: get_weather
Input: {
"location": "Tokyo"
}
✅ Mock result: {"location": "Tokyo", "temperature": 75, "unit": "fahrenheit", "conditions": "partly cloudy", "humidity": 61, "wind_speed": 9}
--- Turn 2 ---
✓ Conversation complete
ASSISTANT: The weather in Tokyo is currently:
- **Temperature:** 75°F (about 24°C)
- **Conditions:** Partly cloudy
- **Humidity:** 61%
- **Wind Speed:** 9 mph
It's a pleasant day with comfortable temperatures and some cloud cover!
================================================================================Example 2: Finance Query
Let's try a financial calculation query that requires discovering and using finance tools:
================================================================================
USER: If I invest $10,000 at 5% annual interest for 10 years with monthly compounding, how much will I have?
================================================================================
--- Turn 1 ---
🔧 Tool invocation: calculate_compound_interest
Input: {
"principal": 10000,
"rate": 5,
"years": 10,
"frequency": "monthly"
}
✅ Mock result: {"principal": 10000, "rate": 5, "years": 10, "compounding_frequency": "monthly", "final_amount": 16470.09, "interest_earned": 6470.09}
--- Turn 2 ---
✓ Conversation complete
ASSISTANT: If you invest $10,000 at 5% annual interest for 10 years with monthly compounding, you will have:
**Final Amount: $16,470.09**
This means you'll earn **$6,470.09** in interest over the 10-year period.
The monthly compounding means that interest is calculated and added to your principal every month, which allows your investment to grow faster than with annual compounding due to the effect of earning "interest on interest" more frequently.
================================================================================Conclusion
In this cookbook, we implemented a client-side tool search system that enables Claude to work with large tool libraries efficiently. We covered:
- Semantic tool discovery: Using embeddings to match natural language queries to relevant tools, enabling Claude to find the right capability without seeing all available tools upfront
- Dynamic tool loading: Returning tool definitions in tool results using Claude's tool search feature, allowing Claude to discover and immediately use new tools mid-conversation
- Context optimization: Reducing initial context from thousands of tokens (19+ tool definitions) to just the single
tool_searchdefinition, cutting context usage by 90%+
Applying This to Your Projects
Consider tool search when:
- You have >20 specialized tools and context usage becomes a concern
- Your tool library grows over time and manual curation becomes impractical
- You need to support domain-specific APIs with hundreds of endpoints (database operations, internal microservices, third-party integrations)
- Cost and latency optimization are priorities for your application
Next Steps
To take this implementation further:
- Persist embeddings: Cache embeddings to disk to avoid recomputing on every session, reducing startup time
- Improve search quality: Experiment with different embedding models (e.g., larger models like
all-mpnet-base-v2) or implement hybrid search combining semantic and keyword matching (BM25) - Scale to larger libraries: Test with hundreds or thousands of tools to see how the pattern performs at production scale
- Add tool metadata: Include usage statistics, cost information, or reliability scores in your search ranking
- Implement caching: Cache frequently used tool definitions to reduce repeated searches
Further Reading
- Claude Tool Use Guide(opens in new tab) - Comprehensive guide to building with tools
- SentenceTransformers Documentation(opens in new tab) - Learn more about embedding models and semantic search
- Tool Search Tool Documentation(opens in new tab) - Official documentation on the tool search pattern