Agentic AI · L-Memory
How an agent built on a stateless model remembers: the session and its compaction, long-term memory and its selection, and the choice of who decides what is kept.
Memory is a service of the runtime, not a property of the model. Part I fixes the vocabulary — three operations and four memory modules — and every later part applies it to one store:
| Part | The question it answers | Sections |
|---|---|---|
| I · Memory Operations and Modules | What does an agent built on a stateless model store, and which operations act on the store? | Runtime Memory: Short-Term & Long-Term · Memory Modules: Working, Semantic, Episodic, Procedural |
| II · Short-Term Memory | How is a session kept within the context window, and what remains recoverable after compaction? | Session Log · Compaction |
| III · Long-Term Memory | What is kept beyond the trial, in which module, and how is each module written, managed and read? | Semantic Memory · Episodic Memory · Procedural Memory |
| IV · Memory Control | Which party computes $W$, $P$ and $R$ — the harness, the model or a fresh agent? | Context Reset vs. Compaction |
Memory Evaluation and privacy close the lecture, and both are organised by operation as well.
A language model keeps no state between two calls, so whatever an agent remembers has been stored by the runtime and placed back into the context. Memory is a component of the harness, described along two independent axes: by operation — what the harness does to a store (write, manage, read) — and by module — the role a store plays for the agent (working, semantic, episodic, procedural). Every mechanism in the later parts is a choice of the three operations, applied to one of the four modules.
The model is stateless: each call re-sends the whole context — the context box of the agent loop, i.e. everything placed into one model call. "Memory" is therefore whatever the runtime stores and re-assembles into that box, and it comes in two durations:
"Short-term" and "long-term" are durations, and durations are a vague way to draw the line. Zhang et al. (2024) draw it at an observable event instead — the end of a trial — and build the definitions from three terms (§3.1):
Each step passes through three phases: the agent stores what it perceived, processes what is stored, and acts on the result (§3). Memory is defined by where its contents come from, and operated by one function per phase — write, manage, read.
Narrow memory is derived only from the current trial: before step $t$ it is the history $\xi_t = \{a_1, o_1, \dots, a_{t-1}, o_{t-1}\}$, and it is emptied when the trial ends (§3.2). Broad memory for task $\mathcal{T}_k$ is derived also from earlier trials $\Xi^k$ and from external knowledge $D^k_t$ (§3.3), with the task index $k$ written as a superscript, $\xi^k_t$; this lecture calls a store the agent does not write a knowledge base (see Memory and Knowledge Base).
| Narrow memory | Broad memory | |
|---|---|---|
| Derived from | $\xi_t$ | $(\xi^k_t,\ \Xi^k,\ D^k_t)$ |
| Survives the end of the trial | no — emptied | yes — across trials and tasks |
| Usual name (§5.1.2) | short-term | long-term |
This lecture treats a session — one persisted conversation — as a trial. Long-term memory is therefore not a vaguer memory — it is the same machinery allowed to survive the end of a trial.
Writing turns the raw outcome of a step into what is actually stored (§3.4):
$$m_t \;=\; W(\{a_t, o_t\})$$
$W$ is a projection: it maps the action $a_t$ and the observation $o_t$ of step $t$ to the record $m_t$, which is meant to be more informative and more concise than the raw pair. The record is natural-language text or a structure derived from it — a fact, a triple, an embedded passage — stored outside the model. The survey also admits a parametric record, written into the model's weights by fine-tuning or knowledge editing (§5); that form lies outside this course, which treats the weights as given. $W$ decides what is worth storing, and in what form — a verbatim turn, an extracted fact, a summary of the step.
Management processes what is already stored, so that it remains useful (§3.4):
$$M_t \;=\; P(M_{t-1},\, m_t)$$
$M_{t-1}$ is the content of the store before step $t$, and $P$ combines it with the new record $m_t$ into the store $M_t$ after it. $P$ is applied again at every step, and it is where the store is improved rather than merely extended:
Management changes records already stored; the new record itself is only added. §3.4 of Zhang et al. (2024) defines management as processing "the stored memory information to make it more effective", and summarising, merging and forgetting each change $M_{t-1}$. Where $P$ performs none of them, it adds $m_t$ and leaves $M_{t-1}$ unchanged — $M_t = M_{t-1} \cup \{m_t\}$, or, for a store kept in order, $m_t$ placed after the last record — and the store grows by one record per step without being managed. An append-only log is a store of exactly this kind.
The reach of $P$ is what separates the two definitions of memory. For narrow memory it iterates only inside one trial, and the store is emptied when the trial ends. For broad memory it iterates across trials and tasks, and it also takes in external knowledge.
Reading selects from the store what the next action needs (§3.4):
$$\hat M_t \;=\; R(M_t,\, c_{t+1})$$
$c_{t+1}$ is the context of the next action — the task and the situation at step $t+1$ — and $\hat M_t$ is the part of the store $M_t$ selected for it. $R$ is usually implemented as a similarity between each record and $c_{t+1}$, and $\hat M_t$ becomes part of the prompt that produces the next action. $R$ therefore decides which records the next action gets; a record that is stored but never selected has no effect on the agent.
A prompt is filled by one read per store. An agent that keeps both a working memory $M_t$ and a long-term store $L_t$ reads each of them, and the two results share one context window of $T_{\max}$ tokens:
$$\hat M_t \;=\; R_M(M_t), \qquad \hat L_t \;=\; R_L(L_t,\, c_{t+1}), \qquad \lvert c_{t+1}\rvert + \lvert \hat M_t\rvert + \lvert \hat L_t\rvert \;\le\; T_{\max},$$
where $\lvert x\rvert$ is the length of $x$ in tokens and the subscript names the store that is read. $R_L$ selects: a long-term store holds more records than one prompt, so $R_L$ returns the $k$ records most similar to $c_{t+1}$. $R_M$ usually renders working memory whole and in order, and does not use $c_{t+1}$; the bound on $\hat M_t$ is then enforced by $P$, as compaction (Compaction). Zhang et al. write one store and one $R$ for both. Without a subscript, $R$ denotes either read — a statement about $R$ holds for $R_M$ and $R_L$ alike, and where only one store is meant, the context names it; $W$ and $P$ are written the same way.
The three operations compose into the agent loop, from the outcome of step $t$ to the action of step $t+1$:
$$a_{t+1} \;=\; \mathrm{LLM}\bigl(c_{t+1},\ \hat M_t\bigr), \qquad \hat M_t \;=\; R\bigl(P(M_{t-1},\, W(\{a_t,o_t\})),\; c_{t+1}\bigr)$$
Here $\mathrm{LLM}$ is the model, read as a map from a prompt — the context $c_{t+1}$ together with the selected records $\hat M_t$ — to the next action. Read from the inside out: the step is written as a record, the record is managed into the store, the store is read against the next context, and the model acts on the context and what was read. Applying the loop at every step reproduces the whole interaction between agent and environment. With a long-term store as well, the model receives both reads, $a_{t+1} = \mathrm{LLM}(c_{t+1},\ \hat M_t,\ \hat L_t)$, and $W$, $P$ and $R$ act on each store separately.
A knowledge base read by retrieval-augmented generation adds a further argument to $\mathrm{LLM}$; it is not part of $M_t$, because the agent does not write it.
Whatever the store is made of, an agent does exactly these three things to it, so a memory design is specified by its choice of $W$, $P$ and $R$ — and published systems differ in exactly that choice.
This lecture calls a store memory when the agent writes it, and a knowledge base when it is written by others and only read. Memory is filled from the agent's own experience, by the write operation $W$ applied to its steps; a knowledge base — a document corpus, a product catalogue, a wiki — is written outside the agent, even when it is held in the same vector database. The convention is the lecture's own; the literature draws the line in more than one place. The founding RAG paper calls a dense Wikipedia index a non-parametric memory (Lewis et al., 2020), and the nearest sourced criterion, CoALA's controllability, asks who may write the store, not who wrote it (Sumers et al., 2024, §7). The convention decides which operations apply: memory is written by $W$, managed by $P$ and read by $R$; a knowledge base is only read.
Reading from a knowledge base is retrieval-augmented generation (RAG). A retriever $R_D$ selects the passages of the knowledge base $D$ most similar to the context, and the prompt carries both selections:
$$\hat M_t = R_M(M_t), \qquad \hat L_t = R_L(L_t,\, c_{t+1}), \qquad \hat D_t = R_D(D,\, c_{t+1}), \qquad a_{t+1} = \mathrm{LLM}\bigl(c_{t+1},\ \hat M_t,\ \hat L_t,\ \hat D_t\bigr)$$
$R_D$ uses the same mechanism as $R_L$ — similarity to $c_{t+1}$ — applied to a store the agent does not write; all three results share the window of $T_{\max}$ tokens.
What triggers the retrieval decides where it sits in the loop:
| Retrieval triggered by | Where it sits | Instance |
|---|---|---|
| the harness, before every model call | reading: $R$ over memory, $R_D$ over a knowledge base | RAG in its original form: retrieve for each turn and place the result in the prompt |
| the model, through a search tool | a step: the call is an action $a_t$, its result the observation $o_t$; what is kept of it reaches memory through writing, $W$ | agentic RAG: the model decides whether to search, and for what |
In the second case the knowledge base is reached like any other part of the environment, and only what the agent writes down from the observation becomes memory. The survey's external knowledge form of memory — information fetched through a tool when it is needed (Zhang et al., 2024, §5.2) — is this case.
The model is stateless, so everything an agent knows sits in one of four memory modules — one short-term, three long-term. The decomposition comes from Soar, a cognitive architecture — a program that models human problem solving with separate memory stores — and was carried into language agents by Sumers et al. (2024).
| Type | Stores | In practice |
|---|---|---|
| Working (short-term) | the current decision cycle (one pass of observe, decide, act) — perceptual input, knowledge just retrieved or reasoned, the active goals | the context box and the runtime's own state; each prompt is synthesised from it, each output parsed back into it |
| Semantic | facts — "knowledge about the world and itself": user preferences, facts the agent has inferred, and — in CoALA's reading — a corpus loaded from outside | a user profile (JSON) or a collection of facts (LangChain, 2026, Core Concepts); recalled by similarity |
| Episodic | experiences — "experience from earlier decision cycles" (CoALA); LangMem narrows it to successful interactions (LangChain, 2026, Core Concepts) | few-shot examples of past runs ("how I did this before") |
| Procedural | how-to — two stores at once: the model weights, and the agent's own code | the system prompt and skill files; self-refinable via reflection (→ L-ToT) / prompt optimisation (→ L-Eval) |
Working memory is not the context window. Sumers et al. define it as "a data structure that persists across LLM calls" — the context is one rendering of it. The distinction matters for compaction: shortening the rendering need not shorten the store, so a summary may replace old turns in the context while the complete record remains on disk.
Short-term memory is kept in two stores, and compaction manages only one of them. Both are derived from the current session alone — the narrow memory of Narrow and Broad Memory:
| Store | $W$ | $P$ | $R$ |
|---|---|---|---|
| session log (JSONL) | append every step verbatim | none — nothing is rewritten | only to recover or to audit |
| working memory $M_t$ | the record $m_t$ of each step | compaction | renders $M_t$ into the prompt |
The context window bounds the rendering, not the list, and the usable bound is shorter than the window: in multi-document question answering, GPT-3.5-Turbo answers less accurately with the answer document in the middle of its context than with no document at all, from its weights alone (56.1 %, the closed-book accuracy; Liu et al., 2024). Two designs keep the rendering within the bound. Trimming leaves the list unchanged and lets the read $R_M$ render its longest suffix that fits, starting at a user turn so that no tool result appears without its call. Compaction — a management step $P$ — shortens the list itself, for example by a rolling summary into which the messages leaving the window are folded (Packer et al., 2024). A record removed from $M_t$ remains recoverable exactly as long as the log still holds it.
A session log written only by appending is stored one record per line, and the properties below follow from that layout. A session — one persisted conversation, one trial — is stored as JSONL (JSON Lines): one JSON object per line, one line per event, and the log is written by a single operation, append. JSONL is a convention in wide use for logs, event streams and growing conversation histories. The records below are a simplified example from the session files of the agent toolkit on which OpenClaw is built (Völkl, 2026a); their field names belong to that implementation.
{"type":"message","role":"user","content":"Hi","id":"c3","parent_id":"a1"}
{"type":"message","role":"assistant","content":"Hello!","id":"e5","parent_id":"c3"}
{"type":"compaction","summary":"user greeted","id":"g7","parent_id":"e5"}
parent_id. Editing an earlier
message or retrying a turn appends a new record with the same parent, which creates a branch;
the conversation currently continued is the path from the latest record (the leaf) back to the
root.Compaction is the manage operation $P$ applied to working memory: it replaces the records before a cut point by one record and keeps the records after it verbatim. With the record $m_t$ of step $t$ written by $W$,
$$M_t \;=\; P(M_{t-1},\, m_t) \;=\; \bigl(\,s_k,\; m_{k+1}, \dots, m_t\,\bigr), \qquad s_k \;=\; \sigma(m_1, \dots, m_k),$$
where $k < t$ is the cut point and $\sigma$ maps the records up to it to the single record $s_k$ that stands in for them; the forms of compaction differ in the choice of $\sigma$. Between two compactions $P$ only appends $m_t$; each compaction moves $k$ forward, and $\sigma$ then receives the earlier $s_k$ in place of the records it already replaced — so a second summary summarises the first.
Each form of compaction is either a write $W$, which shortens the record of a step before it enters working memory, or a management step $P$, which changes records already in it. The forms differ in what they remove, whether they call a model, and whether every record left in $M_t$ is still text from the log.
Under compaction, $R_M$ selects nothing: $\hat M_t = R_M(M_t) = M_t$, so every record in $M_t$ is in the next prompt, and which records of the session reach the prompt is decided by $P$ alone.
| Form | Operation | What it does | Removed from $M_t$ | Model call | Every record in $M_t$ is verbatim from disk or a marker |
|---|---|---|---|---|---|
| persist | $W$ | if the observation $o_t$ exceeds a size limit, $o_t$ is written to a file, and $m_t$ holds the file path and the first lines of $o_t$ instead of $o_t$; records already in $M_{t-1}$ are not changed | the full $o_t$ — it never enters $M_t$ | no | yes |
| sliding window | $P$ | keeps the last $N$ records and deletes all earlier ones: $\sigma$ returns the empty record | whole steps $m_1, \dots, m_{t-N}$ | no | yes |
| placeholder (also called pruning) | $P$ | replaces the content of every observation older than the last $n$ by a one-line marker — Old output omitted (101 lines) in SWE-agent (Yang et al., 2024) — or by the file path saved by persist; the action $a_j$, the tool call, stays in $M_t$ at its position |
the content of old observations | no | yes |
| token deletion | $P$ | a small language model (GPT-2 or LLaMA-7B) computes, for each token $x_i$ of a record, the probability $p(x_i \mid x_{<i})$ given the tokens before it; the tokens with the highest probability carry the least information, $-\log p(x_i \mid x_{<i})$, and are deleted until the text reaches a target length (Jiang et al., 2023) | single tokens inside records | a small model | no — records are shortened token by token |
| summarise | $P$ | a model call writes one text $s_k$ that replaces $m_1, \dots, m_k$ | old steps | yes | no — $s_k$ is new text |
A placeholder keeps the record and removes only its content. Model APIs reject a tool call whose result is missing, so the result record of a call has to remain; the marker in it states that the call returned output, how much, and — where it holds a path — where the agent can read that output again with a tool. For the same reason a sliding window never places its cut between a tool call and its result.
Extraction to long-term memory removes nothing from $M_t$. It is a second write $W$ applied to the same step $\{a_t, o_t\}$: a model call derives facts from it — a preference, a name, a decision — and stores them in the long-term store (Extraction), while $m_t$ enters $M_t$ as before. It changes what a later compaction loses: after a window or a summary has removed the step from $M_t$, the facts extracted from it return to the prompt when the long-term read $R_L$ selects them.
Restoring is a lookup only while working memory is a sub-selection. After a persist, a window or a placeholder every record in $M_t$ is verbatim, or a marker at its original position, so the lost content is recovered by reading the log. A summary is new text written by a model: it is not in the log, undoing it means reading the turns again, and any error it contains has entered $M_t$ as if it were established.
Long-term memory consists of three modules — semantic, episodic and procedural — and each module is one choice of $W$, $P$ and $R$, as The Memory Loop states for every memory design. The three sections of this part follow the rows of the table:
| Module | $W$ — what is stored | $P$ — how it is managed | $R_L$ — how it is read |
|---|---|---|---|
| Semantic — facts | facts extracted by a model call, admitted by a scope test | consolidation: duplicates merged, contradictions resolved | similarity to $c_{t+1}$ |
| Episodic — experiences | the steps, verbatim and dated, without a model call | reflection: insights derived from episodes, stored as new records | recency · importance · relevance |
| Procedural — how-to | skill files, by a designer; a revision only after validation | versioning | in stages: description first, body on a match |
The current session reaches the prompt through working memory, read whole by $R_M$; the three long-term stores contribute records from earlier sessions, selected by $R_L$. The edge from episodic to semantic memory is reflection, the one operation that moves content between modules.
Semantic memory stores what an extractor concludes from the conversation, not the conversation. Its write $W$ is a model call that returns short facts; each fact is embedded and stored under the user's id, and the read $R_L$ is a similarity search restricted to that id (Mem0, 2026). The design has to settle which candidate facts are admitted (Extraction) and how a stored fact is replaced when a later turn contradicts it (Consolidation). Similarity is not relevance: a record about the user's favourite cuisine can outrank one about an allergy, because both concern food.
The write is a filter: after a turn a model proposes candidate facts, and a candidate is stored only
if it holds beyond the current trial — tagged persistent rather than current_task, in the file
design below. The record takes one of three forms:
| Record | Store | Instance |
|---|---|---|
one markdown file per fact, listed in an index MEMORY.md |
files, read through the index | claude-code |
| one embedded sentence per fact | a vector store scoped by user_id / run_id |
mem0 (Mem0, 2026) |
| an instance of a schema — text, a triple, a profile | a key–value store; a record is patched by its id | LangMem (LangChain, 2026) |
Relative expressions are resolved at the write. "Last week", stored verbatim and read a month later, names the wrong week, so $W$ replaces it by an absolute date and a pronoun by a name. Without that step the F1 on LoCoMo's temporal questions falls from 58.62 to 25.40 (Liu et al., 2026, Table 5).
Consolidation removes what is redundant from a semantic store: once the store exceeds a size threshold, a model merges duplicate, contradictory and stale records, on a copy that is restored if the merge fails (shareAI-lab, 2025). A contradicted fact is resolved at one of three points:
| Policy | Mechanism | Trade |
|---|---|---|
| replace at write time | a model patches the record by id (Langmem: LangChain, 2026, How-to Guides) | one current value; the old one is lost |
| append, resolve at read time | the new record is added beside the old; dates decide when reading (Mem0, 2026) | nothing is destroyed; every read must decide |
| invalidate | the old record is marked invalid and kept (Zep: Rasmussen et al., 2025) | history and a current value, at the cost of timestamps |
Episodic memory keeps the record of what happened, as it happened. The steps are stored verbatim, without a model call, and tagged with their session and date, so the record keeps what an extractor would discard, such as a confirmation number (Mem0, 2026). Many questions about episodes are predicates on their structure — the last turns of a session, the sessions of a week, the sessions with a tool call — which a relational table answers exactly and a similarity search only approximates. The memory stream of Generative Agents (Park et al., 2023) — one dated natural-language record per observation — is such a store: it is read by a score (Scored Recall) and managed by reflection (Reflection).
$R_L$ ranks by more than similarity, because the most similar record may be old or trivial. Park et al. (2023) score each record $m$ of the memory stream against the query $q = c_{t+1}$ and place the top-ranked records that fit:
$$\textit{score}(m) \;=\; \alpha_{\text{rec}}\cdot \text{recency}(m) \;+\; \alpha_{\text{imp}}\cdot \text{importance}(m) \;+\; \alpha_{\text{rel}}\cdot \text{relevance}(q, m),$$
each term min–max normalised over the candidates (smallest value $\mapsto 0$, largest $\mapsto 1$), all weights $\alpha = 1$.
| Term | Computed as | Computed |
|---|---|---|
| recency | $0.995^{h}$, $h$ hours since the record was last accessed | per query, no model call |
| importance | the model's 1–10 rating, from "purely mundane" to "extremely poignant" | once, at the write |
| relevance | cosine similarity of record and query embeddings | per query |
The weights are the memory policy. With $\alpha_{\text{rec}} = \alpha_{\text{imp}} = 0$ the score is plain similarity, which ranks by wording, not currency: for "Where does Anna live?", the outdated "lives in Berlin" outranks "moved to Hamburg".
Reflection turns episodes into records that no single observation contains — the answer to "who would you spend an hour with?" generalises over many events. In Generative Agents (Park et al., 2023, §4.2):
Each insight is stored in the stream with pointers to the records it cites, and a reflection may cite earlier reflections, so the store grows trees of reflections: observations at the leaves, increasingly abstract insights above them, each checkable against its evidence.
Procedural memory is the part of the agent that decides how it acts, and in an agent built on a fixed model it is largely prompt text — a system prompt, a skill, the rules of a tool loop. It is initialised by the designer, and writing it is the risky operation (Sumers et al., 2024, §4.1). Keeping each version under its own key makes every change an explicit, reversible write, and a revision produced from trajectories by a prompt optimiser is promoted only after a validation check. Skills are the form in which such text is stored and read.
A skill is procedural memory read in stages, so its prompt cost grows with the number of skills,
not with their length. A skill is a directory containing a SKILL.md — YAML frontmatter with name
and description, then a Markdown body — and optional scripts/, references/, assets/ (Agent
Skills specification; Anthropic, 2026). The format is an open standard, published at
agentskills.io. A designer writes it; the model reads it (progressive
disclosure):
With $n$ skills, $d \approx 100$ tokens of metadata and $b \lesssim 5000$ tokens of body each, the resident cost is $n\,d$ — $4\,000$ tokens for $n = 40$ — plus $b$ per activated skill, against $n\,b \approx 200\,000$ tokens for loading every body (→ L-Att). A skill supplies instructions and does not enforce them; a rule for every call belongs in a hook (→ L-Gateway). (Sources: Anthropic, 2026; Sabherwal & Agarwala, 2026.)
Memory control — which party computes $W$, $P$ and $R$ — is a design decision of its own (Sumers et al., 2024): the harness by fixed rules, the model by emitting memory operations as actions, or a fresh agent from a handoff.
| Design | $W$ | $P$ | $R$ |
|---|---|---|---|
| compaction pipeline | harness | harness; the summary by a model call | harness |
| Mem0 (Mem0, 2026) | harness, add after every exchange |
exact-duplicate check only | harness |
| LangMem (LangChain, 2026) | model, by tool — or a background manager | background manager | model, by tool |
| MemGPT (Packer et al., 2024) | model, by function call | harness, at the flush | model, by function call |
| MemLLM (Modarressi et al., 2025) | model emits MEM_WRITE |
none needed — a triple is unique | model emits MEM_READ |
| context reset | the ending agent writes a handoff | working memory is emptied | the new agent reads the handoff |
A rule cannot anticipate what a task will need, a model may omit its memory calls, and a handoff carries only what was written into it.
A context reset empties working memory and starts a fresh agent from a handoff $h$ written by the
ending session, $M \leftarrow h$ (Rajasekaran, 2026). The handoff is not a message but a set of
files in the environment, which the new agent reads with its tools: in the harness of Young (2025), a
progress file of what has been done, the git history with one descriptive commit per completed step,
and a JSON feature list in which each feature carries a passes flag. A new session begins by reading
the progress file, the git log and the feature list, and then selects the highest-priority feature not
yet passing.
| Compaction | Context reset | |
|---|---|---|
| The history | summarised in place; the same agent continues | cleared; a new agent starts from $h$ |
| Costs | whatever the summary dropped | orchestration, tokens and latency (below); $h$ must carry enough state |
A reset costs a second agent start. The harness must decide when to end the running agent, launch the next one and pass it $h$ — the orchestration — and the new agent spends tokens and time rebuilding its working state from $h$ before it continues the task; Rajasekaran (2026) names these costs "orchestration complexity, token overhead, and latency".
A reset repairs context anxiety, which compaction cannot: the model "begin[ning] to wrap up work prematurely as [it] approach[es] what [it] believe[s] is [its] context limit". A shorter history does not change that belief; an empty one does. One harness needed resets on Sonnet 4.5 and none on Opus 4.5 (Rajasekaran, 2026), so an inherited reset is re-tested.
A memory benchmark hides questions inside a long conversation history, spread over many sessions, and scores the answers — so an end-to-end score says whether a memory system failed, not which operation failed.
| Benchmark | Setting | Question types |
|---|---|---|
| LoCoMo (Maharana et al., 2024) | 10 conversations, ~600 turns, up to 32 sessions each | single-hop · multi-hop · temporal · open-domain · adversarial (unanswerable) |
| LongMemEval (Wu et al., 2025) | 500 questions in histories of ~115 K to ~1.5 M tokens | extraction · multi-session · knowledge updates · temporal · abstention |
Stage-wise evaluation locates an error at the operation that made it, where LoCoMo and LongMemEval score only the final answer and cannot tell whether the write, the management or the read failed. HaluMem — a benchmark of hallucinations in memory systems (Chen et al., 2025) — annotates a gold standard for each operation: the memory points a dialogue should cause to be stored, the old → new pairs it should cause to be updated, and the answers:
| Operation | Compared | Failure it isolates |
|---|---|---|
| write | extracted records vs. gold memory points | a fact never stored, or one invented |
| manage | applied updates vs. gold old → new pairs | an update omitted or applied wrongly |
| read + use | answer vs. gold answer | a wrong recall, or an unsupported answer |
The failures start at the write: four of five measurable systems extract fewer than 60 % of the gold memory points, most omit more than half of the updates, and none answers more than 70 % correctly — an update cannot be applied to a fact that was never written.
What a persistent agent stores about its users, for how long, and whether they can delete it, is decided by the three operations.
For security the dangerous operation is $W$. Greshake et al. (2023) hide an instruction in content the agent retrieves with a tool, such as a web page — an indirect prompt injection — and the model, which cannot distinguish instructions from data in its context, obeys it and calls its memory tool to store part of the payload in its key-value store. After a session reset the agent behaves correctly until it reads its notes, when "it re-poisons itself". A reset empties working memory, not the long-term store, and a stored record is read back indistinguishable from a legitimate one — so the check belongs at the write. The same holds for a wrong generalisation written by consolidation or reflection.
lecture-Memory-exercises.ipynb: a one-step Bayes update; why JSONL over JSON.
lecture-Memory-lab.ipynb: implement a session store — the AgentSession pattern: a JSONL
writer/reader — and a simple compaction step (summarise old turns).
Peer-reviewed papers
Preprints & other non-peer-reviewed papers
MEM_WRITE / MEM_READ API over a structured triple store: schema-level deduplication, thresholded retrieval, eviction of the read call from the context, and the write / retrieve / use error decomposition.SUMMARIZE / PRUNE as high-level actions of the prompting MDP (§5.3), and §6.3 naming the bounded context window as an open problem whose two candidate answers are intermediate-computation prompting and retrieval of past observations.(task, observation, action, Q-value) records updated by Q-learning and retrieved as encouraged and discouraged actions; the ablation in which the discouraged actions matter most.Textbooks & monographs
Blogs, documentation & other web sources
SKILL.md format: required name / description, the scripts/ references/ assets/ layout, three-stage progressive disclosure. https://agentskills.io/specificationMEMORY.md index; the first 200 lines / 25 KB of the index loaded at session start; memory files read on demand with the model's file tools; four memory types.add) and reads before the next (search). ⚠ The current release extracts append-only, without the update and delete operations its 2025 paper describes.MEMORY.md and memory/*.md, indexed into SQLite with FTS5 and embeddings.parent_id, and the reasons given for the format: appending without rewriting the file, and reading it line by line.