Module 11 of 30
Multi-Layer
Memory

Give your agent a brain that remembers — across turns, across sessions, across years. Different memory tiers for different jobs, plus the full Claude-native memory landscape.

Track 3: Memory & Context ⏱ ~30 min read 11 / 30
Concept 1 of 10

One store can't carry three jobs

An agent juggles three completely different kinds of memory. Working: the scratchpad for the current task — user intent, extracted entities, intermediate tool results. Episodic: a searchable archive of past conversations and decisions. Procedural: a library of proven action sequences ("for X, do A then B then C").

Stuff all three into one bucket and retrieval gets polluted. A search for "did the user mention their address?" turns up grocery-list scratchpads, last week's billing chat, and the recipe for fixing TLS errors. Separate them and each retrieval stays focused, each prompt stays lean.

The architecture is what lets agents scale from one-session toys to multi-year production assistants. Without layering you eventually run out of either context or coherence.

Concept 1 of 10

The single-notebook brain

BEFORE: Imagine your brain stored everything in one notebook — today's grocery list, how to ride a bike, your wedding day, the recipe for pasta carbonara, every meeting you've ever had — all on the same pages, in arrival order.

PAIN: Every recall means flipping through every page. The notebook fills up fast. Important long-term memories get crowded out by ephemeral notes — you'd "forget" how to ride a bike because you scribbled over it with a shopping list.

MAPPING: Real brains don't work that way. They use working memory (what you're holding right now), episodic memory (specific past events), and procedural memory (skills and habits). Multi-layer memory architectures give agents the same separation — and the same scaling benefits.

Concept 1 of 10

Three stores, one prompt

  1. Per turn, load three slicesThe runtime grabs the current working-memory dict, the top 2–3 episodes from the vector DB, and any matching procedural template.
  2. Format as labelled blocksEach tier becomes a clearly-tagged block in the system prompt — [Working], [Past Interactions], [Suggested Procedure] — so Claude knows which is which.
  3. Claude reasons over all threeWorking anchors the now. Episodic provides past context. Procedural suggests the plan. Claude weights them and acts.
  4. Update working as you goEach tool result, decision, or partial answer gets written back to working memory in real time.
  5. Promote at session endSummarize the conversation, embed it, store it in episodic. If a plan succeeded enough times, promote it to procedural.
Concept 1 of 10

Which tier does each fact belong in?

LifespanTierExample
This task onlyWorking"Currently looking up order #4521"
Across sessionsEpisodic"User prefers email over Slack"
Across many users / alwaysProcedural"Refund flow: verify → check policy → issue"
Stale after minutesWorkingAPI response just received
Stale after weeksEpisodic + TTL"Q3 budget was $50K"

Start with the tier that solves your real problem. A simple FAQ bot needs none of this.

Concept 1 of 10

Common misconceptions

"Every agent needs all three tiers."
A simple FAQ bot needs zero. A single-session helper might only need working memory. Add tiers when a real problem demands them — not because the architecture diagram looks neat.
"One vector DB will cover everything."
Mixing scratchpads, past chats, and procedure templates in one collection causes retrieval pollution. A query for "last week's address" pulls back tool results and recipes too. Separate stores keep retrieval clean.

Working · Episodic · Procedural. Three different stores for three different memory jobs. Separation is the design — mixing them pollutes retrieval and bloats prompts.

Concept 2 of 10

Working memory: the agent's clipboard

Working memory is a fast, mutable scratchpad for the current task. It holds the user's parsed intent, extracted entities (names, dates, IDs), intermediate tool results, and the running plan. Concretely, it's a Python dict (or Redis cache for distributed agents) that lives in RAM.

Every LLM call sees this scratchpad through a to_prompt() method that formats the whole dict as a labelled block in the system prompt. That's how the agent never "forgets" what it learned two tool calls ago in a multi-step task.

Lifetime matches the task — created when a request arrives, cleared (or archived to episodic) when the response is sent.

Concept 2 of 10

The doctor's clipboard

BEFORE: Imagine a doctor seeing a patient without a clipboard. They walk in, the patient describes three symptoms, the doctor orders a blood test, then walks to the lab.

PAIN: Without notes, the doctor has to ask the patient to repeat everything. They lose track of what they learned, repeat questions, order duplicate tests. The visit takes three times longer and the patient loses trust.

