Data as of Aug 25, 2026 · Based on 38 AI responses from ChatGPT Search and Google AI Mode · See how Parse measures this
Your brand can be here too.
An AI agent does not gain memory by itself; you give it memory by storing information outside the model and retrieving the right pieces when a new session starts. The basic pattern is:
Store → Index → Retrieve → Inject into context → Update
LLMs are stateless between calls, so persistent memory requires an external memory layer.
A good agent usually needs several memory types rather than one giant chat log.
Current task state:
Storage:
Example:
{
"task": "Prepare quarterly report",
"current_step": "Collect sales numbers",
"open_questions": ["Need Q4 forecast"]
}
"What happened before?"
Examples:
Usually stored as:
Example record:
{
"type": "episode",
"text": "User prefers weekly progress updates on Fridays.",
"timestamp": "2026-08-01",
"embedding": [0.123, 0.456]
}
"What is known?"
Examples:
Store these as structured data:
{
"fact": "User prefers Python",
"confidence": 0.92,
"source": "conversation_184"
}
"How should the agent do things?"
Examples:
A common architecture looks like:
User
|
v
Agent runtime
|
+---------+---------+
| |
v v
Retrieve memories Save memories
| |
v v
Vector DB + SQL DB Memory pipeline
Typical storage choices:
| Need | Good options |
|---|---|
| Semantic recall | Pinecone, Qdrant, Weaviate, pgvector |
| Structured facts | PostgreSQL, SQLite |
| Fast session state | Redis |
| Simple agents | JSON/files/SQLite |
Redis, for example, can support session state, semantic recall, and event logs in one system.
A common mistake is:
"Store every conversation forever." Instead, run a memory extraction step after conversations.
Example:
Conversation:
User: "I hate Monday meetings. Schedule reviews on Wednesdays." Memory extractor:
{
"memory": "User prefers reviews on Wednesdays.",
"category": "preference",
"importance": 0.95
}
Discard the rest.
When a new session starts:
"Help me plan my week."
Relevant memories:
- User prefers Wednesday reviews.
- User has a recurring Friday deadline.
- User works on project Atlas.
Known user context:
- Prefers Wednesday reviews
- Project Atlas is active
User request:
Help me plan my week.
The model still has no memory; your application is supplying the memory.
Long-lived agents need policies:
Store:
{
"importance": 0.8,
"created": "2026-08-28",
"last_used": "2026-08-28"
}
Remove:
Periodically summarize:
Before:
User mentioned Python preference 12 times.
User uses FastAPI.
User dislikes JavaScript tooling.
After:
User prefers Python-based backend development.
Memory can create problems if the agent trusts bad information.
Useful rules:
Recent research also highlights that memory retrieval itself is a trust boundary: a wrongly retrieved memory can influence future behavior.
For many agents, a practical starting point is:
PostgreSQL
├── users
├── facts
├── conversations
└── memories
pgvector
└── embeddings for semantic search
Worker process
├── extracts memories
├── summarizes conversations
└── removes stale entries
Flow:
New message
|
v
Search memories
|
v
Build prompt
|
v
LLM response
|
v
Extract important memories
|
v
Save
Frameworks such as LangChain's memory tooling and similar agent frameworks provide abstractions for these patterns, including user-scoped memory, episodic memory, and background consolidation workflows.
If you are building from scratch, start with SQLite/Postgres + embeddings + a memory extraction prompt. Add more sophisticated memory types only when you have real usage data showing you need them.
Memory extractor:
To give your AI agent persistent, long-term memory across sessions, you must move memory outside the LLM context window and store it in an external data layer . Because LLMs are inherently stateless, passing the entire raw chat history back into the prompt does not scale and quickly overflows token limits.
Building a robust, cross-session memory architecture requires a multi-step process utilizing external infrastructure.
🛠️ The 4-Step Memory Pipeline
To make memory persist across restarts and entirely new conversations, your agent pipeline must follow an Extract → Consolidate → Store → Retrieve workflow.
[ User Input ] ──> (1. Semantic Search) ──> [ External DB / Memory Layer ]
│ ▲
▼ │
(2. Inject Context) ──> [ LLM Generation ] ──> (3. Extract & Update Facts)
Do not store raw transcripts. Instead, use an LLM background task to isolate core facts.
Save the distilled facts into a permanent database mapped to a unique user_id rather than a temporary session_id.
When a user starts a brand-new session, do not wait for them to re-explain their preferences.
Dynamically stuff the retrieved long-term facts into the system prompt of the current session.
"Relevant historical profile facts about this user: [User prefers dark mode; User is located in Los Angeles]. Use this information to tailor your response.".📦 Out-of-the-Box Tools & Frameworks
If you prefer not to build the vector pipelines, text splitters, and embedding models from scratch, use dedicated agent memory frameworks:
⚠️ Critical Best Practices
If you would like to start implementing this, let me know:
I can provide the specific code snippets or architectural diagrams to help you set it up.
Giving your AI agent persistent long-term memory across sessions requires moving beyond the standard short-term context window. This is typically achieved by implementing a retrieval-augmented generation (RAG) architecture paired with a vector database and an external state store.
Here is a structured, step-by-step approach to building persistent long-term memory:
text-embedding-3-small or open-source equivalents).user_id or agent_id.If you'd like, let me know:
I can provide a code snippet or architecture tailored to your setup.
Yes. The key is to separate conversation history from long-term memory.
A good architecture looks like this:
┌─────────────────────┐
User ──────────────►│ AI Agent │
└─────────┬───────────┘
│
┌─────────────┴─────────────┐
▼ ▼
Short-term memory Long-term memory
"What happened "What should I
in this thread?" remember?"
│ │
conversation DB memory store
│ │
└─────────────┬─────────────┘
▼
Future sessions
Don't key memory by conversation/session ID.
Instead:
user_id = "user_123"
Then give each conversation its own ID:
thread_id = "conversation_456"
That lets the agent have multiple conversations while still sharing the user's long-term memories.
For example, turn:
"I'm vegetarian, I live in Seattle, and I'm preparing for a marathon." into structured memories such as:
{
"user_id": "user_123",
"memories": [
{
"type": "preference",
"content": "User is vegetarian"
},
{
"type": "location",
"content": "User lives in Seattle"
},
{
"type": "goal",
"content": "User is preparing for a marathon"
}
]
}
This is much more useful than stuffing the entire historical conversation into every prompt.
A common production design uses semantic, episodic, and procedural memories—for example, facts/preferences, past experiences, and learned ways of doing things. LangChain's current memory architecture similarly separates thread-level state from cross-session long-term memory.
Conceptually, expose tools like:
remember(
user_id,
memory="User prefers concise answers"
)
recall(
user_id,
query="What does this user prefer?"
)
Before answering, the agent can retrieve relevant memories:
User asks question
↓
retrieve relevant memories
↓
put memories into agent context
↓
generate answer
After the conversation, have a memory-writing process decide whether anything is worth retaining.
Importantly, don't automatically save every message.
Good candidates:
Poor candidates:
For development you can use an in-memory store, but that disappears when your process does.
For production, use something persistent such as:
For example, LangGraph's current architecture uses a checkpointer for thread-level persistence and a separate store for memories shared across threads. Its documentation recommends database-backed stores such as Postgres, MongoDB, or Redis for production.
If you're using the OpenAI Agents SDK, its Session abstraction can persist conversation history across runs, with implementations for things such as SQLite, Redis, SQLAlchemy-backed databases, and MongoDB.
Once you have thousands of memories, don't retrieve everything.
Store embeddings alongside memories:
memory:
"User prefers Python over JavaScript"
embedding:
[0.021, -0.183, ...]
Then when the user says:
"What programming language should I use for this?" retrieve memories semantically related to programming preferences.
You can also combine:
semantic similarity
+
user ID filtering
+
recency
+
importance
to rank memories.
A particularly effective pattern is:
Conversation
│
▼
Memory extractor
│
┌────────┴────────┐
▼ ▼
New memory? Existing memory?
│ │
save update
│ │
└────────┬────────┘
▼
Memory DB
For example:
Old:
User prefers dark mode.
New conversation:
"I switched to light mode recently."
→ update existing preference
rather than creating contradictory memories.
You can run this extraction synchronously, or as a background job after the interaction. LangChain's current guidance explicitly discusses background memory creation as a way to reduce latency and avoid making memory management part of the main response path.
For a serious agent, I'd start with:
PostgreSQL
│
├── conversations
│ └── thread/session history
│
├── memories
│ ├── user_id
│ ├── memory_type
│ ├── content
│ ├── importance
│ ├── created_at
│ └── updated_at
│
└── embeddings
└── semantic retrieval
Then your agent loop becomes:
def handle_message(user_id, thread_id, message):
history = load_conversation(thread_id)
memories = recall_relevant_memories(
user_id=user_id,
query=message
)
context = {
"conversation": history,
"long_term_memory": memories
}
response = agent.run(message, context)
save_conversation(thread_id, message, response)
extract_and_update_memories(
user_id=user_id,
conversation=[message, response]
)
return response
The important conceptual distinction is:
Session memory = "remember this conversation."
Long-term memory = "remember this user/application across conversations."
If you're building with the OpenAI Agents SDK specifically, you can use its built-in Sessions for the first part and layer a database-backed user-memory system on top for the second. The SDK documentation explicitly distinguishes session conversation history from longer-lived agent memory.
If you tell me whether your agent is Python, TypeScript/Node, LangGraph, OpenAI Agents SDK, or something custom, I can show you the concrete production implementation.
{
"user_id": "user_123",
"memories": [
{
"type": "preference",
"content": "User is vegetarian"
},
{
"type": "location",
"content": "User lives in Seattle"
},
{
"type": "goal",
"content": "User is preparing for a marathon"
}
]
}
This is much more useful than stuffing the entire historical conversation into every prompt.
A common production design uses semantic, episodic, and procedural memories—for example, facts/preferences, past experiences, and learned ways of doing things. LangChain's current memory architecture similarly separates thread-level state from cross-session long-term memory.
Conceptually, expose tools like:
remember(
user_id,
memory="User prefers concise answers"
)
recall(
user_id,
query="What does this user prefer?"
)
Before answering, the agent can retrieve relevant memories:
User asks question
↓
retrieve relevant memories
↓
put memories into agent context
↓
generate answer
After the conversation, have a memory-writing process decide whether anything is worth retaining.
Importantly, don't automatically save every message.
Good candidates:
Giving your AI agent persistent long-term memory across sessions requires shifting from a stateless LLM call to an architecture that captures, stores, retrieves, and updates information over time.
Here is the step-by-step breakdown of how to build this system:
<long_term_memory>.If you'd like, tell me:
I can provide a more specific code example or architecture blueprint for your setup.
Yes. The key is to separate conversation history from long-term memory.
A good architecture looks like this:
User
↓
Agent
├── Short-term/session memory
│ └── recent conversation turns
│
└── Long-term memory
├── user preferences
├── important facts
├── past decisions
├── learned corrections
└── durable project/context information
↓
Persistent database / memory store
Don't key memory to a process or chat window. Use something like:
user_id = "user_123"
Then associate all durable memories with that ID.
After each interaction—or periodically—have the agent determine whether anything is worth remembering:
{
"user_id": "user_123",
"memory": "User prefers concise technical explanations.",
"category": "preference",
"confidence": 0.95,
"created_at": "...",
"updated_at": "..."
}
Typical categories:
Avoid saving every utterance. That creates a giant, noisy memory that eventually hurts retrieval.
On a new session:
User message
↓
Extract/search relevant memory
↓
Top relevant memories
↓
Agent context
↓
Response
For example, if the user asks:
"Can you modify my API client?"
your memory search might return:
- User's projects use Python.
- User prefers typed interfaces.
- Their API client uses httpx.
- They previously rejected automatic retries.
Only those relevant memories need to enter the model's context.
For a production system, you can use:
A particularly useful pattern is hybrid memory:
PostgreSQL
├── user_id
├── memory_id
├── category
├── text
├── timestamps
└── embedding
+
Semantic search
↓
Relevant memories
LangChain's current long-term-memory architecture, for example, separates memory across conversations/sessions and stores memories in a persistent store organized by namespace and key.
This distinction is important.
Session memory:
"What have we been talking about in this conversation?"
Long-term memory:
"What should I know about this user even if this conversation ended six months ago?"
The OpenAI Agents SDK currently provides persistent session mechanisms for conversation history, including SQLite, Redis, SQLAlchemy-backed sessions, and server-managed conversation state.
For example, a Python agent can persist a session with SQLite:
from agents import Agent, Runner, SQLiteSession
agent = Agent(
name="Assistant",
instructions="Be helpful and concise."
)
session = SQLiteSession(
"user_123",
"conversations.db"
)
result = await Runner.run(
agent,
"Remember that my project uses PostgreSQL.",
session=session
)
The same session can later restore the conversation history.
But that's conversation persistence, not necessarily a good long-term user-memory system.
A robust system often does:
┌───────────────┐
│ User message │
└───────┬───────┘
↓
┌───────────────┐
│ Retrieve │
│ memories │
└───────┬───────┘
↓
┌───────────────┐
│ Main agent │
└───────┬───────┘
↓
┌───────────────┐
│ Extract new │
│ memories │
└───────┬───────┘
↓
┌───────────────┐
│ Persistent DB │
└───────────────┘
The extraction prompt might effectively ask:
Identify information from this interaction that is likely to remain useful in future conversations. Ignore temporary details and don't infer facts that weren't stated.
Then have your application validate and save the resulting memories.
This is often overlooked.
Memory needs operations such as:
CREATE
UPDATE
DELETE
EXPIRE
MERGE
For example:
Old:
"user prefers JavaScript"
New:
"user prefers TypeScript"
Don't simply append both forever. Either update the old memory or mark it obsolete.
Also give the user control:
"What do you remember about me?"
and:
"Forget that I use PostgreSQL."
If I were building this today, I'd start with:
Agent → OpenAI Agents SDK / your agent framework
Session state → PostgreSQL or Redis
Long-term memory → PostgreSQL + embeddings (rather than immediately introducing a specialized vector database)
Memory retrieval → semantic + metadata filtering
Memory generation → a small/cheap model that extracts durable facts
Main model → receives only the memories relevant to the current task
This keeps the architecture simple and prevents your context window from becoming the database.
OpenAI's newer Agents SDK also has a separate sandbox-agent Memory capability that explicitly distills prior runs into reusable memory artifacts; importantly, the documentation distinguishes this from conversational Session memory.
The core principle: don't try to make the LLM itself remember. Make memory an external state-management system that the LLM can read and write.
If you're building this with OpenAI's API specifically, I can also show you a concrete implementation with Python + PostgreSQL + embeddings + automatic memory extraction/retrieval, including the database schema and agent code.
To give an AI agent persistent long-term memory across sessions, you generally do not make the model itself remember. Instead, you build a memory layer around the model: a system that decides what to store, where to store it, and what to retrieve when the agent runs again. LLMs are stateless between calls unless your application supplies previous information.
A practical architecture looks like this:
┌─────────────────┐
│ User message │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Memory manager │
└───────┬─────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
Short-term Long-term Knowledge
context memory store
│ │ │
▼ ▼ ▼
Chat window Vector DB SQL/Graph DB
Use a database that survives process restarts:
Vector database → for fuzzy recall:
Relational database → for exact facts:
Event log → for history:
Many agent systems separate memory into categories such as episodic (events), semantic (facts), and procedural (how to do things).
Example memory record:
{
"user_id": "123",
"type": "preference",
"content": "User prefers code examples in Python",
"created_at": "2026-08-16",
"importance": 0.8,
"embedding": [0.012, -0.034, ...]
}
Do not save every message. That creates a noisy memory store.
Use a memory filter:
Store:
Avoid storing:
A common pattern:
Conversation
|
▼
Memory extractor
|
├── "important fact" → save
|
└── "temporary detail" → discard
At the start of a new session:
Example:
User:
"Help me plan my next project."
Memory retrieval finds:
- User prefers TypeScript
- User works on SaaS products
- Previous project was a scheduling app
The agent receives:
System:
You are an assistant.
Relevant memories:
- User prefers TypeScript.
- User builds SaaS applications.
- Previous project involved scheduling software.
User:
Help me plan my next project.
Over time, raw memories should be summarized.
Example:
Raw memories:
Aug 1:
User asked about AWS costs.
Aug 5:
User compared AWS and GCP.
Aug 12:
User decided to use AWS.
Consolidated memory:
User's current cloud preference: AWS.
Reason: cost comparison and existing familiarity.
This prevents your memory database from growing forever. Memory consolidation is a common design pattern in long-lived agents.
A useful schema:
{
"fact": "User prefers dark mode",
"confidence": 0.9,
"last_confirmed": "2026-08-01",
"expires": null
}
Examples:
For multi-user agents:
memory/
├── user_001/
│ ├── preferences
│ ├── history
│ └── projects
│
├── user_002/
├── preferences
└── history
Never allow retrieval across users unless you explicitly support shared organizational memory.
A simple implementation:
A minimal flow:
New message
↓
Extract memories
↓
Store important ones
↓
Retrieve relevant memories
↓
Build prompt
↓
Call LLM
↓
Save outcome
The key idea: persistent memory is an application feature, not a model feature. The agent becomes “long-lived” because your software maintains a carefully managed external memory system and feeds the right pieces back into each new session.
Giving an AI agent persistent long-term memory across sessions requires moving beyond the model's immediate context window and storing information in an external database . When a new session starts, the agent queries this storage to retrieve relevant context.
Here is a clean, structured breakdown of how to build this architecture:
If you'd like to dive deeper, let me know:
I can provide a code snippet tailored to your exact stack.
Giving an AI agent persistent long-term memory across sessions requires moving beyond standard short-term context windows . You need an external storage architecture that allows the agent to read, write, and recall past interactions, user preferences, and historical facts.
Here is the standard architectural approach to building persistent memory for an AI agent:
If you want to dive deeper, let me know:
I can provide a code snippet or architectural blueprint tailored to your setup.
To give an AI agent persistent long-term memory, you need to move memory outside the model and build a memory layer that the agent can read from and write to across sessions. An LLM itself is stateless: each new run only knows what you include in its context.
A practical architecture looks like this:
┌─────────────────┐
│ AI Agent │
│ (LLM + tools) │
└────────┬────────┘
│
┌────────────┴────────────┐
│ Memory Layer │
└────────────┬────────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
Working memory Long-term memory Event history
(current task) (facts/preferences) (what happened)
│ │ │
Redis/session DB Vector DB + DB SQL/document store
Do not just save entire chat transcripts. Extract useful memories.
Example:
User says:
"I prefer concise answers and I usually deploy with Kubernetes."
Convert that into:
{
"type": "user_preference",
"fact": "User prefers concise answers",
"confidence": 0.92,
"created": "2026-08-12"
}
and:
{
"type": "technical_preference",
"fact": "User commonly deploys with Kubernetes",
"confidence": 0.85
}
The agent should decide:
Memory systems increasingly treat this as a lifecycle problem: ingestion, revision, forgetting, and retrieval—not just storage.
A good agent usually needs several kinds of memory:
Short-lived state:
Example storage:
Lifetime:
"What happened before?"
Examples:
Store:
{
"event": "Deployment failed",
"cause": "Missing environment variable",
"solution": "Added secret configuration"
}
Useful for learning from previous attempts.
"What is true?"
Examples:
Store as:
Example:
(User)
|
prefers
|
(Concise explanations)
"How should I do things?"
Examples:
At the start of every session:
Example:
User:
"Help me write this deployment script."
Memory retrieval:
Relevant memories:
- User uses Kubernetes
- User prefers YAML examples
- Previous deployment used Helm
Injected context:
Known user preferences:
- Use Kubernetes examples
- Keep explanations concise
Do not dump the entire memory database into the prompt. Retrieval quality matters more than raw storage size.
A common production setup:
| Need | Storage |
|---|---|
| Current conversation state | Redis / SQLite |
| Structured facts | PostgreSQL |
| Semantic recall | Vector database |
| Relationships | Graph database |
| Raw history | Object storage |
Example stack:
PostgreSQL
├── users
├── preferences
├── projects
└── facts
Vector DB
└── embeddings for semantic search
Event log
└── every important interaction
Vector search alone is usually insufficient because it does not naturally handle things like contradictions, timelines, or fact updates.
Instead of every tool call writing memories directly:
Conversation
|
v
Memory Extractor
|
├── discard trivial info
├── merge duplicates
├── update old facts
└── save important memories
Example rules:
Remember:
Do not remember:
Memory needs expiration and revision.
Example:
Old:
{
"fact": "User works at Company A"
}
Later:
{
"fact": "User works at Company B"
}
Do not keep both as equally true. Mark the old one:
{
"status": "superseded"
}
A simple first version:
Agent
|
|-- session memory
| SQLite table: conversations
|
|-- long-term memory
| PostgreSQL table: memories
|
|-- embeddings
pgvector / vector database
Flow:
New message
|
Retrieve relevant memories
|
Build prompt
|
Run LLM
|
Extract new memories
|
Store updates
You can build a surprisingly capable system this way before adding more complex graph memory or specialized frameworks.
The key design principle: your agent should not "remember everything"; it should maintain a curated, searchable memory that evolves over time.