Back to blogThe Commit Message Was Perfect. That's Exactly the Problem.

Last month I approved a PR from one of our agents. Commit message: "Refactor retry logic to use exponential backoff with jitter." Clean, accurate, the kind of sentence you'd point to as a good example in a code review workshop. Six weeks later that same retry logic broke a downstream rate limiter, and I went looking for why the jitter had been added in the first place — load testing, a vendor complaint, someone's educated guess? Nobody knew. Not the engineer who'd merged it, not me. I opened a fresh session and asked the agent directly. It read its own diff back to me and told me, in detail, what the code did. It could not tell me why. Not because it was hiding anything — because the message was never capable of holding that answer. It was a summary of a diff, written by the same process that wrote the diff.

The pipeline runs the wrong direction

Watch how an agent actually produces a commit message and the mystery evaporates. Your prompt goes in, the agent generates a diff, and then — as a separate, later step — it's asked to describe that diff in a sentence. The commit message sits downstream of the code change. It isn't a record of a decision, it's a caption on a finished photo. Nothing in that captioning step has access to the reasoning that produced your prompt, because that reasoning was never part of the artifact being summarized in the first place.

Notice where the actual "why" lives in that chain: back at A, before the prompt even exists. By the time you reach D, it's already survived three lossy translations. Asking the agent to write a better commit message is asking it to reach backward across a gap it has no bridge over.

The trap: "just prompt it to explain why"

The obvious fix — the one every team reaches for first — is a stricter commit template, or a system prompt telling the agent to always explain its reasoning. I tried this too. It produces messages that sound more thoughtful and are exactly as empty. At message-generation time the agent has exactly two things in context: the diff it just wrote, and whatever you typed into the prompt. It doesn't have the Slack thread where your tech lead said "just patch it for now, we'll do it properly after the migration." It doesn't have the meeting where someone decided the workaround was temporary. It doesn't have the ticket's comment history. So it does the only honest thing left available to it: infers a plausible-sounding reason from the diff itself, after the fact. What you get back is a better-written guess. Not a recovered fact.

Why this slides past review

Here's the part that actually costs you money. A fluent, grammatically tight commit message reads as diligence. A human who writes "fix bug" gets called out in review — the terseness itself is a tell that something's missing. An agent that writes "Refactor retry logic to use exponential backoff with jitter to reduce thundering-herd load on the payments service" sounds like it did the analysis. It sounds like documentation. Reviewers — me included — stop asking the follow-up question precisely because the sentence is well-formed enough to feel like an answer already. A confident sentence is a worse failure mode than a lazy one, because the lazy one at least nudges someone to go find the real reason.

The reframe: this was never a writing problem

Once you see the pipeline laid out like that, the fix stops being "improve the summarizer." You can't summarize your way to information that was never in the input. The why exists exactly once, at exactly one moment: when a human forms the ask, before any generation happens. Miss it there and it's not degraded, it's gone — and every downstream step, however carefully instructed, is reconstructing rather than reporting. That's the actual insight, and it's why teams that keep tuning their commit-message prompts keep coming away disappointed: they're optimizing the wrong stage of the pipeline. The stage that matters sits upstream of the diff, not downstream of it.

What capturing intent upstream actually looks like

In practice this is less exotic than it sounds. It's mostly discipline about what gets persisted, not new tooling:

  • Treat the prompt itself as an artifact, not scratch text — link it to the PR instead of letting it get paraphrased into a commit message after the fact.
  • Write constraints stated in the ask straight into the ticket or PR description, verbatim, before the agent starts — "temporary until the migration lands," "matches the vendor's rate limit, don't touch without checking with them" — rather than trying to reconstruct them from the diff later.
  • When the decision happens in a meeting or a Slack thread, paste the relevant line into the ticket before you prompt the agent. Call it the two-sentence tax that saves you a six-week mystery.
  • In review, look for a linked why, not a well-written commit message. A beautifully worded message with no linked reasoning behind it should get treated the same as no message at all.

None of this asks the agent to do better. It asks the team to stop treating the commit message as the place where intent lives, and start treating it as what it actually is — a caption, fine for skimming history, useless for archaeology.

Why this gets sharper with multiple agents

In a single-agent, single-session world, a missing why is an annoyance — you go ask a human and move on. In a multi-agent setup, where one agent's output becomes another agent's input across sessions with no shared memory of the original ask, the missing why doesn't just sit there quietly. It gets acted on. An agent with no access to the constraint behind a workaround doesn't leave it alone out of caution — caution isn't in its context either. It sees an inconsistency, reads it as sloppiness, and confidently "cleans it up," deleting the exact hack that was load-bearing. This is the failure mode I actually worry about in my research on multi-agent coordination — not that agents hallucinate code, but that they correctly and confidently act on an incomplete record, because nothing ever marked the record as incomplete. The fix is the same at any scale: capture the why before the diff exists. But the cost of skipping it compounds every time another agent inherits the diff without the ask that produced it.

Discussion

Chat with Chi Cong (AI) about this article. Your conversation is private to you — you can publish a summary for others when you're done.

Ask me anything about “The Commit Message Was Perfect. That's Exactly the Problem.” — trade-offs, decisions, or the story behind it.