Plan, implement, verify
Coding with agents · topic coding-with-agents/workflow
A repeatable rhythm for shipping with a coding agent: plan before editing, drive the change from a specification or a failing test, land it in small working increments ordered so feedback arrives early, keep every step reversible, and record the work in commits and pull requests a team can review.
Concepts
- Plan mode
- Having the agent explore and propose before it edits anything. In plan mode it reads the code, asks questions and writes down the steps it intends to take; you correct the plan while corrections are cheap. Most agent mistakes are cheaper to catch in a plan than in a diff, so use it for any change touching more than a couple of files. glossary
- Spec-driven change
- Writing the specification of a change, including its success criteria, as a document the agent works from and the reviewer checks against. The spec stays the source of truth while the agent iterates; when the code and the spec disagree, one of them is updated deliberately. It suits changes where the design matters more than any single test. glossary
- Test-driven change
- Writing or having the agent write a failing test that captures the desired behavior, then implementing until it passes, then cleaning up. The test gives the agent an unambiguous target it can run on its own and gives you proof that the change does what was asked. It suits bounded behavioral changes and bug fixes. glossary
- Working increments
- Landing a change as a series of small steps, each of which leaves the system working and tested. Increments keep the diff reviewable, keep the agent's context focused and make it obvious which step introduced a problem. An agent will happily produce a large change in one go; asking for increments is part of the brief. glossary
- Sequencing for early feedback
- Ordering increments so the riskiest assumption or the most visible behavior is tested first. Build the thin end-to-end path before the details, the integration before the polish, the part you are least sure about before the part you are certain of. Early feedback turns a possible rewrite into a small correction. glossary
- Reversibility
- Keeping every change easy to undo: committed in small steps, on a branch, with no destructive operations mixed in, and with data migrations that can be rolled back. Reversibility is what makes it safe to let an agent try something. If a step cannot be reversed, it is the step that needs a human to look before it runs. glossary
- Commits and PRs
- Recording agent-assisted work in the team's normal units: focused commits with messages that say why, and pull requests that explain the change, link the specification and state what was verified and how. Good commit boundaries make review and revert possible; a PR that describes the agent's role lets reviewers calibrate their attention. glossary
Links
- Builds on: Running a coding agent, Deciding and specifying
- Leads to: Context engineering for code, Verifying agent work
- Competencies drawing on it: Ships a change with a coding agent through plan, implement and verify, Works with agents alongside a team
Lessons
- Staying the engineer who understands the system (explanation)
- Plan first, then drive the change from a failing test (tutorial)
- Keeping every agent change easy to undo (tutorial)
- Working from a spec in small increments (tutorial)
Your reference
Each lesson above adds its takeaways and its example here once you finish it. Your reference lists every lesson you have finished.
Staying the engineer who understands the system
Unlocks when you finish Staying the engineer who understands the system.
Takeaways
- Understanding leaks when the agent writes and you only run the tests. Passing tests check the change and say nothing about whether you can still explain the system.
- Read agent code with the attention you give a colleague's pull request. Stop at every line you can't explain, and ask for a plain-language explanation and a test that documents it.
- After an increment is merged, explain from memory how the parts fit and why, then check the explanation against the code. A gap is a review finding.
- Architecture decisions and their reasons go in a decisions folder in the repository, and the project instructions point the agent at it, so the next session reads the reason before it proposes to reverse the decision.
Example
In todo.py, the due command validates the date with datetime.date.fromisoformat(text). Explain in plain language which inputs that accepts and which it refuses, and add a test that documents one accepted and two refused inputs.
fromisoformat accepts a date written as four digits, a dash, two digits, a dash and two digits, such as 2026-10-01, and raises ValueError for tomorrow and for 2026-10-1, where the day has one digit. Which other forms it accepts depends on the Python version. On 3.9 and 3.10 the dashed form is the only one. From 3.11 it also accepts other ISO 8601 forms, such as 20261001 without dashes and the week form 2026-W40-4. The spec's bad date criterion names tomorrow, and the due command catches the error and prints bad date: <input> for it on every version. I added test_due_date_formats in test_due.py with 2026-10-01 accepted and tomorrow and 2026-10-1 refused, which holds on 3.9 and on 3.11. If you want 20261001 refused too, the check needs to be stricter than fromisoformat alone, and that is a spec decision.
Plan first, then drive the change from a failing test
Unlocks when you finish Plan first, then drive the change from a failing test.
Takeaways
- For a change you can't place in one file, start the agent in plan mode: it reads and proposes, and it edits nothing until you approve. If you could write the diff in one sentence, skip the plan.
- Read the plan against the cause it names, and correct or drop a step that doesn't follow while the correction costs a sentence.
- The failing test comes before the fix. It has to fail on the code as it is, or it isn't looking at the bug.
- The agent implements until the test passes. You run the check yourself, and you read the diff to see that it touched only what the plan said.
- A test suits a bug fix or a bounded behavior change. A design question starts from a spec, and the two work together.
Example
Show the list · open in the lesson
Run this, and compare what you see with the output below.
python3 todo.py listPrints the lines below (verified in CI from site/examples/coding-with-agents/plan-then-test/list.py)
1. [ ] Buy milk 2. [x] Call the plumber 3. [x] Renew the passport 4. [ ] Water the plants 2 open, 2 done
Keeping every agent change easy to undo
Unlocks when you finish Keeping every agent change easy to undo.
Takeaways
- A change is reversible when it is on a branch in commits small enough to revert one at a time, and no step in it is one that can't be undone. That's what makes it safe to let an agent try.
- Ask for one commit per increment in the brief, and rule out the git commands that discard history by name. The step with no way back is the one you read before it runs.
- A data or schema change is designed with its way back written down before it runs: add and backfill first, drop later, and prefer a switch that turns the change off over a revert that needs a deploy.
- The commit message says what changed and why. The pull request description names the spec, says what was verified and how, and says what the agent did and what you did. The reviewer then spends their time where no person has looked yet.
Example
Read SPEC.md and land its three increments on this branch, one commit per increment. After each increment run python3 -m unittest -q, and commit only when it passes. Use a one-line commit message that starts with feat: and says what the increment adds. Don't touch main, don't rewrite a commit once it exists, and don't run any git command that deletes or force-pushes anything. Stop after the third commit and show me git log --oneline main..HEAD.
The branch due-dates has one commit per increment, and the suite passes after each one.
a3f9c1e feat: refuse a malformed date5b27d04 feat: overdue command with TODO_TODAYe81a6b2 feat: due command and the date in listEach commit touches todo.py and adds one test file. The first also changes render.py. store.py and todos.json are unchanged.
Working from a spec in small increments
Unlocks when you finish Working from a spec in small increments.
Takeaways
- A feature starts from a one-page spec with a goal, the commands, the limits and success criteria you can tick one by one. The spec is the source of truth while the agent works. When code and spec disagree, one of them changes on purpose.
- Ask for increments in the brief. Each one leaves the program working and tested and adds one thing you can run, and the agent's default without that ask is one large diff.
- Order the increments with the least certain assumption first, as the thin end-to-end path through every module before any detail is built on it.
- After each increment, run the tests and the criteria yourself, commit, and only then brief the next one.
Example
Show the list · open in the lesson
Run this, and compare what you see with the output below.
python3 todo.py listPrints the lines below (verified in CI from site/examples/coding-with-agents/spec-driven-increments/list.py)
1. [ ] Buy milk 2. [x] Call the plumber 3. [x] Renew the passport 4. [ ] Water the plants 2 open, 2 done
Sources
DLAI-5Claude Code: A Highly Agentic Coding Assistant, DeepLearning.AI (course)DLAI-6Introduction to Generative AI for Software Development, DeepLearning.AI (course)Brilliant INCDeveloping incrementally, Brilliant, Coding with AI skills map (reference)Academy claude-code-101Claude Code 101, Claude Academy (course)Academy ai-native-sdlc-playbookThe AI-native SDLC playbook, Claude Academy (course)