CHAPTER 13 · MASTERY

Driving Coding Agents

The previous twelve chapters gave you mental models and vocabulary. This one assembles them into a repeatable workflow: how to turn fuzzy intent into a spec an agent can execute precisely, where to step in, and how to review output efficiently. The goal is for you to always hold the direction and the pace, instead of being pushed along by whatever the agent produces.

⏱ ~60 minDeep (why it works this way) Use (templates and checklists to take away)
By the end of this chapter you should be able to:
  • Drive a feature through "explore → spec → plan → implement → verify → review" and know which points you must decide yourself.
  • Write a task description using the six-element template.
  • Translate a vague symptom ("the page is slow", "the data is wrong") into precise technical language.
  • Review an agent-generated PR in 10 minutes with a checklist.
  • Recognize the signs of an agent going in circles and know what to do.

Opening: two developers, one feature

Opening question

A and B use the same agent to add "filter by tag" to LinkNote. A types "add a tag filter" and spends two hours going back and forth: the agent uses useState, A says the filter is lost on refresh; the agent switches to localStorage, A says others don't see the filter in shared links; the agent switches to a URL param but "helpfully" refactors the list component and breaks pagination… B spends 15 minutes writing a description, and the agent finishes in one go with all tests passing. What did B do right?

Where the answer lies: A is making the agent guess the requirements by trial and error, exposing one hidden requirement per round; B said the hidden requirements out loud before starting: filter state in the URL (shareable, survives refresh), don't touch pagination, and what "done" means. Agents execute extremely well, but they can't read requirements you never stated. B's 15 minutes weren't "writing docs" — they were design, which is your core job in the agent era.

The workflow at a glance

① Exploreagent investigates ② Specyou define the what ③ Planyou approve it ④ Implementagent, in small steps ⑤ Verifytypes · tests · preview ⑥ Reviewyou read the key diffs ⑦ Commit / mergesmall PRs · CI gates ⑧ Captureupdate AGENTS.md / tests fail → back to implement (the agent loops itself) Red nodes are where you must decide personally; blue and green nodes can largely go to the agent and automated checks.
The full loop for one feature. Small features can merge steps (explore and plan together), but "spec" and "review" can't be skipped.

① Explore: have the agent investigate before it touches anything

For unfamiliar code or complex changes, the first instruction should be "investigate and report", not "implement". For example: "How does the list page load its data? Where do filter and pagination state live? Read only, change nothing, give me a short report." It's cheap, and it exposes your own wrong assumptions.

② Spec: your core output

See the six-element template in the next section.

③ Plan: reject the wrong direction when it's cheapest

Have the agent produce a plan before writing code (many tools have a dedicated "plan mode"). Reviewing a plan is ten times cheaper than reviewing code. Ask of the plan:

④ Implement: small, verifiable, committable steps

Cut work into vertical slices: each slice is the smallest end-to-end runnable piece ("first make the URL param filter the list; no UI yet"), rather than "all DB code, then all endpoints, then all UI". Run checks and commit after each slice. If something breaks, you roll back one small step.

⑤ Verify: let the machines check first

Chapter 10's Definition of Done kicks in here: the agent may only say "done" when type checks, lint and tests all pass. For UI, open the preview link and click through yourself — nothing automated replaces that.

⑥ Review → ⑦ Merge → ⑧ Capture

Review method below. After merging, spend one minute asking: what did I have to tell the agent more than once? Write it into AGENTS.md or turn it into a test or lint rule. Every correction should happen only once.

The six elements of a task description

ElementQuestion it answersTypical result when missing
1. Goal & contextWhy? For whom?Technically correct, solves the wrong problem
2. ScopeWhat to do, and explicitly what not to doThe agent "optimizes" unrelated code on the way
3. ConstraintsRequired / forbidden tech, patterns, dependenciesNew libraries, a different state approach, strict checks turned off
4. Interfaces & dataShape of the data, where it lives, function signaturesA different data model every time; front and back don't line up
5. Acceptance criteriaWhat counts as done? (executable, observable)"Looks like it works", every edge case missed
6. DeliverablesWhat to hand back: code, tests, notes, screenshotsNo idea what changed or how to verify

A description like this takes 10–15 minutes. It forces you to decide first: where state lives, which layer filters, what the edge cases are. Leave those decisions for the agent to make implicitly and you get A's two hours.

When you can't write the description

If you can't write acceptance criteria, you probably haven't decided what you want yet. Then flip it and let the agent help: "I want tag filtering. Interview me to clarify the requirements, one question at a time, then write it up as a task description." That uses the agent for requirements analysis instead of making it guess.

Precise language: from symptom to term

What you observe is usually a "symptom"; what the agent needs is a "direction for diagnosis". This table maps common vague descriptions to precise expressions from earlier chapters. Fluency with these words is the most direct lever you have over an agent:

What you seeA likely precise expressionCh.
The page keeps re-requesting an endpointuseEffect depends on an unstable reference, forming a "render → effect → setState" loop06
Changed the data, UI didn't updateState object was mutated; reference unchanged; use an immutable update03 / 06
Filter / pagination lost on refreshThat state belongs in URL query params, not component-local state06
Search results don't match the inputRequest race: an older request returned after a newer one; cancel or discard stale results by key06
Same data shown differently in two placesStored derived state / no single source of truth; or a cache that wasn't invalidated06 / 08
First page load is slowToo much first-screen JS / request waterfall / should be server-rendered or streamed07
Page shows one thing, then flashes to anotherHydration mismatch / client refetching data07
Others can see or delete my dataMissing authorization (IDOR); put the ownership condition in the query08
API errors in the browser, curl worksCORS: declare allowed origins and credentials, or go same-origin05
Occasional lost data or wrong counts after deployShared state kept in serverless instance memory09
"Too many connections" at peakConnection explosion under serverless; need a pooling proxy or HTTP driver08
Batch processing "finishes early"forEach(async) not awaited; or a floating promise03
AI answers take ages to appearNo streaming; time to first token (TTFT) too long11
AI output format is right only sometimesMissing structured output and schema validation11
The agent gets messier and repeats mistakesContext too long or polluted; write progress to a file and start a new session12

