← all writing hot take

Spec before you build, especially with an agent

A fast coding agent pointed at a fuzzy target doesn't slow down when it's confused, it accelerates, and produces a lot of confident, wrong code very quickly.

The faster my tools got, the more the five-minute spec started to pay off, which is the opposite of what I expected. I assumed a tireless coding agent would make planning matter less. It made it matter more, because a fast builder aimed at an unclear target doesn’t pause to ask what you meant. It just sprints, confidently, in the wrong direction, and hands you a thousand clean lines built on a guess.

So now I have a standing rule on every feature, agent or not: nothing gets built until we’ve ironed out who the users are, the edge cases, the dependencies, and what each ambiguous field actually means. It feels slow. It is the single biggest thing that has sped me up.

Why speed makes specs more important, not less

There’s a comforting intuition that a smart enough builder will figure out the gaps as it goes. With a human junior, that’s sometimes true. They get uneasy, they slack you a question, the uncertainty leaks out as hesitation. A coding agent has no hesitation. Ambiguity doesn’t slow it down, it just gets resolved silently, by whatever assumption was cheapest to reach for, and you don’t find out which assumption until you’re reading the diff.

I learned this the expensive way on a feature where the word “active” was doing two jobs. To me, an active order meant currently being delivered. The agent decided active meant “not archived,” which technically covers everything that ever existed. It built filtering, badges, a count on the dashboard, all internally consistent, all wrong, all very fast. Every line was correct against the spec in its head. There just wasn’t a spec in mine yet.

A slow builder pointed at a fuzzy target wanders. A fast one arrives, on time and on budget, at the wrong place.

The lesson isn’t “agents are bad at ambiguity.” It’s that the cost of ambiguity scales with the speed of the thing resolving it, and I’d handed the ambiguity to the fastest resolver I’ve ever worked with.

What I actually nail down first

The spec doesn’t need to be a document. It needs to be a short conversation that kills the questions that would otherwise get answered by accident. For most features it’s four things.

  • Who actually uses this. An ops lead and a driver want opposite affordances on the same data. Naming the user picks the defaults.
  • The edge cases, said out loud. What happens with zero records, a duplicate, a half-finished one, the thing two people touch at once. The boring path is never where the bug lives.
  • The dependencies and side effects. Especially the cross-cutting ones. If this writes a row, who reads it, what email fires, what report shifts. Those are the seams nobody sees in a single file.
  • Every ambiguous field, defined to one meaning. If a column could mean two things, it eventually means both, and passes every test while corrupting every report. Pin it before a line is written.

Make the agent surface its assumptions

Here’s the move that changed the most: I stopped letting the agent start. Before it writes anything, I make it ask me every question it has and list the assumptions it’s about to bake in, especially about side effects. Then I actually answer them, in writing, instead of waving it on.

It feels like friction. It’s the cheapest friction in the whole process, because a wrong assumption surfaced in a sentence costs me one reply. The same assumption surfaced in production costs me a debugging session, a migration, and a conversation with a client about why the dashboard counted things nobody asked it to count.

The temptation with a tool this fast is to just go. Resist it. The faster the builder, the more a confident wrong target costs you, and the more those five quiet minutes up front are worth. Speed is only an asset once you’ve made sure it’s pointed at the right thing.

Email