Aller au contenu principal

Mémoire de travail

Alors que l'historique des messages et le rappel sémantique aident les Agents à se souvenir des conversations, la mémoire de travail leur permet de conserver des informations persistantes sur les utilisateurs d'une interaction à l'autre.

La mémoire de travail est le bloc-notes actif de l'Agent : elle contient les informations clés qu'il garde à disposition sur l'utilisateur ou la tâche. Elle peut retenir le nom d'une personne, ses préférences ou d'autres détails importants au cours d'une conversation.

Elle est utile pour conserver un état courant qui reste pertinent et doit toujours être accessible à l'Agent.

Si vous utilisez la mémoire observationnelle, observationalMemory.observation.manageWorkingMemory permet à OM de mettre à jour la mémoire de travail de l'Agent.

📹 Regarder

Regardez La mémoire de travail dans Mastra pour découvrir comment les Agents conservent un contexte utilisateur persistant d'une interaction à l'autre.

La mémoire de travail peut persister selon deux portées différentes :

  • Portée ressource (par défaut) : la mémoire persiste dans tous les fils de conversation d'un même utilisateur
  • Portée fil : la mémoire est isolée dans chaque fil de conversation

Condition requise : lorsque vous changez de portée, l'Agent ne voit pas la mémoire de l'autre portée : la mémoire limitée au fil est entièrement distincte de celle limitée à la ressource.

Démarrage rapide
Lien direct vers Démarrage rapide

Voici un exemple minimal de configuration d'un Agent avec une mémoire de travail :

import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'

// Create agent with working memory enabled
const agent = new Agent({
id: 'personal-assistant',
name: 'PersonalAssistant',
instructions: 'You are a helpful personal assistant.',
model: 'openai/gpt-5.6-sol',
memory: new Memory({
options: {
workingMemory: {
enabled: true,
},
},
}),
})

Fonctionnement
Lien direct vers Fonctionnement

La mémoire de travail est un bloc de texte Markdown que l'Agent peut mettre à jour au fil du temps afin de stocker des informations pertinentes en continu.

Portées de persistance de la mémoire
Lien direct vers Portées de persistance de la mémoire

La mémoire de travail peut fonctionner selon deux portées différentes, ce qui vous permet de choisir comment elle persiste entre les conversations :

Mémoire limitée à la ressource (par défaut)
Lien direct vers Mémoire limitée à la ressource (par défaut)

Par défaut, la mémoire de travail persiste dans tous les fils de conversation d'un même utilisateur (resourceId), ce qui permet de conserver une mémoire utilisateur durable :

const memory = new Memory({
storage,
options: {
workingMemory: {
enabled: true,
scope: 'resource', // Memory persists across all user threads
template: `# User Profile
- **Name**:
- **Location**:
- **Interests**:
- **Preferences**:
- **Long-term Goals**:
`,
},
},
})

Cas d'utilisation :

  • Assistants personnels qui mémorisent les préférences de l'utilisateur
  • Bots de service client qui conservent le contexte du client
  • Applications pédagogiques qui suivent les progrès des élèves

Utilisation avec des Agents
Lien direct vers Utilisation avec des Agents

Lorsque vous utilisez une mémoire limitée à la ressource, veillez à transmettre le paramètre resource dans les options de mémoire :

// Resource-scoped memory requires resource
const response = await agent.generate('Hello!', {
memory: {
thread: 'conversation-123',
resource: 'user-alice-456', // Same user across different threads
},
})

Mémoire limitée au fil
Lien direct vers Mémoire limitée au fil

La mémoire limitée au fil isole la mémoire de travail dans chaque fil de conversation. Chaque fil conserve ainsi sa propre mémoire isolée :

const memory = new Memory({
storage,
options: {
workingMemory: {
enabled: true,
scope: 'thread', // Memory is isolated per thread
template: `# User Profile
- **Name**:
- **Interests**:
- **Current Goal**:
`,
},
},
})

Cas d'utilisation :

  • Conversations distinctes portant sur des sujets différents
  • Informations temporaires ou propres à une session
  • Workflows dans lesquels chaque fil a besoin d'une mémoire de travail, mais où les fils sont éphémères et sans lien entre eux

Prise en charge par les adaptateurs de stockage
Lien direct vers Prise en charge par les adaptateurs de stockage

