[!NOTE] Traduction automatique Cet article a été traduit automatiquement depuis la version originale en anglais.
AI L’architecture mémoire des agents en 2026 : Checkpoints, les stores vectoriels et la mémoire basée sur des fichiers
Deuxième partie de la série « Ingénierie de la pile Agentic »
Un reasoning loop ne survit qu’à une seule requête, à moins que son état ne soit stocké en dehors du worker. Sans mémoire d’agent, celui‑ci ne peut pas reprendre un plan interrompu, se remettre d’une panne, ni récupérer une préférence issue d’une session antérieure. Partie 1 Ce texte couvre le flux de contrôle. Il indique quel état chaque tour ultérieur nécessite et où cet état doit être stocké.
J’expliquerai en détail l’architecture mémoire du Agent d’analyse de marché, Je montrerai comment les stores de vecteurs chauds checkpoints, froids, ainsi que la mémoire de documents basée sur des fichiers collaborent pour alimenter des agents fonctionnant sur de longues périodes. Ensuite, j’aborderai les cas d’usage appropriés pour PostgreSQL, Redis, Qdrant, les stores clé-valeur et les fichiers Markdown classiques.
TL;DR : Séparez la mémoire en fonction du schéma d’accès. La mémoire chaude représente l’état au niveau des threads checkpoint, utilisé pour les pauses et les reprises. La mémoire froide stocke des données inter-sessions dans un système de type clé-valeur ou un stockage vectoriel. La mémoire documentaire conserve les connaissances propres à un projet au sein de fichiers consultables. Commencez par le problème que vous devez résoudre, puis choisissez le type de stockage adapté. Ne placez pas des données précises dans un système de recherche floue, et ne traitez pas un checkpoint comme un journal d’audit.
Qu’est-ce que la mémoire d’agent AI ?
AI mémoire d’agent correspond à la couche d’état qui permet à un agent de conserver l’avancement des tâches, de récupérer des connaissances antérieures et de mettre à jour ses informations au cours de différentes exécutions. En environnement de production, il ne s’agit pas d’une seule base de données vectorielle ; il s’agit plutôt d’un mélange de stockages checkpoints actifs, de stockages sémantiques ou structurés passifs, ainsi que d’une mémoire de documents lisible par les humains.
| Nécessite | Meilleure valeur par défaut | Pourquoi ? |
|---|---|---|
| Pauser et reprendre une exécution | PostgreSQL checkpoint de stockage | Des données d’application durables, consultables et faciles à manipuler |
| État transitoire à faible latence | Stockage Redis checkpoint | Reprise rapide et état à durée de vie courte, avec des compromis liés à la persistance |
| Rappel sémantique inter-sessions | Récupère les souvenirs en se basant sur leur signification, et non uniquement sur des clés exactes. | |
| Faits structurés sur l’utilisateur | PostgreSQL ou stockage clé-valeur | Les mises à jour déterministes surpassent la recherche floue pour les préférences et les identifiants. |
| Conventions de projet et procédures éprouvées | Fichiers Markdown ou JSON | Lisible par l’humain, permettant des diffs et facile à mettre à jour par les agents |
| Mémoire des relations entre multiples entités | Graphe de connaissances | Utile lorsque les relations priment sur les faits individuels. |
Ne commencez pas par la mémoire, car ce terme donne une impression d’intelligence artificielle. Commencez plutôt par l’échec visible pour l’utilisateur : perte des progrès réalisés, oubli d’une préférence, répétition de recherches, ou incapacité à réutiliser une convention de projet.
Les échecs qui nécessitent une mémoire
Un agent sans état peut répondre à une question isolée, mais il oublie la requête dès la fin de l’appel. Cette conception échoue lorsque le produit nécessite l’un des comportements suivants :
- Pause et reprise : un utilisateur lance une tâche de recherche, ferme son ordinateur portable et revient le lendemain. En l’absence d’état enregistré sous forme de point de contrôle, l’agent doit redémarrer depuis zéro.
- Coherence sur plusieurs tours : au cours d’une conversation prolongée, l’agent doit se souvenir des outils qu’il a utilisés, des données qu’il a collectées ainsi que des étapes du plan qu’il a achevées.
- Personnalisation : un utilisateur qui revient s’attend à ce que l’agent connaisse sa tolérance au risque, le niveau de profondeur d’analyse préféré et ses interactions antérieures.
- Human-in-the-loop (HITL) : l’agent rédige un rapport et attend l’approbation. L’état de « attente » doit être conservé même en cas de redémarrage du processus.
Dans le Agent d’analyse de marché de Partie 1, La requête « Analyser NVDA » génère un plan, cinq tool calls, des données collectées ainsi qu’un projet de rapport. Lorsque l’utilisateur répond par « Cela a l’air bon, mais ajoutez une analyse des concurrents », un checkpoint store permet à l’agent de charger l’état du nœud précédent et d’ajouter l’étape relative aux concurrents. En l’absence d’état enregistré via des points de contrôle, il ne peut pas déterminer ce que signifie « Cela a l’air bon » et doit tout reprendre depuis le début.
La mémoire à long terme gère un cas différent. Si l’utilisateur revient une semaine plus tard et demande : « Mettez à jour mon analyse NVDA », l’agent peut devoir se remémorer la préférence pour des évaluations de risque conservatrices ainsi que l’intérêt porté aux actions de semi-conducteurs. Un stockage de mémoire basé sur des vecteurs permet de récupérer ces informations entre les sessions sans avoir à les demander à nouveau.
LangGraph effectue cette séparation en fonction du périmètre d’action. Chaque exécution de graphe s’effectue au sein d’un thread, ce qui correspond à une conversation ou une tâche donnée. L’état persistant au sein de ce thread constitue la mémoire à court terme. L’état partagé entre les threads représente quant à lui la mémoire à long terme. Le contexte actuel du modèle ainsi que les variables en cours de traitement forment la couche de mémoire de travail située au-dessus de ces deux types de stockage.
Une taxonomie de la mémoire d’agent AI
Avant de passer à la mise en œuvre, il est utile de classer ce que les agents doivent mémoriser. CoALA framework <SUMERS_YAO_2023> est la taxonomie de référence qui s’appuie sur les principes de la science cognitive. J’y ai introduit le concept de ciblage de la mémoire dans mes travaux.</SUMERS_YAO_2023> context engineering publication; Voici sa décomposition en six catégories :
| Type de mémoire | Champ d’application | Durée de vie | Exemple | Pattern de stockage |
|---|---|---|---|---|
| En fonctionnement | Étape actuelle | Milisecondes | Tool call arguments, réponse LLM actuelle | |
| À court terme | Thread actuel | Minutes–heures | Historique de conversation, progression du plan, données collectées | Checkpoint stocker |
| Épisodique | Inter-thread | Jours–mois | La semaine dernière, l’utilisateur a demandé des informations concernant les résultats financiers de NVDA. | Stockage vectoriel / Stockage KV |
| Sémantique | Inter-thread | Mois – permanent | « L’utilisateur préfère des investissements conservateurs » | Stockage vectoriel / Stockage KV |
| Document | Inter-thread | Jours – permanent | Notes de projet, résumés de recherche, motifs identifiés | Stockage de fichiers (Markdown/JSON) |
| Procédural | À l’échelle du système | Permanente | Lors de l’analyse des actions, il est indispensable de consulter systématiquement les documents déposés auprès de la SEC. | Config / system prompt |
Mémoire de travail est ce avec quoi le LLM raisonne activement en ce moment : les variables Python de la fonction en cours, le contenu de la fenêtre de contexte, ainsi que les arguments tool call pendant l’exécution. Il s’agit de la couche la plus rapide mais aussi la plus éphémère ; rien ne persiste au-delà de l’étape actuelle. La mémoire de travail est limitée par la fenêtre de contexte du modèle, ce qui en fait le véritable goulot d’étranglement. Tout ce que l’agent « sait » au moment de prendre une décision doit y trouver sa place, que ce soit provenant du stockage checkpoint, d’une requête vectorielle ou d’une lecture de fichier. Les autres niveaux existent pour fournir les informations appropriées à la mémoire de travail au bon moment.
La mémoire à court terme correspond aux données checkpoint que LangGraph écrit après chaque nœud. Les mémoires épisodique et sémantique persistent au sein des threads. La mémoire de document conserve les notes de projet, les résumés de recherche ainsi que les conventions apprises dans des fichiers accessibles tant aux humains qu’aux agents. Quant à la mémoire procédurale, elle est intégrée dans les instructions système et les définitions d’outils, sans être modifiée pour chaque utilisateur.
Pour la mise en œuvre, ces catégories se résument en trois niveaux. La mémoire à chaud stocke la session en cours. La mémoire à froid permet de récupérer des données entre différentes sessions. La mémoire de documents garantit que les connaissances accumulées sur un projet restent lisible et directement modifiables.
CoALA classe la mémoire de travail, épisodique, sémantique et procédurale. Le La mémoire à l’ère des agents AI : une étude de terrain Il met l’accent sur les stockeurs de vecteurs et les graphes de connaissances, tandis que LangGraph décrit checkpoints ainsi que son interface Store. Les connaissances propres aux projets, stockées sous forme de fichiers, restent en dehors de ces taxonomies, même si Claude Code, Cursor, Windsurf et Devin chargent tous des fichiers persistants de projet.
Ce même schéma de stockage se retrouve dans d’autres domaines. Voyager conserve les compétences de jeu réutilisables sous forme de bibliothèques de code, les équipes ECR3 ont itéré sur des documents procéduraux prompt, et la mémoire de flux de travail d’agent permet de générer des flux de travail web réutilisables à partir d’épisodes réussis. Les fichiers rendent ces connaissances inspectables et versionnables, sans avoir recours à un service embedding distinct.
La mémoire gérée par un agent diffère également d’une pipeline RAG fixe quant à l’entité responsable des écritures. C’est l’agent ou son harness qui décide de ce qui doit être stocké, mis à jour ou supprimé, avant de choisir le moment opportun pour le récupérer.
Le Article sur les agents génératifs (Park et al., 2023) ont démontré jusqu’où cela peut aller : des agents simulés ont été capables de stocker, de réfléchir sur et de récupérer leurs propres mémoires. Leur flux de mémoire classait les candidats en fonction de la proximité dans le temps, de l’importance et de la pertinence, une approche qui constitue encore aujourd’hui un point de référence utile pour la récupération de mémoires d’agent.
Mémoire à court terme de l’agent : le stockage checkpoint
Chaque fois qu’un nœud LangGraph est exécuté, le framework serialize l’état complet du graphe et l’écrit dans un checkpoint store. C’est cette base qui permet les fonctionnalités de pause/reprise, le débogage par « voyage dans le temps », ainsi que les workflows HITL.
Un checkpoint contient l’état du graphe nécessaire pour reprendre : le AgentState de Partie 1 (messages, identité, profil utilisateur, étapes du plan, données de recherche, mode d’exécution), ainsi que les métadonnées de LangGraph telles que le nœud qui les a générés et son ID checkpoint. Lors d’une interruption HITL ou d’un redémarrage de processus, le graphe charge la limite la plus récente enregistrée et reprend l’exécution depuis le nœud suivant. Il ne continue pas à partir d’une ligne Python arbitraire. Un checkpoint diffère également d’un journal d’événements ou d’un traceur à écriture seule ; Partie 5 isole explicitement ces surfaces d’observabilité runtime.
Comment fonctionne le checkpointing de LangGraph
de LangGraph BaseCheckpointSaver Il s’agit d’une interface simple : put() écrit un checkpoint, get_tuple() lit la dernière version d’un fil de discussion. list() retourne l’historique. Chaque checkpoint est identifié par un clé. (thread_id, checkpoint_ns, checkpoint_id), où thread_id identifie la conversation. checkpoint_ns gère l’espacement des noms de sous-graphes, et checkpoint_id Il s’agit d’une version unique.
La décision cruciale consiste à déterminer quel backend placer derrière ce mécanisme. PostgreSQL et Redis représentent deux choix courants en environnement de production.
PostgreSQL contre Redis
| Dimension | PostgreSQL (langgraph-checkpoint-postgres) | Redis (langgraph-checkpoint-redis) |
|---|---|---|
| Modèle de durabilité | Les transactions ACID, le WAL et la réplication | Persistance configurable en mode AOF ou RDB |
| Checkpoint historique | Historique persistant pour le suivi des états et le débogage | La durée de conservation dépend des paramètres de sauvegarde et d’éviction. |
| Contrainte principale | Latence d’écriture dans la base de données et croissance des tables | Utilisation de la RAM, éviction et configuration de la persistance |
| Adéquation opérationnelle | Les équipes qui utilisent déjà des bases de données relationnelles | Les équipes qui utilisent déjà Redis atteignent déjà un débit élevé. |
| Meilleure valeur par défaut pour | Reprise fiable du travail et débogage reproductible | État de session réversible et sensible à la latence |
Une base de données générique benchmarks ne permet pas de prédire les performances checkpoint. Il convient de mesurer la taille de l’état serialisé, la fréquence d’écriture, les paramètres de persistance ainsi que le niveau de concurrence de votre propre graphe.
PostgreSQL : le choix par défaut fiable
PostgreSQL constitue le choix par défaut plus sûr pour la plupart des équipes. Grâce aux Checkpoints capables de survivre aux pannes, on bénéficie d’une sémantique de transactions complète, et l’historique checkpoint permet de réaliser des débogages en « voyage dans le temps » de manière très simple.
Depuis checkpointer_setup.py:
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
async def create_postgres_checkpointer(connection_string: str) -> AsyncPostgresSaver:
"""Create a PostgreSQL-backed checkpoint store.
PostgreSQL gives us ACID guarantees — if a checkpoint write succeeds,
the state is durable even if the process crashes immediately after.
"""
checkpointer = AsyncPostgresSaver.from_conn_string(connection_string)
# Create the checkpoint tables if they don't exist.
# This is idempotent — safe to call on every startup.
await checkpointer.setup()
return checkpointer
# Usage: wire into the graph compilation
checkpointer = await create_postgres_checkpointer(
"postgresql://user:pass@localhost:5432/agent_memory"
)
graph = create_graph(checkpointer=checkpointer)
# Every invoke/stream call now persists state automatically
config = {"configurable": {"thread_id": "user-123-session-1"}}
result = await graph.ainvoke({"messages": [HumanMessage(content="Analyze NVDA")]}, config)
# Resume later — loads the latest checkpoint for this thread
result = await graph.ainvoke({"messages": [HumanMessage(content="approved")]}, config)
Le AsyncPostgresSaver utilise langgraph-checkpoint-postgres package, qui crée trois tables : checkpoints (l’état serialisé) checkpoint_blobs (données binaires de grande taille), et checkpoint_writes (Pending les écritures nécessaires à la récupération en cas de panne.) Le schéma prend en charge l’accès concurrentiel et utilise des verrous consultatifs afin d’éviter les conflits d’écriture.
Redis : lorsque la latence constitue le goulot d’étranglement
Lorsque des latences inférieures à un milliardième de seconde checkpoint sont cruciales (agents conversationnels en temps réel, boucles d’outil à haute fréquence), Redis constitue le choix préférable.
Depuis checkpointer_setup.py:
from langgraph.checkpoint.redis.aio import AsyncRedisSaver
async def create_redis_checkpointer(redis_url: str) -> AsyncRedisSaver:
"""Create a Redis-backed checkpoint store.
Redis stores checkpoints in memory for sub-millisecond access.
Trade-off: less durable than PostgreSQL unless AOF is enabled.
"""
checkpointer = AsyncRedisSaver.from_conn_string(redis_url)
# Initialize Redis data structures
await checkpointer.setup()
return checkpointer
# Usage: same graph API, different backend
checkpointer = await create_redis_checkpointer("redis://localhost:6379")
graph = create_graph(checkpointer=checkpointer)
Le AsyncRedisSaver de langgraph-checkpoint-redis Il stocke checkpoints sous forme de documents JSON identifiés par leur ID de thread. Le v0.1.0 refonte j’ai remplacé plusieurs opérations de recherche par une seule JSON.GET Appel, réduisant de manière significative la latence. Redis 8.0+ intègre par défaut RedisJSON et RediSearch — aucune module supplémentaire à installer.
Pour les déploiements soumis à des contraintes de mémoire, ShallowRedisSaver Il ne conserve que la dernière valeur de checkpoint par thread — sans historique, mais avec une consommation mémoire minimale. Utilisez cette approche lorsque vous avez besoin de fonctionnalités de pause/reprise sans avoir recours à un débogage permettant de revenir en arrière dans le temps.
Quand utiliser lequel
Utilisez PostgreSQL lorsque :
- Vous avez besoin d’un historique complet de checkpoint pour le débogage par « voyage dans le temps » ou afin d’obtenir un état reproductible
- La durabilité est une exigence absolue (secteurs des services financiers et de la santé)
- Vous utilisez déjà PostgreSQL dans votre stack technologique
- Votre agent exécute des tâches longues où la perte de l’état entraîne des heures de recomputation
- Vous souhaitez un stockage de données unifié — PostgreSQL associé à pgvector peut fonctionner comme un unique backend pour gérer les checkpoints, la mémoire à long terme ainsi que la recherche vectorielle, ce qui simplifie considérablement votre infrastructure.
Utilisez Redis lorsque :
- La latence Checkpoint constitue votre goulot d’étranglement (chat en temps réel, expérience utilisateur en streaming).
- Vous développez des bots vocaux : conversion STT-en LLM-en TTS pipelines nécessaire. accès à l’état en sous-milliseconde
- Vous avez besoin d’une mise à l’échelle horizontale sur de nombreux threads simultanés
- Des schémas de diffusion à forte concurrence où plusieurs agents partagent un état commun
- Des sessions de courte durée pour lesquelles la perte d’un checkpoint est récupérable
- Vous souhaitez un cache sémantique afin de réduire les appels redondants à LLM (Redis LangCache il stocke les requêtes sémantiquement similaires afin d’éviter des appels répétés à LLM)
Autres options : langgraph-checkpoint-sqlite Fonctionne pour le développement local ainsi que les déploiements en mode processus unique. Pour les stacks natives d’AWS, langgraph-checkpoint-aws fournit un DynamoDBSaver grâce à un traitement intelligent du chargement : les petits fichiers checkpoints (<350 KB) restent stockés dans DynamoDB, tandis que les plus volumineux sont automatiquement transférés vers S3. Le modèle de tarification serverless ainsi que l’absence d’infrastructure à gérer en font une solution attractive pour les déploiements à charge variable.
Mémoire à long terme : mémorisation entre sessions
La mémoire à court terme gère la conversation en cours. Mais que se passe-t-il pour l’utilisateur qui reviendra la semaine prochaine ? La mémoire à long terme stocke des faits, des préférences ainsi que l’historique des interactions, ce qui permet à ces données de persister au-delà des différentes sessions.
LangGraph propose un Store interface permettant l’accès à la mémoire entre threads via son BaseStore classe. Chaque élément de mémoire est un (namespace, key) être associé à une valeur JSON ainsi qu’à un vecteur optionnel embedding. L’espace de noms indique généralement l’utilisateur ou l’organisation : ("user", "user-123", "preferences").
Stockage vectoriel : récupération sémantique grâce à Qdrant
Lorsque l’agent doit récupérer des faits non structurés (« Qu’a dit l’utilisateur au sujet de son calendrier d’investissement ? »), la recherche vectorielle permet une récupération sémantique. Au lieu de rechercher des clés exactes, l’agent effectue des requêtes en se basant sur le sens.
Qdrant C’est une base de données vectorielle conçue spécifiquement en Rust, qui gère le stockage embedding, l’indexation (HNSW) ainsi que les recherches filtrées. J’ai abordé en détail HNSW et ses compromis dans mon classement des résultats de recherche. Qdrant propose également un serveur MCP qui agit comme une couche de mémoire sémantique — utile si votre agent framework prend en charge le Model Context Protocol.
Depuis memory_store.py:
from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct, Distance, VectorParams
from langchain_anthropic import ChatAnthropic
import hashlib
import json
class UserMemoryStore:
"""Long-term memory backed by Qdrant vector search.
Stores user facts as embedded vectors for semantic retrieval.
Each fact is a short natural-language statement about the user.
"""
def __init__(self, qdrant_url: str, collection_name: str = "user_memory"):
self.client = QdrantClient(url=qdrant_url)
self.collection_name = collection_name
self._ensure_collection()
def _ensure_collection(self):
"""Create the collection if it doesn't exist."""
collections = [c.name for c in self.client.get_collections().collections]
if self.collection_name not in collections:
self.client.create_collection(
collection_name=self.collection_name,
vectors_config=VectorParams(
size=1536, # text-embedding-3-small dimensions
distance=Distance.COSINE,
),
)
def store_fact(self, user_id: str, fact: str, embedding: list[float]):
"""Store a user fact with its embedding."""
point_id = hashlib.md5(f"{user_id}:{fact}".encode()).hexdigest()
self.client.upsert(
collection_name=self.collection_name,
points=[PointStruct(
id=point_id,
vector=embedding,
payload={"user_id": user_id, "fact": fact},
)],
)
def recall(self, user_id: str, query_embedding: list[float], top_k: int = 5):
"""Retrieve the most relevant facts for a user given a query."""
results = self.client.query_points(
collection_name=self.collection_name,
query=query_embedding,
query_filter={"must": [{"key": "user_id", "match": {"value": user_id}}]},
limit=top_k,
)
return [hit.payload["fact"] for hit in results.points]
Le flux de travail est le suivant : (1) après chaque conversation, un LLM extrait les faits clés issus de l’interaction (« l’utilisateur présente une forte tolérance au risque », « l’utilisateur s’intéresse aux actions de semi-conducteurs »), (2) ces faits sont intégrés et stockés dans Qdrant, (3) au début de la conversation suivante, l’agent interroge Qdrant à l’aide du nouveau message de l’utilisateur afin de récupérer le contexte pertinent.
Évaluation des résultats de récupération : au-delà de la similarité cosinus
La similarité cosinus brute constitue un point de départ, mais les systèmes de mémoire en environnement de production exigent des méthodes de récupération plus sophistiquées. Article sur les agents génératifs (Park et al., 2023) ont introduit une fonction de scoring qui combine trois signaux :
- Récence : Déclin basé sur des règles, de sorte que les souvenirs récents obtiennent un score plus élevé. Une fonction de décroissance exponentielle fait en sorte qu’un fait d’hier prime sur un fait équivalent datant de six mois auparavant.
- Importance : Significativité évaluée selon LLM sur une échelle de 1 à 10. L’expression « Le portefeuille de l’utilisateur a chuté de 40 % » obtient un score plus élevé que « L’utilisateur a dit bonjour ».
- Rélevance : Similarité cosinus Embedding entre la requête et le fait stocké.
Le score final de récupération est une somme pondérée : score = alpha * recency + beta * importance + gamma * relevance. Cela empêche que des faits récents et importants ne soient enterrés sous des données obsolètes mais sémantiquement similaires. Pour le Agent d’analyse de marché, J’accorde la plus grande importance à la pertinence (0,5), suivie de la proximité dans le temps (0,3) et de l’importance relative (0,2), car l’intention de la requête actuelle de l’utilisateur est primordiale. Il s’agit de poids de point de départ adaptés du papier sur les agents génératifs (où des poids égaux étaient utilisés) ; j’ai constaté que mettre l’accent sur la pertinence donnait de meilleurs résultats pour les requêtes d’analyse financière, mais ces valeurs reposent sur l’intuition plutôt que sur une optimisation empirique.
Alternatives à la recherche vectorielle
La recherche vectorielle est puissante, mais elle n’est pas toujours l’outil adapté. Voici les cas où il convient d’utiliser des alternatives :
| Approche | Idéal pour | Coût opérationnel principal |
|---|---|---|
| Recherche vectorielle (Qdrant) | Rappel sémantique des faits non structurés | Embedding ainsi que le cycle de vie de l’index |
| Stockage clé-valeur (Redis) | Profils d’utilisateurs structurés et préférences | Politique d’utilisation de la mémoire et de persistance |
| Stockage de documents (fichiers) | Connaissances de projet et notes gérées par l’agent | Concurrence, permissions et recherche |
| Recherche plein texte (PostgreSQL) index GIN)** | Rappel des mots-clés à partir de l’historique de la conversation | Croissance de l’index et optimisation des requêtes |
| Graphe de connaissances (Neo4j) | Relations entre entités et requêtes à plusieurs sauts | Modélisation de graphes et autres systèmes de données |
| Hybride (vecteur + mot-clé) | Rappelons que l’intention de la requête varie | Deux chemins de scoring à ajuster et à évaluer |
Les stockages clé-valeur s’avèrent particulièrement adaptés aux données structurées. Lorsque votre mémoire à long terme correspond à un profil d’utilisateur — tolérance au risque, horizon d’investissement, secteurs préférés — l’utilisation d’un hash Redis ou d’une colonne JSONB dans PostgreSQL est plus simple et plus rapide que embedding ainsi que que la recherche sur des vecteurs. Préférez la recherche vectorielle lorsque les données sont non structurées et que les requêtes de récupération varient en formulation.
Le stock intégré de LangGraph offre une interface clé-valeur basée sur des noms d’espace, complétée éventuellement par une recherche vectorielle. Le BaseStore API est simple : put(), get(), search(), et delete() avec un encadrement de nom d’espace hiérarchique. Trois implémentations sont disponibles :
InMemoryStore— destiné au développement et aux tests (les données sont perdues en cas de sortie du processus)PostgresStore— stockage de production persistant permettant des requêtes SQL complètesAsyncRedisStore— mémoire inter-thread avec recherche vectorielle, prise en charge de TTL et filtrage des métadonnées
Le index La configuration permet une recherche vectorielle sur les éléments stockés à l’aide d’un modèle embedding configurable. Pour de nombreux cas d’usage, ce stockage intégré est suffisant, sans nécessiter l’utilisation d’une base de données vectorielles dédiée.
from langgraph.store.memory import InMemoryStore
# Create a store with vector search enabled
store = InMemoryStore(
index={
"dims": 1536,
"embed": my_embedding_function, # e.g., OpenAI text-embedding-3-small
}
)
# Store a user preference (namespace scopes to user)
await store.aput(
namespace=("user", "user-123", "preferences"),
key="risk-profile",
value={"risk_tolerance": "high", "horizon": "long-term"},
)
# Semantic search across user's memories
results = await store.asearch(
namespace=("user", "user-123"),
query="What is their investment style?",
limit=5,
)
Sélection d’une stratégie de mémoire à long terme
Commencez par une structure clé-valeur lorsque votre mémoire est structurée et bien définie (profils d’utilisateurs, paramètres, entités nommées). Ajoutez la recherche vectorielle lorsque vous avez besoin d’une récupération sémantique sur des données non structurées ou lorsque la formulation des requêtes varie de manière imprévisible.
Les graphes de connaissances s’avèrent particulièrement utiles lorsque les relations entre les entités jouent un rôle clé, par exemple : « Quelles entreprises que l’utilisateur a consultées sont des concurrents de NVDA ? » Le projet le plus intéressant dans ce domaine ces derniers temps est Graphiti (par Zep), qui construit un graph de connaissances conscient du temps permettant de suivre quand les faits étaient vrais, et non seulement ce qui était vrai. Chaque arête intègre des intervalles de validité, de sorte qu’une modification de la tolérance au risque de l’utilisateur rend caduque la valeur précédente au lieu de la remplacer silencieusement. Graphiti génère des rapports 94,8 % de précision sur le DMR benchmark, Et son modèle bitemporal permet de gérer le problème de la mémoire obsolète au niveau du layer de données.
Le problème réside sur le plan opérationnel. Gérer une base de données graphique n’est pas chose aisée, et pour la plupart des applications d’agents, la recherche vectorielle associée à un filtrage par métadonnées permet d’obtenir les mêmes résultats avec moins d’infrastructure.
Mémoire gérée frameworks telle que Mem0 et Letta (auparavant MemGPT), ce système gère à votre place l’extraction, la consolidation et la récupération pipeline. L’approche de Mem0 se distingue par le fait qu’un LLM extrait des mémoires candidates, un moteur de décision compare chaque nouvelle information aux entrées existantes dans le stockage vectoriel, et un résolveur décide s’il convient d’ajouter, de mettre à jour ou de supprimer ces données, ce qui permet de maintenir le stockage de mémoires cohérent et sans redondances. Letta, quant à elle, adopte une perspective inspirée des systèmes d’exploitation : les agents gèrent eux-mêmes leur fenêtre de contexte à l’aide d’outils de gestion de la mémoire, transférant de manière autonome les données entre la « mémoire principale » (dans le contexte) et la « mémoire d’archivage » (en dehors du contexte). Ces deux solutions méritent d’être évaluées si vous souhaitez accélérer le processus de mise en production sans avoir besoin d’un contrôle total sur la gestion de la mémoire pipeline.
Mémoire de document : le classeur de l’agent
Dans les taxonomies de mémoire mentionnées ci-dessus, la mémoire basée sur des fichiers bénéficie d’une adoption plus importante que d’une couverture exhaustive. Lors d’une évaluation LoCoMo menée par un fournisseur, Letta a fait son rapport 74,0 % pour son approche basée sur un système de fichiers. Il convient de maintenir ce résultat dans le cadre de son modèle, sous les conditions de benchmark et harness, mais l’avantage opérationnel est facile à observer : les développeurs peuvent lire, modifier et comparer les connaissances stockées directement.
Des fenêtres de contexte plus larges permettent également de lire des fichiers entiers de manière pratique pour certains documents de projet. La récupération par morceaux reste adaptée aux corpus volumineux, mais un fichier de conventions ou de transfert de petite taille peut souvent être chargé directement. Le choix dépend de la taille du document, de la précision de la récupération, du budget de contexte, ainsi que de la fréquence à laquelle il est nécessaire de revoir ou d’éditer cette mémoire.
Les bases de données vectorielles et les systèmes de stockage clé-valeur gèrent efficacement la récupération sémantique ainsi que les recherches structurées. Cependant, il existe une troisième catégorie de connaissances propres aux agents qui n’est pas prise en charge de manière optimale par ces solutions : le contexte de projet accumulé, c’est-à-dire les conventions, les notes de recherche et les décisions dont l’agent a besoin au fil des sessions, et qui bénéficient d’un format lisible par les humains ainsi que d’un contrôle de version.
Il s’agit de la mémoire de document : l’agent lit et écrit des fichiers structurés (Markdown, JSON, YAML) dans un répertoire prédéfini. Aucun embeddings, aucune base de données, aucune infrastructure. Seulement des fichiers sur le disque accessibles tant par l’agent que par le développeur. cat, grep, git diff, puis l’éditer manuellement.
Pourquoi des fichiers ?
Pour les flux de travail d’agents à longue durée de vie, le pattern le plus efficace que j’aie observé n’est pas une base de données vectorielle. Il s’agit plutôt d’un répertoire contenant des notes bien organisées. Pensez à ce qui se passe lorsque un agent de codage travaille sur un projet sur plusieurs semaines :
- Il détecte que le projet utilise Pydantic v2 et non v1
- Il constate que les tests doivent être exécutés avec
pytest -x --tb=short - Il accumule des connaissances concernant l’architecture du codebase
- Il apprend les préférences du développeur (« utiliser toujours »)
pathlib, jamaisos.path”)
Ces faits présentent une structure trop rigide pour une recherche vectorielle (il est nécessaire d’obtenir un taux de rappel exact, et non une similarité floue), et leur nombre est trop élevé pour un stockage clé-valeur (ils forment des documents interconnectés, et non des faits isolés). De plus, il s’agit de faits que le développeur souhaite voir et modifier directement. Si l’agent apprend quelque chose de faux, il suffit d’ouvrir le fichier pour y apporter les corrections.
Voici donc comment Claude Code’s CLAUDE.md et .claude/ Travail sur les répertoires. L’agent lit au niveau du projet CLAUDE.md fichiers contenant des conventions et des instructions, ainsi que les écritures vers ~/.claude/MEMORY.md Pour le transfert de connaissances entre sessions. Ces fichiers sont en Markdown pur : vous les lisez, les modifiez, les committez dans Git, puis les partagez avec votre équipe. le curseur de .cursorrules et Le windsurfing .windsurfrules des fichiers texte simples que l’agent charge au démarrage afin de prendre connaissance du contexte du projet.
Mise en œuvre d’un stockage mémoire de fichiers
L’implémentation est délibérément simplifiée. L’agent dispose de quatre opérations : écrire un document, lire un document, lister les documents disponibles, et effectuer une recherche par mot-clé à l’intérieur des documents.
Depuis file_memory.py:
from pathlib import Path
import json
import fnmatch
class FileMemory:
"""Document memory backed by the local filesystem.
Stores agent knowledge as human-readable files organized by topic.
No embeddings, no database — just files that both the agent and
the developer can read, edit, and version-control.
"""
def __init__(self, base_dir: str | Path):
self.base_dir = Path(base_dir)
self.base_dir.mkdir(parents=True, exist_ok=True)
def write_doc(self, path: str, content: str, metadata: dict | None = None):
"""Write or overwrite a document at the given path.
Paths are relative to base_dir. Directories are created automatically.
Metadata (if provided) is stored as a JSON sidecar file.
"""
full_path = self.base_dir / path
full_path.parent.mkdir(parents=True, exist_ok=True)
full_path.write_text(content, encoding="utf-8")
if metadata:
meta_path = full_path.with_suffix(full_path.suffix + ".meta")
meta_path.write_text(json.dumps(metadata, indent=2), encoding="utf-8")
def read_doc(self, path: str) -> str | None:
"""Read a document by path. Returns None if not found."""
full_path = self.base_dir / path
if full_path.exists():
return full_path.read_text(encoding="utf-8")
return None
def list_docs(self, pattern: str = "**/*") -> list[str]:
"""List documents matching a glob pattern."""
return [
str(p.relative_to(self.base_dir))
for p in self.base_dir.glob(pattern)
if p.is_file() and not p.name.endswith(".meta")
]
def search_docs(self, query: str, pattern: str = "**/*.md") -> list[dict]:
"""Search documents by keyword. Returns matching files with context.
This is intentionally simple — grep-style keyword search.
For semantic search, use a vector store instead.
NOTE: This is a sketch for demonstration. A simple substring check
won't scale beyond a few hundred documents. For production with 500+
documents, use TF-IDF/BM25 scoring (e.g., rank_bm25) or a full-text
search backend (PostgreSQL GIN index, Elasticsearch).
"""
results = []
for path in self.base_dir.glob(pattern):
if not path.is_file() or path.name.endswith(".meta"):
continue
content = path.read_text(encoding="utf-8")
if query.lower() in content.lower():
# Return the paragraph containing the match for context
for paragraph in content.split("\n\n"):
if query.lower() in paragraph.lower():
results.append({
"path": str(path.relative_to(self.base_dir)),
"match": paragraph.strip()[:500],
})
return results
Structure des dossiers
La majeure partie de la valeur de la mémoire de document provient de la manière dont le répertoire est organisé. Voici la structure que j’utilise pour le Agent d’analyse de marché:
.agent-memory/
README.md # What this directory is, for human readers
user-profiles/
user-123.md # Preferences, history, risk profile
user-456.md
research/
NVDA-2026-02.md # Research notes from recent analysis
TSLA-2026-01.md
conventions/
analysis-format.md # How to structure analysis reports
data-sources.md # Preferred data sources and API patterns
learnings/
common-errors.md # Mistakes the agent has learned to avoid
tool-patterns.md # Effective tool call sequences
Chaque fichier est au format Markdown. La finalité de chaque fichier est évidente à partir de son chemin. Vous pouvez git diff afficher tout le répertoire de mémoire afin de connaître ce que l’agent a appris au cours d’une session. git revert Un mauvais apprentissage peut survenir, ou bien il est possible de copier le répertoire vers un autre projet. Essayez de faire l’une de ces opérations avec une collection Qdrant.
Quand utiliser la mémoire de document, les vecteurs ou le format clé-valeur
Les trois backends mémoire répondent à des schémas d’accès distincts :
| Dimension | Stockage vectoriel | Stockage clé-valeur | Stockage de documents |
|---|---|---|---|
| Pattern de requête | « Trouver des faits similaires à X » | Récupérer la valeur associée à la clé | ”Lisez le document situé à l’adresse indiquée.” |
| Idéal pour | Rappel non structuré et varié | Recherches structurées | Contexte du projet, notes |
| Lisible par l’humain | Non (embeddings) | Partiellement (JSON) | |
| Débogable | Score de similarité élevé | Facile (clés exactes) | Trivial (ouvrir le fichier) |
| Version contrôlable | Possible | Oui (native Git) | |
| Embedding infrastructure | Obligatoire | Pas nécessaire | Pas nécessaire |
| Évolue jusqu’à | Des millions de faits | Des millions de clés | Des milliers de documents |
| Capacité de recherche | Similitude sémantique | Correspondance exacte | Basé sur des mots-clés ou des chemins |
Utilisez la mémoire de document lorsque :
- L’agent accumule des connaissances sur le projet au cours de plusieurs sessions.
- Les développeurs doivent pouvoir examiner, modifier ou remplacer ce que l’agent « sait ».
- Ces connaissances sont structurées sous forme de documents (notes, résumés, conventions) plutôt que de faits isolés.
- On souhaite disposer d’une gestion de versions basée sur Git pour la mémoire de l’agent.
- Aucune infrastructure n’est autorisée : c’est une exigence stricte.
Utilisez des entrepôts vectoriels lorsque :
- Vous avez besoin d’une récupération sémantique floue (« trouver des souvenirs liés à X »)
- La formulation des requêtes varie de manière imprévisible
- Vous disposez de milliers voire de millions de faits individuels
Utilisez des stores clé-valeur lorsque :
- Vous avez besoin de recherches précises et rapides sur des données structurées (profils d’utilisateurs, paramètres)
- Le schéma des données est bien défini
En pratique, les agents en environnement de production combinent fréquemment les trois approches. Le Agent d’analyse de marché il utilise PostgreSQL checkpoints pour la gestion de la mémoire à haute performance, Qdrant pour le rappel des faits utilisateurs sémantiques, ainsi qu’un stockage de documents basé sur des fichiers pour les conventions de projet et les notes de recherche.
Exemples du monde réel
Ce schéma est déjà largement répandu dans les assistants de codage AI :
- Claude Code lit
CLAUDE.mdles fichiers situés dans la racine du projet ainsi que dans les répertoires parents, et écrit dans~/.claude/MEMORY.mdpour les apprentissages inter-sessions. L’ensemble du système de mémoire se compose de fichiers Markdown classiques que vous committez avec votre code. - Cursor charge
.cursorrulesFichiers contenant les instructions spécifiques au projet pour les agents : conventions de codage, préférences framework, décisions architecturales. - Windsurf utilise
.windsurfrulesfichiers en plus d’unmemories/dossier dans lequel l’agent stocke les motifs appris à partir de votre base de code. - Outil de mémoire d’Anthropic pour Claude API fournit
create_memory,read_memory,update_memory, etdelete_memoryLes opérations sont exécutées du côté client. Votre application détermine l’emplacement réel des fichiers (disque local, S3, base de données).
Le point commun : tous ces systèmes stockent les connaissances de l’agent sous forme de fichiers texte lisibles par l’homme, avec des opérations de lecture/écriture explicites. Aucune embeddings. Aucune infrastructure vectorielle. C’est l’agent qui décide de ce qui doit être écrit, le développeur peut consulter et modifier tout le contenu, et l’ensemble du système tient dans un git diff.
Au-delà des assistants de codage
La mémoire de document n’est pas réservée aux agents de codage. Ce phénomène se retrouve dans des domaines d’agents très variés :
-
Agents de jeux de monde ouvert : Voyager (Wang et al., 2023) met en place une bibliothèque de compétences persistante composée de programmes JavaScript vérifiés, que l’agent Minecraft accumule au fil du temps ; cela lui permet de collecter 3,3 fois plus d’éléments uniques et d’atteindre les étapes clés 15,3 fois plus rapidement que les versions de référence. Les compétences peuvent être transférées vers de nouveaux mondes sans nécessiter de réentraînement. JARVIS-1 Il s’agit d’étendre ce modèle en y intégrant une mémoire multimodale capable de fusionner des plans textuels et des observations visuelles, ce qui permet d’atteindre un taux de réussite de 5 fois supérieur sur les tâches les plus difficiles.
Une distinction importante à souligner ici : les bibliothèques de compétences représentent une mémoire exécutable (des fichiers de code importés et exécutés), tandis que la mémoire documentaire dans les assistants de codage est de nature déclarative (du Markdown injecté dans prompts). Les modes de défaillance diffèrent : un mauvais code exécutable fait planter l’agent, alors qu’un mauvais texte déclaratif entraîne des erreurs de raisonnement. Cependant, le modèle de stockage ainsi que les avantages opérationnels (facilité de débogage, contrôle de version) restent identiques.
-
Automatisation des workflows d’entreprise : La Compétition ECR3 Les équipes gagnantes ont utilisé la mémoire de document pour effectuer une mise au point itérative prompt. Les agents Analyzer et Versioner d’une équipe lauréate ont parcouru 80 prompt versions stockées sous forme de documents procéduraux. Une autre équipe de premier plan a développé plus de 20 modules d’enrichissement en tant que connaissances procédurales au format document. LEGOMem (2025) formalise cela sous la forme d’une mémoire modulaire framework destinée aux systèmes multi-agent, comprenant des types de mémoire spécialisés (sensorielle, à court terme, à long terme) que les agents peuvent assembler comme des blocs de construction.
-
Automatisation web : Mémoire de flux de travail d’agent (Wang et al., 2024) montre que les agents web peuvent générer des flux de travail réutilisables à partir d’épisodes réussis, ce qui permet d’améliorer le taux de succès de 51 % sur WebArena. SkillWeaver (2025) va encore plus loin : les agents synthétisent des outils API réutilisables à partir de leurs explorations, ce qui permet d’obtenir une amélioration de leur taux de succès de 31,8 %. Les compétences acquises se transmettent également aux modèles moins performants (amélioration de 54,3 %), de sorte que la mémoire accumulée par un agent plus puissant peut bénéficier à un agent de moindre capacité.
-
Support client : Gartner prévoit Ces agents AI résoudront de manière autonome 80 % des problèmes courants de service client d’ici 2029. Pour ce faire, ils s’appuient sur des procédures opérationnelles standard, des guides de gestion et les historiques des clients, qui constituent toutes des formes de mémoire documentaire.
Le Atelier MemAgents au ICLR 2026 C’est un signe que la communauté de recherche rattrape ce que les praticiens ont déjà mis en place. La mémoire documentaire a clairement dépassé ses origines en tant qu’outil d’assistance à la programmation.
Les compétences utilisent des documents pour emballer des instructions procédurales. Norme des compétences d’agent stocke ces instructions dans SKILL.md Des fichiers contenant du frontmatter en YAML ainsi qu’un corps en Markdown. Cela ressemble à une mémoire de document au niveau du stockage, mais la fonction est différente : une compétence indique à l’agent comment effectuer un type de tâche, tandis que la mémoire enregistre les faits appris lors d’un projet ou d’une exécution précédente. Partie 3 Il prend en compte cette distinction du point de vue de l’outil.
MCP (Protocole de contexte du modèle) se dirige dans la même logique : les définitions d’outils sont des fichiers JSON Schema que tout agent peut découvrir et appeler. Le protocole dispose de 97 millions de téléchargements mensuels SDK Il est également pris en charge par OpenAI, Google, Microsoft et AWS. MCP n’est pas spécifique au codage. Ces mêmes serveurs permettent aux agents de se connecter aux bases de données, aux APIs internes ainsi qu’aux systèmes d’entreprise.
Tous deux indiquent le même schéma : des connaissances procédurales stockées sous forme de documents contrôlés par des schémas, comprenant des opérations de lecture/écriture explicites. MCP, désormais régies par le Agentic AI Fondation, c’est ce qui se rapproche le plus d’une norme d’interopérabilité dans l’écosystème des agents.
Échelle de la mémoire des documents en environnement de production
L’implémentation basée sur des fichiers présentée ci-dessus fonctionne bien pour les ordinateurs portables utilisés par un seul développeur ainsi que pour des déploiements à petite échelle. Une environnement de production multi-locataires accueillant des centaines d’utilisateurs et des milliers de documents exige une architecture complètement différente.
La limite de taille des fichiers en mode un seul nœud devient évidente : il est impossible d’effectuer une scalabilité horizontale des opérations I/O sur les fichiers, les écritures simultanées nécessitent un verrouillage, et la gestion des permissions entre différents locataires s’avère complexe. En environnement de production, il est indispensable d’utiliser un stockage de secours capable de gérer correctement la concurrence, les recherches et le modèle multi-locataires.
Trois approches courantes :
Approche A : hybride avec une couche de base de données légère
Conservez les fichiers destinés à l’élaboration (les développeurs modifient le Markdown localement), mais servez-les depuis une base de données à runtime. Lors du déploiement, synchronisez les fichiers avec les enregistrements de PostgreSQL. L’agent lit alors dans la base de données et non sur le disque. Cela vous offre :
- Ergonomie du développeur (éditer du Markdown, faire des commits dans Git)
- Performance des requêtes en production (lectures dans une base de données indexée)
- Séparation stricte entre l’élaboration et serving
Approche B : stockage d’objets + sidecar d’index vectoriel
Les documents sont stockés dans S3/GCS sous forme d’objets, et une collection Qdrant est utilisée pour indexer leurs embeddings. L’agent interroge Qdrant afin d’obtenir les identifiants des documents pertinents, puis récupère leur contenu depuis le stockage d’objets. Cette architecture permet une scalabilité horizontale et prend en charge la recherche sémantique, mais elle ajoute de la complexité : il faut gérer deux systèmes, assurer une embedding pipeline entre eux, et faire face à une cohérence éventuelle entre le stockage et l’index.
Approche C : stockage structuré de documents avec PostgreSQL (recommandée)
Stockez les documents sous forme de lignes JSONB dans PostgreSQL, en bénéficiant d’une recherche plein texte grâce à l’index GIN ainsi que, facultativement, de la recherche vectorielle embeddings (pgvector). Cela vous permet d’obtenir une recherche hybride (mots-clés + sémantique), des transactions ACID, et un seul système opérationnel.
Esquisse de l’Approche C :
from typing import Optional
import asyncpg
class ProductionDocumentMemory:
"""PostgreSQL-backed document memory with hybrid search.
Schema:
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
tenant_id TEXT NOT NULL,
path TEXT NOT NULL,
content TEXT NOT NULL,
metadata JSONB,
embedding vector(1536), -- pgvector extension
ts_vector tsvector GENERATED ALWAYS AS (to_tsvector('english', content)) STORED,
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(tenant_id, path)
);
CREATE INDEX ON documents USING GIN(ts_vector);
CREATE INDEX ON documents USING ivfflat(embedding vector_cosine_ops);
"""
def __init__(self, pool: asyncpg.Pool):
self.pool = pool
async def write(
self,
tenant_id: str,
path: str,
content: str,
metadata: Optional[dict] = None,
embedding: Optional[list[float]] = None,
):
"""Write or update a document."""
async with self.pool.acquire() as conn:
await conn.execute(
"""
INSERT INTO documents (tenant_id, path, content, metadata, embedding)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (tenant_id, path) DO UPDATE
SET content = EXCLUDED.content,
metadata = EXCLUDED.metadata,
embedding = EXCLUDED.embedding
""",
tenant_id, path, content, metadata, embedding,
)
async def search(
self,
tenant_id: str,
query: str,
embedding: Optional[list[float]] = None,
limit: int = 5,
) -> list[dict]:
"""Hybrid search: full-text + optional vector similarity."""
async with self.pool.acquire() as conn:
if embedding:
# Hybrid scoring: 0.6 * text relevance + 0.4 * vector similarity
rows = await conn.fetch(
"""
SELECT path, content, metadata,
(0.6 * ts_rank(ts_vector, plainto_tsquery('english', $2)) +
0.4 * (1 - (embedding <=> $3))) AS score
FROM documents
WHERE tenant_id = $1
AND ts_vector @@ plainto_tsquery('english', $2)
ORDER BY score DESC
LIMIT $4
""",
tenant_id, query, embedding, limit,
)
else:
# Full-text search only
rows = await conn.fetch(
"""
SELECT path, content, metadata,
ts_rank(ts_vector, plainto_tsquery('english', $2)) AS score
FROM documents
WHERE tenant_id = $1
AND ts_vector @@ plainto_tsquery('english', $2)
ORDER BY score DESC
LIMIT $3
""",
tenant_id, query, limit,
)
return [dict(row) for row in rows]
Ce que vous obtenez :
- Recherche hybride : correspondance de mots-clés (index GIN) + similarité sémantique (pgvector), les deux scores étant additionnés
- Multitenancy :
tenant_idDéfinition du périmètre avec la sécurité au niveau des lignes - Garanties ACID : pas de problèmes de cohérence éventuelle
- Un seul système d’exploitation : pas de base de données vectorielle distincte à gérer
- Échelle horizontale : répliques de lecture pour gérer la charge des requêtes, partitionnement par client pour l’échelle des écritures
Les fichiers s’avèrent très utiles pour les workflows impliquant un seul développeur. Dans un environnement de production multi-locataires, un stockage de documents structuré basé sur PostgreSQL offre généralement le bon équilibre entre simplicité, performances et maturité opérationnelle.
Assemblage : l’architecture complète
C’est ainsi que les trois niveaux de mémoire collaborent entre eux dans le Agent d’analyse de marché. Le diagramme illustre le flux complet, de la demande utilisateur à la réponse, en montrant que tous les niveaux de mémoire sont activés.
L’architecture dispose de trois chemins mémoire :
-
Chemin critique (checkpoint store) : Chaque nœud de LangGraph écrit son état de graphe résumable dans le checkpoint store. Lorsque le graphe rencontre un
interrupt_beforenode (comme le rapporteur dans Partie 1), Des pauses d’exécution surviennent. L’utilisateur peut fermer l’application, et lorsqu’il la réouvre, le graphe reprend son exécution à partir du checkpoint. Les journaux d’événements et les traces générées par les Runtime relèvent de considérations distinctes en environnement de production. -
Chemin froid (stockage à long terme) : Au début de chaque conversation, l’agent interroge le stockage à long terme afin d’obtenir le contexte pertinent de l’utilisateur. À la fin, il extrait et enregistre de nouvelles informations. Ce processus s’exécute de manière asynchrone — il ne doit en aucun cas bloquer le reasoning loop principal.
-
Chemin du document (stockage de fichiers) : Lors du démarrage, l’agent charge les conventions de projet ainsi que les notes de recherche pertinentes depuis le stockage de fichiers. Pendant l’exécution, il enregistre sur disque de nouveaux résumés de recherche et les motifs appris. Contrairement à la voie « froide », les lectures de documents sont synchrones (elles influencent la tâche en cours), tandis que les écritures peuvent être différées.
La configuration des connexions dans LangGraph est assez simple : le checkpoint store ainsi que le long-term store sont transmis lors de la compilation du graphe, tandis que le document store est injecté en tant que dépendance. Le schéma local ci-dessous utilise InMemoryStore Ainsi, le fragment reste compact ; la topologie Docker de référence utilise Qdrant pour assumer la même fonction de rappel sémantique.
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
from langgraph.store.memory import InMemoryStore
# Hot memory: PostgreSQL for durable checkpoints
checkpointer = await create_postgres_checkpointer(pg_connection_string)
# Cold memory: local sketch with vector search
# (The reference Docker topology uses Qdrant for persistent recall.)
memory_store = InMemoryStore(
index={"dims": 1536, "embed": embedding_function}
)
# Document memory: file-based store for project knowledge
doc_memory = FileMemory(base_dir=".agent-memory")
# Checkpoint store and long-term store wired into the graph
graph = create_graph(
checkpointer=checkpointer,
store=memory_store,
)
# The store is accessible inside any node via the store parameter
def planner_node(state: AgentState, *, store: BaseStore) -> dict:
"""Plan with user context from long-term memory."""
# Recall relevant user facts from vector store
user_memories = store.search(
namespace=("user", state.user_id),
query=state.messages[-1].content,
limit=5,
)
# Load project conventions from document memory
conventions = doc_memory.read_doc("conventions/analysis-format.md")
# Inject both into planning context
memory_context = "\n".join(m.value["fact"] for m in user_memories)
# ... rest of planning logic with personalized context and conventions
Le flux complet
Que se passe-t-il lorsque un utilisateur revenant envoie « Analyser TSLA » à la Agent d’analyse de marché:
-
Charge mémoire des documents : Lors du démarrage, l’agent lit les conventions de projet stockées dans le système de gestion de documents : préférences de format d’analyse, sources de données privilégiées, schémas d’utilisation des outils. Ceux-ci définissent le comportement de base.
-
Rappel en mémoire froide : Avant que le nœud routeur ne s’exécute, le graphe interroge le stockage à long terme afin d’y récupérer le message de l’utilisateur. Il extrait alors les informations suivantes : « L’utilisateur présente une forte tolérance au risque », « L’utilisateur préfère des analyses détaillées des concurrents », « L’utilisateur a déjà étudié NVDA et AMD ».
-
Routeur + Planificateur : la classe de routeur classe cet élément comme
DEEP_RESEARCHLe planificateur génère un plan de recherche en 5 étapes, personnalisé en fonction des préférences identifiées. Il comprend une étape d’analyse concurrentielle, car l’historique de l’utilisateur indique qu’il en a besoin. Ce plan respecte le format défini dans le document des conventions. -
Boucle d’exécution (mémoire chaude) : Chaque étape s’exécute selon le schéma ReAct Partie 1. Après chaque nœud (routeur, planificateur, chaque étape d’exécution), LangGraph écrit un checkpoint dans PostgreSQL. Si le processus plante après l’étape 3 sur 5, il faut le redémarrer pour reprendre à partir de l’étape 4.
-
Interruption HITL : le graphe atteint
reporternœud doté deinterrupt_before. Le projet de rapport se trouve dans le checkpoint. L’utilisateur le consulte quelques heures plus tard, et le graphe charge le checkpoint avant de poursuivre son exécution. -
Mises à jour de la mémoire : Une fois la conversation terminée : (a) un processus asynchrone extrait de nouvelles informations sur l’utilisateur (« l’utilisateur suit désormais TSLA », « l’utilisateur a approuvé le format du rapport ») et les stocke dans le stockage vectoriel à long terme, et (b) l’agent écrit un résumé des recherches dans le stockage de documents.
research/TSLA-2026-02.md) à titre de référence future.
Le modèle à trois niveaux permet de séparer clairement les préoccupations fonctionnelles. Le stock checkpoint gère la durabilité et la reprise des opérations ; il s’agit d’infrastructures. Le stock à long terme est chargé de la personnalisation ; il correspond à la logique de produit. Enfin, le stock de documents conserve les connaissances accumulées sur le projet ; il constitue en quelque sorte le carnet de notes de l’agent.
Compromis et considérations
La mémoire ajoute de la valeur, mais elle entraîne également des coûts et une complexité accrues. Soyez honnête quant aux compromis à envisager :
-
Coût Embedding : Chaque fait stocké dans une base de données vectorielle nécessite une requête embedding API. Le tarif est de 0,02 dollar par million de tokens (OpenAI)
text-embedding-3-small), le coût par opération est négligeable, mais il s’accumule au fil des milliers d’utilisateurs et de sessions. Il convient de regrouper les appels embedding en lots et de mettre en cache les résultats. Le véritable coût réside dans la latence : une latence embedding API de 100 à 300 ms lors de la récupération depuis la mémoire froide, ce qui est bien plus important que le coût monétaire pour les agents conversationnels en temps réel. Mettez en cache embeddings pour les requêtes fréquentes, ou utilisez un modèle embedding local pour les charges de travail sensibles à la latence. -
Mémoire obsolète : Les préférences de l’utilisateur évoluent. Un fait enregistré il y a six mois (« l’utilisateur privilégie des investissements conservateurs ») peut ne plus être exact. Il convient donc d’implémenter des politiques de durée de validité. J’applique une période de 365 jours pour les préférences et de 90 jours pour les événements ponctuels, comme décrit dans mon context engineering publication.
-
Surcoût mémoire dans le contexte : Chaque fait rappelé consomme des tokens dans la fenêtre de contexte du LLM. Si vous rappelez 20 faits par requête, cela représente plusieurs centaines de tokens de contexte mémoire qui concurrencent la tâche elle-même. Limitez le nombre de faits rappelés et priorisez-les en fonction de leur score de pertinence.
-
Confidentialité et conformité : La mémoire à long terme stocke les données des utilisateurs. Il est impératif d’effectuer une suppression des informations personnelles identifiables avant le stockage, de définir des politiques de conservation claires, ainsi que de mettre en place des outils accessibles aux utilisateurs pour supprimer leurs données. Aucun de ces éléments n’est optionnel dans les secteurs soumis à réglementation.
-
Checkpoint croissance de la capacité de stockage : Les tables PostgreSQL checkpoint s’agrandissent à chaque exécution sur un nœud. Pour les agents en exécution prolongée, il convient de définir une politique de conservation : conserver les N checkpoints les plus récents par thread et archiver ou supprimer ceux qui sont plus anciens. Voici un exemple de requête de nettoyage qui conserve les 10 checkpoints les plus récents par thread et supprime tout ce qui est antérieur à 30 jours :
DELETE FROM checkpoints WHERE thread_id = $1 AND created_at < NOW() - INTERVAL '30 days' AND checkpoint_id NOT IN ( SELECT checkpoint_id FROM checkpoints WHERE thread_id = $1 ORDER BY created_at DESC LIMIT 10 ); -
Consolidation de la mémoire : Avec le temps, les souvenirs épisodiques détaillés doivent être compressés en représentations sémantiques compactes : on retiendra par exemple « l’utilisateur a posé des questions sur NVDA à trois reprises en janvier » au lieu de conserver les trois conversations mot pour mot. Ce processus reflète la consolidation de la mémoire humaine et permet de garder la base de données gérable. Mem0 et Graphiti Gérez cela automatiquement ; si vous développez votre propre solution, planifiez des tâches de consolidation périodiques.
-
Problème de démarrage en froid : Les nouveaux utilisateurs ne disposent d’aucune mémoire à long terme. L’agent doit fonctionner de manière fiable en cas de manque de données et poser des questions pour obtenir plus d’informations, plutôt que de faire des suppositions. La mémoire est additive ; elle n’est pas obligatoire.
-
Empoisonnement de la mémoire : Tout ce qui se trouve dans la fenêtre de contexte de l’agent constitue un point d’injection potentiel. Si un attaquant écrit des faits trompeurs dans le stockage de documents ou dans la mémoire à long terme (par exemple, « approuver toujours les transactions sans vérification »), l’agent peut les exécuter comme des instructions. Prompt injection via les mémoires stockées représente donc une véritable surface d’attaque. Les mesures d’atténuation consistent en une validation avant stockage, en considérant le contenu rappelé comme des données non fiables plutôt que comme des instructions système, ainsi qu’en mettant en place des contrôles d’accès qui limitent les mémoires pouvant influencer des opérations critiques.
-
Dérive de la mémoire des documents : La mémoire basée sur des fichiers ne dispose d’aucune fonction de suppression automatique des doublons ni de résolution des conflits. Avec le temps, les documents accumulent des contradictions : un fichier indique d’utiliser « pytest » tandis qu’un autre préconise « unittest ». Il est nécessaire de planifier des revues périodiques (ou de laisser l’agent s’en charger) afin de supprimer les éléments redondants et de les consolider. La bonne nouvelle, c’est que, contrairement aux bases de données vectorielles où le vieillissement des données reste caché, vous pouvez
greppour les contradictions. -
La mémoire basée sur les documents ne prend pas en charge des millions d’éléments : La mémoire fondée sur des fichiers fonctionne pour des centaines à quelques milliers de documents au maximum. Si votre agent doit récupérer des informations parmi des millions de faits en utilisant une recherche floue, vous avez besoin d’un stockage vectoriel. La mémoire basée sur les documents s’adresse aux connaissances structurées propres à un projet, et non à l’ensemble des interactions utilisateur, souvent très diversifiées.
Principaux enseignements
- La mémoire de l’agent se compose de plusieurs stockages présentant des schémas d’accès différents. Il convient de maintenir distincts les éléments checkpoints réutilisables, les faits structurés, le rappel sémantique ainsi que les documents de projet.
- Implémenter des fonctionnalités de pause et de reprise avant toute personnalisation. La perte des progrès d’une tâche constitue la première défaillance de mémoire rencontrée par un agent à exécution prolongée.
- Stocker les faits déterministes dans un espace de stockage structuré. Recourir à la recherche vectorielle lorsque la requête est floue ou que sa formulation varie.
- Utiliser des fichiers pour conserver les connaissances liées aux projets, qui doivent pouvoir être consultées, modifiées, versionnées ou comparées via des diff.
- Définir pour chaque type de mémoire des règles relatives à l’expiration, aux conflits et à la suppression. Une mémoire que le système ne peut pas corriger devient une dette technique.
- Limiter ce qui est renvoyé au modèle. La mémoire stockée n’a de valeur que si sa récupération permet d’intégrer les preuves appropriées dans le contexte actuel.
La couche suivante concerne les actions à entreprendre
Partie 3, AI Agent Tool Use en 2026, Il passe de l’état stocké à une action. Il examine la manière dont un agent découvre et invoque des outils, ainsi que le mécanisme par lequel les limites de ces outils renvoient des erreurs que le reasoning loop peut exploiter. Les parties 5 et 6 traitent du retour vers la mémoire depuis le point de vue opérationnel : le runtime restaure un checkpoint, tandis que le harness détermine ce qui doit être transmis lors du passage à la session de modèle suivante.
Références
Articles de recherche
- Architectures cognitives pour les agents linguistiques (CoALA) — Sumers, Yao et al., 2023 — Taxonomie de base des types de mémoire d’agent La mémoire à l’ère des agents AI : une étude de synthèse — Déc. 2025 — Taxonomie tridimensionnelle complète de la mémoire des agents
- MemGPT : Vers LLMs en tant que systèmes d’exploitation — Packer et al., 2023 — Gestion du contexte virtuel pour les agents LLM Agents génératifs : simulacres interactifs du comportement humain — Park et al., 2023 — Architecture de flux mémoire intégrant une évaluation de la fraîcheur, de l’importance et de la pertinence Zep : une architecture de graphe de connaissances temporelles pour la mémoire des agents — Rasmussen, 2025 — Graph de connaissances bitemporal pour la mémoire des agents
- Mem0 : Conception d’agents AI prêts pour le déploiement en production dotés d’une mémoire à long terme scalable — 2025 — Extraction/consolidation pipeline à l’aide de benchmarks
- Voyager : un agent incarné à finalité ouverte intégrant des grands modèles de langage — Wang et al., 2023 — Bibliothèque de compétences en tant que mémoire documentaire pour les agents de jeux du monde ouvert
- JARVIS-1 : Agents multi-tâches dans un monde ouvert utilisant des modèles de langage multimodaux augmentés en mémoire — 2023 — Bibliothèque de mémoire multimodale pour les agents Minecraft Mémoire de flux de travail d’agent — Wang et al., 2024 — Induction de workflows réutilisables pour les agents d’automatisation web SkillWeaver : les agents web peuvent concevoir eux-mêmes leurs bibliothèques de compétences — 2025 — Outils réutilisables API auto-synthétisés pour les agents web
- LEGOMem : Mémoire modulaire Framework pour les systèmes d’agents LLM — 2025 — Modules mémoire composables pour les systèmes multi-agent
Documentation de LangGraph
- Persistance de LangGraph (enregistrement de points d’état) — Concepts fondamentaux de la mémoire basée sur checkpoint Stockage de mémoire LangGraph — Croiser la mémoire à long terme entre threads avec l’interface Store
- Persistance inter-thread de LangGraph — Fonctionnalité API pour la mémoire inter-thread Comment ajouter de la mémoire à l’agent préconstruit ReAct — Guide pratique pour l’ajout de mémoire
Checkpoint des backends
langgraph-checkpoint-postgres— Sauvegardeur PostgreSQL checkpoint pour LangGraphlanggraph-checkpoint-redis— Sauvegardeur Redis checkpoint pour LangGraph LangGraph Redis Checkpoint 0.1.0 – Rediseign — Détails d’architecture du sauvegardeur Redis checkpointlanggraph-checkpoint-aws— Sauvegarde DynamoDB checkpoint grâce au transfert vers S3
Bases de données vectorielles et outils de mémoire
- Qdrant — Base de données vectorielle open source dotée d’un système d’indexation et de filtrage HNSW Guide des constructeurs Qdrant Agentic — Guide pratique pour la construction de la mémoire des agents avec Qdrant
- pgvector — Extension de recherche par similarité vectorielle pour PostgreSQL Graphiti — Moteur de graphe de connaissances temporelles open source développé par Zep
Mémoire basée sur les documents et les fichiers
- La mémoire de Claude Code — Système de mémoire basé sur des fichiers CLAUDE.md et MEMORY.md Outil de mémoire anthropique — Mémoire basée sur des fichiers côté client pour les agents Claude API
- Règles du curseur — Fichiers .cursorrules au niveau du projet pour le contexte de l’agent Souvenirs de windsurf — Mémoire basée sur des fichiers et .windsurfrules pour les agents de codage
Mémoire frameworks
- Mem0 — Couche de gestion de la mémoire avec extraction et consolidation pipeline
- Letta (MemGPT) — Gestion de contexte virtuel inspirée des systèmes d’exploitation pour les agents
- LangMem SDK — Outils de gestion de la mémoire pour LangGraph
Benchmarks
- Performance de PostgreSQL contre Redis — Latence et débit de CyberTec benchmarks
- Comparaison PostgreSQL vs Redis — Comparaison des architectures RisingWave
- Redis AI pour l’ingénierie d’agents — Modèles Redis pour les charges de travail d’agents
Ateliers
- MemAgents : mémoire pour les systèmes Agentic basés sur LLM — Atelier ICLR 2026
Projet de démonstration
- Agent d’analyse de marché — Implémentation complète incluant les trois niveaux de mémoire
Le code complet de l’Agent Analyste de marché, y compris l’architecture mémoire décrite dans cette publication, se trouve sur GitHub si vous souhaitez suivre le texte en même temps._
Série : Conception de la pile Agentic
- Partie 1 : AI Boucles de raisonnement d’agent en 2026 — ReAct, ReWOO, et Plan-and-Execute
- Partie 2 : L’architecture de mémoire des agents AI en 2026 (cet article) Partie 3 : AI Agent Tool Use en 2026 — MCP, CLI, compétences, exécution de code et ACI Partie 4 : AI La sécurité des agents en 2026 — garde-fous, permissions, sandboxes, HITL, ainsi que le cadrage MCP
- Partie 5 : Agents AI à exécution prolongée Runtime en 2026 — sessions, sandboxes, checkpoints, mécanismes d’orchestration et schémas de déploiement
- Partie 6 : Harness Engineering pour les agents AI (à paraître prochainement) — vérifications d’acceptation, traces, tentatives de réessai, transferts de responsabilités, ainsi que le cycle associé au modèle