MAPPING: Working memory is the agent's clipboard. It rides along with every LLM call so the agent always knows the current intent, entities, and intermediate findings — no rediscovery, no duplicate tool calls, no looping.

Concept 2 of 10

Set, get, format, clear

  1. InitializeAt task start, create a fresh dict tagged with a session ID and timestamp.
  2. Set as you learnEach parsed intent, extracted entity, or tool result writes a key into the dict with an updated_at stamp.
  3. Inject every turnBefore each Claude call, to_prompt() formats the whole dict into a structured text block prepended to the system prompt.
  4. Read on demandWithin a turn, the agent's own code can get() any prior value to pass to a tool.
  5. Clear or archiveWhen the task ends, either drop the dict or hand it to the summarizer for promotion to episodic memory.
Concept 2 of 10

Pseudocode — WorkingMemory

CLASS WorkingMemory:
  state = {}     # key → {value, updated_at}

  METHOD set(key, value):
    state[key] = {value, now()}

  METHOD get(key, default=null):
    RETURN state[key].value OR default

  METHOD clear():
    state = {}

  METHOD to_prompt():
    IF empty: RETURN "[Working: empty — new task]"
    lines = ["[Working — session " + id + "]"]
    FOR EACH (key, entry) IN state:
      lines.append("  " + key + ": " + format(entry.value))
    RETURN JOIN(lines, newline)

The to_prompt() method is the load-bearing piece — it's how the dict becomes context Claude can reason over.

Concept 2 of 10

Common misconceptions

"Working memory persists across sessions."
It doesn't — that's episodic's job. Working memory is task-scoped. If a fact needs to outlive the task, summarize it and write it to episodic before clearing.
"Just dump tool results into the messages array."
That works for one tool call. Across five, the messages array grows fast and Claude has to re-derive structure from chat history. A structured working dict gives Claude the same facts in 80% fewer tokens.

Working memory is the clipboard, not the diary. Structured dict · injected as a labelled prompt block · cleared at task end. Without to_prompt() riding along, multi-step tasks lose state between tool calls.

Concept 3 of 10

Episodic memory: a searchable diary

Episodic memory stores summarized records of past conversations in a vector database, indexed by semantic embeddings and timestamps. After each session ends, the conversation is summarized into a compact record (~200–400 tokens) and embedded into a vector DB like ChromaDB.

When a new message arrives, the agent embeds it and searches for the closest matches — not by keyword, but by meaning. Top 2–3 hits are injected into the prompt as "relevant past context." That gives the agent cross-session continuity without replaying entire transcripts.

This is the difference between a stateless chatbot and a persistent assistant who remembers your last visit.

Concept 3 of 10

The personal assistant's diary

BEFORE: Picture an assistant who keeps a detailed diary that's searchable by topic. They don't reread the whole diary every morning — that would take hours. When you ask "what did we decide about the budget last week?", they search and find the right entry in seconds.

PAIN: Without the diary, the assistant starts every day with amnesia. You re-explain your preferences, past decisions, and ongoing projects every single session. For a support agent, every returning customer feels like a stranger.

MAPPING: Episodic memory is that searchable diary. Conversations end, the agent writes a short summary, files it by meaning, and pulls back the right entry the next time it's relevant.

Concept 3 of 10

Summarize, embed, search, inject

  1. At session endSend the conversation to Claude with a structured prompt that extracts topics, decisions, preferences, and outcomes. Output: ~300 tokens of structured summary.
  2. EmbedConvert the summary text into a vector (often ~1,536 floats) using an embedding model.
  3. Store with metadataSave embedding + summary text + metadata (session_id, timestamp, user_id, topic tags) in ChromaDB / Pinecone / Weaviate.
  4. At new session startEmbed the user's message. Run a cosine-similarity search over stored episode vectors.
  5. Inject top 2–3Format the closest matches as a "Relevant Past Interactions" block in the system prompt. Cap at 3 to avoid noise.
Concept 3 of 10

Pseudocode — EpisodicMemory

vector_db = PERSISTENT ChromaClient(path="./chroma")

FUNCTION store_episode(summary, metadata):
  vec = EMBED(summary.text)
  vector_db.ADD(
    id      = uuid(),
    vector  = vec,
    text    = summary.text,
    meta    = {session_id, user_id, timestamp, topics}
  )

