Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/langchain-ai/langgraph/llms.txt

Use this file to discover all available pages before exploring further.

Memory in LangGraph enables agents to remember information across interactions, creating more contextual and personalized experiences.

Types of Memory

LangGraph supports two types of memory:
  • Short-term memory: Conversation state within a single thread (via checkpointers)
  • Long-term memory: Persistent storage across threads and sessions (via stores)

Short-Term Memory

Short-term memory is automatically handled through checkpointers and message state.

Message History

Use MessagesState or add_messages for conversation history:
from typing import Annotated
from collections.abc import Sequence
from langchain_core.messages import BaseMessage
from langgraph.graph import StateGraph, add_messages
from typing_extensions import TypedDict

class ChatState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], add_messages]

graph = StateGraph(ChatState)
The add_messages reducer maintains conversation history:
from langgraph.checkpoint.memory import InMemorySaver

memory = InMemorySaver()
app = graph.compile(checkpointer=memory)

# First message
config = {"configurable": {"thread_id": "user-123"}}
app.invoke(
    {"messages": [{"role": "user", "content": "My name is Alice"}]},
    config,
)

# Later message - agent remembers Alice
app.invoke(
    {"messages": [{"role": "user", "content": "What's my name?"}]},
    config,
)

Trimming History

Manage message history length:
from langchain_core.messages import trim_messages

def trim_history(state: ChatState) -> dict:
    """Keep only the last 10 messages."""
    messages = state["messages"]
    trimmed = trim_messages(
        messages,
        max_tokens=4000,
        strategy="last",
        token_counter=len,  # Use actual token counter
    )
    return {"messages": trimmed}

# Add as a node
graph.add_node("trim", trim_history)

Semantic Trimming

Keep important messages:
from langchain_core.messages import filter_messages

def keep_important(state: ChatState) -> dict:
    """Keep system messages and recent user messages."""
    messages = filter_messages(
        state["messages"],
        include_types=["system", "user"],
        max_count=20,
    )
    return {"messages": messages}

Long-Term Memory

Long-term memory persists information across conversations using stores.

Store Interface

Stores provide key-value storage with namespaces:
from langgraph.store.memory import InMemoryStore

# Create store
store = InMemoryStore()

# Compile with store
app = graph.compile(checkpointer=memory, store=store)

Storing User Preferences

from langgraph.store.base import BaseStore

def save_preference_node(state: State, *, store: BaseStore):
    """Extract and save user preferences."""
    user_id = state["user_id"]
    preference = state["detected_preference"]
    
    # Store in user namespace
    store.put(
        namespace=("users", user_id),
        key="preferences",
        value={"preference": preference},
    )
    
    return {"status": "saved"}

def retrieve_preference_node(state: State, *, store: BaseStore):
    """Load user preferences."""
    user_id = state["user_id"]
    
    # Retrieve from store
    item = store.get(
        namespace=("users", user_id),
        key="preferences",
    )
    
    preference = item.value.get("preference") if item else None
    return {"user_preference": preference}

Memory Store Pattern

Create a dedicated memory system:
class MemoryState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], add_messages]
    user_id: str
    memories: list[str]

def extract_memories(state: MemoryState, *, store: BaseStore):
    """Extract and store important information."""
    messages = state["messages"]
    user_id = state["user_id"]
    
    # Use LLM to extract facts
    facts = extract_facts_from_conversation(messages)
    
    # Store each fact
    for fact in facts:
        store.put(
            namespace=("memories", user_id),
            key=str(uuid.uuid4()),
            value={"fact": fact, "timestamp": datetime.now()},
        )
    
    return {}

def recall_memories(state: MemoryState, *, store: BaseStore):
    """Retrieve relevant memories."""
    user_id = state["user_id"]
    current_message = state["messages"][-1].content
    
    # Search memories
    items = store.search(
        namespace=("memories", user_id),
        query=current_message,  # Semantic search if supported
        limit=5,
    )
    
    memories = [item.value["fact"] for item in items]
    return {"memories": memories}

Vector Store Integration

For semantic search over memories:
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings

class VectorMemoryState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], add_messages]
    context: str

# Initialize vector store
embeddings = OpenAIEmbeddings()
vector_store = FAISS.from_texts([], embeddings)

def store_memory(state: VectorMemoryState):
    """Store conversation in vector DB."""
    last_message = state["messages"][-1].content
    
    # Add to vector store with metadata
    vector_store.add_texts(
        [last_message],
        metadatas=[{"timestamp": datetime.now().isoformat()}],
    )
    
    return {}

