← All posts
Concepts

Don't let the agent grade its own homework

An agent writes a function. Then the same agent writes the test for that function. The test passes. You merge.

You just shipped a bug with a green checkmark on it. The agent misread the spec, wrote code that embodies the misreading, and then wrote a test asserting that the misreading is correct. Because both halves came from the same mental model, the test has no way to see what the code got wrong. Nothing anywhere in that loop was ever checked against a source outside the agent's own head.

Most of the 2026 discourse on autonomous coding agents has converged on one point: never let the thing that wrote the change be the thing that certifies it. DevAssure's take on the 2026 QA playbook puts it plainly. The faster agents ship code, the more the bottleneck moves to independent checking, and self-authored tests don't count as independent, because "the author cannot be the examiner." None of this is new; it's the oldest rule in testing, restated for a world where the author happens to be a model. You wouldn't accept a PR whose only evidence was "I also wrote a test and it passes and I promise I read the requirements right," and an agent earns exactly that much skepticism.

Why self-authored tests inherit the bug

Think about where a test's correctness comes from. A test encodes an expectation: "given this input, the system should do that." If the expectation is wrong, the test is wrong, no matter how green it runs.

When an agent generates both code and test in one pass, the expectation baked into the test comes from the same place as the behavior in the code: the agent's interpretation of the spec. If that interpretation is off by one, both are off by one, and they agree with each other.

Concretely. Suppose the requirement is: a discount code applies to the subtotal before tax. The agent misreads it as after tax. Here's what you get:

// Implementation — applies discount after tax
const total = (subtotal + tax) * (1 - discount);

// The agent's own test — asserts the same wrong thing
test('applies 10% discount', () => {
  const result = checkout({ subtotal: 100, tax: 8, discount: 0.1 });
  expect(result.total).toBe(97.2); // (100 + 8) * 0.9 — wrong, and green
});

Both are internally consistent, the test passes, and every layer the agent controls agrees with every other layer it controls. What's missing is a source of truth the agent didn't author. Piling on more assertions won't help you here, because more self-authored assertions only restate the same misunderstanding in greater detail. What you need is an expectation that came from somewhere other than the code's author.

Independent means "generated from intent, run against reality"

For a verification layer to actually be independent, two things have to be true, and both matter.

It has to derive its expectations from the product description, not the code. A test written from "the discount applies before tax" (the words a human wrote about what the app should do) has no way to inherit the after-tax bug, because it never saw the buggy code; it only saw intent. So when the implementation computes the after-tax total, the intent-derived test goes red, and that red is the entire point of the exercise. It's the disagreement between what someone asked for and what actually got built, which is exactly the signal a self-authored test erases.

And it has to run against the real, running app, not against the agent's idea of the app. A model can hallucinate a passing test as fluently as it hallucinates working code. The one thing that can't be faked is a browser actually driving the live application and observing what comes back; until code executes against reality, a green result is a claim rather than a check. We've argued the same thing about generated tests in general (a test you didn't run is a liability no matter who wrote it), and it lands with double force when the author is the same agent whose work is under review.

This is where behavior-level, black-box tests structurally beat agent-authored unit tests as a verification layer. A unit test pokes at the code's own internals, so it easily ends up sharing the code's assumptions. An end-to-end test drives the app the way a user would, clicking the button and reading the confirmation, and checks an observable outcome; it has no idea how the discount was computed internally and doesn't need one, because it only knows that the number on the receipt is wrong. That outside-in stance is what makes it independent, and it's a big part of why end-to-end tests carry the weight they do in a 2026 test strategy.

Where TestVibe sits in the loop

This is the layer TestVibe is built to be. You describe the behavior you want in plain language, the intent rather than the implementation. TestVibe generates real Playwright tests from that description, then does the part that makes the whole scheme trustworthy: it runs them in a clean, isolated cloud sandbox against your actual URL and hands you the screenshots, video, and full Playwright trace. The expectations come from your words, the verdict comes from a real browser hitting the real app, and neither one came from the agent that wrote your feature code.

That separation is the whole point. The coding agent (Claude Code, Cursor, whatever you drive) lives in your repo and writes the change; TestVibe lives outside it and checks the behavior, and when the two disagree, you've caught something before your users did. You can wire it up exactly that way through the CLI, REST API, or MCP server, so that an agent finishes a change, an independent suite runs against the deployed result, and nothing merges until it's passed. One system writes the code and a different one decides whether it actually works.

And because the tests assert on observable outcomes with web-first assertions that retry until the real state settles, a green run means a browser genuinely did the thing and saw the right result, not that a model talked itself into believing it would.

The rule is old and it survives the shift to agents intact: the author doesn't grade the work. Keep the layer that checks behavior separate from the layer that writes it, feed the checker intent instead of code, and make it run against something real. Do that and an agent's speed becomes an asset instead of a faster way to ship confident, well-tested bugs.

Want an independent verification layer that generates tests from plain-language intent and runs them against your real app? Get early access, or read how generation works.

Early access

Ready for tests that write themselves?