AI Agent Memory: Sessions, Long-Term State, and Retrieval
What is AI agent memory?
AI agent memory is application-managed state carried across steps, turns, or sessions so an agent can resume work and recall relevant facts. It may include thread history, workflow checkpoints, durable user or project facts, and retrieved prior experiences, each with separate scope and lifecycle.
TL;DR
- -Conversation history, workflow checkpoints, long-term facts, and document retrieval solve different problems; storing all four in one vector index creates ambiguity
- -A memory needs scope, provenance, timestamps, sensitivity, and lifecycle—not only text and an embedding
- -Write memory from explicit user statements or verified outcomes; treat model-extracted facts as candidates until policy accepts them
- -Retrieve with identity filters and task relevance before semantic similarity, then fit results into a fixed context budget
- -Measure write precision, useful recall, contradiction rate, cross-user leakage, staleness, and deletion completion with fixed scenarios
“Give the agent memory” sounds like one feature. In production it is at least four different data systems:
current run state
conversation or workflow checkpoint
long-term facts and preferences
retrieval over documents and prior experiences
Mix them together and the agent starts treating an old chat summary as current account state, a private preference as organization policy, or a failed attempt as a proven procedure.
Memory is not a bigger prompt and not a vector database with every conversation dumped into it. It is a governed path from event → candidate → stored record → retrieval → context → correction or deletion.
This article focuses on that path. The broader context engineering guide covers how memory competes with instructions, tools, and retrieved documents inside the context window. For multiple cooperating agents, pair it with the multi-agent architecture guide.
Separate the four state problems
| Layer | Scope | Example | Storage shape |
|---|---|---|---|
| Working state | One run or step | Current plan, intermediate IDs, retry count | Typed in-memory state |
| Thread state | One conversation or workflow | Messages, approvals, checkpoint, pending tool call | Ordered log and checkpoints |
| Long-term memory | User, project, agent, or organization | Preference, verified fact, reusable experience | Structured records with lifecycle |
| Knowledge retrieval | Corpus and access domain | Product docs, tickets, repository files | Source documents plus index |
The boundaries matter more than the names. OpenAI’s Agents SDK, for example, uses a
Session to store conversation history for one session. Its current
state-management guide
distinguishes client-managed sessions from server-managed conversations and warns
against mixing both persistence strategies in one run because context can be
duplicated.
LangGraph makes a similar split: checkpoints persist thread state, while a Store holds data that can be recalled across threads. The memory overview calls these short-term and long-term memory. The framework may differ; the scopes should not.
Model memory as records, not prose
A single memory_text field is quick to ship and hard to operate. Use a record that can
answer who it belongs to, where it came from, whether it is still valid, and how it may
be used:
{
"memory_id": "mem_01...",
"subject_id": "usr_internal_42",
"namespace": ["user", "travel_preferences"],
"kind": "preference",
"fact": {
"field": "seat_preference",
"value": "aisle"
},
"source": {
"type": "explicit_user_statement",
"event_id": "evt_01..."
},
"confidence": "confirmed",
"sensitivity": "personal",
"valid_from": "2026-08-21T10:00:00Z",
"valid_until": null,
"created_at": "2026-08-21T10:00:02Z",
"supersedes": null
}
Keep the embedding as an index derived from this source record. It is not the source of truth. That distinction makes corrections, access changes, and deletion possible without trying to reverse-engineer a vector.
Choose memory types deliberately
Three long-term types are useful:
- Semantic: facts such as a user’s language or a project’s deployment region.
- Episodic: an earlier attempt, its actions, and verified outcome.
- Procedural: instructions for how the agent should perform a task.
Procedural memory deserves the strongest gate. An agent that can rewrite its own shared instructions can turn one poisoned conversation into persistent behavior. Keep organization policy and high-impact procedures versioned, reviewed, and read-only to the runtime. Let the agent propose a change; do not let it silently publish one.
Design the write path before retrieval
Most memory failures begin when too much is written. “The user mentioned it” is not a retention policy.
Use three write paths:
1. Explicit and immediate
The user says “remember that I prefer aisle seats.” Validate that the data class is allowed, show what will be stored when the consequence is not obvious, then write a confirmed record.
2. Deterministic outcome
Application code records a completed booking, approved decision, or successful tool result. Store the verified state or a reference to its system of record. Do not ask the model to rephrase an identifier and then trust the paraphrase.
3. Inferred candidate
The model infers a preference or extracts a lesson from several events. Write a candidate with provenance, not an accepted fact. A background job can deduplicate, check policy, compare current records, and request user review where needed.
Background consolidation keeps memory work off the response path and can examine more than one event. It also introduces lag and races. Assign each candidate an event ID, make writes idempotent, and ensure an older job cannot overwrite a newer confirmed record.
The OpenAI Agents SDK’s current sandbox memory feature uses a similar separation:
conversation extracts are consolidated into smaller memory files, while its ordinary
Session remains conversation history. Its
agent memory documentation
also treats saved memory as guidance and tells the agent to trust the current
environment when they conflict.
Resolve conflicts instead of appending forever
Memory changes. A user moves, a project migrates, a preference was temporary, or an earlier extraction was wrong.
Define a precedence policy in code. One workable order is:
current system of record
> explicit current user statement
> approved organization or project record
> recent verified outcome
> model-inferred candidate
> old summary
Do not merge incompatible values into prose. Preserve versions or a supersession link, select the active record deterministically, and surface the conflict when policy cannot resolve it. “I found two different billing contacts; which is current?” is better than choosing the closest embedding.
Use validity intervals and TTLs for facts that naturally expire. Recency alone is not truth: an attacker should not be able to override an approved policy merely by writing a newer note.
Retrieve by scope before similarity
The retrieval pipeline should narrow authority first:
verified principal
→ allowed namespace and tenant
→ memory kind and validity
→ task filters
→ lexical or semantic retrieval
→ reranking
→ context budget
Never retrieve a broad global index and filter the results after they have reached the
model. Enforce identity and tenant boundaries in the storage query. A namespace should
be derived from verified runtime context, not from user_id supplied in a prompt.
Use structured lookup for exact facts:
- current timezone;
- approved language;
- active workflow ID;
- policy version;
- object ownership.
Use semantic search for fuzzy experiences and notes: similar incidents, previous approaches, or relevant preferences expressed in different words. Combine it with metadata filters and lexical search when identifiers or exact phrases matter.
Return a small typed packet with provenance:
{
"fact": "Prefers aisle seats",
"status": "confirmed",
"source_date": "2026-08-21",
"memory_id": "mem_01..."
}
Give memory a fixed token budget. If ten records fit, retrieval should not return fifty and hope the model ignores forty. Log candidates, selected records, and rejection reasons so missed or noisy retrieval can be debugged.
Summaries are lossy indexes
Conversation compaction is useful, but a summary should not silently become the only record of approvals, tool results, or user commitments.
Keep an append-only event log or source messages according to your retention policy. Store the summary with:
- the source range it covers;
- prompt or summarizer version;
- creation timestamp;
- explicit unresolved items;
- references to important source events.
Regenerate summaries after a correction or deletion. Otherwise the source fact may be gone while its paraphrase survives in every future prompt.
Resume workflows from checkpoints, not chat guesses
A durable agent needs exact state for side effects:
workflow_id
current_step
completed_steps
pending_approval
tool_call_id and idempotency key
artifacts produced
last verified outcome
This is thread state, not long-term memory. Persist it transactionally around tool effects and authorize every resume. A model-generated summary saying “payment probably completed” cannot decide whether to charge again.
LangGraph’s persistence model writes checkpoints per thread and uses a separate Store for cross-thread memory. That separation is a useful architecture even when you do not use LangGraph.
Privacy and deletion are part of the schema
Before storing a class of memory, decide:
- purpose and allowed readers;
- whether the model may write, read, or only propose it;
- sensitivity and encryption requirements;
- default TTL and maximum retention;
- export, correction, and deletion paths;
- whether it may cross user, project, or organization boundaries.
Do not store passwords, access tokens, recovery codes, payment data, raw government IDs, or secrets as conversational memory. Use the appropriate system of record and return only the minimum needed fact to the agent.
A delete operation must fan out to the source record, vector and lexical indexes, summaries, caches, checkpoints where applicable, and asynchronous replicas. Use a deletion job with status and retry. Keep a content-free tombstone long enough to stop a delayed indexing event from recreating the record. Verify completion with a read path, not only a successful queue submission.
Evaluate memory as a retrieval-and-write system
Build fixed scenarios from real failure shapes:
| Metric | What the scenario checks |
|---|---|
| Write precision | Did the system store only facts worth retaining? |
| Write recall | Did it retain the explicit permitted fact it should remember? |
| Useful retrieval | Did the task receive the relevant active record? |
| Noise | Did irrelevant memories consume context or change the answer? |
| Contradiction handling | Did newer or higher-authority data win correctly? |
| Isolation | Can one principal ever retrieve another principal’s record? |
| Staleness | Are expired or superseded records excluded? |
| Deletion | Does removed content disappear from every read surface? |
Add adversarial cases: indirect instructions inside a remembered note, a prompt trying to change namespace, a poisoned shared procedure, and a deletion racing a background consolidation job. The memory store is untrusted input to the model and sensitive data to the application at the same time.
Production checklist
- Working state, thread checkpoints, long-term memory, and knowledge retrieval are separate.
- Every durable memory has owner, scope, provenance, timestamps, and sensitivity.
- Explicit facts and inferred candidates use different write paths.
- Conflicts and supersession are resolved by deterministic policy.
- Identity and tenant filters run before semantic search.
- Retrieval has a fixed context budget and exposes provenance.
- Workflow resume uses checkpoints and idempotency, not summaries.
- Shared procedures are reviewed and versioned.
- Correction and deletion propagate through indexes, summaries, and caches.
- Fixed tests cover quality, isolation, staleness, and deletion.
Good memory is selective and boring. The agent recalls the right fact, can show where it came from, forgets it on command, and does not turn yesterday’s chat into today’s authority.