FUNCTION retrieve(user_message, k=3, user_id=null):
  q_vec  = EMBED(user_message)
  hits   = vector_db.QUERY(q_vec, k=k,
            filter={user_id: user_id})
  RETURN [{summary, when, score} FOR h IN hits]

FUNCTION to_prompt(user_message):
  hits = retrieve(user_message, k=3)
  IF empty: RETURN ""
  RETURN "[Relevant Past Interactions]\n"
       + JOIN("- " + h.summary FOR h IN hits)

Use PersistentClient, not the default in-memory client — otherwise everything evaporates on restart.

Concept 3 of 10

Common misconceptions

"Episodic memory gives perfect recall."
It stores summaries, not transcripts. Summarization is lossy — specific names, numbers, and edge-case nuances get dropped. If you need exact recall of a value, store it as structured metadata, not buried in summary prose.
"More retrieved episodes = better responses."
Injecting 10 past episodes is usually worse than 2–3. Each extra episode dilutes the prompt with maybe-relevant context, raises cost, and hurts attention to the actual task. Cap aggressively.

Summaries in, semantic search out. Episodic memory turns conversations into searchable embeddings, then injects the 2–3 closest matches at the next session start. Persistence is non-negotiable — default in-memory mode loses everything on restart.

Concept 4 of 10

Procedural memory: the skill library

Procedural memory stores reusable action sequences — tool chains, proven workflows, task templates — as structured records. Each record has two parts: a trigger description ("user asks for a weekly sales report") stored as an embedding, and an ordered list of execution steps ("query_db → aggregate → chart_gen → format_pdf") stored as JSON.

At runtime, the agent embeds the current request, searches procedural memory for matching triggers, and — if a high-confidence match is found — loads the procedure as a suggested plan. Claude can then follow or adapt it instead of replanning from scratch.

This is how agents get faster and more consistent over time without retraining.

Concept 4 of 10

The chef's recipe book

BEFORE: An experienced chef who's cooked the same pasta dish 200 times doesn't re-read the recipe each time. They've internalized it: boil water, salt it, cook 8 minutes, sauté garlic, toss together. Automatic.

PAIN: A novice without recipes reasons through every step from first principles, makes mistakes, takes 3x longer. Worse, they solve the same problem differently each time. Customers ordering the same dish twice get different meals.

MAPPING: Procedural memory is the agent's recipe book. When a tool sequence works, the agent saves it as a template. Next time a similar request arrives, it retrieves the template instead of replanning — faster, cheaper, more consistent.

Concept 4 of 10

Trigger match → suggested plan

  1. Save successful plansWhen a multi-step task completes successfully, store the trigger description, the ordered tool calls, and a success counter.
  2. Embed the triggerConvert the trigger description into a vector and index it for semantic search.
  3. Match on each new requestEmbed the user's request, search procedural memory, get a similarity score for the best match.
  4. Threshold the matchBelow ~0.7 similarity, ignore the match and let Claude reason from scratch. Above, load the steps as a suggested plan.
  5. Inject as suggestion, not mandateFormat as [Suggested Procedure (used 12x)]. Claude can adapt, skip, or override based on current context.
Concept 4 of 10

Pseudocode — ProceduralMemory

FUNCTION save_procedure(name, trigger, steps):
  vec = EMBED(trigger)
  proc_db.ADD(
    id     = name,
    vector = vec,
    meta   = {name, trigger, steps_json,
              success_count: 0}
  )

FUNCTION match(user_request, min_sim=0.7):
  q   = EMBED(user_request)
  hit = proc_db.QUERY(q, k=1)
  IF hit.score < min_sim:
    RETURN null   # let Claude plan from scratch
  RETURN hit.meta

FUNCTION to_prompt(user_request):
  proc = match(user_request)
  IF proc IS null: RETURN ""
  RETURN "[Suggested Procedure: " + proc.name
       + " (used " + proc.success_count + "x)]\n"
       + format_steps(proc.steps_json)

The threshold matters. Match too eagerly and the agent forces wrong-shaped plans onto novel requests.

Concept 4 of 10

Common misconceptions

