> Discover all available pages from the documentation index: https://mastra.zisheng.pro/fr/llms.txt # Signaux **Ajouté dans :** `@mastra/core@1.39.0` > **Beta:** Cette fonctionnalité est en version bêta. Des modifications incompatibles peuvent survenir sans changement de version majeure tant que l’API n’est pas stable. Les signaux permettent d’interagir avec un agent par l’intermédiaire d’un thread. Au lieu de démarrer chaque interaction avec `agent.stream()`, abonnez-vous à un thread et envoyez des messages ou des signaux. Mastra réveille l’agent lorsque le thread est inactif, injecte l’entrée dans la boucle active de l’agent ou la place en file d’attente pour le tour suivant. Utilisez les API de messages pour les entrées rédigées par les utilisateurs. Utilisez `sendSignal()` pour le contexte système de plus bas niveau, comme les notifications de tâches en arrière-plan, les rappels de politiques ou le contexte généré par un processeur. > **📹 Regarder:** Regardez la [présentation des signaux Mastra](https://www.youtube.com/watch?v=7It2y89TVP4) pour découvrir comment les signaux réveillent et orientent les agents de longue durée. ## Quand utiliser les signaux Utilisez les signaux lorsqu’un thread d’agent a besoin d’une nouvelle entrée ou d’un contexte qui ne fait pas partie de l’appel `stream()` initial. Les signaux sont utiles lorsque des utilisateurs envoient des messages de suivi pendant une exécution, lorsque des systèmes en arrière-plan doivent ajouter du contexte à un thread, ou lorsque des événements externes doivent réveiller, mettre à jour ou notifier l’agent. Utilisez `sendMessage()` et `queueMessage()` pour les entrées rédigées par les utilisateurs. Utilisez `sendSignal()` pour le contexte système de plus bas niveau. Utilisez `sendStateSignal()` pour les canaux d’état durables et `sendNotificationSignal()` lorsqu’un événement externe doit créer un enregistrement durable dans la boîte de réception des notifications. ## Démarrage rapide Créez un agent, abonnez-vous à un thread, puis envoyez un message à ce thread. L’abonnement reçoit le flux actif lorsque le message réveille l’agent ou entre dans une boucle en cours d’exécution. ```typescript import { Agent } from '@mastra/core/agent' const agent = new Agent({ id: 'support-agent', name: 'Support Agent', instructions: 'Help the user compare options.', model: 'openai/gpt-5.6-sol', }) const thread = { resourceId: 'user_123', threadId: 'thread_456', } const subscription = await agent.subscribeToThread(thread) await agent.sendMessage('Compare that with the previous option.', thread) for await (const chunk of subscription.stream) { console.log(chunk) } ``` Lorsque le thread possède un flux d’agent actif, `sendMessage()` devient une nouvelle entrée dans cette boucle de l’agent. Lorsque le thread est inactif, Mastra démarre un flux avec le message comme première entrée. ## Entrée de messages ### Envoyer un message immédiatement Utilisez `sendMessage()` lorsque l’utilisateur s’attend à ce que l’agent actif voie le message immédiatement. ```typescript agent.sendMessage( { contents: 'Use the latest customer note too.', attributes: { name: 'Jane', sentFrom: 'slack' }, }, { resourceId: 'user_123', threadId: 'thread_456', }, ) ``` Le modèle reçoit les messages dotés d’attributs sous forme d’entrées utilisateur enveloppées dans du XML : ```xml Use the latest customer note too. ``` Les messages sans attribut sont envoyés comme de simples entrées utilisateur. ### Mettre un message en file d’attente pour le tour suivant Utilisez `queueMessage()` lorsqu’un utilisateur envoie un message de suivi, mais que l’appel actif au modèle doit d’abord se terminer. Mastra attend la fin de l’exécution active, puis démarre une nouvelle exécution dans le même thread. ```typescript agent.queueMessage('Also check whether the tests need updates.', { resourceId: 'user_123', threadId: 'thread_456', }) ``` Lorsque le thread est inactif, `queueMessage()` démarre immédiatement une exécution. Lorsqu’il est actif, la méthode préserve l’ordre des tours en démarrant une nouvelle exécution après la fin de l’exécution en cours. ## Contexte des signaux ### Contrôler le comportement de bas niveau des signaux Utilisez `sendSignal()` lorsque vous devez envoyer un contexte généré par le système plutôt qu’une entrée rédigée par un utilisateur. Pour les événements externes, utilisez `type: 'notification'`. Par défaut, Mastra transmet les signaux aux exécutions actives et réveille les threads inactifs. Utilisez `ifActive.behavior` et `ifIdle.behavior` pour modifier ce comportement. ```typescript const result = agent.sendSignal( { type: 'notification', contents: 'GitHub CI failed on PR #123: 3 tests failed.', }, { resourceId: 'user_123', threadId: 'thread_456', ifIdle: { behavior: 'persist', }, }, ) await result.persisted ``` Transmettez `ifIdle.streamOptions` lorsque le flux qui réveille un thread inactif nécessite des options telles que des paramètres de modèle, des outils ou du contexte d’exécution. Consultez la [référence de `Agent.sendSignal()`](https://mastra.zisheng.pro/fr/reference/agents/agent) pour `ifActive`, `ifIdle`, les attributs de branche et `streamOptions`. ### Envoyer un contexte de notification Les signaux possèdent un `type` sémantique et un `tagName` destiné au LLM. Utilisez `type` pour décrire la catégorie du signal. Utilisez `tagName` pour contrôler la balise XML que voit le modèle. Pour les événements externes, utilisez `type: 'notification'`. Les signaux réactifs sont réservés au contexte généré par un processeur ou l’environnement d’exécution, comme les directives de politique, les résultats de tâches en arrière-plan et les instructions chargées automatiquement. ```typescript agent.sendSignal( { type: 'notification', contents: 'PR #123 has a new review comment from User X about the API surface.', attributes: { source: 'github', pr: '123', }, }, { resourceId: 'user_123', threadId: 'thread_456', }, ) ``` Le modèle reçoit le signal sous la forme de contexte suivante : ```xml PR #123 has a new review comment from User X about the API surface. ``` Utilisez un `tagName` et des noms d’attributs compatibles avec XML. Ils peuvent contenir des lettres, des chiffres, des deux-points, des points et des traits d’union. Ils doivent commencer par une lettre ou un trait de soulignement. #### Prise en charge du stockage Le stockage de la boîte de réception des notifications est disponible dans les adaptateurs qui prennent en charge des workflows de mémoire et de signaux plus riches : [libSQL](https://mastra.zisheng.pro/fr/reference/storage/libsql), [PostgreSQL](https://mastra.zisheng.pro/fr/reference/storage/postgresql) et [MongoDB](https://mastra.zisheng.pro/fr/reference/storage/mongodb). Ces adaptateurs exposent les enregistrements de notification par l’intermédiaire de `getStore('notifications')`. ### Envoyer du contexte depuis un processeur Les processeurs peuvent envoyer des signaux réactifs pendant une exécution. Un processeur doit inspecter l’historique de la conversation, réagir à un déclencheur précis et éviter d’envoyer plusieurs fois le même contexte. L’exemple suivant présente un processeur qui injecte les instructions d’`AGENTS.md` après qu’un appel d’outil a lu un fichier `AGENTS.md`. ```typescript import type { Processor, ProcessInputStepArgs } from '@mastra/core/processors' export const agentsMdReminderProcessor: Processor = { id: 'agents-md-reminder', async processInputStep({ messageList, sendSignal }: ProcessInputStepArgs) { const messages = messageList.get.all.db() const agentsMdPath = findAgentsMdPathFromToolCalls(messages) if (!agentsMdPath || hasAlreadySentAgentsMdReminder(messages, agentsMdPath)) { return messageList } await sendSignal?.({ type: 'reactive', contents: readAgentsMdInstructions(agentsMdPath), attributes: { type: 'dynamic-agents-md', path: agentsMdPath, }, metadata: { path: agentsMdPath, }, }) return messageList }, } ``` Les signaux réactifs utilisent par défaut `tagName: 'system-reminder'` ; le modèle reçoit donc ce contexte sous la forme suivante : ```xml $agentsMdFileContents ``` Attendre la fin de `sendSignal()` préserve l’ordre de renvoi dans le flux lorsqu’un thread abonné est actif. ### Attributs conditionnels Utilisez `ifActive.attributes` et `ifIdle.attributes` pour étiqueter une entrée avec du contexte qui dépend de l’état actif ou inactif de l’agent au moment de la livraison. Les `attributes` de premier niveau s’appliquent toujours, et Mastra y fusionne les `attributes` de la branche sélectionnée lorsque l’entrée est acceptée. Consultez la [référence de `Agent.sendMessage()`](https://mastra.zisheng.pro/fr/reference/agents/agent) et la [référence de `Agent.sendSignal()`](https://mastra.zisheng.pro/fr/reference/agents/agent) pour les attributs propres aux branches. ## Signaux d’état et de notification ### Signaux d’état Les signaux d’état exposent des canaux de contexte nommés et propres au thread. Utilisez-les pour du contexte durable qui évolue au fil du temps, comme l’état d’un navigateur, l’état d’un éditeur ou le résultat d’un observateur en arrière-plan. Utilisez `sendStateSignal()` lorsqu’un producteur externe détecte un changement d’état. Chaque signal d’état identifie un canal d’état, une clé de cache gérée par le producteur et le type de mise à jour : instantané ou delta. ```typescript await agent.sendStateSignal( { id: 'browser', mode: 'snapshot', cacheKey: 'browser:https://example.com:3-tabs', contents: 'Browser is open. Active tab URL: https://example.com. 3 open tabs.', value: { activeUrl: 'https://example.com', tabCount: 3, open: true, }, }, { resourceId: 'user_123', threadId: 'thread_456', }, ) ``` Lorsque Mastra accepte un signal d’état, il stocke des métadonnées de suivi compactes dans le thread. Si un producteur renvoie le même `cacheKey` et le même mode alors que cet état est toujours actuel, Mastra ignore le doublon. Utilisez `computeStateSignal()` lorsqu’un processeur gère un canal d’état. Mastra l’appelle une fois par étape d’entrée du modèle, après `processInputStep()`. Consultez la [référence de `Agent.sendStateSignal()`](https://mastra.zisheng.pro/fr/reference/agents/agent) pour connaître les champs des signaux d’état et les valeurs de retour. ```typescript import type { ComputeStateSignalArgs, Processor } from '@mastra/core/processors' export const browserStateProcessor: Processor = { id: 'browser-state', stateId: 'browser', computeStateSignal(args: ComputeStateSignalArgs) { const browser = readCurrentBrowserState() const previous = readMostRecentBrowserState(args.activeStateSignals) const changed = previous ? diffBrowserState(previous, browser) : browser const shouldRefreshSnapshot = Boolean(args.lastSnapshot && !args.contextWindow.hasSnapshot) if (previous && Object.keys(changed).length === 0 && !shouldRefreshSnapshot) { return } const isDelta = Boolean(previous && !shouldRefreshSnapshot) return { mode: isDelta ? 'delta' : 'snapshot', cacheKey: stableBrowserStateCacheKey(browser), contents: isDelta ? describeBrowserDelta(changed) : describeBrowserSnapshot(browser), value: browser, ...(isDelta ? { delta: changed } : {}), } }, } ``` Mastra transmet `lastSnapshot` et `deltasSinceSnapshot` à `computeStateSignal()`. Il les résout à partir de l’historique des messages lorsque la liste actuelle ne contient pas le dernier instantané. Le processeur reste responsable de la logique de fusion et de calcul des différences. `contextWindow.hasSnapshot` indique au processeur si la fenêtre de messages active contient déjà un instantané pour ce canal d’état. Si sa valeur est `false`, renvoyez un nouvel instantané `snapshot` afin que le modèle voie l’état actuel, même après que les anciens messages d’état ont été retirés de la fenêtre de contexte. Le processeur intégré de contexte du navigateur émet l’état sous l’identifiant `browser`, avec les modes instantané et delta. ### Signaux de notification Les signaux de notification représentent des événements externes tels qu’une activité GitHub, un e-mail, une mention Slack, un état de CI, un incident, un enregistrement ou un message direct. Utilisez `agent.sendNotificationSignal()` lorsque l’événement doit créer un enregistrement durable dans la boîte de réception. La livraison des notifications comporte deux phases. Lors de l’ingestion, `agent.sendNotificationSignal()` stocke un enregistrement de notification et détermine la politique de livraison de l’agent. Lors de la distribution, Mastra consomme les enregistrements arrivés à échéance et émet des signaux de notification complets ou récapitulatifs. La politique de livraison par défaut tient compte de la priorité. Les notifications urgentes sont livrées immédiatement, tandis que celles de priorité moindre peuvent être regroupées dans des récapitulatifs ou attendre que le thread soit inactif. Consultez la [référence de `Agent.sendNotificationSignal()`](https://mastra.zisheng.pro/fr/reference/agents/agent) pour les champs de notification, la [référence du constructeur d’`Agent`](https://mastra.zisheng.pro/fr/reference/agents/agent) pour la configuration de `notifications.deliveryPolicy` et la [référence de `createNotificationInboxTool()`](https://mastra.zisheng.pro/fr/reference/signals/create-notification-inbox-tool) pour les actions de l’outil de boîte de réception. ```typescript await agent.sendNotificationSignal( { source: 'github', kind: 'ci-status', priority: 'high', summary: 'CI failed on main: 3 tests failed.', payload: { repository: 'acme/app', branch: 'main', }, dedupeKey: 'github:acme/app:main:ci', }, { resourceId: 'user_123', threadId: 'thread_456', }, ) ``` Le modèle reçoit les notifications complètes sous forme de contexte : ```xml CI failed on main: 3 tests failed. ``` Les récapitulatifs de notifications indiquent au modèle que des enregistrements l’attendent dans la boîte de réception : ```xml github: 3, email: 5, slack: 2 ``` Lorsque Mastra émet un récapitulatif, il efface `summaryAt` et définit `summarySignalId` sur chaque enregistrement récapitulé. Les enregistrements restent en attente et lisibles. Lorsque Mastra émet une notification complète, il définit `deliveredSignalId` et marque l’enregistrement comme `delivered`. Si l’outil de boîte de réception lit d’abord une notification, il peut injecter le signal de notification complet et marquer l’enregistrement comme `seen`, ce qui évite une livraison complète en double. Configurez une politique de livraison sur l’agent lorsque certaines notifications doivent attendre une autre fenêtre de distribution ou un autre regroupement récapitulatif. Activez la distribution planifiée au niveau de Mastra lorsque les notifications différées et les regroupements récapitulatifs doivent être livrés automatiquement. Consultez la [référence du constructeur d’`Agent`](https://mastra.zisheng.pro/fr/reference/agents/agent) pour `notifications.deliveryPolicy` et la [référence de la classe `Mastra`](https://mastra.zisheng.pro/fr/reference/core/mastra-class) pour la configuration de la distribution des notifications au moment de l’exécution. #### Outil de boîte de réception des notifications Utilisez `createNotificationInboxTool()` pour fournir aux agents un seul outil destiné aux actions de la boîte de réception, plutôt que de nombreux outils CRUD. Utilisez `read` après un signal `` lorsque l’agent a besoin des enregistrements complets associés au récapitulatif. Le contenu des notifications est transmis sous forme de signaux, et non comme une sortie d’outil ordinaire. Consultez la [référence de `createNotificationInboxTool()`](https://mastra.zisheng.pro/fr/reference/signals/create-notification-inbox-tool) pour l’exemple de configuration, le schéma d’entrée et le comportement des actions. `sendNotificationSignal()` nécessite un domaine de stockage prenant en charge `notifications`. Utilisez `sendSignal({ type: 'notification' })` uniquement pour un contexte de bas niveau présenté comme une notification et qui doit contourner le stockage de la boîte de réception. ## Déploiements distribués et sans serveur Les signaux coordonnent les exécutions au moyen d’un backend pub/sub. Lorsqu’un signal arrive sur un backend qui implémente `LeaseProvider`, Mastra acquiert un lease sur le thread cible afin qu’un seul processus possède la conversation à la fois, puis réveille l’agent ou route l’entrée vers la boucle en cours d’exécution. Les backends dépourvus de mécanisme de lease se rabattent sur une opération vide qui accorde toujours la propriété ; cela convient à un processus unique, mais pas à plusieurs instances. Le backend pub/sub en mémoire utilisé par défaut ne peut pas franchir les limites d’une instance. Sur les plateformes sans serveur telles que Vercel, ou dans tout déploiement comportant plusieurs instances, un signal de suivi peut être routé vers une instance différente de celle qui exécute l’agent. Sans pub/sub partagé, cette instance ne peut pas atteindre l’exécution active et démarre la sienne, laissant l’exécution d’origine intacte et traitant le thread deux fois. Configurez dans l’instance `Mastra` un pub/sub partagé reposant sur Redis Streams afin de coordonner les leases et les signaux entre les instances : ```typescript import { Mastra } from '@mastra/core' import { RedisStreamsPubSub } from '@mastra/redis-streams' export const mastra = new Mastra({ agents: { agent }, pubsub: new RedisStreamsPubSub({ url: process.env.REDIS_URL, keyPrefix: 'mastra:my-app', }), }) ``` `RedisStreamsPubSub` implémente à la fois le contrat de livraison des événements et la gestion distribuée des leases ; un seul backend gère donc la livraison des signaux entre les instances ainsi que la propriété des leases. L’intégration Redis gérée de Vercel et Upstash Redis conviennent toutes deux. Pour en savoir plus sur les situations qui nécessitent un pub/sub distribué, consultez le [guide PubSub](https://mastra.zisheng.pro/fr/docs/server/pubsub) et la [référence de `RedisStreamsPubSub`](https://mastra.zisheng.pro/fr/reference/pubsub/redis-streams). ## Compatibilité et API ### Compatibilité Mastra accepte toujours les anciennes charges utiles de signaux telles que `type: 'user-message'` et `type: 'system-reminder'`. Il les normalise en interne selon la nouvelle catégorie et la nouvelle forme de balise : - `type: 'user-message'` : normalisé en `type: 'user'` et `tagName: 'user'` - `type: 'system-reminder'` : normalisé en `type: 'reactive'` et `tagName: 'system-reminder'` Les lignes de signaux déjà stockées et les anciens clients continuent à se charger grâce à la couche de compatibilité. Les nouveaux clients appellent les routes de messages lorsque le serveur les prend en charge ; le chemin des signaux de thread de React se rabat sur l’ancienne route `/signals` lorsqu’il détecte un serveur plus ancien. Consultez la [référence des signaux d’Agent](https://mastra.zisheng.pro/fr/reference/agents/agent) pour obtenir l’ensemble des types de messages, de signaux et d’abonnements. ### Approuver les appels d’outils Lorsqu’une exécution abonnée se met en pause pour demander l’approbation d’un outil, approuvez ou refusez l’appel d’outil avec les méthodes propres à l’abonnement. Les fragments de la reprise arrivent par l’abonnement au thread existant. Consultez la [référence de `client.getAgent().sendToolApproval()`](https://mastra.zisheng.pro/fr/reference/client-js/agents) et les [routes serveur des agents](https://mastra.zisheng.pro/fr/reference/server/routes) pour les formes des requêtes et des réponses. ### Utiliser les routes HTTP Si vous appelez Mastra directement par HTTP, utilisez `POST /api/agents/:agentId/send-message` pour les messages immédiats et `POST /api/agents/:agentId/queue-message` pour les messages du tour suivant. Pour approuver un outil au moyen de l’abonnement, utilisez `POST /api/agents/:agentId/send-tool-approval`. Consultez la [référence des routes serveur](https://mastra.zisheng.pro/fr/reference/server/routes) pour les schémas de requête et de réponse. ### Utiliser le SDK client Le client JavaScript expose les API de signaux de thread. Utilisez `subscribeToThread()` avant d’envoyer une entrée au thread afin que le client puisse afficher le flux qui reçoit cette entrée ou se réveille en réponse à celle-ci. ```typescript const agent = client.getAgent('supportAgent') const subscription = await agent.subscribeToThread({ resourceId: 'user_123', threadId: 'thread_456', }) await agent.sendMessage({ message: 'Show the shorter version.', resourceId: 'user_123', threadId: 'thread_456', }) await subscription.processDataStream({ onChunk: chunk => { console.log(chunk) }, reconnect: true, }) ``` Utilisez `reconnect: true` pour les abonnements de longue durée. Consultez la [référence de `client.getAgent().subscribeToThread()`](https://mastra.zisheng.pro/fr/reference/client-js/agents) pour les options de reconnexion. ### Maintenir les abonnements SSE personnalisés actifs Si vous exposez votre propre endpoint Server-Sent Events (SSE) pour les abonnements aux threads, envoyez périodiquement des trames de maintien en vie lorsque le flux est inactif. Cela empêche les navigateurs, les proxys et les répartiteurs de charge de fermer la connexion avant l’arrivée du signal ou du fragment de modèle suivant. L’exemple suivant envoie un commentaire SSE toutes les 25 secondes : ```typescript const heartbeat = setInterval(() => { controller.enqueue(encoder.encode(': keep-alive\n\n')) }, 25_000) request.signal.addEventListener('abort', () => { clearInterval(heartbeat) }) ``` Utilisez les signaux de maintien en vie avec une logique de reconnexion côté client. Ils réduisent les déconnexions pendant les périodes d’inactivité, tandis que les reconnexions permettent de récupérer la connexion lorsque le réseau ou l’environnement d’exécution ferme tout de même le flux. ## Ressources associées - [`Agent.sendMessage()`](https://mastra.zisheng.pro/fr/reference/agents/agent) - [`Agent.queueMessage()`](https://mastra.zisheng.pro/fr/reference/agents/agent) - [`Agent.sendSignal()`](https://mastra.zisheng.pro/fr/reference/agents/agent) - [`Agent.sendStateSignal()`](https://mastra.zisheng.pro/fr/reference/agents/agent) - [`Agent.subscribeToThread()`](https://mastra.zisheng.pro/fr/reference/agents/agent) - [`createNotificationInboxTool()`](https://mastra.zisheng.pro/fr/reference/signals/create-notification-inbox-tool) - [`client.getAgent().sendMessage()`](https://mastra.zisheng.pro/fr/reference/client-js/agents) - [`client.getAgent().queueMessage()`](https://mastra.zisheng.pro/fr/reference/client-js/agents) - [`client.getAgent().sendSignal()`](https://mastra.zisheng.pro/fr/reference/client-js/agents) - [Routes serveur des agents](https://mastra.zisheng.pro/fr/reference/server/routes) - [`client.getAgent().subscribeToThread()`](https://mastra.zisheng.pro/fr/reference/client-js/agents) - [`client.getAgent().sendToolApproval()`](https://mastra.zisheng.pro/fr/reference/client-js/agents) - [`RedisStreamsPubSub`](https://mastra.zisheng.pro/fr/reference/pubsub/redis-streams) - 📹 [Atelier sur les signaux Mastra](https://www.youtube.com/watch?v=KLg6uFKz9aw\&t=3020s)