def retrieve_context(state: VectorMemoryState):
    """Retrieve relevant context."""
    query = state["messages"][-1].content
    
    # Semantic search
    docs = vector_store.similarity_search(query, k=3)
    context = "\n".join([doc.page_content for doc in docs])
    
    return {"context": context}

Memory Architectures

Summary Memory

Summarize old messages to save context:
def summarize_conversation(state: ChatState):
    """Summarize older messages."""
    messages = state["messages"]
    
    if len(messages) > 20:
        # Summarize messages 0-15
        old_messages = messages[:15]
        summary = llm.invoke(
            f"Summarize this conversation: {old_messages}"
        )
        
        # Keep summary + recent messages
        new_messages = [
            {"role": "system", "content": f"Previous conversation: {summary}"},
            *messages[15:],
        ]
        return {"messages": new_messages}
    
    return {}

Entity Memory

Track entities across conversations:
class EntityMemory(TypedDict):
    entities: dict[str, dict]  # name -> properties

def extract_entities(state: State, *, store: BaseStore):
    """Extract and update entity information."""
    user_id = state["user_id"]
    message = state["messages"][-1].content
    
    # Extract entities with LLM
    entities = extract_entities_from_text(message)
    
    for entity_name, properties in entities.items():
        # Get existing entity
        item = store.get(
            namespace=("entities", user_id),
            key=entity_name,
        )
        
        # Merge properties
        existing = item.value if item else {}
        updated = {**existing, **properties}
        
        # Update store
        store.put(
            namespace=("entities", user_id),
            key=entity_name,
            value=updated,
        )
    
    return {}

Knowledge Graph Memory

Build relationships between entities:
import networkx as nx

class GraphMemory:
    def __init__(self):
        self.graph = nx.DiGraph()
    
    def add_fact(self, subject: str, predicate: str, object: str):
        """Add a fact to the knowledge graph."""
        self.graph.add_edge(subject, object, relation=predicate)
    
    def query(self, entity: str, hops: int = 2):
        """Get related entities within N hops."""
        if entity not in self.graph:
            return []
        
        # Get subgraph within N hops
        nodes = nx.single_source_shortest_path_length(
            self.graph, entity, cutoff=hops
        )
        
        return list(nodes.keys())

# Use in node
def query_knowledge(state: State, *, graph_memory: GraphMemory):
    current_topic = state["current_topic"]
    related = graph_memory.query(current_topic)
    return {"related_topics": related}

Memory Management

Forgetting

Implement memory decay:
import datetime

def clean_old_memories(store: BaseStore, user_id: str, days: int = 30):
    """Remove memories older than N days."""
    cutoff = datetime.datetime.now() - datetime.timedelta(days=days)
    
    # List all memories
    items = store.search(
        namespace=("memories", user_id),
        filter={},
    )
    
    # Delete old ones
    for item in items:
        if item.value.get("timestamp") < cutoff:
            store.delete(
                namespace=("memories", user_id),
                key=item.key,
            )

Memory Consolidation

Merge similar memories:
def consolidate_memories(state: State, *, store: BaseStore):
    """Merge similar memories to reduce redundancy."""
    user_id = state["user_id"]
    
    # Get all memories
    items = store.search(
        namespace=("memories", user_id),
        filter={},
    )
    
    # Group similar memories (using embeddings)
    clusters = cluster_similar_memories(items)
    
    # Merge each cluster
    for cluster in clusters:
        merged = merge_memory_cluster(cluster)
        
        # Delete old memories
        for item in cluster:
            store.delete(
                namespace=("memories", user_id),
                key=item.key,
            )
        
        # Store merged memory
        store.put(
            namespace=("memories", user_id),
            key=str(uuid.uuid4()),
            value=merged,
        )
    
    return {}

Best Practices

  • Separate thread and cross-thread memory: Use checkpointers for thread state, stores for cross-thread data
  • Index your stores: Add indexes on frequently queried fields
  • Implement memory limits: Prevent unbounded growth
  • Use semantic search: Vector stores enable better context retrieval
  • Privacy considerations: Implement user data deletion
  • Test memory behavior: Verify memories persist and load correctly
  • Monitor memory size: Track storage usage per user

Next Steps

  • Add Interrupts to review memories before saving
  • Learn about Deployment for production memory systems
  • Explore Debugging to trace memory operations