Claude & OpenAI: Deconstructing Agent Memory
A coding agent needs memory it can retrieve.
Concept. An LLM model only sees the context supplied for its current call. Agent memory persists decisions outside the model, then retrieves relevant rows for later context. One SQLite file can support local memory. A replicated database can support memory across a global product.
Intuition. Storage preserves information across calls. Retrieval decides what the model sees again. That split between working context and persistent memory are key ideas for this course.
Figure: Agent memory from local retrieval to a global serviceThree panels left to right. A model call can miss an earlier decision when the current context does not contain it. A local agent can retrieve saved project evidence from SQLite. A global product can serve user memory from a replicated Postgres deployment supporting 800 million users.
| 1 · Model alone | 2 · + Local memory | 3 · + Global memory |
|---|---|---|
| ✗ Hallucinates a function | ✓ Looks it up · per laptop | ✓ One per user · ×800M |
Figure 1. Context (or memory) lives outside the model. The current context is short-term working memory, limited to what a single call includes. A local agent persists saved evidence in an embedded database (SQLite on one machine) that survives every session. OpenAI reports a read-heavy Postgres deployment serving 800 million users, with one primary and nearly 50 read replicas.
A new session can miss prior decisions
On Monday you and Claude Code build a custom auth module. You choose several function names, fix an edge case, and ship it. On Tuesday you open a new session and ask Claude to extend the module. If the new request neither includes Monday's decisions nor retrieves the relevant code, the agent may call a plausible function such as verifyJWTWithScope(), even though that function does not exist.
That is a hallucination: a confident output unsupported by the available evidence. A second failure mode is rediscovery, where the agent repeats work because it cannot retrieve an earlier decision.
Figure: A plausible answer is still wrongOn Tuesday you ask the agent to extend the auth module you built on Monday. The current request does not include the earlier decision, and the agent does not retrieve the relevant code. It predicts a plausible function named verifyJWTWithScope, but the codebase contains no such function.
Figure 2. Monday produced a working module. Tuesday's request does not contain the earlier decision. The agent generates verifyJWTWithScope() from patterns rather than retrieved evidence. Persistent memory gives the next session something to query.
The context window is the agent's working-memory limit
Remember the RAM limit from the previous case study: a fast working memory that cannot hold the whole problem. An agent hits the same limit, with a different name.
Modern agents work inside a context window, the text the model receives for one request. Current Claude models support roughly 200,000 to 1,000,000 tokens, depending on the model and deployment. A chat application may save an earlier transcript, but the model sees it again only when the application includes or retrieves it for the next request.
Figure: The context window is working memoryThree model calls run left to right. The first context reaches its token limit. Later calls contain only the context the application supplies. A persistent database below the calls retains saved records, and retrieval selects which records return to a later context.
Figure 3. The context window stays bounded at roughly 200,000 to 1,000,000 tokens. Persistent memory can retain records outside that window across sessions. The application retrieves selected records when a later request needs them.
Local memory: a database on your machine
Figure: Local memory: capture, store, retrieveLocal agent memory. A model captures records in SQLite on your machine. Keyword search uses FTS5. Vector search can use Chroma or sqlite-vec: claude-mem documents Chroma, while QMD uses sqlite-vec. Retrieved records return to the model through the retrieval arrow.
Figure 4. Local memory captures records in SQLite and retrieves selected evidence into later context. The diagram shows FTS5 keyword search and Chroma or sqlite-vec for vector search. claude-mem documents an optional Chroma index; QMD uses sqlite-vec.
QMD, created by Tobi LΓΌtke, is a local search engine for documents, notes, and code (github.com/tobi/qmd). It stores indexed content in SQLite, uses FTS5 for keyword search and sqlite-vec for vector search, and exposes retrieval through its CLI and MCP server. An agent can retrieve a saved function name instead of guessing it.
The tools solve related problems with different designs. claude-mem records sessions, observations, prompts, and summaries in SQLite. Aider builds a compact repository map and uses graph ranking to choose which code definitions fit in the active context.
SQLite fits local memory for four practical reasons:
-
No separate database server. The local tool opens SQLite directly.
-
Embedded. SQLite runs inside the local process or service without a network hop.
-
Transactional. A write mid-task must not corrupt the database if the laptop sleeps or the process dies.
-
One file. You can copy it, back it up, or inspect it with a SQL client.
Global memory: the same need, at scale
Figure: Global memory: one primary, nearly 50 read replicasChatGPT users send writes to one PostgreSQL primary. The primary replicates changes to nearly 50 read replicas across regions. Read results return from the replicas to the users. This is a simplified view of OpenAI's reported read-heavy PostgreSQL deployment.
Figure 5. OpenAI reports one Azure PostgreSQL primary and nearly 50 read replicas supporting a read-heavy workload for 800 million users. The primary accepts writes and replicates changes across geographic regions; the read replicas serve queries and return results to users.
Local agent memory and global product memory store different records, but they use the same systems principle: memory lives outside the model. A local tool can use one SQLite file. OpenAI's read-heavy product workload uses PostgreSQL replication to distribute queries across many machines.
The next case study applies the same local-to-global progression to UberEats, where diners, drivers, and restaurants must agree on every order.
Takeaway: Agent memory stores records outside the model and retrieves relevant evidence into a later context. SQLite supports the local case, while replicated databases support larger products.
Going deeper
How the database and the retrieval work, in detail.
The observations table
An illustrative agent-memory schema can fit in one table:
CREATE TABLE observations (
id INTEGER PRIMARY KEY, -- unique row id; no two observations share one
session_id TEXT, -- which working session produced this
project TEXT, -- which codebase/project it belongs to
created_at TIMESTAMP, -- when it was written; used to sort by recency
kind TEXT, -- 'decision' | 'pattern' | 'bug-fix' | 'todo'
content TEXT, -- the actual remembered text the agent searches
embedding BLOB -- optional vector; some systems store it separately
);
-- Indexes make the common lookups fast (more on indexes in Module 3).
CREATE INDEX idx_session ON observations(session_id); -- "everything from this session"
CREATE INDEX idx_project ON observations(project); -- "everything in this project"
QMD's index lives at ~/.cache/qmd/index.sqlite with the sqlite-vec extension and SQLite's built-in FTS5 module. claude-mem stores sessions, observations, prompts, and summaries in SQLite and can add an optional Chroma vector index. Aider's repository map is a separate code-context mechanism.
What compaction costs
Long histories may be summarized before they return to the context. Summaries use fewer tokens but omit detail. A system can retain the original records for later search while injecting only the shorter summary into the active context.
Three ranking signals
Memory retrieval systems rank different kinds of evidence. QMD combines keyword and vector search with reranking. Aider ranks definitions in a code-dependency graph. These signals can complement one another, but they do not have to live in one table or execute as one SQL expression.
Figure: Three retrieval signals feed combined fusion rankingThree vertically stacked boxes show BM25 keyword matching, vector similarity, and graph ranking. Arrows connect each signal to a fourth box for combined fusion ranking, which merges ranked candidates, removes duplicates, and selects evidence for the next context. This illustrates a possible combined pipeline, not a claim that every tool uses all three signals.
Figure 6. BM25 ranks stored text by term matches. Vector similarity ranks stored text by embedding distance, so "login" can match "auth." Graph ranking orders code definitions by their relationships to other definitions. The fourth box illustrates combined fusion ranking: merge ranked candidates, remove duplicates, and select evidence for the next context. This is a possible combined design; QMD and Aider do not necessarily use all three signals.
1. Keyword search with BM25. Classical full-text search weighted by term frequency and inverse document frequency, built into SQLite via FTS5. Best for exact terms: "find where we mentioned verifyJWTWithScope."
-- "What did we decide about auth in this project?"
-- observations_fts is an FTS5 virtual table over observations.content.
SELECT o.content FROM observations o
JOIN observations_fts f ON f.rowid = o.id
WHERE observations_fts MATCH 'auth'
AND o.project = 'cs145'
AND o.kind = 'decision'
ORDER BY bm25(observations_fts)
LIMIT 10;
2. Vector similarity. Embedding-based semantic search. An embedding model converts the question to a vector. The agent retrieves observations with nearby vectors. Best for paraphrase: "what are we doing about token refresh?" surfaces any observation about session lifetime even if "refresh" never appears.
-- :query_embedding is computed beforehand by an external embedding model.
SELECT content FROM observations
WHERE project = 'cs145'
ORDER BY vec_distance_cosine(embedding, :query_embedding) ASC
LIMIT 10;
3. Graph ranking. Aider's RepoMap uses tree-sitter to extract definitions and references, builds a dependency graph, and ranks the portions that fit the available token budget. This operates on code structure rather than text similarity.
The three signals answer different questions. BM25 catches the words you used. Vectors catch related meaning. Graph ranking finds structurally important code. A retrieval pipeline can filter by project or recency, combine scores, and place the highest-ranked evidence into the next context.
Video
Play video: π Claude & OpenAI: Deconstructing Agent Memory