メインコンテンツへ移動

ToolSearchProcessor

ToolSearchProcessor は、実行時に定義された Tool の検出と読み込みを可能にする input processor です。すべての Tool を最初から Agent に渡す代わりに、2つのメタ Tool(search_toolsload_tool)を提供し、必要に応じて Tool を検索して読み込めるようにします。大規模な Tool ライブラリを扱う際のコンテキストトークン使用量を削減できます。

使用例
使用例への直接リンク

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:

ToolSearchProcessorOptions
Tool 検索 processor の設定オプション
ToolSearchProcessorOptions

tools:

Record<string, Tool>
動的に検索して読み込めるすべての Tool。これらの Tool は Agent がすぐに利用できるわけではなく、検索で検出し、必要に応じて読み込む必要があります。

includeResolvedTools?:

boolean
Agent がこのリクエスト用に解決した Tool(呼び出し元の認証情報が必要な MCP Tool や、動的な tools 関数が返す Tool)も検索対象にし、Agent が読み込むまでプロンプトに含めません。メタ Tool は除外されません。リクエストごとに解決される Tool はリクエスト単位でインデックス化されるため、各リクエストはそれぞれ固有の Tool インスタンスを検索して読み込みます。

search?:

{ topK?: number; minScore?: number; autoLoad?: boolean }
検索動作の設定。

search.topK?:

number
検索結果として返す Tool の最大数。

search.minScore?:

number
Tool を検索結果に含める最小関連度スコア(0~1)。

search.autoLoad?:

boolean
true の場合、search_tools が返した Tool を検索処理の一部として即座に有効化します。load_tool メタ Tool は公開されず、検索してから読み込む2段階のフローが1回の検索ステップにまとまります。検出された Tool は次のターンから利用できます。一致したすべての Tool が有効になるため、topK は控えめに設定してください。

storage?:

'in-memory' | 'context'
読み込んだ Tool の状態を保持する場所。'in-memory'(デフォルト)は、thread ごとのインメモリマップで読み込み済み Tool を追跡し、TTL でクリーンアップします(ttl を参照)。再起動すると状態は失われ、匿名リクエストは 'default' エントリを共有します。'context' は会話メッセージから読み込み済み状態を導出します。Tool 名を含む search_tools/load_tool の結果がメッセージに残っている間、その Tool は読み込み済みになります。再起動に耐え、Memory を必要とせず、その結果がメッセージからなくなると自動的にアンロードされます。'context' ストアはオプトインです。

ttl?:

number
インメモリの thread 状態の有効期間(ミリ秒)。デフォルトの 'in-memory' ストアだけに適用され、この期間に操作がなければ thread の状態がクリーンアップされます。クリーンアップを無効にするには 0 を設定します。'context' ストアでは無視されます。

filter?:

(args: ToolSearchFilterArgs) => boolean | Promise<boolean>
検索結果から Tool を隠す、Tool の読み込みを拒否する、または現在のリクエストで読み込み済みの Tool を隠すための、リクエスト対応の任意フック。

戻り値
戻り値への直接リンク

id:

string
'tool-search' に設定された processor の識別子

name:

string
'Tool Search Processor' に設定された processor の表示名

processInputStep:

(args: ProcessInputStepArgs) => Promise<ProcessInputStepResult>
各ステップを処理し、検索/読み込み用のメタ Tool と、以前に読み込まれた Tool を Agent の Tool セットへ挿入します。

メソッド
メソッドへの直接リンク

状態の確認(従来の 'in-memory' ストア)
state-inspection-legacy-in-memory-storeへの直接リンク

これらのメソッドは、デフォルトの 'in-memory' ストアだけを操作します。状態をプロセス内のマップではなく会話メッセージに保持する 'context' ストアでは、何も行いません。

clearState(threadId)
clearstatethreadidへの直接リンク

単一の thread について、読み込み済み Tool の状態を消去します。

processor.clearState('thread-123')

clearAllState()
clearallstateへの直接リンク

すべての thread について、読み込み済み Tool の状態を消去します。

processor.clearAllState()

getStateStats()
getstatestatsへの直接リンク

インメモリ使用量の増加をデバッグするため、追跡対象の thread 数と最も古いアクセス時刻を返します。

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

戻り値: { threadCount: number; oldestAccessTime: number | null }

cleanupNow()
cleanupnowへの直接リンク

スケジュールされた実行を待たず、TTL クリーンアップをすぐに実行します。

const cleaned = processor.cleanupNow()

戻り値: number: クリーンアップされた thread の数。

リクエスト対応のフィルタリング
リクエスト対応のフィルタリングへの直接リンク

