Day 122 · The intern's notebook

Agents III — Memory & Context

You will be able to
  • Budget an agent's context window across system prompt, tools, history, and retrievals — in numbers
  • Implement history compaction: keep recent turns verbatim, roll older turns into a summary
  • Distinguish scratchpad, episodic, and semantic memory and pick storage for each
  • Wire retrieval-backed memory: store episode outcomes in a vector index and recall them for new tasks
Today's ~120 minutes
Spaced-rep: due cards + write a done_when for a sample subtask (D121)10 min
ELI5 + tech read; context-window visualizer20 min
Guided: drown-then-compact + episodic memory45 min
Practice: the triage-agent context budget18 min
Project: agent/memory.py with tests20 min
Quiz + flashcards7 min

Builds on: Day 120Agents I — the loop · Day 121Agents II — planning · Day 115Embeddings & vector databases · Day 104Context windows & lost-in-the-middle

The analogy

The intern's brain (the context window) holds maybe one desk's worth of paper at a time. On a long mission the papers pile up — every file she opened, every dead end — until the important sheet slides off the desk. The fix is not a bigger desk; even the biggest desk fills, and the middle of a tall pile is exactly where things get lost. The fix is a notebook system.

Three notebooks, actually. The scratchpad: today's working page — the current plan, the running total, the thing she's in the middle of. Torn out when the mission ends. The diary (episodic memory): one paragraph per finished mission — "checked settings.yaml for rate limits, found it; notes.txt is always stale." Tomorrow's missions start by skimming relevant diary entries. And the reference binder (semantic memory): distilled durable facts — "the config lives in settings.yaml" — no story attached, just what's true. When the desk fills mid-mission, she doesn't dump papers randomly: she summarizes the oldest ones onto one sheet ("mornings work: ruled out 3 files") and keeps the recent ones verbatim. The desk stays small; the mission stays whole.

Why this matters on the job

Context management is where real agents live or die: the model's per-call memory is the window and nothing else, every token costs money on every lap (history is re-sent each iteration — cost grows quadratically with naive accumulation), and Day 104 taught you the middle of a stuffed window is a dead zone. Long-running agents that "get dumber over time" are almost always drowning in their own history. This is also this week's RAG payoff: retrieval-backed memory is literally your Day 115 vector store pointed at the agent's own past. Claude Code, cursor-style agents, and every support bot with "memory" run exactly the machinery you build today.

Watch it happen

The intern's notebook — a fixed context window under pressure

step 1 / 6
memo
SYS
0
u1
1
a1
2
·
3
·
4
·
5
·
6
·
7

The context window is working memory: everything the model can "see" this call — here, a toy 8-slot window. The system prompt occupies the front permanently.

Guided practice

guided 1

Watch it drown, then build the compactor

30 min
  1. Create agent_memory.py with the starter code. Part 1 simulates a 12-step mission with a naive append-everything history and a 900-token budget (tiny on purpose). The printed table shows tokens-per-lap climbing until the budget breaks mid-mission — and the cumulative-token column shows the O(N²) bill shape.
  2. Part 2 adds ContextManager: last 3 turns verbatim, older turns rolled into a summary (scripted extractive summarizer standing in for the LLM call — the compaction PROMPT it replaces is printed). Rerun: tokens-per-lap now plateau under budget for the same 12 steps.
  3. Verify the safety property: the file name "settings.yaml" and error code "ERR-4092" appearing in early turns must still appear VERBATIM in the compacted context at lap 12 (the code asserts this). Break it: make the summarizer drop identifiers and watch the assert fail — that corrupted-summary bug is real and nasty.
  4. Compute from the printout: total tokens sent across the mission, naive vs compacted. Write the ratio in your notes — that is money.
🐍 python — editable, runs in your browser
Ctrl/⌘+Enter runs · Tab indents · numpy/pandas/sklearn auto-load on import (torch and network calls need a local run)
guided 2

Episodic memory on the Day 115 vector store

15 min
  1. Append the starter code below (it reuses your VecStore contract from Day 115 with the bag-of-words embedder — swap Chroma in locally).
  2. Run it: three finished missions are written to memory as episode summaries with metadata. Then a NEW task arrives — "investigate why API calls fail after the 20th of the month" — and the agent retrieves relevant past episodes before starting.
  3. Confirm the retrieved episode is the quota one (vocabulary overlap on quota/monthly/API), and note what gets injected into the system prompt: the LESSON, not the whole transcript. Memory injection competes with everything else for the context budget you just engineered.
  4. Promote a fact: the quota lesson has now appeared twice (episodes 1 and 3). Write it into a SEMANTIC dict as a durable fact with a source-episode list — that promotion step (in production, a periodic LLM distillation pass) is how diaries become reference binders.
  5. Forget something: delete the episode about the superseded legacy config (its lesson is now wrong). Note this is Day 115's deletability argument, aimed at the agent's own past.
