← all writing tech

When the agent is making it worse, take the keyboard back

When you've patched the same bug five times, the bug isn't in the code the agent keeps rewriting. The bug is the architecture you keep asking it to defend.

The fifth time I pasted the same context into the agent, I realized the agent wasn’t the problem and neither was the bug. The thing we were both circling, patch after patch, was an architecture that could not be made correct, and every fix made it slightly worse while looking slightly more reasonable.

The symptom was small and maddening. A status indicator in a field app claimed location tracking was on when it was off, and off when it was on. Easy, surely. I described it, the agent produced a fix, I tested, it lied differently. I described that, it produced another fix, it lied in a third new way. We did this for the better part of two days.

The shape of the loop

There’s a specific failure mode that creeps up on you when you work with a tireless coding agent, and it doesn’t announce itself. It feels like progress because something changes every round. Code gets added, a callback gets rewired, a flag gets introduced. But you’re not converging. You’re walking in a circle and the circle has good lighting.

Here’s how I now recognize it, before I’ve burned the second day:

  • You’re re-explaining the same context. If you’ve pasted the same three paragraphs of “here’s how this is supposed to work” more than twice, the agent isn’t learning the system, it’s guessing inside it. The repetition is the tell.
  • Each fix is plausible and each fix is wrong. Not obviously, embarrassingly wrong. Subtly wrong, in a new place. That pattern means the real defect is somewhere neither of you is looking.
  • The diff is growing. Real fixes usually delete as much as they add. When every round only piles on more plumbing to compensate for the last round’s plumbing, the plumbing is the disease.

My status indicator had all three. By round four it was reading from secure storage that was silently dropping writes, waiting on a cross-thread callback that never fired, and reconciling two sources of truth that disagreed. Every one of those was a real bug. None of them was the bug.

The breakthrough was a delete key

The fix, when it finally came, was not another layer. It was a deletion. I threw out the secure-storage cache, the callback, the reconciliation logic, all of it. Then I derived the status from the single thing that was unambiguously true at any instant: whether the tracking service was actually running. Not whether we’d recorded that we started it. Whether the process was alive right now. One source, no storage, no callback, no lie.

The indicator has been honest ever since. And the lesson wasn’t about that bug at all.

When you’ve patched the same bug five times, stop debugging the bug. The bug is your architecture, and the agent will faithfully defend a broken architecture forever, because that’s exactly what you keep asking it to do.

Taking the keyboard back

An agent is extraordinary at executing inside a frame you’ve given it. That’s the trap. When the frame is wrong, its competence works against you: it will produce a confident, well-structured fix for a problem that cannot be solved at that layer, and it will do it faster than you can notice you’re stuck. The speed is what hides the loop.

So I’ve made the exit explicit. When I catch the three tells above, I do one of two things, and never a sixth patch. Either I force a wholesale rethink (“ignore every fix so far, here’s the one thing that’s actually true, rebuild the status from only that”), or I take the keyboard back and write the deletion myself, because sometimes the move that unsticks it is one no prompt would have proposed: throwing away the clever part.

The agent didn’t fail me. It did precisely what I asked, five times. Knowing when to stop asking is still my job.

Email