実行時定義の Tool にリクエスト固有のポリシーを適用するには、filter を使用します。フックは、解決された Tool ID を toolName として受け取るほか、Tool、request context、phase を受け取ります。toolNamesearch_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: 許可されていない Tool を load_tool が読み込むことを拒否します。
  • active: 読み込み済みの Tool が許可されなくなった場合、現在のリクエストから隠します。

フックが例外をスローするか reject された場合、ToolSearchProcessor はそのリクエストで Tool を不許可として扱います。フックは一致する検索候補ごとに実行される可能性があるため、非同期のポリシーチェックは低コストにするかキャッシュしてください。search_tools メタ Tool は常に利用できます。load_tool は、search.autoLoad が有効でない限り利用できます。Agent または processInputStep を通じて直接渡された Tool は、ToolSearchProcessor の外部でフィルタリングするか includeResolvedTools を有効にしない限り、引き続き利用できます。

リクエストごとに解決された Tool を検索する
リクエストごとに解決された Tool を検索するへの直接リンク

tools オプションは構築時に固定されるため、リクエストごとにのみ存在する Tool(呼び出し元の認証情報が必要な MCP Tool や、動的な tools 関数が返す Tool)を列挙できません。デフォルトでは、これらの Tool は検索を経由せず、毎ターンでプロンプト領域を占有します。

リクエスト用にインデックス化し、Agent が読み込むまでプロンプトから除外するには、includeResolvedTools: true を設定します。

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

各リクエストは個別にインデックス化されるため、ある呼び出し元が読み込んだ Tool が、別の呼び出し元にある同名 Tool のインスタンスとして解決されることはありません。

このオプションは、Memory、Workspace、Skill、ブラウザーの Tool を含め、リクエスト用に解決されるすべての Tool に適用されます。プロンプトに残るのは search_toolsload_tool のメタ Tool だけです。そのため、Agent が暗黙に依存する Tool も、呼び出す前に検索で見つける必要があります。

詳細な使用例
詳細な使用例への直接リンク

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 が結果を確認し、Tool 名を指定して load_tool を呼び出す
  4. 読み込まれた Tool が次のターンから利用可能になる
  5. Agent が通常どおり読み込んだ Tool を使用する

autoLoad による1ステップの検出
single-step-discovery-with-autoloadへの直接リンク

個別の読み込みステップを省略するには、search.autoLoadtrue に設定します。search_tools が返した Tool はすぐに有効化され、load_tool メタ Tool は公開されません。検出ごとにモデルのターンが1回減るため、トークン使用量とレイテンシーが低下し、どの Provider でも同じように動作します。

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

autoLoad を使用したワークフローは次のようになります。

  1. Agent がユーザーメッセージを受け取る
  2. Agent がキーワードを指定して search_tools を呼び出す
  3. 一致した Tool が自動的に有効化され、次のターンから利用可能になる
  4. Agent が通常どおり Tool を使用する

一致したすべての Tool が有効になるため、Agent が必要としない Tool の追加を避けるには、topK を小さく(たとえば 3 に)設定してください。有効化された Tool は既存の Tool の後に追加されるため、prompt caching をサポートする Provider では、キャッシュ済みプロンプトの prefix が安定します。

読み込み済み Tool のストレージ
読み込み済み Tool のストレージへの直接リンク

storage オプションは、読み込み済み Tool のセットを追跡する場所を制御します。デフォルトは 'in-memory' です。'context' ストアはオプトインです。

'in-memory'(デフォルト)
in-memory-defaultへの直接リンク

読み込み済み Tool は thread ごとのインメモリマップで追跡され、ttl オプション(デフォルトは1時間)に基づいてクリーンアップされます。これは従来の動作です。

  • Memory の設定は不要です。
  • プロセスを再起動すると状態は失われます。
  • thread ID がないリクエストは単一の 'default' エントリを共有します。

このストアの確認やリセットには、clearStateclearAllStategetStateStatscleanupNow を使用します。

'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 の読み込みはキャッシュと相性がよい処理です。読み込みは追加だけを行うため、prompt caching をサポートする Provider では、キャッシュ済みプロンプトの prefix が安定します。

Tool をアンロードするとモデルへ送る Tool 定義が変わるため、キャッシュ済み prefix がずれ、次のターンでは cache hit ではなく cache write が発生します。'in-memory' モードでは、thread の状態が ttl により削除されたときに発生します。'context' モードでは、Tool の検出結果がメッセージからなくなったとき(たとえば古いメッセージがトリミングされた場合)に発生します。Tool はアンロードされ、再利用する前にモデルがもう一度検索する必要があります。これは想定された動作です。使用していない Tool を削除することで、1回の 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),
],
})