Skip to content

Week 2: Advanced context engineering

Learning objectives

By the end of this week, you can:

  • LO2: choose, order and check context for a coding-agent task, and design a small MCP-style tool whose name, schema and errors guide a model toward a safe call.
  • LO3: turn a project proposal into executable acceptance cases, including a case that must fail, and use the cases to connect research, a plan, implementation and verification.

Every example below has a generate step and a verify step. The examples are course-authored and synthetic; they are not claims about a product or a benchmark.

Minimal example

One constraint, four places to lose it

Suppose a proposal says: “A report may read reports/, but it must never write there.” A direct request to an agent—“add CSV export”—does not say where the rule came from or how to check it. The constraint can disappear in four transitions:

  1. Research: the agent reads an old README but not the current permission test.
  2. Plan: the plan says “add export” and drops the read-only boundary.
  3. Implement: the tool schema exposes path with no allowed-root description.
  4. Verify: the test checks that a CSV exists but never attempts a write to reports/.

Generate: write a one-paragraph plan for the export request. Verify: underline the constraint, its source, the implementation boundary and the negative test. If one is missing, the plan is incomplete even when the generated code looks plausible.

Research, plan, implement

Use three short artifacts rather than one unbounded prompt:

Phase Question Artifact that can be checked
Research What is true at this revision? Evidence table with paths, symbols and unknowns
Plan What small change would satisfy the request? Ordered steps, boundaries and acceptance cases
Implement What code expresses that plan? Patch plus the commands that exercise each case

Generate: for the synthetic export request, make an evidence table with two rows naming the export handler and its rejection test. Mark an unknown explicitly rather than guessing. Verify: open both files at your checkout revision; change “confirmed” to “cannot tell” when the source does not show the claim. A plan is more useful when a reader can disagree with one row and run one check.

A specification that can fail

Write acceptance cases as observable input and output. The following cases are deliberately small:

Given an export root called out/
When the request names out/summary.csv and rows are valid
Then the file is created and the command reports exported

Given the same root
When the request names reports/summary.csv
Then no file is written and the command reports refused: read-only root

Given the same root
When a row is missing its id
Then no file is written and the command reports invalid row: id

Generate: implement the smallest function that could satisfy the three cases. Verify: run the positive case and each negative case against a fresh temporary directory. A specification that only says “export works” cannot reveal a missing refusal or a partial write.

The project proposal due this week is the first version of this artifact. Keep its core scenario, boundary and three to five failure-capable acceptance cases together. Revise it when research shows that a case is not observable.

Context packets and compaction

A context window is a working budget. Tool output, repeated reads and failed attempts consume it; a later request can then miss the one constraint that mattered. The retained session recording and dissection let you inspect this effect without making a model call. The course-written compaction script shows it on one hand-written session. It reads the session file beside it, so run it from its own folder:

(cd lectures/week-03/fixture && python compaction.py full)
(cd lectures/week-03/fixture && python compaction.py auto)

full keeps all 19 messages, reports "check": "passed" and exits 0. auto clears the older tool results, loses the line that says not to edit view.py, reports "check": "failed" and exits 1. No model is called in either run.

Generate: before shortening a history, write a handoff with the task, source of each constraint, current file state, last failed check and next action. Verify: compare each line with the recorded messages, then rerun the check on the current revision. A summary that says “tests passed” without the tested revision is not evidence.

When most entries are stale or contradictory, restart with a written handoff and reread the next files. Compacting is a choice about information, not a guarantee that the model will remember the right information.

Tool design for a model reader

A model sees a tool's name, description, input schema and returned message. Treat these as a contract, not decoration. A small example:

{
  "name": "export_report",
  "description": "Write a CSV below out/; never writes reports/.",
  "inputSchema": {
    "type": "object",
    "additionalProperties": false,
    "required": ["path", "rows"],
    "properties": {
      "path": {"type": "string", "pattern": "^out/[A-Za-z0-9_.-]+\\.csv$"},
      "rows": {"type": "array", "items": {"type": "object"}}
    }
  }
}

Generate: propose a call for out/summary.csv and one for reports/summary.csv. Verify: validate both against the schema and run the handler. The first should reach the handler; the second should produce a short, actionable error and no file effect.

Use five design checks:

  1. Name: a verb and object make the intended action selectable.
  2. Description: state the allowed root and the important exclusion.
  3. Schema: make required fields, types, closed properties and simple patterns machine-checkable.
  4. Errors: identify the bad field and the next repair; never return a traceback.
  5. Result: return the observation the next decision needs, including refusal and partial-failure states.

MCP names the protocol family used to connect a model application with tools and resources. The protocol does not make a vague tool safe: the handler still enforces its boundary, and the controller still has to pass the result back to the model. Read the interface as a model reader would, then test the behavior with calls.

Reading a production agent's instructions

The factsheet readings compare two pinned open-source files. Select one rule about plans, one about a tool schema and one about stopping. For each, write four labels: what the text asks the model to do, what code checks, what the runtime checks and what remains unknown. A description can ask for three lines of context while tool code enforces only a single-match rule; keep those claims separate. Do not infer current releases from a pinned source.

Hands-on exercise

The studio is an individual 75-minute pass over your own project proposal. You will write three to five acceptance cases that can fail, then tighten one small tool schema and error message. Keep the before/after schema and every command result. The retained Week 1 fixture and session remain available for inspection.

Verification

Use this order:

  1. Check each research claim against the file and revision named in the evidence table.
  2. Validate every acceptance case once on a fresh temporary directory, including its expected failure.
  3. Validate the revised schema with a valid call, an invalid call and an unknown field.
  4. Record the command, exit status, observed output and the decision to accept, shrink, recheck or stop.

Common mistakes

  • Prompt first, evidence later: search the relevant files and record unknowns before asking for an implementation.
  • A plan with no rejection: add a malformed or forbidden input whose expected result is an observable refusal.
  • A schema that accepts everything: close the object and constrain paths, enums or bounds that the handler relies on.
  • An error that only says “invalid”: name the field and a repair, then test that the model receives the message.
  • Confusing a generated answer with verification: rerun the acceptance case after the last write; preserve the failed result and tested revision.
  • Treating a protocol name as enforcement: identify the handler and runtime checks; mark anything else as unknown.
  • Compacting away the rule: keep the task, constraint source, current state, open failure, paths and next action in the handoff.