1 · Context Engineering — The Central Skill¶
The quality of an agent's output is capped by the quality of its context: an agent can only act on what it can see. Before any technique for driving an agent comes the skill of controlling what enters its view. That is the subject of this module, and every later module depends on it.
An agent's context window is its working memory, and it is finite. Everything the agent knows about the task at hand — the files it has read, your instructions, the last few things it tried — lives in that window, and nothing else does. When the files it needs are absent, it guesses. When the window is crowded with irrelevant material, the signal it needs is buried. In both cases the output degrades, and the cause stays hidden unless you are watching the context rather than the code. The operator's first job is therefore curation: put in what the task needs, and leave out what it does not.
The governing rule is that fresh context beats bloated context. A focused window of the right files and instructions outperforms a large dump of everything. When an agent begins to thrash, the fix is usually less context rather than more: start clean and reintroduce only what matters.
The widget below makes the tradeoff concrete. Fill the window and watch the readout change from focused to bloated as you add a repository dump and stale dead-ends.
Interactive: a fixed context window you fill with items — watch focused change to bloated as you add the repo dump and stale dead-ends. (Enable JavaScript to try it.)
Concept¶
Three levers control what is in the window. Two are file choices: the project instruction file and the files for the current task. The third is a session choice: whether the current thread is still fresh enough to keep using.
-
Project instructions — the
CLAUDE.mdcraft. The agent reads a project instruction file at the start of every session. In this course, that file isCLAUDE.mdat the repository root. A goodCLAUDE.mddoes not explain the whole repository. It tells the agent where to look and what is not obvious from the code: the tribal knowledge, the landmines, the conventions a newcomer would violate. Think of it as an onboarding document for a teammate who reads fast and forgets nothing, but starts each day knowing nothing about this repository.Use a simple placement rule when deciding what belongs there. Put only the always-needed map and landmines in
CLAUDE.md. Leave raw implementation detail in the codebase, where the agent can search for it when the task reaches that deep. The file should point the agent to the right places without copying those places into the resident context.For example,
CLAUDE.mdmight say where request handlers live and name the rule that every handler change needs a test. It should not copy the handler code, the full testing guide, or the framework reference.CLAUDE.mdgives the agent the starting map; the task determines which files it should open next. -
The files the task actually touches. A single task usually changes only two or three files. Everything else in the repository is noise the agent must read past, and the risk runs both ways: if the files that matter are missing, the agent guesses at code it cannot see, and if too much else is in the window, the few lines that matter are buried. So the operator's job is to get the task's files into view and leave the rest out.
Most of the time a good
CLAUDE.mddoes this for you, because it records where each kind of change lives. A single line such asChange wording the model sees → app/llm/prompts.pyis enough: when you ask the agent to reword the prompt, it reads that line and opensprompts.pydirectly instead of grepping the tree. The instructions file turns a vague request into the right file before the agent takes a step.When the file has no such line, or you simply want to be explicit, name the file in the prompt. "Edit the prompt in
app/llm/prompts.pyto add a confidence score" starts the agent in the right place; "fix the classifier" leaves it guessing and sends it hunting. If a change spans two files, name both, for example "update the response shape inapp/models.pyand the code that builds it inapp/triage/classify.py."The reverse habit matters too: leave out files that only look related. For a prompt change the files are the prompt and the test that checks it; the application's entrypoint (
app/main.py) is usually unrelated, and pulling it in just spends context for nothing. -
Freshness — start clean when the thread goes stale. A long session fills with dead ends, abandoned plans, and stale file contents, and that residue drags down the agent's later moves. The tool fights this for you by compacting — summarizing the older parts of the window to make room — but a summary loses detail. When a thread has clearly gone sideways, the stronger move is to reset: start a fresh session and restate the goal in a sentence or two.
In short: write the standing map, put each task's files in view, and start clean when the window goes stale.
Bad / Good / Great — a CLAUDE.md for the Practice Repo¶
The examples use Triage, the small support-ticket classifier used in the course labs. Here is the same repository with three instruction files. The distance between Good and Great is the lesson.
# CLAUDE.md
This is a Python project. It uses FastAPI. The app does ticket triage with AI.
Please write clean, well-tested code and follow best practices. Be careful and
make sure everything works. We value code quality. Always add tests. Use type
hints. Don't break anything. Thanks!
Why it fails: generic filler the agent already assumes. It offers no navigation, no tribal knowledge, and no way to verify work. "Follow best practices" tells it nothing it did not already know. This file leaves the agent no smarter about this repository.
# CLAUDE.md — Triage
A support-ticket assistant: classify an incoming ticket into a category.
## Layout
- `app/triage/classify.py` — core classification
- `app/llm/` — provider wrapper (`client.py`) and prompts (`prompts.py`)
- `app/models.py` — request/response shapes
- `eval/` — offline eval set + runner
## Run / test
- Serve: `uvicorn app.main:app --reload`
- Test: `pytest`
Why it is solid: a real map and the commands to run. A newcomer agent can find its way and verify a build. This is already most of the value.
# CLAUDE.md — Triage
A support-ticket assistant: classify a ticket into a category. Read this, then
the file it points you to — don't scan the tree.
## Where things live (start here, don't grep the repo)
- Change classification logic → `app/triage/classify.py`
- Change wording the model sees → `app/llm/prompts.py` (NOT inline in classify.py)
- Change models/providers → `app/llm/client.py` only
## Non-obvious rules (the landmines)
- Never hardcode a model id. It lives in settings, read once in `llm/client.py`.
A model string anywhere else is a bug.
- `eval/` is the source of truth for any prompt change. Edit a prompt → run
`python -m eval.run` and check the score didn't drop before you call it done.
- The LLM call is mocked in `tests/` (`conftest.py`). Don't hit the real
provider in a unit test.
## Verify your work
- `pytest` must pass. A prompt change ALSO requires `python -m eval.run` to hold.
Why it is great: it is not longer for its own sake. It is navigational, saying where to look rather than describing the whole tree; it captures the tribal knowledge the code does not show (the model-id rule, the eval gate, the mocked LLM call); and it tells the agent how to verify itself. It makes the agent behave like someone who has worked here for a year.
In short, a great instructions file is not longer than a good one. It points to where things live, it records the tribal knowledge the code cannot show, and it tells the agent how to check its own work. Length is not what makes it great; aim is.
The through-line of this course is one question: how long can the agent run before it needs you? Context is the first lever on that runway. The sharper the instructions file, the longer the agent navigates and checks its own work without you.
Guided Lab¶
On the Practice Repo, you will run one cold task three times — with no CLAUDE.md, with a Good one, and with a
Great one — and measure how the agent's wasted turns shrink each time.
-
Clone Triage and start the agent in the repo root:
Expected: the agent opens at the repo root and no
CLAUDE.mdis present (confirm withls CLAUDE.md→No such file or directory). -
Cold run, with no context. Give the agent this exact task:
add a confidence score to the classification output
Expected: it grep-scans the tree, opens several wrong files, and takes multiple turns to locate the two files that matter,
app/triage/classify.pyandapp/llm/prompts.py. Note how many turns it spends before touching the right file. That number is your baseline. -
Write a Good
CLAUDE.md. CreateCLAUDE.mdat the repo root with the layout and run/test content from the Good tab above (the## Layoutmap and the## Run / testcommands).Expected:
CLAUDE.mdexists at the repo root (ls CLAUDE.mdnow succeeds). -
Fresh run. Start a clean session so the stale cold-run context is gone, then repeat the same task:
add a confidence score to the classification output
Expected: the agent opens
app/triage/classify.pyearly instead of scanning blindly, using fewer turns than your step-2 baseline. -
Push to Great. Edit
CLAUDE.mdto add the three things from the Great tab: the "where things live" map, one real landmine (the model-id rule, where a model string outsideapp/llm/client.pyis a bug), and the verify step (pytest, pluspython -m eval.runfor any prompt change). -
Fresh run again. Run
/clear, then repeat the same task.Expected: the agent edits the prompt in
app/llm/prompts.pyrather than inline inclassify.py, does not hardcode a model id, and ends by runningpytestandpython -m eval.runon its own, because the file told it how to check itself. The turn count falling from step 2 to step 4 to step 6 is the runway getting longer.
A /lesson-1-cold-navigation instructor skill can coach this live from a second terminal. It watches your session,
stops at each checkpoint, and asks a leading question before handing you the next move; it does not edit
your repository for you. The skill ships in the Practice Repo; for now you can also follow the numbered
steps above.
On your own codebase, repeat the exercise. Write the three non-obvious rules a new hire always trips on; those three lines are often worth more than the entire layout section.
Keep the artifact¶
The artifact is the CLAUDE.md you wrote: a "where things live" map, the tribal rules, and a verify step. It
is not a worksheet to throw away. It ships in the repository and earns its keep on every future session, for
you and for every teammate's agent, so commit it. The standing rule from here is simple: when you learn a
non-obvious thing about a repository the hard way, add the line to CLAUDE.md so neither you nor the agent has
to learn it twice. That file growing sharper over time is the first instance of compounding
(Module 6).
Self-check¶
You did it right if, in a fresh session with your CLAUDE.md in place, the agent:
- opens the correct file for the task without you naming the path, and
- respects at least one rule you wrote that it would otherwise have broken — for example, it edits the prompt
in
prompts.pyinstead of inlining it, or it does not hardcode a model id.
If it still flails or breaks a rule you wrote, the file is describing the repository rather than navigating it. Tighten it toward the Great example.
Recall¶
Before moving on: name the three things that make a
CLAUDE.mdgreat rather than merely good, and why "add more detail" is not one of them.
Answer
Navigation — it points to where things live; tribal knowledge — the rules the code cannot show; self-verification — how the agent checks its own work. Length is not on the list; a great file is often shorter, just better aimed.