Middleware: ToolSearch
ToolSearch Middleware
adk/middlewares/dynamictool/toolsearch
π‘ This middleware was introduced in v0.8.0.Beta.
Overview
The toolsearch middleware implements dynamic tool selection. When the tool library is large, passing all tools to the model would overflow the context. This middleware’s approach is:
- Add a
tool_searchmeta-tool that accepts regex patterns to search tool names - Initially hide all dynamic tools
- After the model calls
tool_search, matched tools become available in subsequent calls
Architecture
Agent initialization
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββ
β BeforeAgent β
β - Inject tool_search tool β
β - Add DynamicTools to Tools list β
βββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββ
β WrapModel β
β Before each Model call: β
β 1. Scan message history to find all tool_search return results β
β 2. Full Tools minus unselected DynamicTools = tools for this Model β
β call β
ββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
Model call
Configuration
type Config struct {
// Tools that can be dynamically searched and loaded
DynamicTools []tool.BaseTool
}
tool_search Tool
The tool injected by the middleware.
Parameters:
| Parameter | Type | Required | Description |
regex_pattern | string | Yes | Regex pattern to match tool names |
Returns:
{
"selectedTools": ["tool_a", "tool_b"]
}
Usage Example
middleware, err := toolsearch.New(ctx, &toolsearch.Config{
DynamicTools: []tool.BaseTool{
weatherTool,
stockTool,
currencyTool,
// ... many tools
},
})
if err != nil {
return err
}
agent, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: myModel,
Handlers: []adk.ChatModelAgentMiddleware{middleware},
})
How It Works
BeforeAgent
- Get all DynamicTools
- Create
tool_searchtool using DynamicTools - Add
tool_searchand all DynamicTools torunCtx.Tools, at this point Agent has full Tools
WrapModel
Before each Model call:
- Iterate through message history to find all
tool_searchreturn results - Collect selected tool names
- Filter out unselected DynamicTools from full tools
- Call Model with filtered tool list
Tool Selection Flow
Round 1:
Model can only see tool_search
Model calls tool_search(regex_pattern="weather.*")
Returns {"selectedTools": ["weather_forecast", "weather_history"]}
Round 2:
Model can see tool_search + weather_forecast + weather_history
Model calls weather_forecast(...)
Notes
- DynamicTools cannot be empty
- Regex matches tool names, not descriptions
- Selected tools remain available unless the tool_search call result is deleted or modified
- tool_search can be called multiple times, results accumulate