Heidelberg AICurriculum
Track 15 · Advanced
15.2

Memory is a write problem

Extraction, consolidation, and knowing when a fact stops being true

8 lessons 2026-08-13 AI-generated

1Overview

The write side of an agent memory system: extraction from conversation, consolidation against what is already stored, invalidation, and forgetting.

The RAG chapter taught retrieval over a corpus that sits still. Memory is the opposite problem: the corpus is being written, constantly, by a conversation — and almost every memory project fails on the write path rather than the read one. → What to extract from a transcript, how to merge a new fact with a contradicting old one, when to forget, and how to show what was dropped. → Two live systems anchor it: a memory layer you add to an app, and a runtime whose agents edit their own memory blocks.

Where memory systems actually fail. Not retrieval — writing: what to extract, how to merge a contradiction, when a fact stops being true, and what to throw away. Built on two live systems and on the failure mode they both have to manage, which is a store that grows until nothing in it can be trusted.

1.2After this chapter you can
Separate the read path from the write path and say why the write path is harder
Extract durable facts from a transcript instead of storing the transcript
Resolve a new fact that contradicts a stored one
Decide what expires, when, and what must be extracted before it does
Show a user what the system remembered and let them correct it
Recognise memory turning into garbage before it is unusable
1.3When to reach for it

As soon as an assistant needs to know something a user told it in a previous session, and re-sending the whole history stops being affordable.

1.4Key parts

An extraction step, a dedupe and merge policy, an invalidation rule, an expiry job, and a surface where a human can see and correct what was stored.

1.5Free vs paid

Both anchors are open source and self-hostable, and both also sell a hosted tier. Self-hosted, the running cost is a database and the extraction model.

1.6Watch out

Storing everything is the same as storing nothing. Volume is the failure mode, and curating it after the fact does not work — the policy has to exist before the store does.

2Lessons 8

2.1 Distinguish the write responsibilities in a memory system

The four write jobs – Extraction, Consolidation, Invalidation, Forgetting – are the responsibilities that determine what enters and leaves the memory store.

Separate reading from writing in a memory system and explain why failures occur on the write side

  1. Examine the retrieval description and note the added question marked Memory that asks what enters the store
  2. List the four write jobs – Extraction, Consolidation, Invalidation, and Forgetting – and describe how skipping any degrades performance
  3. Compare a demo that only shows read (retrieval) with one that also tests the store, observing that the latter reveals write‑side failures
  4. Configure a max_memories limit in the memory client to trigger automatic compaction and merging of duplicate memories for continual consolidation
  • You'll see Two assistants receive the same transcript; one stores it raw, the other extracts facts first, and after contradictory updates only the extracted version returns a single current answer
  • Takeaway Write determines what should exist in the store and for how long, which is where memory systems actually fail
  • Check What happens to performance when one of the four write jobs—Extraction, Consolidation, Invalidation, or Forgetting—is skipped?
  • Cost Nothing to reason about. The cost shows up later, as a system that is expensive to fix because nobody decided the write policy before the store existed.

2.2 Distinguish library‑based and runtime‑based memory systems

A mem0 client instantiated in code and its client.add() call represent a library‑based write path, while the Letta agent’s memory_replace tool embodies a runtime‑based write.

Identify whether a memory system is a library or a runtime based on where its write path executes

  1. Install mem0 with pip install mem0ai
  2. Instantiate a mem0 client in your application code
  3. Call client.add() after a turn to write a memory entry
  4. Start the Letta server and create an agent on it
  5. Invoke the agent’s memory_replace tool inside its reasoning loop to modify a memory block
  • You'll see The same fact – “the user prefers dark mode” – arriving via an explicit client.add() call for mem0 and via a memory_replace tool call inside a Letta agent’s transcript
  • Takeaway A library writes when your code tells it to, a runtime writes when its own agent decides to
  • Check How can you identify whether a memory system’s write operation occurs in your application code versus inside the agent’s reasoning loop?
  • Cost Free to reason about — both are open source and self-hostable. mem0 and Letta each also sell a hosted tier; self-hosted, the running cost is a database plus whichever model does the extraction or the agent reasoning.

2.3 Extract durable facts from a conversation

The infer=True setting in the mem0 Code Editor activates fact extraction mode, causing only essential statements to be stored as discrete facts.

Create a store that keeps only the essential facts instead of the full transcript

  1. Open the mem0 settings in Code Editor and set infer=True to enable fact extraction mode
  2. Run the conversation through mem0 so the LLM extracts statements such as "user's name is Priya" and stores only those facts
  3. Verify the store contents by opening Data Viewer, where you will see a list of extracted facts rather than full messages
  4. If you need to keep the original text, switch infer to False in Code Editor and re‑run the conversation
  • You'll see A query a week later returns a single‑line answer from the extracted store while the raw store shows three paragraphs to read through
  • Takeaway Extracting facts at write time eliminates repeated work on every read and makes a dense store as useful as an empty one
  • Check What change do you observe in the store contents after enabling infer=True for fact extraction?
  • Cost One LLM call per turn (or per batch of turns) for the extraction step itself. Cheaper in total than storing raw text, because every later read is cheaper too.