"Procedural memory replaces Claude's reasoning."
It provides a suggested plan, not a mandate. Claude can adapt, skip steps, or override the template when the current context calls for it. Think of it as a recipe an experienced chef can riff on, not a robotic script.
"Save every successful run as a procedure."
You'll fill the store with one-off plans that match nothing later. Promote a sequence to procedural only after it's succeeded several times on similar requests — otherwise it's just noise during retrieval.

Procedural memory is the agent's recipe book. Trigger embedding for matching, JSON steps for execution, similarity threshold to avoid forcing wrong plans. Saves tokens on planning and stabilizes outputs across repeated tasks.

Concept 5 of 10

Summarization: the bridge to long-term memory

The summarization pipeline is what turns short-term conversation into durable cross-session memory. At session end, Claude condenses the full transcript (4,000+ tokens) into a compact structured record (~300 tokens) capturing topics, decisions, preferences, action items, and outcomes.

That record is then embedded and stored in episodic memory. At the next session, the new user message is embedded and matched against the stored summaries — closest hits get injected. That's how an agent on Tuesday remembers what was decided on Friday without replaying every word in between.

Without summarization, you'd hit storage and context limits within a week.

Concept 5 of 10

The end-of-day project recap

BEFORE: A project manager writes a brief summary at the end of each workday: key decisions, action items, blockers, what's pending for tomorrow. Files it in a searchable archive.

PAIN: Without the habit, Monday morning is chaos. Nobody remembers Friday's decisions. Action items fall through the cracks. The team re-discusses the same issues. Effective weekly amnesia.

MAPPING: The summarization pipeline automates this end-of-day habit. Conversation ends, Claude writes a structured recap, embeds it, files it. Next session loads it. The agent never starts from scratch.

Concept 5 of 10

Summarize → embed → store → compact

  1. SummarizeSend the conversation to Claude with a structured prompt extracting topics, decisions, preferences, action items, outcomes. Output: structured JSON, ~200–400 tokens.
  2. EmbedConvert the summary text into a vector embedding using an embedding model (Voyage AI, OpenAI, etc.).
  3. StoreSave embedding + summary + metadata (session_id, timestamp, user_id, topic tags) in the vector DB.
  4. Compact periodicallyMerge related episodes from the same week, drop entries older than the TTL, deduplicate near-identical summaries — keeps the store from growing unbounded.
  5. Trigger only at session endNot after every turn. Mid-conversation summarization wastes tokens and loses context that only makes sense in the full flow.
Concept 5 of 10

Pseudocode — summarize_conversation

FUNCTION summarize_conversation(messages):
  text = format_transcript(messages)

  prompt = "You are a conversation summarizer. "
         + "Return JSON with these fields: "
         + "summary, topics, decisions, "
         + "user_preferences, action_items. "
         + "Return ONLY valid JSON."

  reply = CALL Claude(system=prompt, user=text)
  record = PARSE_JSON(reply)

  IF parse_failed:
    record = {summary: reply[:500],
              topics: [], decisions: [],
              user_preferences: [], action_items: []}
  RETURN record

# Pipeline at session end:
record = summarize_conversation(log)
vec    = EMBED(record.summary)
episodic.STORE(vec, record, meta={ts: now()})
working.clear()

Use a capable model for summarization. Cheap models drop nuances like "user seemed frustrated" or the difference between "discussed X" and "decided X."

Concept 5 of 10

Common misconceptions

"Summarization is lossless — Claude captures everything."
It's inherently lossy. Specific numbers (contract amounts, rate limits), exact timestamps, and subtle nuances often get dropped. If a detail is business-critical, store it as structured metadata alongside the summary, not in the summary text.
"Summarize after every message."
Summarize at conversation end, not after every turn. Mid-conversation summarization wastes API calls and may lose context that only makes sense in the full flow. The exception: very long conversations (50+ turns) where periodic compaction prevents context overflow.

Compress 4,000 tokens to 300, then embed and file. Summarization is the bridge between today's conversation and next week's recall — treat it as a pipeline (summarize → embed → store → compact), not a single step.

Concept 6 of 10

Persistence: memory that survives a crash

Memory that lives only in RAM disappears when your process restarts. For production agents, all three tiers need durable storage — data written to disk (or a managed DB) that survives crashes, deployments, and OS restarts.

