跳至主要內容

ToolSearchProcessor

ToolSearchProcessor 是一個輸入 processor,可在執行階段探索及載入指定工具。它不會預先向 Agent 提供所有工具,而是提供兩個 meta-tool(search_toolsload_tool),讓 Agent 按需要尋找及載入工具。使用大型工具庫時,這可減少 context 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,
},
})

Constructor 參數
Constructor 參數 的直接連結

options:

ToolSearchProcessorOptions
工具搜尋 processor 的設定選項
ToolSearchProcessorOptions

tools:

Record<string, Tool>
所有可供搜尋及動態載入的工具。Agent 不會即時獲得這些工具,而必須透過搜尋探索,並按需要載入。

includeResolvedTools?:

boolean
同時讓 Agent 為此請求解析的工具(需要呼叫者憑證的 MCP 工具,或動態 tools 函式傳回的任何內容)可供搜尋,並在 Agent 載入前不將它們加入 prompt。meta-tool 永遠不會被保留。系統會按請求為已解析的工具建立索引,因此每個請求都會搜尋及載入其本身的工具 instance。

search?:

{ topK?: number; minScore?: number; autoLoad?: boolean }
搜尋行為的設定。

search.topK?:

number
搜尋結果最多傳回的工具數目。

search.minScore?:

number
工具要納入搜尋結果所需的最低相關性分數(0 至 1)。

search.autoLoad?:

boolean
設為 true 時,search_tools 傳回的工具會立即在搜尋期間啟用。系統不會公開 load_tool meta-tool,將先搜尋再載入的兩步流程整合成單一搜尋步驟。已探索的工具會在下一輪可供使用。由於每個相符項目都會啟用,請將 topK 維持在較小的數值。

storage?:

'in-memory' | 'context'
已載入工具狀態的儲存位置。'in-memory'(預設)會以每個 thread 為單位,在記憶體內的 map 中追蹤已載入工具,並使用 TTL 清理(請參閱 ttl);重新啟動後狀態會遺失,而匿名請求會共用一個 'default' 項目。'context' 會從對話訊息推導已載入狀態——當訊息中仍然存在點名某工具的 search_tools/load_tool 結果,該工具便視為已載入;此模式可承受重新啟動,毋須 memory,而當該結果不再出現在訊息中時,工具會自動卸載。'context' store 須選擇啟用。

ttl?:

number
記憶體內 thread 狀態的存活時間,以毫秒為單位。只適用於預設的 'in-memory' store;閒置時間超過此時限後,系統會清理 thread 狀態。設為 0 可停用清理。'context' store 會忽略此設定。

filter?:

(args: ToolSearchFilterArgs) => boolean | Promise<boolean>
選用的請求感知 hook,可從搜尋結果隱藏工具、阻止載入工具,或為目前請求隱藏已載入的工具。

傳回值
傳回值 的直接連結

id:

string
Processor 識別碼,設為 'tool-search'

name:

string
Processor 顯示名稱,設為 'Tool Search Processor'

processInputStep:

(args: ProcessInputStepArgs) => Promise<ProcessInputStepResult>
處理每個步驟,將搜尋/載入 meta-tool 及任何先前已載入的工具注入 Agent 的工具集。

方法
方法 的直接連結

狀態檢查(舊有的 'in-memory' store)
state-inspection-legacy-in-memory-store 的直接連結

這些方法只會操作預設的 'in-memory' store。它們對 'context' store 不會執行任何操作,因為其狀態位於對話訊息,而非 process 內的 map。

clearState(threadId)
clearstatethreadid 的直接連結

清除單一 thread 的已載入工具狀態。

processor.clearState('thread-123')

clearAllState()
clearallstate 的直接連結

清除所有 thread 的已載入工具狀態。

processor.clearAllState()

getStateStats()
getstatestats 的直接連結

傳回受追蹤的 thread 數目及最早存取時間,以便除錯記憶體增長問題。

const { threadCount, oldestAccessTime } = processor.getStateStats()

傳回:{ threadCount: number; oldestAccessTime: number | null }

cleanupNow()
cleanupnow 的直接連結

立即執行 TTL 清理,而非等待排程掃描。

const cleaned = processor.cleanupNow()

傳回:number:已清理的 thread 數目。

請求感知篩選
請求感知篩選 的直接連結

使用 filter 將請求特定的政策套用至執行階段指定的工具。此 hook 會接收已解析的工具 ID(以 toolName 傳入)、工具、request context 及 phase。toolNamesearch_tools 傳回的 ID,可能與 tools object 中使用的 key 不同。

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 值描述套用 filter 的位置:

  • search:篩選 search_tools 傳回的結果。
  • load:阻止 load_tool 載入不允許的工具。
  • active:如果目前請求不再允許某個已載入的工具,便隱藏該工具。

