AI Coding Agents: A Workflow That Holds Up
Treat a coding agent like a fast colleague who needs a clear ticket and a way to check its own work. Write the task with acceptance criteria, ask for a plan before any code, give the agent commands that prove the change works, keep every diff small, and review it as the owner. Speed is the agent’s

Posted on Oct 14 • Originally published at ahmadhsn1.github.io on Oct 14
Treat a coding agent like a fast colleague who needs a clear ticket and a way to check its own work. Write the task with acceptance criteria, ask for a plan before any code, give the agent commands that prove the change works, keep every diff small, and review it as the owner. Speed is the agent’s job. Judgment stays with you.
Coding agents write and change code quickly, and they follow instructions well. That shifts where the effort goes in a project. Less of it is typing. More of it lands in two places: saying exactly what you want, and checking that you got it.
Both are old engineering skills. Writing a clear ticket and reviewing a change were always part of the job, and they matter more now because the cost of producing a change has dropped while the cost of understanding it has not. The workflow below does not depend on any vendor. It works whether your agent lives in a terminal, an editor or a pull request bot.
An agent fills every gap you leave with its own best guess. A vague request returns a confident answer to a question you did not quite ask. A useful task has four parts: the goal, the constraints, how to tell it is done, and what is out of scope.
Goal Add a "resend verification email" button to the account page. Constraints Reuse the existing sendVerificationEmail service. Do not add dependencies. Limit resends to 3 per hour per user. Done when * A signed in user with an unverified email sees the button. * The fourth request within an hour returns a 429 and shows a clear message. * Tests cover the limit and the already verified case. Out of scope Email template changes, the signup flow, anything under /billing. Enter fullscreen mode Exit fullscreen mode The last section matters more than it looks. Without it, an agent will helpfully tidy things you never mentioned, and you end up reviewing a larger change than the one you wanted.
For anything beyond a small edit, ask the agent to read the code and propose a plan, and do not let it change files until you have read that plan. Most agents have a planning or read only mode for exactly this. A plan is cheap to read and cheap to correct. A wrong plan caught here saves a wrong implementation and the review that would have followed.
When I read a plan I check three things. Does it touch only the files I expect? Does it reuse code that already exists instead of writing a parallel copy? Does it say how the change will be tested? If a plan proposes a new dependency or a new pattern, I ask why before it writes a line.
The biggest single improvement to agent output is giving it a way to check itself. If tests, type checks and linting run with one command, the agent can change code, run the command, read the failures and fix them without you in the loop.
{ "scripts": { "check": "eslint. && tsc --noEmit && vitest run" } } Enter fullscreen mode Exit fullscreen mode Tell the agent in plain words to run that command before it says the task is finished. Better still, start from a failing test that describes the behaviour you want and let the agent make it pass. A test you wrote is a specification. A test the agent wrote for its own code can quietly confirm its own assumptions, so read those more closely than the code itself.
Review quality falls quickly as a diff grows. A change you can read in a few minutes gets a real review. A change spread over thirty files gets a skim. Ask for one concern at a time, commit at checkpoints, and treat a revert as an ordinary tool instead of a failure.
You can enforce this instead of hoping for it. This script fails the build when a change is bigger than you agreed to review. Run it in CI against the branch you are merging.
import { execFileSync } from ' node:child_process ' const base = process. env. BASE_REF?? ' origin/main ' const maxFiles = 15 const maxLines = 400 const stat = execFileSync ( ' git ', [ ' diff ', ' --numstat ', base + '...HEAD ' ], { encoding: ' utf8 ' }) const rows = stat. trim (). split ( ' \n ' ). filter ( Boolean ). map (( line ) => line. split ( ' \t ' )) const files = rows. length const lines = rows. reduce (( sum, [ added, removed ]) => sum + ( Number ( added ) || 0 ) + ( Number ( removed ) || 0 ), 0 ) if ( files > maxFiles || lines > maxLines ) { console. error ( ' Diff budget exceeded: ' + files + ' files, ' + lines + ' changed lines. Split this change. ' ) process. exit ( 1 ) } console. log ( ' Diff within budget: ' + files + ' files, ' + lines + ' lines ' ) Enter fullscreen mode Exit fullscreen mode Fifteen files and four hundred lines are a starting point, not a rule.
Pick limits your team can genuinely review, and exclude lockfiles and generated files once they start causing false alarms.
An agent begins each session knowing nothing about your project. Most tools read a plain text instructions file from the root of the repository. AGENTS.md has become a common shared name that several tools understand, and some tools also read a file of their own, such as CLAUDE.md. If your team uses more than one tool, keeping the shared rules in one place avoids them drifting apart.
What goes in it is short and practical: the commands to build and test, the conventions that are not obvious from reading the code, the folders that are off limits, and the mistakes that have happened before. Start small. Add a line when you see the same mistake twice, and where you can, add a test that fails if it returns, so the rule is enforced and not merely written down.
# AGENTS.md ## Commands * Run everything with: npm run check * Never run the seed script against a shared database. ## Conventions * Money is stored as integer minor units. Never use floats for amounts. * New endpoints validate input with the shared schemas in src/schemas. ## Off limits * Do not edit src/generated or any migration that has already run. Enter fullscreen mode Exit fullscreen mode Review it as the owner When a pull request arrives, the reflex is to open the changed files. Start one step earlier. Read the task, decide what a correct change would look like, and then compare. Reviewing against intent catches the most expensive problem of all, a change that is neat and well tested and solves the wrong thing.
This kind of review rests on fundamentals. If you are earlier in your career, the guide on vibe coding versus learning to code covers the basics that make it possible.
Some situations are better handled by hand, or at least with you driving closely.
Apply the same least privilege you would give a new teammate. Work on a branch, keep production credentials out of reach, and restrict destructive commands so a bad guess costs you a revert and not a recovery.
Expect the first few tasks to feel slower while you write tickets and set up checks. The payoff is that the output starts arriving in a state you can trust and review quickly, and that is where the time saving from an agent actually comes from.
Originally published on my portfolio blog.