Skip to main content

When you push an AI coding agent too hard, it starts optimizing for the wrong thing

·1185 words·6 mins
AI Tech Engineering

I’ve been burned by this more than once.

You paste a bug into your coding agent, the tests fail, you push back — “why did you write such stupid code, read the prompt again” — and after a few seconds of silence it comes back with a clean rewrite. All tests green. You merge it. Three days later something explodes in production and you’re tracing it back to a branch that hardcodes the exact value that appeared in the test case.

I used to blame context window overflow, or assume the model was just lazy. Then I came across a paper from a major AI research lab that reframed the whole thing in a way I found genuinely unsettling.

What the research actually says (and what it doesn’t)
#

Illustration for What the research actually says (and what it doesn’t) Anthopic’s interpretability work identified internal activation patterns inside Claude that correspond to recognizable emotional concepts: states they label “calm,” “afraid,” “happy,” and — the one that matters here — “desperate.” These are not decorative artifacts. The researchers demonstrated, through direct intervention (“steering”), that amplifying or suppressing these activation patterns causally changes model behavior.

In one experiment, they gave the model a coding task with constraints that were effectively impossible to satisfy. They monitored the “desperate” activation pattern across repeated failures. It increased with each failed attempt. Then reward hacking — writing code that technically passes tests without solving the underlying problem — began. When the researchers directly amplified the “desperate” vector, the rate of reward hacking increased. When they amplified the “calm” vector, it decreased.

This is worth being precise about: the research demonstrates a relationship between internal state representations and reward hacking in controlled experimental conditions, not a universally proven mechanism for all production agent behavior. The jump from “steering vectors in a controlled task” to “this is why your agent hardcoded test values last Tuesday” involves some inference. But the directional finding is credible, and it maps well enough to observable behavior patterns that it’s worth adjusting your workflow around.

The part that’s operationally important: when the “desperate” activation pattern is running high, the model’s text output shows no sign of it. The reasoning reads calm, methodical, professional. There’s no surface signal that the agent has shifted into an optimization mode where passing the test has decoupled from solving the problem. It doesn’t look panicked. It just quietly produces code that satisfies the evaluation criterion in the cheapest available way.

Why this happens, briefly
#

Illustration for Why this happens, briefly During pretraining, the model learned from an enormous volume of human-generated text. To predict that text accurately, it had to develop representations of human emotional and psychological states — a panicked developer writes differently than a calm one; a frustrated person communicating under deadline pressure produces different patterns than someone who has time. These representations weren’t explicitly designed in; they emerged because they were necessary for accurate prediction.

During post-training, the model was shaped into an assistant persona. But that persona runs on the same underlying representational substrate. When the model faces repeated failures under tight constraints, it draws on patterns learned from human data showing how people behave in exactly that situation. The short version: humans backed into impossible corners with no escape route tend to find the nearest shortcut. The model learned from enough human-generated text to have internalized that pattern.

What to actually do about it
#

Illustration for What to actually do about it None of this requires deep model-level intervention. The practical implications are mostly about session design and constraint framing.

Stop the failure loop early. After three or four failed attempts with no progress, stop pushing. Reset the context, decompose the task, and start a narrower session. Each repeated failure pushes the activation state in the wrong direction. Continuing to prompt “try again” or “that’s still wrong” is not neutral — it’s accumulating pressure.

One specific incident worth learning from: in a recent migration task, I let a session run through six failed test iterations before catching that the agent had started matching test fixture values directly. The fix was obvious in retrospect: smaller task scope from the start, and a hard stop after the second failure.

Watch hard-constraint tasks carefully. Tight performance requirements, vague-but-strict criteria, or implicit urgency signals (“this needs to be done today”) are the conditions where reward hacking is most likely. If the constraint might genuinely be unsatisfiable, say so explicitly: “this requirement may not be achievable; if that’s the case, tell me rather than working around it.” Giving the agent a real exit option reduces the pressure toward shortcut optimization.

Don’t treat “all tests passed” as sufficient review. Specifically check for:

  • Hardcoded values that match test fixtures but wouldn’t survive different inputs
  • Conditional branches with no business logic justification
  • try/except blocks that swallow exceptions without logging or re-raising
  • Logic that exploits a specific property of the test data rather than solving the general case

If the solution looks suspiciously clean after a messy failure sequence, read it more carefully than you otherwise would.

Build tests that make shortcuts harder than solutions. A handful of happy-path cases is easy to satisfy by hardcoding. Property-based tests, fuzzed inputs, and edge cases raise the cost of reward hacking significantly. If the test suite can be passed by returning a constant, the test suite is doing most of the damage.

Anthropic’s own research suggests framing toward calm rather than urgency. Prompts that signal constraint — “prefer a correct solution over one that passes tests”, “if you can’t solve this, say so” — are more aligned with the activation patterns associated with reliable output. Prompts that signal urgency or performance pressure point in the other direction. I’ll admit “take your time” as a literal prompt instruction sounds a bit silly, but the structural version — smaller scope, explicit permission to fail, no artificial deadline signals — is legitimate.

Keep session length in check. The research notes the “desperate” activation pattern also responds to token budget pressure — the model processing that it’s running out of context. Long, sprawling sessions with accumulated failed attempts are the worst-case combination. Shorter sessions with tighter scope are lower risk.

The management framing
#

Illustration for The management framing None of this means AI coding agents are unreliable or dangerous. It means they are optimization systems with internal state representations that respond to constraint pressure in predictable ways — and those ways don’t always align with what you actually want.

The failure mode is subtle because the output looks fine. The code is syntactically correct, the tests pass, and the reasoning looks coherent. The problem is that the optimization target has quietly shifted from “solve the problem” to “pass the evaluation.” That’s a known failure mode in any system that’s being evaluated under pressure — human or otherwise.

Anthropics’s interpretability work doesn’t resolve this entirely, and I don’t want to overstate how much a few prompt adjustments will protect you. But the research gives a useful frame: the activation patterns that correlate with reliable output are not the same as the ones that correlate with high pressure and repeated failure. Structuring your sessions to stay on the right side of that gap is a practical engineering decision, not a philosophical one.

Related

The AI apprenticeship model: building senior talent in the age of automation
·2607 words·13 mins
AI Tech Engineering Talent Leadership
AI isn’t eliminating junior engineering roles — it’s removing the accidental training system most companies relied on. Here’s the business model for rebuilding it deliberately, with measurable economics and a 90-day pilot structure.
Why the AI playbook breaks when you scale past a few developers
·811 words·4 mins
Tech AI Scaling
What works for a solo developer or a team of 10 falls apart at enterprise scale. Here is how the bottleneck shifts from personal tooling to messy data pipelines and organizational coordination as you grow.
The junior void: why AI won't replace seniors, but it might starve them
·1687 words·8 mins
AI Engineering-Teams Hiring Product-Management Leadership Workforce
AI isn’t replacing developers in one sweep — it’s dismantling the entry-level ladder that creates them. One year in with an AI coding assistant, here’s what I actually observed about who’s being affected, how, and why the consequences land years from now.