Note the word "likely". These expressions are hypotheses, not conclusions. The good move is to give the agent both the symptom and your hypothesis, and require it to verify first: "I suspect a request race; add logging first to confirm the order requests are sent and returned, then fix it."

Reviewing agent output

Reviewing a design

When an agent hands you a design doc or technical proposal, the point isn't polished prose but:

Reviewing code: a 10-minute checklist

Don't start reading line by line from the first file. Go from highest information density down:

  1. Scope of change: does the list of modified files match expectations? Anything from the "don't" list touched?
  2. Data structures: schemas, type definitions, Zod schemas, DB migrations. They decide the shape of everything else.
  3. Tests: do they cover the acceptance criteria? Were existing tests modified (Chapter 10)?
  4. Boundaries: is external input validated? Is the authorization condition there? Did secrets leak into client code?
  5. Search for red flags: any, as, !, @ts-ignore, eslint-disable, empty catch, new dependencies, useEffect.
  6. Core logic last: by now you know what it should look like, so it reads much faster.
Let another agent help review

Open a new session (or a subagent), give it only the task description and the diff, and have it find problems with the checklist above. It hasn't been "convinced" by the implementation process and often catches what the implementing session can't see. The final call is still yours.

Controlling the pace

When to step in

Collaborating on debugging

The key: give evidence, ask for hypotheses, verify before changing. That turns the agent from "guess a fix" into "run a small scientific experiment".

When to do it yourself

A one-line config change, a small bug you already know how to fix, UI tweaks that need taste — doing it yourself is often faster than describing it to an agent. You don't have to use an agent for everything.

Running in parallel

Once fluent, you can run several agents on independent tasks at once (one building a feature, one adding tests, one investigating a performance issue), each on its own git worktree or branch. The precondition: the tasks really are independent and you have the bandwidth to review everything — your review capacity is always the bottleneck of parallelism.

Writing AGENTS.md well

How the tools differ Aware

Claude Code, Codex CLI, pi, Cursor and IDE agents share the same underlying principles (Chapter 12), and this chapter's methods apply to all of them. The differences are mostly in harness philosophy: some ship rich built-ins (plan mode, subagents, hooks, plugin marketplaces, cloud runs), others are deliberately minimal and let you assemble what you need via extensions. When choosing, look at: model support, the project-instructions file convention, permission granularity, whether it can run unattended (CI, batch jobs), and whether you like how it feels. No need to chase every new tool — the workflow and your ability to express yourself are the assets that transfer.

Anti-patterns

Anti-patternWhy it hurtsInstead
Never reading code, only checking the resultSecurity holes and data-model problems don't show in the UIAt least review data structures, tests and boundaries with the checklist
"Fix all the errors"The agent makes errors vanish the fastest way (any, as, ignore)Add constraints: forbidden escape hatches; explain before fixing
One session all dayContext rot; quality drops later onOne task per session; progress written to files
One giant requirement at onceVague plan, huge diff, unreviewableVertical slices, each verifiable
Letting the agent make architecture decisions silentlyWhere state lives, which layer filters, which library — these shape the project for a long timeState them in the spec, or approve them at plan time
Building the perfect toolchain before building the productTime goes into preparing instead of shippingShip a minimal working version first; add tools when real problems appear
Interview corner: "How do you use AI coding tools?"

This question is extremely common in 2026 interviews. A good answer isn't "I use tool X and I'm N× faster" but a demonstration of your method and judgment:

  • Write specs and acceptance criteria first, then let the agent implement; review the plan first for complex tasks.
  • Use type checks, tests and CI as an automated verification net instead of reading every line.
  • Review focus: data models, authorization and validation, whether tests were modified, new dependencies.
  • Give an example of catching a subtle agent mistake (an IDOR, an effect loop) and how you caught it.
  • Explain how you turn repeated corrections into project instructions, hooks or lint rules.

Self-check

1. Rewrite this request as a six-element task description (abbreviated is fine): "Add an export feature to LinkNote."

Reference points: goal (users want to back up or migrate bookmarks); scope (export all of the current user's bookmarks as JSON and Markdown; no import, no scheduled exports); constraints (generated server-side, streamed download to avoid memory issues with large data; no new dependencies); data (url, title, summary, tags, createdAt; exclude internal id and userId); acceptance (1,000 bookmarks export without timing out; users can export only their own data; file name includes the date; tests exist); deliverables (plan first).

The point isn't matching this exactly, but whether you thought of "what not to do", authorization, data volume and verification on your own.

2. The agent has tried three times to fix "the list sometimes shows stale data", each time saying "fixed", but it still happens. What should your next message say?

Stop the attempts. Something like: "Don't change code yet. List at least three possible causes of the list showing stale data (cache not invalidated, request race, server-side cache), and how to verify each with logs or tests. Then add logging and give me reproduction steps; we'll fix it once the evidence points to a cause." If the session is already long, have it write findings to a file and continue in a new session.

3. The agent's PR touches 23 files, 15 of which are "code style cleanup while I was there". What do you do?

Ask for a split: move the style changes out of this PR (or just revert them) and keep only the feature changes. Mixed diffs hide the real logic changes, make review hard, and raise conflict and rollback costs. Then add to AGENTS.md: "Don't modify files outside the task's scope; formatting is the formatter's job."