> Discover all available pages from the documentation index: https://mastra.zisheng.pro/fr/llms.txt # ToolSearchProcessor `ToolSearchProcessor` est un **input processor** qui permet la découverte et le chargement d’outils définis à l’exécution. Au lieu de fournir tous les outils à l’Agent dès le départ, il lui donne deux méta-outils (`search_tools` et `load_tool`) qui lui permettent de trouver et de charger des outils à la demande. Cela réduit l’utilisation de tokens de contexte avec de grandes bibliothèques d’outils. ## Exemple d’utilisation ```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, }, }) ``` ## Paramètres du constructeur **options** (`ToolSearchProcessorOptions`): Options de configuration du processeur de recherche d’outils **options.tools** (`Record`): Tous les outils pouvant être recherchés et chargés dynamiquement. Ces outils ne sont pas immédiatement disponibles pour l’Agent : ils doivent être découverts par recherche et chargés à la demande. **options.includeResolvedTools** (`boolean`): Rend également recherchables les outils que l’Agent a résolus pour cette requête (outils MCP nécessitant les identifiants de l’appelant ou tout élément renvoyé par une fonction tools dynamique), et ne les inclut pas dans le prompt avant que l’Agent ne les charge. Les méta-outils ne sont jamais masqués. Les outils résolus par requête sont indexés séparément pour chaque requête ; chacune recherche et charge donc ses propres instances d’outils. **options.search** (`{ topK?: number; minScore?: number; autoLoad?: boolean }`): Configuration du comportement de recherche. **options.search.topK** (`number`): Nombre maximal d’outils à renvoyer dans les résultats de recherche. **options.search.minScore** (`number`): Score de pertinence minimal (0-1) pour inclure un outil dans les résultats de recherche. **options.search.autoLoad** (`boolean`): Lorsque sa valeur est true, les outils renvoyés par search\_tools sont activés immédiatement dans le cadre de la recherche. Le méta-outil load\_tool n’est pas exposé, ce qui réduit le flux en deux étapes de recherche puis chargement à une seule étape de recherche. Les outils découverts deviennent disponibles au tour suivant. Gardez une valeur topK faible, car chaque correspondance est activée. **options.storage** (`'in-memory' | 'context'`): Emplacement de l’état des outils chargés. 'in-memory' (par défaut) suit les outils chargés dans une map en mémoire par thread, avec nettoyage TTL (voir ttl) ; l’état est perdu au redémarrage et les requêtes anonymes partagent une entrée 'default'. 'context' déduit l’état chargé des messages de conversation : un outil reste chargé tant qu’un résultat search\_tools/load\_tool qui le nomme reste dans les messages ; ce mode résiste aux redémarrages, ne nécessite aucune mémoire et décharge automatiquement l’outil lorsque ce résultat n’est plus présent dans les messages. Le magasin 'context' est opt-in. **options.ttl** (`number`): Durée de vie de l’état de thread en mémoire, en millisecondes. S’applique uniquement au stockage par défaut, le magasin 'in-memory' ; après cette durée d’inactivité, l’état du thread est nettoyé. Définissez-la sur 0 pour désactiver le nettoyage. Ignorée par le magasin 'context'. **options.filter** (`(args: ToolSearchFilterArgs) => boolean | Promise`): Hook facultatif tenant compte de la requête, permettant de masquer des outils des résultats de recherche, de bloquer le chargement d’outils ou de masquer les outils déjà chargés pour la requête actuelle. ## Renvoie **id** (`string`): Identifiant du Processor défini sur 'tool-search' **name** (`string`): Nom d’affichage du Processor défini sur 'Tool Search Processor' **processInputStep** (`(args: ProcessInputStepArgs) => Promise`): Traite chaque étape pour injecter les méta-outils de recherche/chargement et les outils précédemment chargés dans l’ensemble d’outils de l’Agent. ## Méthodes ### Inspection de l’état (magasin `'in-memory'` hérité) Ces méthodes fonctionnent uniquement avec le magasin `'in-memory'` par défaut. Elles n’ont aucun effet pour le magasin `'context'`, dont l’état réside dans les messages de conversation plutôt que dans une map du processus. #### `clearState(threadId)` Efface l’état des outils chargés pour un seul thread. ```typescript processor.clearState('thread-123') ``` #### `clearAllState()` Efface l’état des outils chargés pour tous les threads. ```typescript processor.clearAllState() ``` #### `getStateStats()` Renvoie le nombre de threads suivis et l’heure d’accès la plus ancienne, pour déboguer la croissance de la mémoire. ```typescript const { threadCount, oldestAccessTime } = processor.getStateStats() ``` Renvoie : `{ threadCount: number; oldestAccessTime: number | null }` #### `cleanupNow()` Exécute immédiatement le nettoyage TTL au lieu d’attendre le balayage planifié. ```typescript const cleaned = processor.cleanupNow() ``` Renvoie : `number`, le nombre de threads nettoyés. ## Filtrage tenant compte de la requête Utilisez `filter` pour appliquer une politique propre à la requête aux outils définis à l’exécution. Le hook reçoit l’ID de l’outil résolu sous la forme de `toolName`, l’outil, le contexte de la requête et la phase. `toolName` est l’ID renvoyé par `search_tools`, qui peut différer de la clé utilisée dans l’objet `tools`. ```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_') }, }) ``` La valeur `phase` indique où le filtre est appliqué : - `search` : filtre les résultats renvoyés par `search_tools`. - `load` : empêche `load_tool` de charger des outils non autorisés. - `active` : masque les outils déjà chargés de la requête actuelle s’ils ne sont plus autorisés. Si le hook lève une erreur ou rejette, `ToolSearchProcessor` considère l’outil comme non autorisé pour cette requête. Le hook peut s’exécuter pour chaque candidat correspondant de la recherche ; gardez donc les contrôles de politique asynchrones légers ou mis en cache. Le méta-outil `search_tools` est toujours disponible. `load_tool` est disponible sauf si `search.autoLoad` est activé. Les outils transmis directement via l’Agent ou `processInputStep` restent disponibles, sauf si vous les filtrez en dehors de `ToolSearchProcessor` ou activez `includeResolvedTools`. ## Recherche d’outils résolus par requête L’option `tools` est fixée à la construction ; vous ne pouvez donc pas répertorier les outils qui n’existent que par requête (outils MCP nécessitant les identifiants de l’appelant ou tout élément renvoyé par une fonction `tools` dynamique). Par défaut, ces outils contournent la recherche et occupent de l’espace dans le prompt à chaque tour. Définissez `includeResolvedTools: true` pour les indexer pour la requête et ne pas les inclure dans le prompt avant que l’Agent ne les charge : ```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], }) ``` Chaque requête est indexée séparément ; un outil chargé par un appelant n’est donc jamais résolu vers l’instance du même nom d’outil d’un autre appelant. Cette option s’applique à tous les outils résolus pour la requête, y compris les outils de mémoire, de workspace, de skill et de navigateur. Seuls les méta-outils `search_tools` et `load_tool` restent dans le prompt ; tout outil sur lequel l’Agent s’appuie implicitement doit donc être trouvé par recherche avant de pouvoir être appelé. ## Exemple d’utilisation étendu ```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], }) ``` Le flux de travail de l’Agent est le suivant : 1. L’Agent reçoit un message utilisateur 2. L’Agent appelle `search_tools` avec des mots-clés (par exemple, "github issue") 3. L’Agent examine les résultats et appelle `load_tool` avec le nom de l’outil 4. L’outil chargé devient disponible au tour suivant 5. L’Agent utilise normalement l’outil chargé ## Découverte en une étape avec `autoLoad` Définissez `search.autoLoad` sur `true` pour ignorer l’étape de chargement distincte. Les outils renvoyés par `search_tools` sont activés immédiatement et le méta-outil `load_tool` n’est pas exposé. Cela supprime un tour de modèle par découverte, réduit l’utilisation de tokens et la latence, et fonctionne de la même manière avec tous les Providers. ```typescript const toolSearch = new ToolSearchProcessor({ tools: allTools, search: { topK: 3, autoLoad: true, }, }) ``` Avec `autoLoad`, le flux de travail devient : 1. L’Agent reçoit un message utilisateur 2. L’Agent appelle `search_tools` avec des mots-clés 3. Les outils correspondants sont activés automatiquement et deviennent disponibles au tour suivant 4. L’Agent utilise normalement l’outil Chaque correspondance est activée ; gardez donc `topK` faible (par exemple, `3`) afin d’éviter d’ajouter des outils dont l’Agent n’a pas besoin. Les outils activés sont ajoutés après les outils existants, ce qui maintient stable le préfixe du prompt mis en cache pour les Providers qui prennent en charge la mise en cache des prompts. ## Stockage des outils chargés L’option `storage` contrôle l’emplacement où l’ensemble des outils chargés est suivi. La valeur par défaut est `'in-memory'`. Le magasin `'context'` est opt-in. ### `'in-memory'` (par défaut) Les outils chargés sont suivis dans une map en mémoire par thread, avec un nettoyage fondé sur TTL contrôlé par l’option `ttl` (une heure par défaut). Il s’agit du comportement initial : - Ne nécessite aucune configuration de mémoire. - L’état est perdu lors du redémarrage du processus. - Les requêtes sans ID de thread partagent une seule entrée `'default'`. Utilisez `clearState`, `clearAllState`, `getStateStats` et `cleanupNow` pour inspecter ou réinitialiser ce magasin. ### `'context'` L’état chargé est déduit des messages de conversation : un outil est chargé tant qu’un résultat `search_tools` ou `load_tool` qui le nomme reste dans les messages. Ce mode : - Ne nécessite aucune configuration de mémoire. - Résiste aux redémarrages : l’enregistrement durable est l’historique des messages persisté. - Décharge automatiquement un outil lorsque ce résultat n’est plus présent dans les messages. ```typescript import { ToolSearchProcessor } from '@mastra/core/processors' const toolSearch = new ToolSearchProcessor({ tools: allTools, storage: 'context', }) ``` Le chargement d’outils est favorable au cache dans les deux modes : les chargements se font uniquement par ajout, de sorte que le préfixe du prompt mis en cache reste stable pour les Providers qui prennent en charge la mise en cache des prompts. Le déchargement d’un outil modifie les définitions d’outils envoyées au modèle, ce qui décale le préfixe mis en cache et fait que le tour suivant effectue une écriture de cache plutôt qu’une lecture réussie. En mode `'in-memory'`, cela se produit lorsque l’état d’un thread est évincé par `ttl`. En mode `'context'`, cela se produit lorsqu’un résultat de découverte de l’outil n’est plus présent dans les messages (par exemple, lorsque les messages les plus anciens sont tronqués). L’outil est déchargé et le modèle doit le rechercher à nouveau avant de le réutiliser. C’est le comportement attendu : supprimer un outil inutilisé échange une écriture de cache contre un préfixe plus petit lors des tours suivants. ## Combinaison avec d’autres Processors ```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), ], }) ``` ## Ressources associées - [Processors](https://mastra.zisheng.pro/fr/docs/agents/processors) - [Utiliser des Tools](https://mastra.zisheng.pro/fr/docs/agents/using-tools)