> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-HK/llms.txt # ToolSearchProcessor `ToolSearchProcessor` 是一個**輸入 processor**,可在執行階段探索及載入指定工具。它不會預先向 Agent 提供所有工具,而是提供兩個 meta-tool(`search_tools` 及 `load_tool`),讓 Agent 按需要尋找及載入工具。使用大型工具庫時,這可減少 context token 用量。 ## 使用範例 ```typescript 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 參數 **options** (`ToolSearchProcessorOptions`): 工具搜尋 processor 的設定選項 **options.tools** (`Record`): 所有可供搜尋及動態載入的工具。Agent 不會即時獲得這些工具,而必須透過搜尋探索,並按需要載入。 **options.includeResolvedTools** (`boolean`): 同時讓 Agent 為此請求解析的工具(需要呼叫者憑證的 MCP 工具,或動態 tools 函式傳回的任何內容)可供搜尋,並在 Agent 載入前不將它們加入 prompt。meta-tool 永遠不會被保留。系統會按請求為已解析的工具建立索引,因此每個請求都會搜尋及載入其本身的工具 instance。 **options.search** (`{ topK?: number; minScore?: number; autoLoad?: boolean }`): 搜尋行為的設定。 **options.search.topK** (`number`): 搜尋結果最多傳回的工具數目。 **options.search.minScore** (`number`): 工具要納入搜尋結果所需的最低相關性分數(0 至 1)。 **options.search.autoLoad** (`boolean`): 設為 true 時,search\_tools 傳回的工具會立即在搜尋期間啟用。系統不會公開 load\_tool meta-tool,將先搜尋再載入的兩步流程整合成單一搜尋步驟。已探索的工具會在下一輪可供使用。由於每個相符項目都會啟用,請將 topK 維持在較小的數值。 **options.storage** (`'in-memory' | 'context'`): 已載入工具狀態的儲存位置。'in-memory'(預設)會以每個 thread 為單位,在記憶體內的 map 中追蹤已載入工具,並使用 TTL 清理(請參閱 ttl);重新啟動後狀態會遺失,而匿名請求會共用一個 'default' 項目。'context' 會從對話訊息推導已載入狀態——當訊息中仍然存在點名某工具的 search\_tools/load\_tool 結果,該工具便視為已載入;此模式可承受重新啟動,毋須 memory,而當該結果不再出現在訊息中時,工具會自動卸載。'context' store 須選擇啟用。 **options.ttl** (`number`): 記憶體內 thread 狀態的存活時間,以毫秒為單位。只適用於預設的 'in-memory' store;閒置時間超過此時限後,系統會清理 thread 狀態。設為 0 可停用清理。'context' store 會忽略此設定。 **options.filter** (`(args: ToolSearchFilterArgs) => boolean | Promise`): 選用的請求感知 hook,可從搜尋結果隱藏工具、阻止載入工具,或為目前請求隱藏已載入的工具。 ## 傳回值 **id** (`string`): Processor 識別碼,設為 'tool-search' **name** (`string`): Processor 顯示名稱,設為 'Tool Search Processor' **processInputStep** (`(args: ProcessInputStepArgs) => Promise`): 處理每個步驟,將搜尋/載入 meta-tool 及任何先前已載入的工具注入 Agent 的工具集。 ## 方法 ### 狀態檢查(舊有的 `'in-memory'` store) 這些方法只會操作預設的 `'in-memory'` store。它們對 `'context'` store 不會執行任何操作,因為其狀態位於對話訊息,而非 process 內的 map。 #### `clearState(threadId)` 清除單一 thread 的已載入工具狀態。 ```typescript processor.clearState('thread-123') ``` #### `clearAllState()` 清除所有 thread 的已載入工具狀態。 ```typescript processor.clearAllState() ``` #### `getStateStats()` 傳回受追蹤的 thread 數目及最早存取時間,以便除錯記憶體增長問題。 ```typescript const { threadCount, oldestAccessTime } = processor.getStateStats() ``` 傳回:`{ threadCount: number; oldestAccessTime: number | null }` #### `cleanupNow()` 立即執行 TTL 清理,而非等待排程掃描。 ```typescript const cleaned = processor.cleanupNow() ``` 傳回:`number`:已清理的 thread 數目。 ## 請求感知篩選 使用 `filter` 將請求特定的政策套用至執行階段指定的工具。此 hook 會接收已解析的工具 ID(以 `toolName` 傳入)、工具、request context 及 phase。`toolName` 是 `search_tools` 傳回的 ID,可能與 `tools` object 中使用的 key 不同。 ```typescript 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: ```typescript 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_tools` 及 `load_tool` meta-tool 會留在 prompt 中,因此 Agent 暗中依賴的任何工具都必須先經搜尋找到,然後才可呼叫。 ## 進階使用範例 ```typescript 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` 進行單步探索 將 `search.autoLoad` 設為 `true`,即可略過獨立的載入步驟。`search_tools` 傳回的工具會立即啟用,而系統不會公開 `load_tool` meta-tool。這可為每次探索省去一輪 model 操作,從而降低 token 用量及延遲,而且在不同 Provider 上的運作方式相同。 ```typescript 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'`(預設) 系統會以每個 thread 為單位,在記憶體內的 map 中追蹤已載入的工具,並根據 `ttl` 選項執行 TTL 清理(預設為一小時)。這是原有行為: - 毋須設定 memory。 - process 重新啟動後,狀態會遺失。 - 沒有 thread ID 的請求會共用一個 `'default'` 項目。 使用 `clearState`、`clearAllState`、`getStateStats` 及 `cleanupNow` 檢查或重設此 store。 ### `'context'` 已載入狀態會從對話訊息推導:當訊息中仍然存在點名某工具的 `search_tools` 或 `load_tool` 結果,該工具便視為已載入。此模式: - 毋須設定 memory。 - 可承受重新啟動:持久記錄就是已保存的訊息歷史記錄。 - 當該結果不再出現在訊息中時,會自動卸載工具。 ```typescript 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 配合使用 ```typescript 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), ], }) ``` ## 相關內容 - [Processors](https://mastra.zisheng.pro/zh-HK/docs/agents/processors) - [使用工具](https://mastra.zisheng.pro/zh-HK/docs/agents/using-tools)