13

10 Lessons for Agentic Coding

Code got cheap. That doesn't remove the hard part of building software — it relocates it. Where the bottleneck moved, and what to do about it.

When one scarcity disappears, another one shows up

For most of software history, writing code was the expensive part. You budgeted for it, staffed for it, planned releases around how long it would take. That's no longer true — a working first draft of almost anything is now minutes away, not weeks.

It's tempting to read that as "the hard part is solved." It isn't. The bottleneck didn't vanish, it moved — off typing speed and onto judgment, specification, and maintenance. Ten observations, distilled from a widely-read essay on agentic coding, map out where that bottleneck actually sits now.

"Free as in puppies"

The essay's own phrase for agentic code: getting it costs almost nothing, but it isn't free after that. Support, security, and understanding it six months later are real, ongoing costs — they don't shrink just because generation got cheap. Keep that image; it recurs at the end of this module.

The ten, at a glance

A few of these overlap ground the Dojo has already covered in depth — verification and memory (module 7), automating the easy stuff (module 8), and paying down complexity on purpose (module 9). They're listed here for completeness, with a pointer back. The rest get the deep dive on the screens that follow.

1-2. Implement to learn, rebuild often

Writing code surfaces decisions a spec never anticipated. Cheap code means you can afford to redo, not just patch. Deep dive: next screen.

3. Invest in end-to-end tests

Test outcomes, not mechanics — that's the contract that survives a rebuild. See module 7 for the full verification treatment.

4-5. Document intent, keep specs in sync

Tests capture what, code captures how — neither captures why. Write the reasoning down and keep it current. Related: module 9's "strategic investment."

6. Find the hard stuff

Once boilerplate stops being the bottleneck, what's left — architecture, performance, security — is where the value actually lives. Deep dive: screen 4.

7. Automate everything easy

Push repeatable work into loops and reusable skills so attention concentrates on lesson 6. Full treatment: module 8.

8-9. Develop taste, agents amplify experience

Without a compiler yelling at you, you are the feedback loop — and experience packed into a prompt multiplies through the agent. Deep dive: screen 5.

10. Code is cheap, maintenance isn't

The acquisition cost dropped to near zero. The carrying cost didn't. Deep dive: screen 6.

Build it to find out what you actually meant

Writing a full spec before touching code feels responsible. It also has a blind spot: a spec is a guess about what the problem looks like from the outside, and some of that guess is wrong every time. You don't find out which parts until you try to make it real.

Because a Claude Code session can produce a working version in minutes, "try to make it real" is no longer a multi-day commitment. That changes the right default: implement early, let the implementation tell you what the spec missed, then fold that back in — rather than perfecting the document first and hoping.

1
Implement to learn

Treat the first build as a question you're asking the problem, not a final answer. The bugs and awkward edges it surfaces are the spec's missing pieces, found the fast way.

2
Rebuild often

When a rebuild is cheap, "throw it away and redo it differently" stops being wasteful and becomes a normal move. Fork an approach, recode it a second way, compare the two side by side.

This isn't an argument against spec-driven work

Speccing first still works, and for anything with real consequences you still want /speckit.specify or a written plan before you dispatch an agent. The point is narrower: don't mistake "the spec is finished" for "the spec is correct." Cheap implementation is a way to pressure-test it early instead of finding out in production.

Fast boilerplate isn't the same as progress

An agent clears CRUD endpoints, form validation, and plumbing fast enough that it stops feeling like real work got done — because, relative to what's left, it wasn't the hard part. It never was. What's left over once the easy 80% evaporates is architecture, performance under load, security boundaries, and what happens when a dependency fails at 3am.

The hard work is where the value is. The risk with fast agents isn't that they're too slow on the easy stuff — it's that clearing it fast feels like momentum, and momentum on the wrong 80% is a way to arrive at the deadline having built everything except the thing that was actually going to be difficult.

A question worth asking mid-project

"What have I been avoiding because it's the part an agent can't just one-shot?" That's usually the actual work. Everything upstream of it — automating it, as lesson 7 says — exists to buy you time to sit with that question.

You are the feedback loop now

A compiler error is immediate and impersonal — it doesn't care who you are, it just tells you the thing is broken. An agent is more agreeable than that. It will often produce something plausible-looking for a bad idea, and it won't stop you the way a type error would. Between real signals (a user complaint, a production incident), you are the check. That's what "developing taste" means here — domain knowledge and a felt sense of the problem, doing the job the compiler used to do.

The same tool in two different hands produces very different results, and the difference isn't typing speed — it's what gets packed into the prompt without the person even noticing they did it.

"Add rate limiting to the API."
Vague framing — the agent has to guess your constraints from nothing. Which endpoints? All of them, or just the expensive ones? Per-user, per-IP, or per-API-key? What's the actual abuse case? What should happen when the limit is hit — 429, queue, silent drop?
"Rate-limit POST /orders per API key —
20/min, 429 with Retry-After, sliding
window in Redis, exempt the McLeod
webhook key. Match the existing
error-envelope shape."
Same request, but every ambiguity above is already resolved. That specificity isn't extra effort — it's the developer's experience leaking into the prompt without a special "prompting technique." Fewer round trips, because there's nothing left to guess.
Agents amplify experience

This is the multiplier: expertise plus judgment doesn't just help the agent — it multiplies through it. A senior engineer's prompt and a junior engineer's prompt for the same task diverge because of what each person already knows to specify, not because one typed faster.

Free as in puppies

A puppy is free, or close to it, at the shelter. The vet bills, the food, and the walks at 6am for the next twelve years are not. Agentic code has the same shape: the acquisition cost — the cost of getting a working feature — has collapsed toward zero. The carrying cost — patching it, understanding it after you've forgotten why it's shaped that way, supporting whoever depends on it — did not collapse with it. It's a separate bill, and it comes due later.

None of the other nine lessons cancel this one out. Testing outcomes (3), documenting intent (4), and keeping specs current (5) all exist specifically to make that later bill smaller — a well-tested, well-documented feature is cheaper to maintain than one that was merely generated fast. Building fast and accounting for the tail are two separate disciplines; agentic coding makes the first one easy and does nothing about the second.

Before you ship the next agent-built feature

Ask who owns it in six months, whether it has a test that would catch a regression, and whether the reasoning behind it is written down anywhere an agent — or you — could find later. If the answer to any of those is "no one," you've adopted a puppy without a plan.

Check yourself

Three questions on where the bottleneck actually moved.

Scenario

Someone argues "implement to learn" means specs are pointless now — just start typing and see what happens.

What does "implement to learn" actually argue?

Scenario

Three days before a deadline, every CRUD endpoint and form is done. The concurrency bug that only shows up under load hasn't been looked at yet.

What does "find the hard stuff" say about this situation?

Scenario

A teammate says "code is basically free now, so why are we still budgeting time for maintenance?"

What does "free as in puppies" actually mean?

Your move

Look at the last feature Claude Code shipped for you. Where's the hard part it hasn't touched yet, and who's paying the maintenance bill on it six months from now? Write both answers down before you start the next one.