Agents III — Memory & Context
- 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
| Spaced-rep: due cards + write a done_when for a sample subtask (D121) | 10 min |
| ELI5 + tech read; context-window visualizer | 20 min |
| Guided: drown-then-compact + episodic memory | 45 min |
| Practice: the triage-agent context budget | 18 min |
| Project: agent/memory.py with tests | 20 min |
| Quiz + flashcards | 7 min |
Builds on: Day 120 — Agents I — the loop · Day 121 — Agents II — planning · Day 115 — Embeddings & vector databases · Day 104 — Context windows & lost-in-the-middle
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.
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.
The intern's notebook — a fixed context window under pressure
step 1 / 6The 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
Watch it drown, then build the compactor
30 min- Create
agent_memory.pywith 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. - 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. - 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.
- Compute from the printout: total tokens sent across the mission, naive vs compacted. Write the ratio in your notes — that is money.
Episodic memory on the Day 115 vector store
15 min- Append the starter code below (it reuses your VecStore contract from Day 115 with the bag-of-words embedder — swap Chroma in locally).
- 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.
- 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.
- Promote a fact: the quota lesson has now appeared twice (episodes 1 and 3). Write it into a
SEMANTICdict 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. - 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.
On your own
Write the budget, then defend it
18 minYour 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.
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.
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.
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
- MemGPT / letta-style memory hierarchies — Treats 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.
- 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
← 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