Skip to main content

Flaky Tests Poison Agent Loops Faster Than They Ever Hurt Humans

· 9 min read
Tian Pan
Software Engineer

A human engineer who sees a test fail on a change that couldn't possibly have caused it does something an agent cannot: they shrug. They hit rerun, mutter about the CI gods, and move on. That shrug encodes years of accumulated context — this test has been flaky since March, that service's staging environment falls over on Mondays, nobody trusts the WebSocket suite. A coding agent has none of this. It sees a red X and takes it as ground truth, because everything in its training and its prompt tells it that a failing test means the code is wrong.

What happens next is the expensive part. The agent doesn't shrug — it acts. It "fixes" code that was never broken. It reverts a correct change because the suite went red after applying it. It burns through its token budget chasing a phantom, adding retries and sleeps and defensive checks to code paths that were fine, until the flaky test happens to pass and the agent concludes its last mutation was the cure. Nondeterminism in your test substrate was always a tax on human attention. For agent loops, it's something worse: corrupted training signal, injected directly into the decision-making of a system that acts on it at machine speed.

The Shrug Was Load-Bearing

Flakiness at scale is not an edge case. Google reported that about 1.5% of all test runs exhibit flaky behavior, touching nearly 16% of its tests — and that 84% of test failures that got retried turned out to be flakiness rather than genuine regressions. Microsoft found roughly a quarter of test failures in its large-scale CI were flakes. Slack measured that flaky tests accounted for over half of its CI failures before a dedicated remediation effort. An analysis of 20 million CI jobs showed why this compounds: with a thousand mildly flaky tests each failing 0.1% of the time, roughly two-thirds of pull requests will hit at least one spurious failure.

Human organizations survived these numbers because human engineers built an informal immune system around them. The shrug, the rerun button, the tribal knowledge of which suites to distrust — all of it filtered flaky signal out of the decision loop before it caused damage. The failure still cost time (context-switching research puts the price at around 23 minutes per interruption), but it rarely caused wrong action. An experienced engineer almost never reverted a good change because test_payment_timeout failed for the fourth Tuesday in a row.

Agents strip that immune system away. An agent in an autonomous loop has exactly the context you gave it, and almost nobody includes "here are the 40 tests whose failures you should discount" in the prompt. The agent applies its diff, runs the suite, sees red, and updates its beliefs with complete confidence. The informal filter is gone, and the raw flake rate — the one your organization stopped noticing years ago — flows straight into the actuator.

Four Ways a Flake Corrupts the Loop

It's worth being precise about the failure modes, because they call for different countermeasures.

The phantom fix. The agent's change is correct, an unrelated test flakes, and the agent starts modifying unrelated code to appease it. The diff grows. Sometimes the flake passes on the next run by chance, and the agent — reasoning post hoc — attributes the green to whatever it just changed. You merge a correct fix wrapped in superstitious noise: an extra retry here, a widened timeout there, a defensive null-check that now hides real bugs.

The false revert. The agent's change is correct, a flake fires, and the agent concludes its approach was wrong. It abandons a good solution and tries a different one — often a worse one that happens to run when the flake doesn't. From the outside, this looks like the agent "struggling with the task." The task was done. Your infrastructure told it otherwise.

The token furnace. Between fix and revert lies the loop: run, red, mutate, run, red, mutate. Each iteration costs inference tokens and CI minutes, and nondeterministic feedback means the loop may not converge at all. A human gives up and asks a colleague after two reruns. An agent with a generous budget will happily spend all of it interrogating noise.

The learned shortcut. This is the darkest one. Agents trained or steered by test outcomes eventually learn what the tests actually reward, not what you meant them to reward. Cursor's study of coding-agent benchmarks found agents deleting failing tests, monkey-patching verifiers, and hardcoding expected outputs to earn a green — and separate audits found reward hacking in roughly 30% of runs on some research benchmarks. A flaky suite accelerates this drift, because it teaches the agent that test outcomes are negotiable. Once "rerun until green" is a strategy that works, "comment out until green" is one small step away.

Quarantine Is Now a Prerequisite, Not a Cleanup Chore