Each tier has its own backing store. Working memory: Redis or SQLite for distributed setups, JSON files for simple ones. Episodic memory: vector DB with persistent client (ChromaDB on disk, Pinecone, Weaviate Cloud). Procedural memory: SQLite or PostgreSQL for the steps JSON, plus the trigger embeddings in the vector DB.

The tradeoff is operational complexity — you now own a database, a backup story, and a growth plan.

Concept 6 of 10

Session cookie vs database

BEFORE: If you've worked with web apps, you've seen the difference between storing user data in a session cookie and storing it in a database. Cookies vanish when the browser closes.

PAIN: Cookie-only state means your user re-logs-in every refresh, re-fills every form, re-explains every preference. The "session" feels broken every time it ends.

MAPPING: Without a persistence layer, your agent's memory is a session cookie. The dict, the vector index, the procedure templates — all evaporate on restart. Persistence adds the database underneath each tier so memory turns from ephemeral state into durable record.

Concept 6 of 10

One backing store per tier

  1. Working memory → Redis or SQLiteRAM-fast for read/write, periodically flushed to a backing store keyed by session_id. Survives brief disconnects.
  2. Episodic memory → vector DB on diskChromaDB PersistentClient(path="./chroma_db") or Pinecone/Weaviate. Embedding + summary text persist together. Survives full restarts.
  3. Procedural memory → SQL + vector DBSteps JSON in SQLite/Postgres for transactional safety. Trigger embedding in the same vector DB so semantic match is fast.
  4. BackupsSnapshot the DB directory daily. For managed vector DBs, enable provider-side backup. Test restore at least once.
  5. Growth planCompaction job + TTL on episodic. Cap procedural at top-N most-used templates. Without a plan, vector DB grows unbounded.
Concept 6 of 10

Local vs managed storage

NeedPick
Hobby project, single machineSQLite + local ChromaDB
Single server, <100K episodesPostgres + ChromaDB on disk
Multi-region, millions of episodesPinecone / Weaviate Cloud
Distributed agents, shared session stateRedis cluster for working memory
Strict data residency / HIPAASelf-hosted, your VPC

Start simple. Graduate to managed services only when traffic, scale, or compliance forces the move.

Concept 6 of 10

Common misconceptions

"ChromaDB persists by default."
It doesn't. The default client is in-memory and loses everything on restart. You must explicitly use PersistentClient(path=…) or a managed cloud client. This single missed line is the #1 reason "the agent keeps forgetting."
"Persistence = problem solved."
Now you own backups, growth, and recovery. A vector DB without a TTL or compaction job will balloon to TB-scale within a year of real traffic. Persistence is the start, not the end.

Each tier needs its own durable backing store. Use the persistent client variant. Plan for backups, compaction, and growth from day one — otherwise persistence buys you new failure modes instead of protecting against old ones.

Concept 7 of 10

The managed memory tool

Claude exposes a built-in memory tool in the API: a managed key/value-and-namespace store that persists across requests for a given user, project, or org. Instead of standing up Postgres, building a summarization pipeline, and writing your own retrieval prompts, you call memory.write and memory.read tools and Anthropic handles storage, retrieval, and quota.

Enable it by adding the tool to your tools array. Claude calls memory.write to store a fact under a namespaced key (e.g. user_prefs/timezone), memory.read to retrieve, and memory.list to enumerate. Storage and retrieval costs are metered separately from input/output tokens.

Best for prototypes, B2C agents, and simple personalization. Not for regulated data or complex retrieval policies.

Concept 7 of 10

Self-storage vs your own warehouse

BEFORE: You're moving to a new city and need to store your stuff. Two options: rent a self-storage unit at a managed facility, or buy a warehouse and run it yourself.

PAIN: The warehouse gives you total control — security, layout, climate — but takes weeks to set up and you own all maintenance. Self-storage is ready in an hour, but the operator picks the rules and you can't customize the building.

MAPPING: The memory tool is self-storage — ready in minutes, Anthropic handles everything, but you live within their retrieval policy and data residency. Building your own 3-tier system is the warehouse — total control, your VPC, your retrieval logic, but days of work and ongoing operational load.

Concept 7 of 10

