An agent that remembers across conversations
Give an agent the memory tools, a store and a checkpointer. A preference saved in one conversation thread can be searched from a new one.
from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver
from langmem import create_manage_memory_tool, create_search_memory_tool
from memory_model import MemoryModel
namespace = ("memories", "{user_id}")
agent = create_agent(
MemoryModel(),
tools=[create_manage_memory_tool(namespace=namespace), create_search_memory_tool(namespace=namespace)],
store=store,
checkpointer=InMemorySaver(),
)create_agent from LangChain runs the model in a loop with its tools. The tools were created without a store: inside the agent they use the store passed here. InMemorySaver is the checkpointer, keeping each thread's messages.
first = {"configurable": {"user_id": "asha", "thread_id": "chat-1"}}
result = agent.invoke({"messages": [{"role": "user", "content": "Please email me about refunds."}]}, config=first)
for message in result["messages"]:
print(f"{message.type:5} {message.content or message.tool_calls[0]['name']}"[:70])The model called manage_memory, the tool saved the memory, and the model answered. That was thread chat-1.
second = {"configurable": {"user_id": "asha", "thread_id": "chat-2"}}
result = agent.invoke({"messages": [{"role": "user", "content": "How do I like to be contacted?"}]}, config=second)
print(len(result["messages"]))
print(result["messages"][-1].content)A new thread starts with no messages from the first: four messages here, the question, the search call, its result and the answer. The answer came from search_memory, which read Asha's namespace in the shared store. That is the difference between the checkpointer, per thread, and the store, per user.
other = {"configurable": {"user_id": "ravi", "thread_id": "chat-3"}}
result = agent.invoke({"messages": [{"role": "user", "content": "How do I like to be contacted?"}]}, config=other)
print(result["messages"][-1].content)Ravi's search returned an empty list, and the answer says so. The memory tools searched ("memories", "ravi"), so Asha's preference could not be found from Ravi's conversation.
- Ask Asha's question again in
chat-1and count the messages. - Add a
system_prompttelling the agent to save contact preferences. - Print
store.search(("memories", "asha"))after the first call.
Slow is fine. Stopping is the only problem.