deep-agents-memory

Par langchain-ai · langchain-skills

Invoquez cette skill lorsque votre Deep Agent a besoin de mémoire, de persistance ou d'accès au système de fichiers. Couvre StateBackend (éphémère), StoreBackend (persistant), FilesystemMiddleware, et CompositeBackend pour le routage.

npx skills add https://github.com/langchain-ai/langchain-skills --skill deep-agents-memory

<overview> Les Deep Agents utilisent des backends modulaires pour les opérations sur fichiers et la mémoire :

Court terme (StateBackend) : Persiste au sein d'un thread unique, perdu à la fin du thread Long terme (StoreBackend) : Persiste entre les threads et les sessions Hybride (CompositeBackend) : Route différents chemins vers différents backends

FilesystemMiddleware fournit les outils : ls, read_file, write_file, edit_file, glob, grep </overview>

Cas d'usage Backend Raison
Fichiers de travail temporaires StateBackend Par défaut, aucune configuration
CLI de développement local FilesystemBackend Accès direct au disque
Mémoire entre sessions StoreBackend Persiste entre les threads
Stockage hybride CompositeBackend Mélange éphémère + persistant

StateBackend par défaut stocke les fichiers de manière éphémère au sein d'un thread.

from deepagents import create_deep_agent

agent = create_deep_agent()  # Par défaut : StateBackend
result = agent.invoke({
    "messages": [{"role": "user", "content": "Write notes to /draft.txt"}]
}, config={"configurable": {"thread_id": "thread-1"}})
# /draft.txt est perdu quand le thread se termine

StateBackend par défaut stocke les fichiers de manière éphémère au sein d'un thread.

import { createDeepAgent } from "deepagents";

const agent = await createDeepAgent();  // Par défaut : StateBackend
const result = await agent.invoke({
  messages: [{ role: "user", content: "Write notes to /draft.txt" }]
}, { configurable: { thread_id: "thread-1" } });
// /draft.txt est perdu quand le thread se termine

Configurez CompositeBackend pour router les chemins vers différents backends de stockage.

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

store = InMemoryStore()

composite_backend = lambda rt: CompositeBackend(
    default=StateBackend(rt),
    routes={"/memories/": StoreBackend(rt)}
)

agent = create_deep_agent(backend=composite_backend, store=store)

# /draft.txt -> éphémère (StateBackend)
# /memories/user-prefs.txt -> persistant (StoreBackend)

Configurez CompositeBackend pour router les chemins vers différents backends de stockage.

