SearchableToolset
Enable agents to dynamically discover tools from large catalogs using keyword-based search.
| Mandatory init variables | catalog: A list of Tools and/or Toolsets, or a single Toolset |
| API reference | SearchableToolset |
| GitHub link | https://github.com/deepset-ai/haystack/blob/main/haystack/tools/searchable_toolset.py |
Overview
SearchableToolset is designed for working with large tool catalogs.
Instead of exposing all tools at once, which can overwhelm the LLM context, it provides a single search_tools bootstrap tool.
The agent uses this tool to find and load specific tools from the catalog using BM25 keyword search.
Once the agent calls search_tools, the matching tools become immediately available and the agent can invoke them in
subsequent iterations.
Modes of operation
SearchableToolset operates in one of two modes depending on catalog size:
- Search mode (default for large catalogs): The agent starts with only the
search_toolsbootstrap tool and discovers other tools on demand. This is activated when the catalog size meets or exceedssearch_threshold. - Passthrough mode (small catalogs): All tools are exposed directly, with no discovery step needed. This is activated automatically when the catalog has fewer tools than
search_threshold.
Parameters
catalog(required): The source of tools — a list ofTooland/orToolsetinstances, or a singleToolset. This includes MCPTool and MCPToolset instances.top_k(optional): The default number of tools returned by eachsearch_toolscall. Default is3.search_threshold(optional): Minimum catalog size to activate search mode. Catalogs smaller than this value use passthrough mode instead. Default is8.
SearchableToolset does not support adding new tools after initialization or merging with other toolsets. Use catalog to provide all tools upfront.
Usage
Basic usage with an Agent
from typing import Annotated
from haystack.components.agents import Agent
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.dataclasses import ChatMessage
from haystack.tools import create_tool_from_function, SearchableToolset
def get_weather(city: Annotated[str, "The city to get the weather for"]) -> str:
"""Get current weather for a city."""
return f"Sunny, 22°C in {city}"
def search_web(query: Annotated[str, "The search query"]) -> str:
"""Search the web for information."""
return f"Results for: {query}"
# Build a catalog from tools
catalog = [
create_tool_from_function(get_weather),
create_tool_from_function(search_web),
# ... many more tools
]
toolset = SearchableToolset(catalog=catalog)
agent = Agent(
chat_generator=OpenAIChatGenerator(),
tools=toolset,
)
# The agent initially sees only `search_tools`. It will call it to find relevant tools,
# then use the discovered tools to answer the question.
result = agent.run(messages=[ChatMessage.from_user("What's the weather in Milan?")])
print(result["messages"][-1].text)
Reusing the toolset across multiple agent runs
When reusing the same SearchableToolset instance across multiple agent runs, you can call clear() to reset any tools discovered in the previous run:
agent = Agent(
chat_generator=OpenAIChatGenerator(),
tools=toolset,
)
result1 = agent.run(messages=[ChatMessage.from_user("What's the weather in Milan?")])
# Reset discovered tools before the next run
toolset.clear()
result2 = agent.run(messages=[ChatMessage.from_user("Search for news about AI.")])