Three tools, one managed store

  1. Enable the toolAdd the memory tool to your tools array. Pass scoping headers (per-user / per-tenant) to isolate stores.
  2. Write a factClaude decides when to call memory.write(key, value). Keys are namespaced (e.g. user_prefs/timezone).
  3. Read a factClaude calls memory.read(key) when it thinks it needs context. Read decisions are model-driven, not developer-driven.
  4. List for discoveryUse memory.list(prefix) to enumerate all keys under a namespace — useful when Claude is exploring what it knows about a user.
  5. Pay per operationStorage and reads/writes are metered separately from token costs. Cheap at low scale, gets meaningful at high read volume.
Concept 7 of 10

Memory tool vs DIY 3-tier

ConcernMemory toolDIY 3-tier
Setup timeMinutesDays
Where data livesAnthropic-managedYour DB, your VPC
Retrieval policyClaude decides when to readYou decide — eager / lazy / hybrid
ComplianceAnthropic's region/ZDR optionsWhatever your infra supports
Cost modelPer-read/write meteredYour storage + compute
Best forPrototypes, B2C, simple personalizationRegulated data, complex retrieval, multi-tenant SaaS

Common production pattern: memory tool for short-lived per-user prefs; DIY for case-grade context and audit-relevant decisions.

Concept 7 of 10

Common misconceptions

"The memory tool replaces the DIY architecture."
They target different shapes. Use the memory tool for "remember this user prefers JSON output." Use DIY when you need always-load-on-session-start case facts, data residency control, or thousands of facts per user where DB indexes beat per-read metering.
"Claude will always read the right key at the right time."
Read decisions are model-driven and probabilistic. If a fact must be loaded every session (like patient allergies in a medical agent), don't trust the model to remember to read it — load it explicitly into the system prompt yourself.

Memory tool for ease, DIY for control. The managed tool gets you live in minutes for B2C personalization. The 3-tier system is the right answer the moment you need data residency, custom retrieval policy, or high-volume per-user facts.

Concept 8 of 10

Auto Memory: Claude writes its own notes

Auto Memory is a Claude Code feature where Claude itself decides what's worth remembering across sessions and writes it to disk — without you typing a single line of CLAUDE.md. Build commands it figured out, debugging quirks, your discovered preferences — all silently captured and reloaded next session.

It's on by default in Claude Code v2.1.59+. Most learners discover it the first time they see "Writing memory…" in the terminal and wonder what just happened.

CLAUDE.md is what you tell Claude. Auto Memory is what Claude tells itself. Complementary systems — not a replacement.

Concept 8 of 10

The pair-programmer who keeps a notebook

BEFORE: Imagine pairing with a colleague who silently keeps a running notebook of everything they've learned about your codebase — the build commands, the debug quirks, your stylistic preferences — and reads that notebook before every session.

PAIN: Without that notebook, every Monday they re-discover that the local DB is on port 5433, the test runner needs Redis, and you prefer underscores over camelCase. You spend 15 minutes re-explaining the same things every single session.

MAPPING: Auto Memory is exactly that notebook. Claude takes notes about your project as it works, stores them per repo, and re-reads them at the start of every future session in the same working tree.

Concept 8 of 10

The memory directory

  1. Per-repo directoryEach git repo gets its own folder at ~/.claude/projects/<project>/memory/.
  2. MEMORY.md is the indexAlways loaded at session start. Capped at first 200 lines or 25KB — acts as a router pointing to topic files.
  3. Topic files load on demandFiles like debugging.md, build-quirks.md, preferences.md are read by Claude only when relevant.
  4. Two natural triggers"Remember that…" writes to Auto Memory (machine-local). "Add to CLAUDE.md" writes to your committed config (team-shared).
  5. Machine-local by designNot synced across machines, cloud, or teammates. Captures local quirks (your Redis port, your sandbox URL) safely.
Concept 8 of 10

CLAUDE.md vs Auto Memory

CLAUDE.mdAuto Memory
Who writesYouClaude
ContainsRules, conventionsDiscovered patterns & quirks
ScopeProject / user / orgPer working tree (git repo)
LoadedEvery session, in fullFirst 200 lines / 25KB of MEMORY.md
SyncCommitted via gitMachine-local only
Best forCoding standards, "always do X"Build quirks, local prefs Claude discovered

