ToolSearchProcessor
The ToolSearchProcessor is an input processor that enables dynamic tool discovery and loading. Instead of providing all tools to the agent upfront, it gives the agent two meta-tools (search_tools and load_tool) that let it find and load tools on demand. This reduces context token usage when working with large tool libraries.
Usage exampleDirect link to Usage example
import { ToolSearchProcessor } from '@mastra/core/processors'
const toolSearch = new ToolSearchProcessor({
tools: {
createIssue: githubTools.createIssue,
sendEmail: emailTools.send,
getWeather: weatherTools.forecast,
// ... many more tools
},
search: {
topK: 5,
minScore: 0.1,
},
})
Constructor parametersDirect link to Constructor parameters
options:
tools:
search?:
search.topK?:
search.minScore?:
ttl?:
filter?:
ReturnsDirect link to Returns
id:
name:
processInputStep:
Request-aware filteringDirect link to Request-aware filtering
Use filter to apply request-specific policy to dynamic tools. The hook receives the resolved tool ID as toolName, the tool, request context, and phase. toolName is the ID returned by search_tools, which may differ from the key used in the tools object.
import { ToolSearchProcessor } from '@mastra/core/processors'
const toolSearch = new ToolSearchProcessor({
tools: allTools,
filter: ({ toolName, requestContext, phase }) => {
const plan = requestContext?.get('plan')
if (phase === 'search') {
return true
}
return plan === 'pro' || !toolName.startsWith('premium_')
},
})
The phase value describes where the filter is being applied:
search: Filters results returned bysearch_tools.load: Blocksload_toolfrom loading disallowed tools.active: Hides already-loaded tools from the current request if they are no longer allowed.
If the hook throws or rejects, ToolSearchProcessor treats the tool as disallowed for that request. The hook may run for every matching search candidate, so keep async policy checks cheap or cached. The meta-tools search_tools and load_tool are always available. Tools passed directly through the agent or processInputStep remain available unless you filter them outside ToolSearchProcessor.
Extended usage exampleDirect link to Extended usage example
import { Agent } from '@mastra/core/agent'
import { ToolSearchProcessor } from '@mastra/core/processors'
// Tools from various integrations
import { githubTools } from './tools/github'
import { slackTools } from './tools/slack'
import { dbTools } from './tools/database'
const toolSearch = new ToolSearchProcessor({
tools: {
...githubTools, // createIssue, listPRs, mergePR, ...
...slackTools, // sendMessage, createChannel, ...
...dbTools, // query, insert, update, ...
},
search: {
topK: 5,
minScore: 0.1,
},
})
const agent = new Agent({
name: 'dynamic-tools-agent',
instructions:
'You are a helpful assistant with access to many tools. Use search_tools to find relevant tools, then load_tool to make them available.',
model: 'openai/gpt-5.5',
inputProcessors: [toolSearch],
})
The agent workflow is:
- Agent receives a user message
- Agent calls
search_toolswith keywords (e.g., "github issue") - Agent reviews results and calls
load_toolwith the tool name - The loaded tool becomes available on the next turn
- Agent uses the loaded tool normally
Combining with other processorsDirect link to Combining with other processors
import { Agent } from '@mastra/core/agent'
import { ToolSearchProcessor, TokenLimiter } from '@mastra/core/processors'
const agent = new Agent({
name: 'my-agent',
model: 'openai/gpt-5.5',
inputProcessors: [
new ToolSearchProcessor({
tools: allTools,
search: { topK: 5 },
}),
// Place TokenLimiter last to ensure context fits
new TokenLimiter(127000),
],
})