La mémoire de travail limitée à la ressource nécessite des adaptateurs de stockage spécifiques qui prennent en charge la table mastra_resources :

Adaptateurs de stockage pris en charge
Lien direct vers Adaptateurs de stockage pris en charge

  • libSQL (@mastra/libsql)
  • PostgreSQL (@mastra/pg)
  • OracleDB (@mastra/oracledb)
  • Upstash (@mastra/upstash)
  • MongoDB (@mastra/mongodb)

Modèles personnalisés
Lien direct vers Modèles personnalisés

Les modèles indiquent à l'Agent quelles informations suivre et mettre à jour dans la mémoire de travail. Mastra utilise un modèle par défaut si vous n'en fournissez pas. Définissez un modèle personnalisé adapté au cas d'utilisation de votre Agent afin qu'il mémorise les informations les plus pertinentes. Pour les fils partagés entre plusieurs utilisateurs, consultez Fils multi-utilisateurs.

Voici un exemple de modèle personnalisé. Dans cet exemple, l'Agent stocke le nom, la localisation, le fuseau horaire, etc. de l'utilisateur dès que celui-ci envoie un message contenant l'une de ces informations :

const memory = new Memory({
options: {
workingMemory: {
enabled: true,
template: `
# User Profile

## Personal info

- Name:
- Location:
- Timezone:

## Preferences

- Communication Style: [e.g., Formal, Casual]
- Project Goal:
- Key Deadlines:
- [Deadline 1]: [Date]
- [Deadline 2]: [Date]

## Session state

- Last Task Discussed:
- Open Questions:
- [Question 1]
- [Question 2]
`,
},
},
})

Concevoir des modèles efficaces
Lien direct vers Concevoir des modèles efficaces

