The Context Engineering Frame
Learning Objectives
By the end of this bridge module you will be able to:
- Recite the six context layers and place every artifact this course builds β graphs, bundles, MCP answers, index files β into the correct layer.
- Map each of the four context-engineering levers (add, compress, retrieve, offload) onto the specific modules of this course that industrialize it.
- Explain context rot at two altitudes β a rotting transcript and a drifting graph β as the same signal-to-noise disease with two cures.
- Connect static-first ordering and lost-in-the-middle to the design of
index.mdand theexplore()composite answer. - Fix a poisoned transcript with the two levers the sibling course's lab left unimplemented β retrieve and offload β and measure the result.
The Coupling Premise
If you took the sibling course Building AI Agents with Claude, you met context engineering in module M03B: the discipline of deciding what the model sees, in what order, compressed how. If you started here instead, you've spent two modules learning graphs and RAG limits without anyone naming the discipline you were practicing.
Here is the claim this module exists to make explicit: this entire course is applied context engineering. Every mechanism in Tracks 2 through 5 β tree-sitter graphs, OKF bundles, MCP servers, freshness gates β is one of context engineering's four levers, industrialized. The sibling course teaches the levers as techniques you apply by hand inside one conversation. This course builds the infrastructure that pulls those levers automatically, for every agent, on every task.
BEFORE: The sibling course's M03B uses a packing analogy β preparing a suitcase for a trip. You can throw things in (add), use packing cubes (compress), ship a box ahead to the hotel (retrieve it there), or hand bags to a travel buddy (offload). That works beautifully for one traveler packing one suitcase β one agent, one conversation, one context window.
PAIN: Now imagine a company where a thousand travelers take the same trip every day. Each one packs from scratch, ships their own boxes, negotiates their own buddy system. The packing skill doesn't scale β every traveler re-derives the same decisions, and most of them pack badly under deadline pressure. That is your engineering org running coding agents without shared context infrastructure: every session re-explores the repo, re-derives the schema, re-argues about the metric definition.
MAPPING: This course builds the airline's luggage infrastructure: the pre-shipped hotel boxes are your structural graph and OKF bundle (built once, queried by everyone), the packing-cube factory is your report and summary generators, and the freshness gate is the inspection that catches a box that's been sitting at the hotel for three weeks with last season's clothes in it. Same four levers β operated by machinery instead of willpower.
The rest of this module walks the mapping in detail, using the sibling course's own vocabulary and numbers so learners from either side land in the same place.
What the Model Actually Sees: The Six Layers
From the sibling course, verbatim: "Context engineering is the practice of deciding what content occupies the model's context window on each turn, in what order, and how it is compressed or fetched. Prompt engineering is a sub-discipline of context engineering that handles the authoring of one piece of that context (typically the system prompt or current user message)."
And the line that reframes everything: "Prompt engineering asks 'what words go in this message?' Context engineering asks 'what gets included at all, in what order, fresh or cached, full or summarized?' The first is a writing problem. The second is a budgeting problem."
The budget has six line items. On any turn, the model's context window contains: the system promptThe standing instructions loaded at the start of every turn β identity, rules, conventions. Static by design., the tool definitionsThe JSON schemas describing every tool the agent can call. Loaded whether or not the tools get used., the conversation history, any retrieved documents, accumulated tool results, and the current turn β the user's actual message.
M03B grounds this with an inventory of a real research agent at turn 8. Watch the animation build it, and watch where the user's message ends up:
Sit with that 0.9% for a second. When an agent answers badly, the instinct is to rewrite the prompt β to polish the 85 tokens. But the other 9,600 tokens are where the answer actually lives or dies: which files got dumped in as tool results, whether the retrieved doc is the current one or the stale one, whether turn 3's resolved error is still taking up residence. Optimizing the 0.9% while ignoring the 99.1% is why "prompt engineering" alone plateaus.
You have already seen this exact failure in this course, before it had a name. M00's agent read 147 files to fix a 3-line bug β that was the tool results layer eating the whole budget. M02's RAG pipeline retrieved a stale WAU definition β that was the retrieved layer poisoning the well. The six-layer inventory is the diagnostic frame those stories were missing.
Where This Course's Artifacts Land
Every artifact you build in Tracks 2β5 occupies exactly one of those six layers. Naming the layer tells you what budget line the artifact is optimizing:
| Context layer | What this course puts there | Instead of⦠|
|---|---|---|
| tools | MCP tool schemas β graph_callers, explore, search (M09) | nothing β this layer is the price of admission, kept small by composite tools |
| retrieved | OKF concept files, loaded selectively via index.md (M06βM08) | similarity-ranked chunks of whatever the embedder liked (M02) |
| tool results | one compact graph answer β callers, callees, blast radius (M09) | dozens of whole-file dumps from grep-and-read exploration (M00) |
| history (static prefix) | the index.md pre-flight read β stable, cacheable orientation | re-derived architectural chatter scattered through the transcript |
| system | layered CLAUDE.md β repo-wide facts only (M12) | a 340-line everything-file costing every session (M12's before-picture) |
| current | the user's question β the one layer this course leaves alone | β |
Layers turn vague complaints into line items. "The agent is expensive" becomes "tool results are 2,341 of our 3,131 tokens β 75% of the budget is exploration dumps." That is a real number from this module's lab fixture, and once you can see it, the fix is obvious: attack the biggest line, not the prompt. The whole architecture of this course β graph for tool results, bundle for retrieved, index for the static prefix β is an attack plan ordered by layer size.
The Four Levers β This Course's Machinery
M03B's second organizing idea: everything you can do about a context budget is one of four levers β add, compress, retrieve, offload. Its exact words: "Every RAG technique, every memory architecture, every multi-agent pattern you'll learn later is one of these four wearing a different costume." This course is where the costumes come off. Here is the centerpiece of this module β the mapping table:
| Lever (M03B) | What it means | Industrialized by (this course) |
|---|---|---|
| add | put it in context deliberately | M12's layered CLAUDE.md β facts every session genuinely needs, and nothing else, loaded by directory scope |
| compress | same information, fewer tokens | GRAPH_REPORT.md and the ~700-token orientation read (M04, M09); summaries generated once, reused by every session |
| retrieve | fetch on demand instead of carrying | structural graph queries β "answers, not leads" (M03βM05, M09); vector RAG kept for the unstructured long tail (M02, M10) |
| offload | external memory something else maintains | the OKF bundle + log.md (M06βM08); MCP servers holding the graph (M09); subagents exploring in their own window (M12) |
Notice which rows are highlighted: compress, retrieve, and offload are the levers that need infrastructure to pull well. Anyone can add; adding is the default failure mode. The other three require something to exist first β a report to have been generated, a graph to query, a bundle to read back. Building those somethings is Tracks 2 through 5 of this course.
Read the table back the other way and each module of this course acquires a one-line justification in context-engineering terms. Why does M09's server exist? Because retrieve beats carrying 24KB files. Why does M08's enrichment hook exist? Because offload is only safe if something keeps the external memory honest. Why does M12 teach CLAUDE.md layering? Because even the humble add lever has a right way and a wrong way.
Walk it, step by step
The four levers applied to one context window, one at a time. The layer composition on the right is the same six-layer inventory from the animation above, so you can watch each lever move a specific layer.
The Taxonomy Fork
One housekeeping note before we go deeper, because it trips up learners who did both tracks of the sibling course. There are two four-lever taxonomies in circulation there:
- The Claude track uses add / compress / retrieve / offload β the version this module uses.
- The open-source track uses crop / compress / summarize / select β organized around what its
ContextBudget.strategy()lab actually does to a transcript.
They describe the same territory from different angles: crop is the destructive edge of compress, select is retrieve's decision half, summarize is compress with an LLM. Neither is the Anthropic write/select/compress/isolate quartet β a third taxonomy you'll meet in the wild. Don't memorize taxonomies; memorize the moves.
We use the Claude-track names, but the open-source track's crop β deliberately refusing to include something β shows up here in two places worth naming: M12's permission deny rules (generated and vendored code never enters context at all), and Capstone 2's AMBIG_CAP refusal (a call to a name with 150 definitions produces no edges β the extractor declines to guess rather than emit noise). Cropping at the infrastructure level means the noise never even reaches the budget.
Two Altitudes of Context Rot
M03B, verbatim: "Context rot is the degradation of agent quality caused by accumulated stale, contradictory, or low-relevance content in the context window. It's distinct from running out of tokens β you can hit context rot at 60% window utilization. The key signal is signal-to-noise ratio, not raw size."
The sibling course diagnoses rot inside one conversation: duplicate tool results, superseded instructions, resolved detours that keep occupying tokens. Its cure is compaction β summarize the past, crop the noise, keep the signal. That is rot at the transcript altitude.
This course's M11 diagnoses the same disease one level down, at the infrastructure altitude. A structural graph that stopped rebuilding two weeks ago is stale, contradictory, low-relevance content β served fresh to every session that queries it. M11's warning β "a stale structural graph is worse than no graph β it provides high-confidence wrong answers" β is the rot definition wearing infrastructure clothes. The transcript version poisons one conversation; the infrastructure version poisons every conversation that trusts the graph.
Same signal-to-noise disease, two cures that rhyme: compaction cures the transcript, the freshness gate cures the infrastructure. Both are scheduled hygiene, not one-time fixes β and both fail the same way, silently, which is why M11 makes you write down how you'd detect staleness within 24 hours.
Static-First Ordering and the Missing Middle
Two more M03B rules complete the bridge, and both are quietly load-bearing in designs you've already met.
Static-first ordering β the index.md pre-flight
M03B teaches that context should be assembled static-first: the parts that never change between turns (system prompt, tool schemas, stable orientation) go at the front, the volatile parts at the back. The reason is prompt cachingProviders cache the processed prefix of a prompt. If your next request starts with the identical prefix, that part is nearly free. One changed byte early in the prompt invalidates everything after it.: "same content in the wrong order can cost 6x more." A cache is invalidated from the first changed byte β so anything stable that sits behind something volatile gets re-paid every turn.
Now look again at the OKF bundle's index.md with cache-aware eyes. It is a deliberately stable, deliberately small orientation document that an agent reads before touching anything else β the ideal static prefix. The bundle's design puts the stable map first and lets the volatile detail be fetched on demand. Progressive disclosure (M06) and static-first ordering are the same idea seen from two directions: one is about what to load, the other about where the loaded thing sits.
Lost-in-the-middle β the explore() composite
M03B's position-effects rule: models recall the start and end of a long context far better than the middle β so critical facts scattered across a sprawl of tool dumps are effectively hidden even when technically present. This course's answer is M09's explore(): instead of five facts spread across five tool results (each a page of noise), one compact composite β kind, location, callers, callees, blast radius β lands as a single short block adjacent to the question. You cannot lose in the middle what has no middle.
Code Walkthrough: The Two New Levers
The sibling lab's ContextBudget fixed a poisoned transcript with the compress lever. This course's lab adds the other two, and each is startlingly small once the infrastructure exists β which is the entire point. First, retrieve:
What's happening: we throw away every accumulated grep dump β all 2,341 tokens of tool results β and replace them with one graph answer. Why it works: the expensive part (parsing, indexing) happened at extract time; the query is nearly free. Gotcha: explore() reports blast radius as a count, so we name the transitive callers ourselves with the same reverse-index BFS you wrote in M01 β three lines.
def fix_by_retrieve(self) -> dict:
t = json.loads(json.dumps(self.t)) # deep copy
answer = m09.explore("decode_jwt") # ONE tool call
# name the transitive callers β the M01 walk, three lines
queue, seen = deque(seeds), set(seeds)
while queue:
for edge in m09._reverse.get(queue.popleft(), []):
... # collect edge["source"], BFS onward
answer["transitive_callers"] = sorted(transitive)
# one deterministic answer replaces every grep dump
t["tool_results"] = [{"tool": "graph.explore('decode_jwt')",
"content": json.dumps(answer, indent=2)}]
return t
Then offload. What's happening: the transcript contains a whole argument about the WAU definition β a stale retrieved paragraph, a correction, a re-correction. All of it is superseded by one canonical file that something else (M08's enrichment hook) keeps honest. Why it works: settled knowledge doesn't belong in history; it belongs in external memory, read back on demand. Gotcha: when you drop the WAU debate from history, make sure your replacement actually contains the facts β the lab's checker will catch you if the filter ate the answer too.
def fix_by_offload(self) -> dict:
t = json.loads(json.dumps(self.t))
post = frontmatter.load(WAU_CONCEPT) # M06's canonical file
concept = f"[OKF concept {post.metadata.get('title')}]\n{post.content}"
# the canonical file replaces BOTH stale retrieved chunks...
t["retrieved"] = [{"source": WAU_CONCEPT.name, "text": concept}]
# ...and the settled WAU debate leaves the history
t["history"] = [m for m in t["history"]
if "wau" not in m["content"].lower()]
return t
Two levers, maybe fifteen meaningful lines between them β because the hard work lives elsewhere. explore() exists because M03βM05 built extraction and M09 built serving; the WAU concept exists because M06 taught authoring and M08 keeps it fresh. That asymmetry is the bridge's whole lesson: in-conversation context engineering is cheap exactly when the infrastructure behind it is real. The sibling course's levers are hand tools; this course is the power grid they plug into.
Hands-On Lab: Four Arms, One Poisoned Transcript
π Get the files: labs/M02B-context-levers on GitHub β or clone the whole course once: git clone https://github.com/varasrinivas/knowledge-graph-course.git
What you'll build: the two missing levers of the sibling lab, run against a rotted orderflow session. Time: 30β45 min. Lab folder: labs/M02B-context-levers/ (starter with TODOs, solution, expected output).
Step 1 β Meet the poison
Open starter/poisoned_transcript.json. It is a 17-turn session with every rot species from M03B: two timed-out grep retries, the same grep dump attached twice, a stale WAU paragraph retrieved twice, and a fully resolved expiry detour still squatting in history. Run the accounting:
cd labs/M02B-context-levers/starter
python context_levers.pytool_results 2,341 dominating a 3,131-token raw context β 75% of the budget is exploration dumps.Step 2 β Implement fix_by_retrieve() (TODO 1)
One explore() answer plus named transitive callers replaces every tool result. If your check later reports a missing transitive caller, your BFS is walking edges forward β you need callee β caller.
Step 3 β Implement fix_by_offload() (TODO 2) and fix_combined() (TODO 3)
One canonical concept read replaces the stale chunks and the settled debate. Combined = offload first, then retrieve.
Step 4 β Run the check
python context_levers.py --checkThe real measured table (your numbers will match β everything is deterministic):
| arm | tokens | vs raw | facts preserved |
|---|---|---|---|
| raw | 3,131 | 100% | ALL |
| compress (sibling's lever) | 1,551 | 50% | ALL |
| retrieve | 1,049 | 34% | ALL |
| offload | 2,802 | 89% | ALL |
| retrieve+offload | 721 | 23% | ALL |
SUCCESS CRITERION MET: each lever preserves the facts it owns at fewer tokens than raw. If a lever loses its facts, the README's failure-diagnosis notes name the two usual suspects.Read the table like a context engineer. The raw arm also says "ALL facts preserved" β of course it does, nothing was removed. The facts are simply buried under 2,400 tokens of duplicate dumps and dead detours. That is M03B's core claim made concrete: rot is a signal-to-noise problem, not a budget problem. The levers don't add information; they delete everything that isn't the answer. And note offload's modest 89%: it only owns the WAU facts, so it only cleans the WAU mess β levers compose precisely because each one targets a different layer.
Common Misconceptions
"Context engineering is just prompt engineering with a fancier name." β No. Prompt engineering authors one layer (usually the smallest β 0.9% in the M03B inventory). Context engineering budgets all six. One is writing; the other is resource management.
"More context is always better β just include everything." β The lab's raw arm includes everything, preserves every fact, and is the worst of the five arms. Recall degrades with sprawl (lost-in-the-middle), cost grows linearly, and rot compounds. Inclusion is a cost, not a kindness.
"Context rot means running out of tokens." β M03B's exact counter: you can hit rot at 60% utilization. The signal is stale-and-contradictory content, not a full meter. The lab fixture rots at 3,131 tokens β nowhere near any limit.
"The four levers are conversation techniques, so this course's infrastructure is a separate topic." β The mapping table is the refutation: every piece of infrastructure here IS one of the levers, operated by machinery. If you can name the lever, you know which module to reach for.
Knowledge Check
Module Summary
Next: M03 opens Track 2 β parsing code into graphs with tree-sitter. You now know exactly which lever that track is building: retrieve, made deterministic.
References
- Sibling course, M03B Context Engineering (Claude track): M03B-context-engineering.html β the six layers, four levers, and the ContextBudget lab this module bridges to.
- Sibling course, M03B (open-source track, crop/compress/summarize/select taxonomy): opensource variant.
- This module's lab:
labs/M02B-context-levers/β the retrieve and offload arms the sibling lab left unimplemented. - Related modules here: M06 (progressive disclosure), M09 (explore composite), M11 (drift as rot), M12 (the levers by hand).