Add Memory
In shortAdd memory to a 10xGraph agent by compiling the graph with InMemoryCheckpointer, so conversation state persists across calls on the same thread.
- 2 min read
- 7 sections
- Updated
- v0.9.2
- Markdown
Without a checkpointer, each app.invoke call is independent — the agent starts fresh every time. A checkpointer saves state after each run and restores it when the same thread_id is used again.
This page adds InMemoryCheckpointer so your agent remembers the conversation.
Why thread IDs matter now
Every call to app.invoke takes a config with a thread_id. Once a checkpointer is attached, all calls sharing the same thread_id share the same conversation history:
sequenceDiagram
participant App as app.invoke(thread_id="abc")
participant Checkpointer as InMemoryCheckpointer
participant State as AgentState
App->>Checkpointer: load state for "abc"
Checkpointer-->>State: previous context
App->>State: append new message
App->>State: run nodes
App->>Checkpointer: save updated state for "abc"
Without a checkpointer, the “load state” step is skipped and history is lost between calls.
Add InMemoryCheckpointer
InMemoryCheckpointer stores state in memory. It works for development and testing. For production, use PgCheckpointer with a database.
Update your graph to compile with a checkpointer:
from tenxgraph.core.graph import Agent, StateGraph, ToolNode
from tenxgraph.core.state import AgentState, Message
from tenxgraph.storage.checkpointer import InMemoryCheckpointer
from tenxgraph.utils import END
checkpointer = InMemoryCheckpointer()
agent = Agent(
model="google/gemini-2.5-flash",
system_prompt=[
{
"role": "system",
"content": "You are a helpful assistant.",
}
],
)
graph = StateGraph(AgentState)
graph.add_node("assistant", agent)
graph.set_entry_point("assistant")
graph.add_edge("assistant", END)
# Pass the checkpointer when compiling
app = graph.compile(checkpointer=checkpointer)Test multi-turn conversation
Create agent_with_memory.py with the graph above, then add these calls:
THREAD = "memory-demo-1"
# First turn
result = app.invoke(
{"messages": [Message.text_message("My name is Alex.")]},
config={"thread_id": THREAD},
)
print(result["messages"][-1].text())
# Second turn — same thread_id, agent remembers
result = app.invoke(
{"messages": [Message.text_message("What is my name?")]},
config={"thread_id": THREAD},
)
print(result["messages"][-1].text())Run it:
python agent_with_memory.pyExpected output (exact wording varies):
Nice to meet you, Alex!
Your name is Alex.The agent remembered “Alex” from the first turn because both calls shared the same thread_id.
Use a different thread
Each thread_id is an independent conversation. Using a different ID gives the agent a fresh start:
# New thread — agent has no memory of "Alex"
result = app.invoke(
{"messages": [Message.text_message("What is my name?")]},
config={"thread_id": "memory-demo-2"},
)
print(result["messages"][-1].text())Expected output:
I don't know your name yet. Could you tell me?Key imports
from tenxgraph.storage.checkpointer import InMemoryCheckpointerFor production:
from tenxgraph.storage.checkpointer import PgCheckpointer
# Requires: pip install 10xgraph[pg_checkpoint]What you learned
- A checkpointer saves and restores
AgentStatebetween calls. - Conversations are isolated by
thread_id. InMemoryCheckpointeris for development;PgCheckpointeris for production.- Pass the checkpointer to
graph.compile(checkpointer=...).
Next step
Serve the agent over HTTP with Run with the API.