Un modèle bien structuré facilite l'analyse et la mise à jour des informations par l'Agent. Considérez le modèle comme un court formulaire que vous souhaitez voir l'assistant tenir à jour.

  • Utilisez des libellés courts et précis. Évitez les paragraphes ou les titres très longs. Gardez des libellés brefs (par exemple ## Personal Info ou - Name:) afin que les mises à jour restent lisibles et risquent moins d'être tronquées.
  • Adoptez une casse cohérente. Une capitalisation incohérente (Timezone: et timezone:) peut rendre les mises à jour confuses. Utilisez systématiquement la casse de titre ou les minuscules pour les titres et les libellés de listes.
  • Limitez le texte des espaces réservés. Utilisez des indications comme [e.g., Formal] ou [Date] pour aider le LLM à renseigner les bons emplacements.
  • Abrégez les valeurs très longues. Si une forme courte suffit, ajoutez une indication comme - Name: [First name or nickname] ou - Address (short): au lieu du texte juridique complet.
  • Mentionnez les règles de mise à jour dans instructions. Vous pouvez indiquer comment et quand renseigner ou effacer certaines parties du modèle directement dans le champ instructions de l'Agent.

Autres styles de modèles
Lien direct vers Autres styles de modèles

Utilisez un bloc unique plus court si vous n'avez besoin que de quelques éléments :

const basicMemory = new Memory({
options: {
workingMemory: {
enabled: true,
template: `User Facts:\n- Name:\n- Favorite Color:\n- Current Topic:`,
},
},
})

Vous pouvez également stocker les faits essentiels sous la forme d'un court paragraphe si vous préférez un style plus narratif :

const paragraphMemory = new Memory({
options: {
workingMemory: {
enabled: true,
template: `Important Details:\n\nKeep a short paragraph capturing the user's important facts (name, main goal, current task).`,
},
},
})

Mémoire de travail structurée
Lien direct vers Mémoire de travail structurée

La mémoire de travail peut également être définie à l'aide d'un schéma structuré plutôt que d'un modèle Markdown. Vous pouvez ainsi préciser exactement les champs et les types à suivre en utilisant un schéma JSON standard (Zod, Valibot, ArkType, etc.). Lorsqu'un schéma est utilisé, l'Agent consulte et met à jour la mémoire de travail sous forme d'objet JSON conforme à ce schéma.

Condition requise : vous devez spécifier soit template, soit schema, mais pas les deux.

Exemple : mémoire de travail fondée sur un schéma
Lien direct vers Exemple : mémoire de travail fondée sur un schéma

import { z } from 'zod'
import { Memory } from '@mastra/memory'

const userProfileSchema = z.object({
name: z.string().optional(),
location: z.string().optional(),
timezone: z.string().optional(),
preferences: z
.object({
communicationStyle: z.string().optional(),
projectGoal: z.string().optional(),
deadlines: z.array(z.string()).optional(),
})
.optional(),
})

const memory = new Memory({
options: {
workingMemory: {
enabled: true,
schema: userProfileSchema,
// template: ... (do not set)
},
},
})

Lorsqu'un schéma est fourni, l'Agent reçoit la mémoire de travail sous forme d'objet JSON. Par exemple :

{
"name": "Sam",
"location": "Berlin",
"timezone": "CET",
"preferences": {
"communicationStyle": "Formal",
"projectGoal": "Launch MVP",
"deadlines": ["2025-07-01"]
}
}

Sémantique de fusion pour la mémoire fondée sur un schéma
Lien direct vers Sémantique de fusion pour la mémoire fondée sur un schéma

La mémoire de travail fondée sur un schéma utilise une sémantique de fusion : l'Agent ne doit inclure que les champs qu'il souhaite ajouter ou mettre à jour. Les champs existants sont automatiquement conservés.

  • Les champs objets font l'objet d'une fusion profonde : seuls les champs fournis sont mis à jour ; les autres restent inchangés
  • Définissez un champ sur null pour le supprimer : cela retire explicitement le champ de la mémoire
  • Les tableaux sont entièrement remplacés : lorsqu'un champ tableau est fourni, il remplace le tableau existant (les tableaux ne sont pas fusionnés élément par élément)

Choisir entre un modèle et un schéma
Lien direct vers Choisir entre un modèle et un schéma

  • Utilisez un modèle (Markdown) si vous souhaitez que l'Agent conserve la mémoire sous forme de bloc de texte libre, tel qu'un profil utilisateur ou un bloc-notes. Les modèles utilisent une sémantique de remplacement : l'Agent doit fournir le contenu complet de la mémoire à chaque mise à jour.
  • Utilisez un schéma si vous avez besoin de données structurées et typées, qui peuvent être validées et consultées par programmation au format JSON. Le champ workingMemory.schema accepte tout schéma compatible avec PublicSchema (notamment Zod v3, Zod v4, JSON Schema ou les schémas déjà standardisés). Les schémas utilisent une sémantique de fusion : l'Agent ne fournit que les champs à mettre à jour, tandis que les champs existants sont conservés.
  • Un seul mode peut être actif à la fois : définir simultanément template et schema n'est pas pris en charge.

Exemple : conservation en plusieurs étapes
Lien direct vers Exemple : conservation en plusieurs étapes

Voici une vue simplifiée de la manière dont le modèle User Profile se met à jour au cours d'une courte conversation avec l'utilisateur :

# User Profile

## Personal info

- Name:
- Location:
- Timezone:

--- After user says "My name is **Sam** and I'm from **Berlin**" ---

# User Profile
- Name: Sam
- Location: Berlin
- Timezone:

--- After user adds "By the way I'm normally in **CET**" ---

# User Profile
- Name: Sam
- Location: Berlin
- Timezone: CET

L'Agent peut maintenant faire référence à Sam ou Berlin dans ses réponses ultérieures sans redemander ces informations, car elles ont été stockées dans la mémoire de travail.

Si votre Agent ne met pas correctement à jour la mémoire de travail au moment prévu, vous pouvez ajouter des instructions système sur la manière et le moment d'utiliser ce modèle dans le paramètre instructions de votre Agent.

Définir la mémoire de travail initiale
Lien direct vers Définir la mémoire de travail initiale

Bien que les Agents mettent généralement à jour la mémoire de travail à l'aide du Tool updateWorkingMemory, vous pouvez aussi définir une mémoire de travail initiale par programmation lors de la création ou de la mise à jour de fils. Cette approche permet d'injecter des données utilisateur (comme le nom, les préférences ou d'autres informations) que vous souhaitez rendre accessibles à l'Agent sans les transmettre dans chaque requête.

Définir la mémoire de travail par les métadonnées du fil
Lien direct vers Définir la mémoire de travail par les métadonnées du fil

Lors de la création d'un fil, vous pouvez fournir une mémoire de travail initiale au moyen de la clé workingMemory des métadonnées :

src/app/medical-consultation.ts
// Create a thread with initial working memory
const thread = await memory.createThread({
threadId: 'thread-123',
resourceId: 'user-456',
title: 'Medical Consultation',
metadata: {
workingMemory: `# Patient Profile
- Name: John Doe
- Blood Type: O+
- Allergies: Penicillin
- Current Medications: None
- Medical History: Hypertension (controlled)
`,
},
})

// The agent will now have access to this information in all messages
await agent.generate("What's my blood type?", {
memory: {
thread: thread.id,
resource: 'user-456',
},
})
// Response: "Your blood type is O+."

Mettre à jour la mémoire de travail par programmation
Lien direct vers Mettre à jour la mémoire de travail par programmation

Vous pouvez également mettre à jour la mémoire de travail d'un fil existant :

src/app/medical-consultation.ts
// Update thread metadata to add/modify working memory
await memory.updateThread({
id: 'thread-123',
title: thread.title,
metadata: {
...thread.metadata,
workingMemory: `# Patient Profile
- Name: John Doe
- Blood Type: O+
- Allergies: Penicillin, Ibuprofen // Updated
- Current Medications: Lisinopril 10mg daily // Added
- Medical History: Hypertension (controlled)
`,
},
})

Mise à jour directe de la mémoire
Lien direct vers Mise à jour directe de la mémoire

Vous pouvez aussi utiliser directement la méthode updateWorkingMemory :

src/app/medical-consultation.ts
await memory.updateWorkingMemory({
threadId: 'thread-123',
resourceId: 'user-456', // Required for resource-scoped memory
workingMemory: 'Updated memory content...',
})

Mémoire de travail en lecture seule
Lien direct vers Mémoire de travail en lecture seule

Dans certains cas, vous pouvez vouloir qu'un Agent accède aux données de la mémoire de travail sans pouvoir les modifier. Cela est utile pour :

  • Les Agents de routage qui ont besoin du contexte, mais ne doivent pas mettre à jour les profils utilisateur
  • Les Agents secondaires d'un système multi-Agent qui doivent consulter la mémoire sans en être propriétaires

Pour activer le mode lecture seule, définissez readOnly: true dans les options de mémoire :

const response = await agent.generate('What do you know about me?', {
memory: {
thread: 'conversation-123',
resource: 'user-alice-456',
options: {
readOnly: true, // Working memory is provided but cannot be updated
},
},
})

Activer les signaux d'état (expérimental)
Lien direct vers Activer les signaux d'état (expérimental)

Par défaut, la mémoire de travail est transmise au modèle dans le message système. Vous pouvez choisir de la fournir plutôt sous forme de signal d'état en définissant useStateSignals: true :

const memory = new Memory({
storage: new LibSQLStore({ id: 'mastra-storage', url: 'file:./mastra.db' }),
options: {
workingMemory: {
enabled: true,
template: '# User\n- name:\n- location:',
useStateSignals: true, // experimental: deliver as state signal
},
},
})

Ce qui change :

  • Le stockage est identique. Le même champ workingMemory de la ressource ou du fil est lu et écrit.
  • Le Tool conserve la même structure, mais est exposé sous un nouveau nom. Les écritures passent toujours par le même Tool sous-jacent ; sur ce parcours, il est enregistré sous le nom setWorkingMemory (au lieu de updateWorkingMemory). Ce changement de nom empêche les anciens filtres de suppression d'écarter les parties d'appel au Tool : celles-ci restent ainsi dans une piste d'audit normale, et l'étape suivante du modèle récupère automatiquement la nouvelle valeur.
  • Seul le mode de transmission change. Au lieu de l'intégrer au prompt système, Memory attache automatiquement un WorkingMemoryStateProcessor qui émet la mémoire de travail actuelle sous la forme d'un signal state avec stateId: 'working-memory'.

Vous bénéficiez des avantages habituels des signaux d'état : métadonnées de suivi limitées au fil, déduplication par cacheKey afin que les instantanés identiques ne soient émis qu'une seule fois, et réinjection par contextWindow.hasSnapshot lorsqu'un instantané plus ancien sort de la fenêtre.

La valeur par défaut (useStateSignals: false) conserve inchangé le comportement existant du message système. useStateSignals n'est pas pris en charge avec la mémoire de travail fondée sur un modèle lorsque version: 'vnext'.

Exemples
Lien direct vers Exemples