ToolSearchProcessor
ToolSearchProcessor 是一个输入 Processor,支持发现并加载运行时定义的 Tool。它不会预先向 Agent 提供所有 Tool,而是为 Agent 提供两个元 Tool(search_tools 和 load_tool),使其能够按需查找和加载 Tool。使用大型 Tool 库时,这可以减少上下文 token 用量。
使用示例使用示例的直接链接
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,
},
})
构造函数参数构造函数参数的直接链接
options:
tools:
includeResolvedTools?:
search?:
search.topK?:
search.minScore?:
search.autoLoad?:
storage?:
ttl?:
filter?:
返回值返回值的直接链接
id:
name:
processInputStep:
方法方法的直接链接
状态检查(旧版 'in-memory' 存储)state-inspection-legacy-in-memory-store的直接链接
这些方法仅对默认的 'in-memory' 存储生效。对于状态保存在对话消息而非进程内映射中的 'context' 存储,它们不会执行任何操作。
clearState(threadId)clearstatethreadid的直接链接
清除单个线程的已加载 Tool 状态。
processor.clearState('thread-123')
clearAllState()clearallstate的直接链接
清除所有线程的已加载 Tool 状态。
processor.clearAllState()
getStateStats()getstatestats的直接链接
返回所跟踪的线程数和最早的访问时间,用于调试内存增长。
const { threadCount, oldestAccessTime } = processor.getStateStats()
返回:{ threadCount: number; oldestAccessTime: number | null }
cleanupNow()cleanupnow的直接链接
立即运行 TTL 清理,而不等待定时清理。
const cleaned = processor.cleanupNow()
返回:number:已清理的线程数。
请求感知过滤请求感知过滤的直接链接
使用 filter 将请求特定的策略应用于运行时定义的 Tool。此 hook 会接收解析后的 Tool ID(作为 toolName)、Tool、请求上下文和阶段。toolName 是 search_tools 返回的 ID,可能与 tools 对象中使用的键不同。
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_')
},
})
phase 值描述过滤器的应用位置:
search:过滤search_tools返回的结果。load:阻止load_tool加载不允许的 Tool。active:如果已加载的 Tool 不再被允许,则为当前请求隐藏它们。
如果 hook 抛出错误或 Promise 被拒绝,ToolSearchProcessor 会将该 Tool 视为不允许用于此请求。此 hook 可能会针对每个匹配的搜索候选项运行,因此应确保异步策略检查成本较低或使用缓存。search_tools 元 Tool 始终可用。除非启用了 search.autoLoad,否则 load_tool 可用。直接通过 Agent 或 processInputStep 传递的 Tool 会保持可用,除非你在 ToolSearchProcessor 外部将其过滤,或启用 includeResolvedTools。
搜索为请求解析的 Tool搜索为请求解析的 Tool的直接链接
tools 选项在构造时固定,因此无法列出仅针对每个请求存在的 Tool(例如需要调用方凭证的 MCP Tool,或动态 tools 函数返回的任何内容)。默认情况下,这些 Tool 会绕过搜索,并在每一轮占用提示词空间。
设置 includeResolvedTools: true 可为这些 Tool 按请求建立索引,并在 Agent 加载它们之前不将其放入提示词:
import { Agent } from '@mastra/core/agent'
import { ToolSearchProcessor } from '@mastra/core/processors'
const toolSearch = new ToolSearchProcessor({
tools: staticTools,
includeResolvedTools: true,
})
const agent = new Agent({
id: 'mcp-agent',
name: 'mcp-agent',
instructions: 'Search for a tool when you need a capability you do not have.',
model: 'openai/gpt-5.6-sol',
// Resolved per request, then searchable alongside staticTools
tools: async ({ requestContext }) => mcpClient.getTools(requestContext.get('userToken')),
inputProcessors: [toolSearch],
})
每个请求都会单独建立索引,因此一个调用方加载的 Tool 绝不会解析为另一个调用方同名 Tool 的实例。
此选项适用于为请求解析的每个 Tool,包括 memory、workspace、skill 和 browser Tool。只有 search_tools 和 load_tool 元 Tool 会留在提示词中,因此 Agent 隐式依赖的任何 Tool 都必须先通过搜索找到,之后才能调用。
扩展使用示例扩展使用示例的直接链接
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({
id: 'dynamic-tools-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.6-sol',
inputProcessors: [toolSearch],
})
Agent 工作流如下:
- Agent 接收用户消息
- Agent 使用关键词调用
search_tools(例如“github issue”) - Agent 查看结果,并使用 Tool 名称调用
load_tool - 加载的 Tool 会在下一轮可用
- Agent 正常使用加载的 Tool
使用 autoLoad 进行单步骤发现single-step-discovery-with-autoload的直接链接
将 search.autoLoad 设为 true 可跳过单独的加载步骤。search_tools 返回的 Tool 会立即激活,并且不会暴露 load_tool 元 Tool。这样每次发现过程可减少一轮模型交互,从而降低 token 用量和延迟,并且在各 Provider 中行为一致。
const toolSearch = new ToolSearchProcessor({
tools: allTools,
search: {
topK: 3,
autoLoad: true,
},
})
使用 autoLoad 后,工作流变为:
- Agent 接收用户消息
- Agent 使用关键词调用
search_tools - 匹配的 Tool 会自动激活,并在下一轮可用
- Agent 正常使用 Tool
每个匹配项都会被激活,因此请保持较小的 topK(例如 3),以免添加 Agent 不需要的 Tool。激活的 Tool 会追加到现有 Tool 之后,这能为支持提示词缓存的 Provider 保持稳定的缓存提示词前缀。
已加载 Tool 的存储已加载 Tool 的存储的直接链接
storage 选项控制在哪里跟踪已加载的 Tool 集合。默认值为 'in-memory'。'context' 存储需选择启用。
'in-memory'(默认)in-memory-default的直接链接
已加载的 Tool 会在内存映射中按线程跟踪,并由 ttl 选项控制基于 TTL 的清理(默认为一小时)。这是原有行为:
- 无需配置 memory。
- 进程重启后状态会丢失。
- 没有线程 ID 的请求共享一个
'default'条目。
使用 clearState、clearAllState、getStateStats 和 cleanupNow 检查或重置此存储。
'context'context的直接链接
已加载状态从对话消息中推导:只要命名某个 Tool 的 search_tools 或 load_tool 结果仍在消息中,该 Tool 就处于已加载状态。此模式:
- 无需配置 memory。
- 可安全重启:持久化的消息历史记录就是耐久记录。
- 一旦该结果不再出现在消息中,就会自动卸载 Tool。
import { ToolSearchProcessor } from '@mastra/core/processors'
const toolSearch = new ToolSearchProcessor({
tools: allTools,
storage: 'context',
})
两种模式下加载 Tool 都有利于缓存:加载操作只会追加,因此对于支持提示词缓存的 Provider,缓存的提示词前缀会保持稳定。
卸载 Tool 会改变发送给模型的 Tool 定义,从而导致缓存前缀发生偏移,使下一轮需要写入缓存而无法命中缓存。在 'in-memory' 模式下,当线程状态因 ttl 被逐出时会发生这种情况。在 'context' 模式下,当 Tool 的发现结果不再出现在消息中时(例如裁剪较早的消息时)会发生这种情况。Tool 会被卸载,模型必须重新搜索后才能再次使用。这是预期行为:移除未使用的 Tool 会以一次缓存写入为代价,换取后续轮次中更小的前缀。
与其他 Processor 结合使用与其他 Processor 结合使用的直接链接
import { Agent } from '@mastra/core/agent'
import { ToolSearchProcessor, TokenLimiter } from '@mastra/core/processors'
const agent = new Agent({
id: 'my-agent',
name: 'my-agent',
model: 'openai/gpt-5.6-sol',
inputProcessors: [
new ToolSearchProcessor({
tools: allTools,
search: { topK: 5 },
}),
// Place TokenLimiter last to ensure context fits
new TokenLimiter(127000),
],
})