Toggle from /memory in-session. Disable per-run with CLAUDE_CODE_DISABLE_AUTO_MEMORY=1.

Concept 8 of 10

Common misconceptions

"Auto Memory syncs across my devices."
It doesn't. The memory directory is per-machine and not synced to cloud, teammates, or your other laptop. Switch machines, you start with empty Auto Memory. By design — it captures machine-local quirks that wouldn't be safe to share.
"I should put team rules in Auto Memory."
Wrong store. Team-shared rules belong in CLAUDE.md (committed to git). Machine-local Claude-discovered notes belong in Auto Memory. The cert exam tests this exact pattern: "every session I have to remind Claude that local DB is on port 5433" → correct answer is Auto Memory, not CLAUDE.md.

You write CLAUDE.md. Claude writes Auto Memory. Both auto-load every session. CLAUDE.md captures rules everyone needs. Auto Memory captures quirks Claude would otherwise re-discover every Monday morning.

Concept 9 of 10

The full Claude memory landscape

Claude provides at least twelve distinct memory primitives across five scopes — from the conversation-level message array to file-based persistent memory in Claude Code. Knowing all twelve, and which scope each operates at, is what separates "I learned the API" from "I can architect a Claude system."

Two memory patterns from the outermost scope — crash recovery manifests and tool-output trimming — don't fit cleanly into the working/episodic/procedural taxonomy but show up repeatedly as Domain 5 cert questions. Both solve real production failures.

Most production agents use 3–4 of the five scopes simultaneously, because each scope solves a different memory problem.

Concept 9 of 10

The Russian-doll architecture

BEFORE: Picture a set of nested Russian dolls. Each shell wraps the previous one. Each adds a layer of capability.

PAIN: If you only know the innermost doll exists, you're stuck rebuilding everything the outer dolls already give you. Engineers who know only the messages array end up writing summarization for the third time, not realizing the runtime already does it.

MAPPING: Claude's memory is nested the same way. Innermost: a single API call (system prompt + messages + tool_use cycle). Each outer scope wraps it with more persistence. Pick the smallest scope that solves the problem — reaching outside it is wasted complexity.

Concept 9 of 10

Five scopes, twelve primitives

ScopePrimitives
1. Within a single API call
Stateless — whatever you send
system prompt · messages array · tool_use cycle
2. Across calls (server-assisted)
Re-send context cheaply
prompt caching · memory tool · Files API · Citations
3. Within a session (Claude Code / SDK)
Runtime keeps state for you
--resume · fork_session · /compact · PreCompact hook · subagent isolation
4. Persistent across sessions (Claude Code)
Files on disk, auto-loaded
CLAUDE.md hierarchy · Auto Memory · Skills · Slash commands · Hooks
5. External persistence (you build)
Scale, compliance, custom retrieval
RAG + vector DB · 3-tier memory · crash recovery manifests · tool-trim wrapper

Reading the landscape: volatility → scope 1; reuse rate → scope 2; persistence → scopes 4–5.

Concept 9 of 10

Crash recovery & tool-trim

Crash recovery manifest: a small structured file (e.g. .claude/state/manifest.json) the agent writes after every meaningful step. Captures modified files, test status, plan, current step, open TODOs. Lives outside the context window so it survives crashes, compaction, and reboots. On restart, the resumed session reads it and picks up exactly where it left off — instead of replanning the whole 40-minute migration.

Tool-output trimming: a pre-context filter applied to tool results before they hit the message history. The wrapper writes the full result to a side log on disk for debugging, but returns only a trimmed slice to the model (top-N grep matches, head+tail of long stdout, failures-only test output). Solves the silent killer: an 8,000-line grep result floods context and quality drops — not because Claude got worse, but because too much input.

Cert tip: when context-quality drops, the right fix is often less input, not a bigger model.

Concept 9 of 10

Common misconceptions

"Bigger context window solves memory."
Often the opposite. Flooding context with verbose tool output causes "lost in the middle" effects and hurts attention. The fix is trimming the input, not buying more window.
"Always reach for the outermost scope."
Wasted complexity. Scope 4 (CLAUDE.md, Auto Memory) and scope 5 (your DB) are the right answer when data must outlive the session. For one-turn facts, just put it in the system prompt.

