Skip to main content

LangGraph + Memanto

LangGraph Give your LangGraph applications persistent, cross-session memory powered by Memanto. LangGraph natively manages short-term execution state using Checkpointers, but requires a BaseStore to persist semantic memory across different threads or sessions. Memanto integrates seamlessly as a native BaseStore or via @tool functions to give your agents long-term recall.

How It Works

LangGraph Agent → MemantoStore(BaseStore) → Memanto Server → Moorcheh.ai
You can integrate Memanto into LangGraph using three primary patterns:
  1. BaseStore: A drop-in BaseStore implementation that provides cross-thread semantic memory while respecting LangGraph’s namespace architecture.
  2. Nodes: Pre-built graph nodes for automatic memory injection before LLM calls and storage after responses.
  3. Tools: Pre-built agent tools (remember, recall, answer) injected directly into your LangGraph ToolNode.

Prerequisites

Install

pip install memanto langgraph-memanto langgraph langchain-openai

Pattern 1: BaseStore Integration

LangGraph uses a split memory architecture: Checkpointers for short-term thread state, and Stores for long-term semantic memory. MemantoStore maps LangGraph’s key-value namespace API directly to Memanto’s isolated agent buckets (e.g., langgraph_user123_preferences), providing instant, zero-latency semantic recall.

Setup the Store

import os
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver
from memanto_store import MemantoStore # (Copy from memanto examples)

api_key = os.environ.get("MOORCHEH_API_KEY")

# Initialize the MemantoStore
store = MemantoStore(api_key=api_key)

builder = StateGraph(MyState)
# ... add nodes and edges ...

# Compile the graph with the Memanto BaseStore
graph = builder.compile(
    checkpointer=InMemorySaver(),
    store=store
)

Access Memory in Nodes

In any node, simply require the store: BaseStore parameter. LangGraph will automatically inject MemantoStore.
from langgraph.store.base import BaseStore

async def extract_and_store(state: MyState, config, *, store: BaseStore):
    """Save a user preference to long-term memory."""
    user_id = config["configurable"]["user_id"]
    
    await store.aput(
        namespace=(user_id, "preferences"),
        key="allergy_info",
        value={
            "kind": "preference",
            "content": "User is allergic to peanuts"
        }
    )
    return {}

async def recall_context(state: MyState, config, *, store: BaseStore):
    """Recall memories before responding."""
    user_id = config["configurable"]["user_id"]
    
    # MemantoStore performs a semantic search across the user's isolated memory bucket
    memories = await store.asearch(
        namespace_prefix=(user_id, "preferences"),
        query="food allergies",
        limit=5
    )
    
    # ... inject memories into your LLM prompt ...
    return state

Pattern 2: Node-Based Integration

If you prefer a structured, deterministic approach without relying on the LLM to autonomously call tools, you can add pre-built recall and remember nodes directly to your graph’s edges. This guarantees memory is injected before every generation and saved after every response.
import os
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph_memanto import create_recall_node, create_remember_node
from memanto.cli.client.sdk_client import SdkClient

# 1. Initialize the Memanto SDK Client
client = SdkClient(api_key=os.environ.get("MOORCHEH_API_KEY"))

# 2. Create the Nodes
# Nodes can dynamically resolve the agent_id from the graph config at runtime
recall = create_recall_node(client=client, agent_id_from_config="user_id")
remember = create_remember_node(client=client, agent_id_from_config="user_id")

# 3. Wire them into your graph
builder = StateGraph(MessagesState)
builder.add_node("recall", recall)
builder.add_node("agent", agent_node)  # your standard LLM node
builder.add_node("remember", remember)

# Execution flow: Recall -> LLM -> Remember
builder.add_edge(START, "recall")
builder.add_edge("recall", "agent")
builder.add_edge("agent", "remember")
builder.add_edge("remember", END)

graph = builder.compile()

Pattern 3: Tool-Based Integration

If you prefer to let the LLM autonomously decide when to search or save memories (rather than hardcoding store operations in nodes), you can inject Memanto as tools.
import os
from memanto.cli.client.sdk_client import SdkClient
from langgraph_memanto import create_memanto_tools
from langgraph.prebuilt import ToolNode

# 1. Initialize the Memanto client
client = SdkClient(api_key=os.environ.get("MOORCHEH_API_KEY"))

# 2. Create the tools
# The tools will automatically ensure the agent is created and activated
tools = create_memanto_tools(client, agent_id="my-langgraph-agent")

# 3. Create a ToolNode
tool_node = ToolNode(tools)

# 4. Bind tools to your LLM and build the graph
llm_with_tools = llm.bind_tools(tools)
# ...

Persistent Memory Across Runs

Because memories live in Memanto (not in-process), they persist between separate runs, processes, or entire servers. The checkpointer handles short-term context, while Memanto handles lifelong user profiles.

Next Steps