🐍 python — editable, runs in your browser
Ctrl/⌘+Enter runs · Tab indents · numpy/pandas/sklearn auto-load on import (torch and network calls need a local run)

On your own

Write the budget, then defend it

18 min

Your Day 126 triage agent will run on a 32k-token window with: a 1200-token system prompt + tool definitions, tickets up to 800 tokens, RAG context (Day 119 retriever) of 3 chunks × 400 tokens, up to 2 recalled episodes × 150 tokens, and a required 1000-token response reserve. Produce context_budget.md: (1) the line-item budget with a history allowance and an explicit safety margin; (2) the compaction trigger (at what history size do you compact, and to what); (3) which line you would cut first under pressure and why; (4) the two things that must NEVER be compacted.

Hints: budgets that sum to exactly the window are already broken — retrievals vary. Plan compaction to trigger well before the ceiling, not at it.

Ship before you stop

Memory module for the Week 18 agent

Extend the agent package: agent/memory.py with (1) ContextManager from the lab, parameterized by token budget and keep_verbatim, with the identifier-preservation property under test; (2) EpisodeStore wrapping your Day 115 VecStore: record(task, outcome, lesson, meta) after missions, recall(task, k) before them, forget(episode_id); (3) integration: run_agent (Day 120) gains an optional memory argument — recalled lessons injected into the system section, episode recorded at mission end. Tests: compaction keeps context under budget across a scripted 15-turn mission; identifiers survive compaction; recall returns the planted relevant episode; forget removes it. Update the README mapping (compaction call, distillation pass) to their real-LLM equivalents.

Rubric — check what you completed (0/6)

Common mistakes & misconceptions

  • Solving context pressure with a bigger window. Cost scales with tokens re-sent per lap, and lost-in-the-middle worsens with stuffing — budget and compact instead.
  • Summarizing away exact identifiers. A paraphrased file name or error code is corrupted state; summaries must preserve IDs verbatim — assert it in tests.
  • One memory bucket for everything. Scratchpad (this mission), episodic (past missions), semantic (durable facts) have different lifetimes, stores, and injection points.
  • Injecting whole transcripts as memory. Recall lessons, not logs — memory competes with retrievals and history for the same budget you wrote this morning.
  • Never forgetting. Stale lessons misdirect future missions; contradiction should tombstone (Day 115's deletability aimed at the agent's own past). Forgetting is an operation.
  • Compacting the plan state or system prompt. The working plan (Day 121) and the agent's instructions are load-bearing every lap; compaction applies to history only.
Knowledge check

Q1. Why does a naive append-everything agent loop cost O(N²) tokens over an N-step mission?

Q2. Your compactor summarizes "read legacy/old_limits.cfg, found rate_limit 60, superseded" as "checked an old config." What breaks later?

Q3. Where does "the intern learns from experience" live, mechanically?

Go deeper — curated resources

articleLilian Weng — LLM Powered Autonomous Agents (memory section)25 minarticleAnthropic — Building Effective Agents (augmented LLM: retrieval & memory)15 mindocsLangChain docs — short-term & long-term memory15 min
If you have a third hour
  • MemGPT / letta-style memory hierarchiesTreats the context window like RAM and external stores like disk, with the agent paging its own memory via tools — today's architecture taken to its logical extreme.
Done means
  • Naive-vs-compacted token totals measured; savings ratio recorded
  • Identifier-preservation assert understood by breaking it once
  • Episodic recall demo run: right episode recalled, lesson (not transcript) injected
  • context_budget.md written; agent/memory.py committed with tests green
  • Quiz ≥ 2/3
How this connects

← Back: Day 104 named the disease (finite windows, dead middles); Day 115's vector store turned out to be the memory organ; Day 121's plan table was a scratchpad before you had the word for it.

Forward →: Day 125 adds guards around this now-complete agent, and Day 126's triage agent runs on today's budget doc. Day 142's traces will show you context sizes per lap in production.

Unlocks: D125 Agent Reliability · D126 Week 18 Checkpoint: Support-Triage Agent