import { createDeepAgent, CompositeBackend, StateBackend, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore();

const agent = await createDeepAgent({
  backend: (config) => new CompositeBackend(
    new StateBackend(config),
    { "/memories/": new StoreBackend(config) }
  ),
  store
});

// /draft.txt -> éphémère (StateBackend)
// /memories/user-prefs.txt -> persistant (StoreBackend)

Les fichiers dans /memories/ persistent entre les threads via le routage StoreBackend.

# Utilisation de CompositeBackend de l'exemple précédent
config1 = {"configurable": {"thread_id": "thread-1"}}
agent.invoke({"messages": [{"role": "user", "content": "Save to /memories/style.txt"}]}, config=config1)

config2 = {"configurable": {"thread_id": "thread-2"}}
agent.invoke({"messages": [{"role": "user", "content": "Read /memories/style.txt"}]}, config=config2)
# Le thread 2 peut lire le fichier sauvegardé par le thread 1

Les fichiers dans /memories/ persistent entre les threads via le routage StoreBackend.

// Utilisation de CompositeBackend de l'exemple précédent
const config1 = { configurable: { thread_id: "thread-1" } };
await agent.invoke({ messages: [{ role: "user", content: "Save to /memories/style.txt" }] }, config1);

const config2 = { configurable: { thread_id: "thread-2" } };
await agent.invoke({ messages: [{ role: "user", content: "Read /memories/style.txt" }] }, config2);
// Le thread 2 peut lire le fichier sauvegardé par le thread 1

Utilisez FilesystemBackend pour le développement local avec accès direct au disque et boucle humain-agent.

from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
from langgraph.checkpoint.memory import MemorySaver

agent = create_deep_agent(
    backend=FilesystemBackend(root_dir=".", virtual_mode=True),  # Restreindre l'accès
    interrupt_on={"write_file": True, "edit_file": True},
    checkpointer=MemorySaver()
)

# L'agent peut lire/écrire des fichiers réels sur le disque

Utilisez FilesystemBackend pour le développement local avec accès direct au disque et boucle humain-agent.

import { createDeepAgent, FilesystemBackend } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";

const agent = await createDeepAgent({
  backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
  interruptOn: { write_file: true, edit_file: true },
  checkpointer: new MemorySaver()
});

Sécurité : N'utilisez jamais FilesystemBackend sur des serveurs web - utilisez StateBackend ou un sandbox à la place.

Accédez directement au store dans les outils personnalisés pour les opérations de mémoire long terme.

from langchain.tools import tool, ToolRuntime
from langchain.agents import create_agent
from langgraph.store.memory import InMemoryStore

@tool
def get_user_preference(key: str, runtime: ToolRuntime) -> str:
    """Récupère une préférence utilisateur du stockage long terme."""
    store = runtime.store
    result = store.get(("user_prefs",), key)
    return str(result.value) if result else "Not found"

@tool
def save_user_preference(key: str, value: str, runtime: ToolRuntime) -> str:
    """Sauvegarde une préférence utilisateur dans le stockage long terme."""
    store = runtime.store
    store.put(("user_prefs",), key, {"value": value})
    return f"Saved {key}={value}"

store = InMemoryStore()

agent = create_agent(
    model="gpt-4.1",
    tools=[get_user_preference, save_user_preference],
    store=store
)

Ce que les agents PEUVENT configurer

  • Type et configuration du backend
  • Règles de routage pour CompositeBackend
  • Répertoire racine pour FilesystemBackend
  • Boucle humain-agent pour les opérations sur fichiers

Ce que les agents NE PEUVENT PAS configurer

  • Noms des outils (ls, read_file, write_file, edit_file, glob, grep)
  • Accéder à des fichiers en dehors des restrictions virtual_mode
  • Accès aux fichiers entre threads sans configuration backend appropriée

StoreBackend nécessite une instance store.

# INCORRECT
agent = create_deep_agent(backend=lambda rt: StoreBackend(rt))

# CORRECT
agent = create_deep_agent(backend=lambda rt: StoreBackend(rt), store=InMemoryStore())

StoreBackend nécessite une instance store.

// INCORRECT
const agent = await createDeepAgent({ backend: (c) => new StoreBackend(c) });

// CORRECT
const agent = await createDeepAgent({ backend: (c) => new StoreBackend(c), store: new InMemoryStore() });

Les fichiers StateBackend sont limités au thread - utilisez le même thread_id ou StoreBackend pour l'accès entre threads.

# INCORRECT : thread-2 ne peut pas lire le fichier de thread-1
agent.invoke({"messages": [...]}, config={"configurable": {"thread_id": "thread-1"}})  # Écriture
agent.invoke({"messages": [...]}, config={"configurable": {"thread_id": "thread-2"}})  # Fichier non trouvé !

Les fichiers StateBackend sont limités au thread - utilisez le même thread_id ou StoreBackend pour l'accès entre threads.

// INCORRECT : thread-2 ne peut pas lire le fichier de thread-1
await agent.invoke({ messages: [...] }, { configurable: { thread_id: "thread-1" } });  // Écriture
await agent.invoke({ messages: [...] }, { configurable: { thread_id: "thread-2" } });  // Fichier non trouvé !

Le chemin doit correspondre au préfixe de route de CompositeBackend pour la persistance.

# Avec routes={"/memories/": StoreBackend(rt)} :
agent.invoke(...)  # /prefs.txt -> éphémère (pas de correspondance)
agent.invoke(...)  # /memories/prefs.txt -> persistant (correspondance de route)

Le chemin doit correspondre au préfixe de route de CompositeBackend pour la persistance.

// Avec routes: { "/memories/": StoreBackend } :
await agent.invoke(...);  // /prefs.txt -> éphémère (pas de correspondance)
await agent.invoke(...);  // /memories/prefs.txt -> persistant (correspondance de route)

Utilisez PostgresStore pour la production (InMemoryStore perdu au redémarrage).

# INCORRECT                       # CORRECT
store = InMemoryStore()           store = PostgresStore(connection_string="postgresql://...")

Utilisez PostgresStore pour la production (InMemoryStore perdu au redémarrage).

// INCORRECT                              // CORRECT
const store = new InMemoryStore();        const store = new PostgresStore({ connectionString: "..." });

Activez virtual_mode=True pour restreindre l'accès au chemin (empêche les échappements ../ et ~/).

backend = FilesystemBackend(root_dir="/project", virtual_mode=True)  # Sécurisé

CompositeBackend fait correspondre le préfixe le plus long en premier.

routes = {"/mem/": StoreBackend(rt), "/mem/temp/": StateBackend(rt)}
# /mem/file.txt -> StoreBackend, /mem/temp/file.txt -> StateBackend (correspondance plus longue)

Skills similaires