Objective
What you're building
Nothing that touches a real codebase yet. Today is the project skeleton, one file-read tool, and — just as importantly — an honest look at what this course costs to run, before you're 3 lessons deep and surprised by an API bill.
Budget for this before you start, not after
A single realistic task through the finished agent (Lesson 6) typically costs 50k-200k tokens — at Sonnet pricing, roughly $0.50-$2.00 per run, and you will run it more than once while debugging. This isn't a course to work through with your API key on a whim; know the cost before Lesson 4's fix-loop starts burning tokens on retries.
Why "dump the whole repo into context" doesn't work
The obvious first idea — read every file, put it all in the prompt, ask the model to make the change — breaks in two ways: real repos exceed the context window fast (a 50-file repo is easily 100k+ tokens of raw source), and even when it fits, most of those tokens are irrelevant to the specific task, diluting the model's attention on the files that actually matter.
A coding agent's hardest problem isn't writing code -- it's choosing what to read
Claude Code, Cursor, and Devin all solve variations of the same problem before generating a single line: given a task and a codebase, which files actually matter? This course builds that layer explicitly (Lesson 2) rather than treating it as solved — it's the single biggest quality lever in the whole system, more than model choice or prompt wording.
The loop this course builds, end to end
task ──▶ scan repo, score file relevance (Lesson 2)
│
▼
generate + validate a structured plan (Lesson 3)
│
▼
execute plan: backup ──▶ write ──▶ run tests (Lesson 4)
│
tests fail? ──▶ read error, generate fix, retry (max 3x)
│
tests pass ──▶ next file in plan (Lesson 5, ordered + rollback-safe)
│
▼
git commit + structured summary (Lesson 6)
from anthropic import Anthropic
client = Anthropic()
def read_file_tool(path: str) -> str:
with open(path, "r", encoding="utf-8") as f:
return f.read()
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
tools=[{
"name": "read_file",
"description": "Read the full contents of a file in the target repository, given a path relative to the repo root.",
"input_schema": {
"type": "object",
"properties": {"path": {"type": "string"}},
"required": ["path"],
},
}],
messages=[{"role": "user", "content": "What does agent.py do? Read it and summarize."}],
)
This should look familiar from Course 01 -- one tool, one call. What's different starting next lesson isn't the mechanism, it's the stakes: a read_file tool is harmless to get wrong. A write_file tool without the backup pattern Lesson 4 builds can corrupt a real repository you care about. Keep this distinction in mind as complexity ramps up over the next 5 lessons.
Why is a test-driven fix loop (write code, run tests, read failures, retry) generally more reliable than a pure generation agent that just writes code once and stops?
Tests aren't perfect (they only catch what they're written to catch), but they're an external ground truth the model can't talk its way around the way it can in a pure text response. "I've made the change" from a model that never ran anything is a claim; "3 passed, 0 failed" from a real subprocess is a fact the loop can act on. This is the same "checkpoint = functional, not conceptual" principle from Course 01, applied at the scale of a real codebase.
What you're building today
code_agent_skeleton.py: the project setup, one read_file tool, and a single test where the agent reads a real file from your chosen test repo and correctly describes what it does — proving the basic plumbing works before Lesson 2's actual complexity begins.