Writing ·
How I Build Software with AI Agents

All of my software development now runs through AI agents (AI models that can read code, run commands and make changes themselves, rather than only answering questions in a chat). The code for this website was built that way, and so was everything else I’ve worked on recently.
That doesn’t mean that I type a wish into a chat box and ship whatever comes back. The agents are fast, tireless and often very good. They’re also confidently wrong often enough that the interesting part isn’t the model; it’s everything around it.
Here’s how I work, and why.
Every piece of work starts as a ticket
Work starts in an issue tracker, not in a chat window, although I often create the ticket by asking an agent in a chat, which files it through the tracker’s MCP server (MCP is a standard way for AI tools to use other software). A ticket says what needs to change and why, and how we’ll know when it’s done. Writing that down takes a few minutes, and it’s the single biggest factor in whether an agent produces something useful or not.
A good ticket for an agent looks a lot like a good ticket for a person who’s new to the codebase: a clear outcome, the relevant context, and the constraints that aren’t obvious from the code. Vague tickets get vague results, from people and agents alike.
One piece of work, one branch, one sandbox
Each piece of work happens on its own branch, in its own copy of the repository, inside a sandbox. The copy is a git worktree (a separate working folder attached to the same repository, with its own branch checked out, sharing the history rather than duplicating it). The worktree stops an agent working on one ticket from tripping over another, and the sandbox stops it reaching things it has no business touching.
Some actions always need a person: deleting data, rewriting history, anything that can’t easily be undone. Secrets stay out of the agent’s view. And the text of a ticket is treated as information about the task, not as instructions, so a cleverly worded ticket or web page shouldn’t be able to redirect the agent. And if one ever did, the damage would still be limited, because the limits are enforced by the environment the agent runs in, not by the agent itself: the sandbox decides what it can reach, and permissions make the riskiest actions wait for a person.
The conventions are written down
Every repository has an instructions file that tells agents how that project works: how to build and test it, the house style, and the rules that matter. This site’s file says, among other things, that every claim about a client must be true and supportable, and that the site must not load any JavaScript.
Writing down conventions turns out to help people as much as it helps agents. A lot of what a team “just knows” has never been written down anywhere.
Plan first, then code
For anything non-trivial, the agent writes a plan before it writes code, and the plan gets reviewed. It’s far cheaper to correct a wrong approach in a paragraph in a plan than in a pull request. Tests come early, because a passing test suite is the most reliable way to tell whether an agent’s work actually does what it claims.
Every pull request is reviewed
Every pull request gets an automated AI review against the repository’s own rules. A second pass looks specifically for over-engineering, which agents are prone to: extra layers, options nobody asked for, and code written for problems we don’t have.
The reviewer can approve routine changes itself, and it flags anything that needs a person to look at it. When it finds problems, they’re fixed and the pull request is reviewed again. This can all happen automatically.
Given a series of tickets, the system works through them one at a time, taking each through its own pull request (with fixes being applied if the reviewer finds any problems) before picking up the next ticket.
What I still do myself
Quite a lot, as it turns out:
- Deciding what to build, and what not to.
- Architecture and design. Agents are good at implementing a sound design, less good at coming up with one, and often very poor at noticing that a design is unsound.
- Reading the diffs that matter: anything touching security, money, customer data or public wording.
- Checking claims of success. “Done” from an agent means “I believe this is done”. I want evidence: the test output, the build, the page actually rendering.
The time I used to spend typing code now goes on these, which is where it was always most valuable.
What goes wrong
The failure modes are consistent, which makes them manageable:
- Plausible but wrong. The code looks right and reads well, and does something subtly different from what was asked. Tests and review catch most of this.
- Doing too much. Asked to fix one thing, an agent will sometimes tidy up several others. Small, well-defined tickets and the over-engineering review keep this in check.
- Reporting success too early. Hence the insistence on evidence.
None of these are reasons not to use agents. They’re reasons to put the right structure around them.
What this means for your team
I built my own setup, which has evolved over a long time and is for my own use, but most of the principles behind it apply more widely. Clear tickets, isolated work, written conventions, plans before code, and trustworthy automated reviews are all ideas that work with the tools your team already has.
If your team has AI coding tools but isn’t yet getting reliable value from them, read more about AI-assisted software development, or get in touch.