Five scopes, twelve primitives, three signals. Pick by volatility, reuse rate, and persistence. Pair the 3-tier system with crash recovery manifests and tool-output trimming and you've covered the full Domain 5 cert toolkit.

Concept 10 of 10

Memory Manager: the orchestrator

The Memory Manager is the glue that makes the three tiers work as a coherent system. Individual memory classes are building blocks — the Manager is what wires them together with a clear lifecycle: start_session() creates fresh working memory and loads relevant episodes and procedures, build_memory_context() formats all three tiers into the system prompt for each turn, and end_session() summarizes the conversation, stores the episode, and clears working memory.

It's also where routing decisions live: which tier to consult first, how to handle conflicts (e.g. an episodic preference contradicting a procedural template), how to decay stale entries, and when to promote items between tiers.

This is the boundary between "I have three memory classes" and "I have a memory system."

Concept 10 of 10

The orchestra conductor

BEFORE: Picture an orchestra with three skilled sections — strings, brass, percussion — each rehearsed but playing on their own.

PAIN: Without a conductor, sections drift out of sync, enter at the wrong moments, drown each other out. The audience hears noise instead of music. Each section is technically excellent but the whole thing collapses.

MAPPING: The Memory Manager is the conductor. Working, episodic, and procedural each know their job, but the Manager decides the timing, mixes the volume, resolves conflicts, and routes each turn through the right combination. The output is a coherent system instead of three loud soloists.

Concept 10 of 10

Five-step lifecycle

  1. start_sessionCreate fresh working memory tagged with session_id and user_id. Reset the conversation log.
  2. build_memory_context (per turn)Combine working.to_prompt() + episodic.to_prompt(user_msg) (top 3) + procedural.to_prompt(user_msg) into one labelled string for the system prompt.
  3. log_turnAppend every user/assistant exchange to the conversation log for later summarization.
  4. resolve conflictsIf a procedural template contradicts a recent episodic preference (e.g. user said "no email" but procedure ends with "send email"), prefer the more specific recent fact and flag the procedure for review.
  5. end_sessionCall summarize_conversation(log), embed the result, store as an episode in episodic memory, then clear working memory. Optionally promote the conversation's plan to procedural if it succeeded and matches no existing template.
Concept 10 of 10

Pseudocode — MemoryManager

CLASS MemoryManager:
  episodic   = EpisodicMemory(persist_dir)
  procedural = ProceduralMemory(persist_dir)
  working    = null
  log        = []

  METHOD start_session(session_id, user_id):
    working = WorkingMemory(session_id)
    working.set("user_id", user_id)
    log = []

  METHOD build_memory_context(user_msg):
    RETURN JOIN([
      working.to_prompt(),
      episodic.to_prompt(user_msg, k=3),
      procedural.to_prompt(user_msg)
    ], "\n\n")

  METHOD log_turn(role, content):
    log.append({role, content})

  METHOD end_session():
    record = summarize_conversation(log)
    vec    = EMBED(record.summary)
    episodic.STORE(vec, record, meta={user_id, ts})
    working.clear()
    RETURN record.id

The whole 3-tier system is roughly 30 lines of orchestration on top of three storage classes.

Concept 10 of 10

Common misconceptions

"Just inject all three tiers, Claude will figure it out."
Without the Manager's labelled-block formatting and conflict resolution, Claude can mistake an episodic note for a current fact, or follow a stale procedure that contradicts a recent preference. Routing logic is what turns three blobs of memory into coherent context.
"Memory updates can wait until the next session."
Working memory updates happen every turn, not at session end. If you batch updates, multi-step tasks lose state mid-flight and the agent loops or repeats tool calls. Summarization is what waits — per-turn writes are mandatory.

The Manager is the system. Three storage classes give you parts; the lifecycle (start_sessionbuild_memory_context per turn → end_session) gives you a working agent that remembers across turns and across days.

Tap to reveal answers

Open the full module on desktop

The desktop version walks through all three tiers in code — persistent ChromaDB, summarization pipelines, procedural template matching, the Memory Manager that orchestrates them — in Python and Node.js, plus animated diagrams of the timeline, the cert-pattern internals, and the full Claude-native memory landscape.

Open M11 on Desktop → Full code · 3-tier build · cert patterns · ~80 min

Module 11 of 30 · Track 3: Memory & Context