Blog

Coding agents ship. Can you still explain the system?

The work is finished, but how much of it stays with you? On coding agents, the pleasure of understanding, and making a little room to learn.

The feature is finished before you have quite worked out how you would have built it.

The agent has written the code, added tests and explained its choices. You read the diff, ask about an edge case, make a small correction. Everything looks good. There is still time to pick up another ticket.

It is a good afternoon. Then, a few days later, a colleague asks why the background job behaves the way it does, and you realise you remember the agent’s explanation better than you understand the job itself.

You could find the answer. Of course you could. But there is an uncomfortable gap between “I can ask about this” and “I know my way around here.”

That gap is easy to miss when the work is going well.

What used to come with the work

Think about the last bug that took you far too long to find. The fix was probably small. Getting there meant following the wrong lead, reading a module you had hoped to avoid, and discovering that a familiar function did something rather different from what its name suggested.

You would not choose to spend an afternoon that way again. Still, afterwards, you knew that corner of the system. The next time something broke nearby, you had somewhere to start.

With an agent, much of that wandering can disappear. You describe the symptom and get a plausible diagnosis, often with a patch attached. That is a welcome improvement. The awkward part is that the wandering sometimes taught you things you had never thought to ask.

I would be careful about turning this into nostalgia for doing everything by hand. There is no educational virtue in fighting the same build configuration for the fifth time. The question is where the saved effort goes. Does some of it become room to understand a difficult piece of the product? Or does it all become the next task?

A ticket board will happily fill either kind of afternoon. It cannot tell you which one left you better prepared for tomorrow.

The question hidden inside a small fix

Imagine a service that sends documents to an external signing provider. Occasionally, a request times out. The obvious improvement is a retry: if the call fails, try again.

An agent could implement that neatly. The code might be easy to read, and the tests might show exactly what you asked for.

But suppose the signing provider accepted the document before the connection broke. Your service never received the acknowledgement. As far as the caller knows, the request failed. As far as the provider knows, there is a document waiting to be signed.

Now the retry might create another signing request.

The useful question is what the timeout actually tells you. Did the operation fail, or did you lose the ability to see whether it succeeded? Once you notice that distinction, you start looking for a way to recognise a repeated submission or check what happened to the first one. That is the concern behind idempotency in payment APIs, too.

This is an imagined example, but it captures the sort of understanding a review needs. You can read every line of the retry and still miss the assumption underneath it. You have to know enough about the journey beyond that function to feel that something is unresolved.

An agent can help you investigate all of this. You still need to notice where to begin.

Stay with the question a little longer

One small habit seems worth the effort: before asking the agent what happens, decide what you think happens.

Nothing elaborate. A sentence is enough. “If the worker loses the connection here, I think the document stays pending and the next run picks it up.”

Then follow the code together. Ask the agent to show you the functions it is relying on, and open the important ones. When the explanation depends on how the external provider behaves, look at the provider’s contract. Leave room for the answer to be “we don’t know yet.”

Having made a prediction, you have something to revise. Perhaps “pending” covers more states than you realised. Perhaps the next run has no way to distinguish an unsent document from one that was accepted. The explanation now connects to a question you were already trying to answer.

Then try a slightly different situation. What if the user cancels while the job is waiting? You will quickly find out whether you understand the behaviour or can only repeat the walkthrough.

This does take time. It also needs some restraint. A spacing adjustment rarely deserves the same attention as a change to permissions or retries. Look for the places where you hesitate, especially when being wrong would be difficult to undo.

Some untidy code has a history

There is another reason to slow down occasionally: the code that looks easiest to simplify may be protecting against something you have never encountered.

An extra check, an oddly placed write, a comment that sounds more worried than the surrounding code seems to justify. It is tempting to tidy these away, particularly when an agent offers a shorter version with a convincing explanation.

Before accepting, find out when the awkward part arrived. Follow the commit into the old discussion, if there is one. You might discover an incident that makes the current shape sensible. You might also discover that the constraint disappeared long ago and the simplification is overdue.

Either finding is useful. The important thing is to avoid filling a missing history with a story that merely sounds right. If nobody recorded the reason, say so and investigate the behaviour.

This is why writing down architecture decisions helps the next person. A short note about the failure you were trying to prevent gives them a much better starting point than another paragraph describing what the code already says.

It helps your future self, too. You will forget more of this afternoon than you expect.

Leave yourself something beyond the merge

There is a reasonable objection here: the whole point of these tools is to get useful work done. Nobody wants every pull request to turn into homework.

I agree. A learning routine that requires an essay and an exam after every change will soon become another thing to skip when the week gets busy.

A smaller ambition is more useful. Pick a part of the work that made you uneasy and stay with it until you can explain it to a colleague. Perhaps you finally understand what happens to an interrupted job. Perhaps you learn why a check has to happen again at execution time. That is enough for one session.

For a team, making room for that means accepting that someone may spend time tracing a request without producing another commit. It means being able to say “I approved this, but I want to understand it better” without that sounding like a confession.

The pleasure in programming has always included the moment a confusing piece of behaviour starts to make sense. Agents can help us get to that moment with less frustration. It would be a shame to use all that saved time to hurry past it.

The next time a change is ready earlier than expected, open the part you are still curious about. There may be a better use for the remaining afternoon than another ticket.

A conversation, not a newsletter

Let's talk about your system

If this article describes something you recognise, a conversation is the shortest route to an answer.

Let's talk