2.4 Resolve conflicting facts when writing memory

The ADD, UPDATE, and DELETE buttons together with the algorithm dropdown’s ADD‑only option define the write strategies for handling contradictory memories.

Pick a write strategy for contradictory facts and see how each approach stores the information

  1. Retrieve the top‑K similar memories and click ADD when no match exists
  2. When a similar memory is found, click UPDATE to augment it with new detail
  3. If the new fact contradicts an existing one, click DELETE then ADD the new version
  4. Switch mem0 to the single‑pass mode by selecting ADD‑only in the algorithm dropdown
  5. Append a new string to a Letta memory block using memory_insert
  6. Overwrite an entire Letta memory block with memory_replace
  • You'll see The same contradiction appears three ways: an ADD/UPDATE/DELETE operation that replaces "lives in Mumbai" with "lives in Bangalore", an ADD‑only write that keeps both dated entries, and a Letta agent that silently rewrites its own human block without external record
  • Takeaway Overwrite, keep both, or trust the agent to reconcile itself — three real designs, not one correct one
  • Check Which write strategy results in both old and new contradictory entries being retained in the memory store?
  • Cost Write-time reconciliation costs one extra LLM call per fact. Deferred reconciliation costs it later, at read time, spread over however many times the fact is retrieved.

2.5 Filter out expired facts from search results

Supplying an expiration_date to client.add() creates a time‑bound memory entry that can be hidden or shown using the search(show_expired=True) flag.

Separate expired entries from contradictions and retrieve useful information before they disappear

  1. Call client.add() with an expiration_date for the new memory
  2. Run a normal search() query and notice that the expired record is omitted
  3. Execute search(show_expired=True) to retrieve the hidden, expired record
  4. Use get_all() without arguments to confirm the expired entry is excluded from default results
  • You'll see Expired records are omitted from a normal search() but appear when search(show_expired=True) is used
  • Takeaway Expiry hides stale data without deleting it so you must extract needed information before the fact lapses
  • Check How does using search(show_expired=True) alter the retrieval results compared to a standard search() call?
  • Cost One extra field per fact and one policy decision per fact type. Skipping it costs nothing today and a wrong answer to a real user, months later, that nobody can explain because the fact that caused it already looks perfectly current.

2.6 Inspect and edit a user’s core memory

The Core Memory panel in the Agent Development Environment lists stored blocks such as the editable human block.

Show the agent’s stored facts and let the user correct them

  1. Open the Agent Development Environment
  2. Select the Core Memory panel to list all stored blocks for the user
  3. Edit the text in the human block directly in the inline textbox
  • You'll see The Letta ADE displays a core‑memory block labelled human with editable text and a live character count against its limit
  • Takeaway A correction surface must read from and write to the same store so users can spot and fix errors
  • Check What interface element allows you to modify the text of the human block directly within the Agent Development Environment?
  • Cost A read-only list view is close to free if the store already supports filtered reads (mem0's get_all()). An editable view is more work, and it is the version that actually lets someone fix a wrong memory instead of just seeing it.

2.7 Detect when a memory store is degrading

Duplicate fact entries with varied phrasing and a drop in recall@5 metrics serve as indicators of memory store degradation.

Spot the signs of silent decay in a knowledge store and verify vendor benchmarks against your own data

  1. Inspect the store for facts that are stored more than once under different phrasing
  2. Analyse retrieved passages for increasing contradictions with newer entries
  3. Re‑measure retrieval quality on your current corpus using recall@5 against your own questions
  4. Compare vendor benchmark results with your own measurements before accepting any claim
  • You'll see The same fact appears multiple times with different wording and no duplicate warnings, while retrieval quality has slipped unnoticed
  • Takeaway A failing memory store gives poorer answers without errors, so monitor duplicates, contradictions and stale quality metrics and treat every benchmark as a claim until you validate it yourself
  • Check Which symptom indicates that silent decay is occurring when the same fact appears multiple times with different phrasing?
  • Cost A recurring measurement, not a one-time build. The Marvin chapter's recall@5 discipline is the mechanism; this lesson is the judgement call for when to run it again.

2.8 Decide if a memory system is needed

An assessment of context window limits, static prompt capacity, and observed stale or contradictory facts guides the decision to add a memory system.

Determine when extraction, consolidation, invalidation and forgetting can be omitted

  1. Assess whether the assistant operates within a single session and the context window already contains all needed information
  2. Check if the required facts fit comfortably in a static system prompt or hard‑coded profile block
  3. Compare the effort of adding an extraction pipeline to the accuracy of manually maintained preferences for the current fact set
  4. Upgrade to a more complex memory tier only after observing a concrete failure such as stale facts, contradictions, or unmanageable prompt size
  • You'll see The interface shows no additional prompts or storage panels after the assessment
  • Takeaway Use memory mechanisms only when facts must outlive the context window and restating them would be costly
  • Check What concrete failure should prompt you to upgrade from a static prompt to a more complex memory tier?
  • Cost Zero, and that is the point — the cheapest fix for a memory problem you do not have yet is not building the system that would have solved it.

3See also

💬 Discuss this chapter

Ask, share, or report — over on the Heidelberg AI community forum.