
Your AI agent says it works. It probably didn't check.
A green build, an HTTP 200, a passing test, none of them mean the thing actually runs. What I've learned to make an agent check for real.
The agent finishes, types a confident "done, everything works," and shows you a green build. You open the app, and the page is blank. Nothing it told you was a lie, exactly. The build did pass. It just never opened the thing it built.
This is the most common way working with a coding agent goes sideways, and once you see it you can't unsee it. The agent isn't trying to fool you. It's doing exactly what it was pointed at: get to a passing signal as cheaply as possible. "The build compiled" is cheap. "Open the app, click through it, confirm the screen is right" is expensive. So unless you ask for the expensive version, you get the cheap one — and the cheap one is often wrong.
I've lost enough hours to this that I now write the checks into the instructions up front. Here are the traps I keep hitting, and the one line fixes that close them.
"It compiled" is not "it works"
A passing build means the code parsed and the types lined up. It says nothing about whether the page renders, the button does anything, or the form saves. An HTTP 200 from a quick curl is the same trap one layer up the server answered, which is not the same as the server being right.
So the first rule is the dumbest one: actually look at it. Render the page and confirm the change with your eyes, or have the agent do it and report what it saw.
And looking isn't only the pixels. A page can look perfect while the browser console is throwing errors, a request is quietly 404ing, or the data on screen is stale. Half the bugs that "look fine" are sitting in the console and the network tab, one glance away. Make checking them part of "done," not a thing you do later when a user complains.
A green checkmark is a claim about the code. It is not evidence about the software.
Test what ships, not what's easy
The agent will reach for the easiest environment that produces a green light, and that environment is usually not the one your users get.
The clearest case is the production build. A dev server hides bugs that only show up in production — minification, server-versus-static rendering, base paths, environment variables, caching. "Works in dev" is genuinely not the same claim as "works in prod," and the gap between them is where the embarrassing bugs live. If you ship a built artifact, the agent should test the built artifact.
The same goes for containers. If your app runs in Docker, say so explicitly, and say "test it inside the container, both dev and prod." Left to its own devices, the agent will build the project on your laptop, watch it pass, and call it done — having proven nothing about whether the thing actually runs in the box it ships in.
The pattern underneath both: name the real environment, or the agent will quietly substitute a convenient one.

The offline trap
Static, offline web apps have their own specific failure, and it's worth calling out because the agent gets it wrong almost every time.
To test a plain HTML app, the agent will try to open the file directly — the file:// protocol — and the browser blocks half of it for security reasons. Things silently don't load, and the agent either gets confused or reports a problem that isn't real. The fix is to serve the files over a small local HTTP server instead of opening them off disk.
And if the whole point is that the app works offline, "it loaded" isn't the test. The test is that it loaded without reaching the network. That means watching the network tab and confirming nothing went out — an app that quietly phones home is not offline, no matter how fine it looks.
The server it forgot to kill
Agents are great at starting things and bad at stopping them. Tell one to spin up a dev server to test a change, and there's a decent chance it's still running three days later, holding a port, eating memory, serving a build from a branch you abandoned long ago.
Two fixes, and I use both. First: tell the agent to kill any server it starts once testing is done. Cleaning up is part of the job, not an afterthought — and that goes for temp files and stray test data too, not just servers. Second, when you want tighter control, have the agent ask you to start the server rather than launching one in the background itself. You keep one terminal you can see, and there's no orphan to hunt down later.
It's a small thing that compounds. The cost isn't one stray process; it's never being sure which of the four servers you have running is the real one.

Write the contract
Every one of these has the same shape. The agent takes the shortest path to something that looks like success, and "looks like success" and "is success" are different things it has no reason to tell apart — unless you make it.
So I stopped relying on the agent to know what counts as tested, and started writing it down: a short testing contract that lives in the project, right next to the build commands.
- Don't trust a green build. Open the app and confirm the change by eye.
- Check the console and the network tab, not just the rendered page.
- Test the production build, and inside the container if there is one.
- For an offline app, serve it over HTTP and prove it runs with the network off.
- Kill any server you start, and clean up after yourself.
None of this makes the agent meaningfully slower. It just moves the moment of truth from "a user found it broken" to "the agent found it before telling me it was done." That trade is worth making every single time.