LangChain Tools
Five structured memory tools that let a LangChain agent store, search, list, update and delete memories — with scoping, idempotent writes, and failures that never abort an agent run.
The tool set
| Tool | Arguments | Returns |
|---|---|---|
add_memory | text (required), tags, importance 0–1 | Stored memory m_123. — or Already stored as m_123 on a repeat, or guidance when nothing durable was found. |
search_memory | query (required), k 1–50, default 5 | Ranked lines with ids and relevance scores, or No relevant memories found. |
list_memories | limit 1–200, default 20 | Newest-first lines with ids, or No memories stored yet. |
update_memory | memory_id (required), tags, importance | Updated memory m_123. Memory text is immutable — replace a fact by delete plus add. |
delete_memory | memory_id (required) | Deleted memory m_123. — or a not-found sentence when it is already gone. |
Create the tools
from langchain.agents import create_agentfrom langchain_memorysync import create_memorysync_toolstools = create_memorysync_tools(end_user_id="user-123")agent = create_agent(model, tools=tools)agent.invoke({"messages": [{"role": "user", "content": "Remember that I'm allergic to peanuts."}]})
The factory also works with LangGraph’s create_react_agent and the legacy AgentExecutor on 0.3.x — the tools are plain structured tools, nothing framework-version specific.
Scope to the right user
Pass end_user_id whenever the key belongs to an organisation. It is what keeps one customer’s memories out of another’s session: every tool call is isolated to that user, and a delete cannot reach another user’s memory even by id.
tools = create_memorysync_tools(end_user_id="user-123",read_only=True, # only search_memory and list_memories)
Write behaviour worth knowing
add_memoryderives an idempotency key from the content, so an agent that repeats "remember X" gets "already stored" instead of a duplicate.- Extraction judges what is durable: transient chit-chat comes back as "nothing stored" with guidance to rephrase, not as a memory.
- Memory text is immutable by design — the update tool changes tags and importance, and replacing a fact is delete plus add, which keeps history auditable.
- Over-quota writes degrade silently server-side; the agent sees a normal response rather than a billing error to narrate to the end user.
Complete example: an agent that stores, then recalls
The whole loop in one program: the first invocation stores facts the user states, and a later invocation — a different process, days later — searches memory before answering. The tool return strings are exactly what the model sees.
from langchain.agents import create_agentfrom langchain_openai import ChatOpenAIfrom langchain_memorysync import create_memorysync_toolstools = create_memorysync_tools(end_user_id="customer-7")agent = create_agent(ChatOpenAI(model="your-model"), tools=tools)# Run 1 — the user states facts; the agent calls add_memory twice.agent.invoke({"messages": [{"role": "user","content": "Remember that I'm vegetarian and I'm allergic to peanuts.",}]})# Tool results the model saw:# Stored memory m_101.# Stored memory m_102.# Run 2 — a fresh process. The agent calls search_memory before answering.result = agent.invoke({"messages": [{"role": "user","content": "Pick a restaurant for my team dinner on Friday.",}]})print(result["messages"][-1].content)# Tool result the model saw first:# - m_101 (relevance 0.89): The user is vegetarian.# - m_102 (relevance 0.87): The user is allergic to peanuts.