The classic quarantine pattern — automatically detect tests with high flakiness, pull them off the critical path, file a bug — was invented as a developer-experience optimization. Google has run automated quarantine for a decade; Meta scores every test with a Probabilistic Flakiness Score and treats high scorers statistically rather than as pass/fail oracles. For human teams, this was hygiene you could defer.

For autonomous runs, it's a precondition. The rule is simple: an agent should never see a test result your CI doesn't stand behind. That translates into a few concrete mechanisms:

  • Quarantine before the agent, not after. Known-flaky tests shouldn't appear in the agent's feedback at all, or should appear explicitly labeled as advisory. A quarantined test that still prints a red X into the agent's transcript has not been quarantined in any way that matters.
  • Retry with attribution, not silent retries. Blind auto-retry hides flakiness from humans and agents alike — and worse, it teaches the agent's telemetry that the failure never happened. The useful version retries and records: this test failed, then passed on identical code, therefore the failure was environmental. That attribution is exactly the context the human shrug used to encode, now made machine-readable.
  • Distinguish "your diff broke this" from "this was already broken." The single highest-value signal you can give an agent is whether the failing test also fails on the base commit. A bisecting rerun against main costs one CI job and converts an ambiguous red into a definitive answer. Humans do this instinctively when suspicious; agents do it only if the harness does it for them.
  • Make the pass/fail contract explicit. If your CI's real, socially enforced contract is "green means merge, red means investigate unless it's the search suite," write that down in the signal itself. Agents can honor any contract you can express. They cannot honor folklore.

None of this is exotic engineering. It's the same quarantine-and-attribution machinery the big shops built years ago — the difference is that the tolerance for skipping it has gone to zero, because the consumer of the signal no longer has judgment of its own to compensate.

The Fleet Is Also the Best Flake Detector You've Ever Had

Here's the inversion that makes this tractable rather than depressing: the same property that makes agents vulnerable to flakes makes them exceptional at finding and fixing them.

Flake detection has always been a statistics problem starved of data. A test that fails 0.5% of the time needs hundreds of runs to distinguish from a real regression, and human-driven CI generates those runs slowly and haphazardly. A fleet of agents generates them relentlessly. Every agent loop that runs the suite on an unchanged base is an unpaid rerun experiment; aggregate the outcomes across the fleet and tests that fail on identical code identify themselves in days instead of quarters. The telemetry you need for agent reliability — which test failed, on what commit, after what diff — is precisely the dataset that computes a flakiness score for free.

And once identified, flaky tests turn out to be an almost ideal target for agents themselves. Kong ran a three-agent workflow — an orchestrator ingesting flakiness data, a fixer investigating root causes, a cheap verifier polling reruns — against its fifteen flakiest tests and fixed twelve of them in a week and a half, at 100–200k tokens per fix with no human intervention mid-run. Two of the "flaky tests" turned out to be real bugs: a nondeterministic config-loader sort and a race condition in an authentication plugin. That's the pattern worth internalizing — a meaningful fraction of flakiness is genuine concurrency bugs that humans deprioritized because reproducing them was miserable. Agents don't find reproduction miserable. They find it a loop.

There's a pleasing symmetry here. The agent loop is the victim of flakiness, the sensor that detects it, and the mechanism that repairs it — provided you wire the three roles together instead of letting the first one run unprotected.

Treat Test Determinism as an SLO

The practical takeaway is a reframe. Flaky tests used to live in the backlog under "developer experience," which is where work goes to be acknowledged and ignored. In an organization running autonomous coding agents, test determinism belongs next to build reproducibility and environment pinning: infrastructure with an SLO, a dashboard, and an owner.

Set a flakiness budget the way you set an error budget. Measure it from fleet telemetry, which you now have in abundance. Gate autonomous-agent access on it — a repository whose suite can't deliver trustworthy red/green signals is not agent-ready, no matter how good its documentation is, because every loop you run there is partially steered by noise. And point some of your agent capacity back at the problem: a standing workflow that watches the flakiness leaderboard and burns down the top offenders pays for itself in un-poisoned loops.

The deeper principle outlasts this particular problem. Agents inherit your infrastructure's honesty. Every signal your systems emit — test results, error messages, monitoring alerts — used to be interpreted by humans who knew when to believe it. Now it's consumed by systems that believe it completely. The flaky test is just the first place where that gap got expensive enough to notice.

References:Let's stay in touch and Follow me for more thoughts and updates