Conversation memory for LangChain agents
June 18, 2026This post extends the support triage agent from Building AI agents with LangChain into a multi-turn flow: turn 1 looks up the customer and invoice; turn 2 creates the ticket without the user repeating IDs. It is post #5 in the LangChain series, following the overview, loaders/chunking, RAG, and agents posts.
Prerequisites
- OpenAI account
- Generated API key
- Enabled billing
- Node.js version 26
- Packages from the agents post, plus the checkpoint package:
npm i langchain @langchain/openai @langchain/core @langchain/langgraph-checkpoint zod
OPENAI_API_KEYset in the environment
Mental model
Three related concepts:
- Checkpointer - short-term session memory. Saves messages and graph state after each step so the next
invokeon the same thread can resume. thread_id- conversation key passed inconfigurable. Same ID = same history; different ID = isolated session.- Store - long-term memory across threads (user preferences, facts learned over time). LangGraph stores are separate from checkpointers; this post focuses on checkpointers only.
Typical support flow with memory:
- Turn 1 - rep asks to look up
cus_1042andinv_8891; agent calls lookup tools and summarizes findings. - Turn 2 - rep says "create the ticket we discussed"; agent recalls prior tool results and calls
create_support_ticket.
MemorySaver
For demos and tests, use MemorySaver - an in-memory checkpointer that persists state for the lifetime of the process:
import { MemorySaver } from '@langchain/langgraph-checkpoint';const checkpointer = new MemorySaver();
State is lost when the Node process exits. That is fine for local scripts; production apps need a durable backend (see below).
Attach a checkpointer to createAgent
Pass the checkpointer when creating the agent. Reuse the same triage tools and instructions from the agents post:
import { createAgent } from 'langchain';import { MemorySaver } from '@langchain/langgraph-checkpoint';const agent = createAgent({model: 'gpt-5.5',tools: supportTools,systemPrompt: TRIAGE_INSTRUCTIONS,checkpointer: new MemorySaver(),});
The agent loop is unchanged - the checkpointer hooks into LangGraph beneath createAgent.
First turn - lookup
Pass a stable thread_id in the invoke config:
const threadConfig = { configurable: { thread_id: 'support-cus-1042' } };const turn1 = await agent.invoke({messages: [{role: 'user',content:'Look up customer cus_1042 and invoice inv_8891 for a possible duplicate charge. Summarize what you find. Do not create a ticket yet.',},],},threadConfig,);console.log(turn1.messages.at(-1)?.content);
The agent calls get_customer, get_invoice, and search_knowledge_base. LangGraph saves the full message history (including tool results) to the checkpointer.
Second turn - follow-up without IDs
Send only the new user message on the same thread_id. Prior context is restored automatically:
const turn2 = await agent.invoke({messages: [{role: 'user',content: 'Create the support ticket we discussed.',},],},threadConfig,);console.log(turn2.messages.at(-1)?.content);
The agent should call create_support_ticket using customer and invoice details from turn 1 - the user does not repeat cus_1042 or inv_8891.
Read the final answer from result.messages as in the agents post:
const lastAi = [...turn2.messages].reverse().find((message) => message.type === 'ai');console.log(lastAi?.content);
Thread isolation
Different thread_id values do not share history. Two support reps working different cases should use separate thread IDs:
await agent.invoke({ messages: [{ role: 'user', content: 'Look up cus_1042.' }] },{ configurable: { thread_id: 'rep-alice-case-1' } },);await agent.invoke({ messages: [{ role: 'user', content: 'Create the ticket we discussed.' }] },{ configurable: { thread_id: 'rep-bob-case-2' } },);
The second invoke on rep-bob-case-2 has no knowledge of Alice's lookup - Bob's thread starts empty.
Production checkpointers
MemorySaver is process-local and not suitable for production. LangGraph supports durable checkpointers backed by Postgres, SQLite, and other stores via @langchain/langgraph-checkpoint integrations. Swap the checkpointer implementation; the thread_id API stays the same.
Pick a backend that matches your deployment: Postgres for multi-instance apps, SQLite for single-node services.
Demo
See the langchain-agent-memory-nodejs-demo folder for multi-turn triage and thread-isolation scripts.