如果 hook 拋出錯誤或被拒絕,ToolSearchProcessor 會將該工具視為不允許用於該請求。每個相符的搜尋候選項目都可能執行此 hook,因此非同步政策檢查應保持輕量或使用快取。search_tools meta-tool 永遠可供使用。除非啟用了 search.autoLoad,否則 load_tool 亦可供使用。直接透過 Agent 或 processInputStep 傳入的工具會維持可用,除非你在 ToolSearchProcessor 以外篩選它們,或啟用 includeResolvedTools

搜尋請求解析的工具
搜尋請求解析的工具 的直接連結

tools 選項在建構時已固定,因此你無法列出只在個別請求中存在的工具(需要呼叫者憑證的 MCP 工具,或動態 tools 函式傳回的任何內容)。這些工具預設會略過搜尋,並在每一輪佔用 prompt 空間。

includeResolvedTools: true 設定為為請求建立這些工具的索引,並在 Agent 載入它們前不加入 prompt:

src/mastra/agents/mcp-agent.ts
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],
})

每個請求都會獨立建立索引,因此某位呼叫者載入的工具絕不會解析為另一位呼叫者同名工具的 instance。

此選項適用於為請求解析的每個工具,包括 memory、workspace、skill 及 browser 工具。只有 search_toolsload_tool meta-tool 會留在 prompt 中,因此 Agent 暗中依賴的任何工具都必須先經搜尋找到,然後才可呼叫。

進階使用範例
進階使用範例 的直接連結

src/mastra/agents/dynamic-tools-agent.ts
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 的工作流程如下:

  1. Agent 收到使用者訊息
  2. Agent 使用關鍵字(例如「github issue」)呼叫 search_tools
  3. Agent 檢視結果,並使用工具名稱呼叫 load_tool
  4. 已載入的工具會在下一輪可供使用
  5. Agent 如常使用已載入的工具

使用 autoLoad 進行單步探索
single-step-discovery-with-autoload 的直接連結

search.autoLoad 設為 true,即可略過獨立的載入步驟。search_tools 傳回的工具會立即啟用,而系統不會公開 load_tool meta-tool。這可為每次探索省去一輪 model 操作,從而降低 token 用量及延遲,而且在不同 Provider 上的運作方式相同。

const toolSearch = new ToolSearchProcessor({
tools: allTools,
search: {
topK: 3,
autoLoad: true,
},
})

使用 autoLoad 時,工作流程變為:

  1. Agent 收到使用者訊息
  2. Agent 使用關鍵字呼叫 search_tools
  3. 相符的工具會自動啟用,並在下一輪可供使用
  4. Agent 如常使用工具

每個相符項目都會啟用,因此請將 topK 維持在較小的數值(例如 3),以免加入 Agent 不需要的工具。已啟用的工具會附加在現有工具之後,讓支援 prompt caching 的 Provider 可維持穩定的快取 prompt prefix。

已載入工具的儲存方式
已載入工具的儲存方式 的直接連結

storage 選項控制在何處追蹤已載入的工具集。預設為 'in-memory''context' store 須選擇啟用。

'in-memory'(預設)
in-memory-default 的直接連結

系統會以每個 thread 為單位,在記憶體內的 map 中追蹤已載入的工具,並根據 ttl 選項執行 TTL 清理(預設為一小時)。這是原有行為:

  • 毋須設定 memory。
  • process 重新啟動後,狀態會遺失。
  • 沒有 thread ID 的請求會共用一個 'default' 項目。

使用 clearStateclearAllStategetStateStatscleanupNow 檢查或重設此 store。

'context'
context 的直接連結

已載入狀態會從對話訊息推導:當訊息中仍然存在點名某工具的 search_toolsload_tool 結果,該工具便視為已載入。此模式:

  • 毋須設定 memory。
  • 可承受重新啟動:持久記錄就是已保存的訊息歷史記錄。
  • 當該結果不再出現在訊息中時,會自動卸載工具。
import { ToolSearchProcessor } from '@mastra/core/processors'

const toolSearch = new ToolSearchProcessor({
tools: allTools,
storage: 'context',
})

兩種模式下,載入工具都有利於快取:載入操作只會附加,因此對於支援 prompt caching 的 Provider,快取 prompt prefix 會維持穩定。

卸載工具會改變傳送至 model 的工具定義,令快取 prefix 移位,並令下一輪出現 cache write,而非 cache hit。在 'in-memory' 模式下,當 ttl 淘汰某個 thread 的狀態時便會發生。在 'context' 模式下,當訊息中不再存在工具的探索結果時(例如裁剪較舊的訊息時)便會發生。工具會被卸載,而 model 必須再次搜尋,才可重用該工具。這是預期行為:移除未使用的工具會以一次 cache write 換取後續輪次較小的 prefix。

與其他 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),
],
})