A coding agent will sometimes invent a method, use an outdated API or claim that tests pass (see Hallucinations). Do not take its word for it. Two habits deal with this: make it read before it writes, and give it a check it can run, so it catches its own mistakes before you do.
When to use it
On every change you plan to keep. It matters most when the agent works on its own for a while, touches libraries that change often, or adds dependencies.
How to do it
Make it read instead of guess
- Point it at the sources first. “Before changing anything, read
src/auth/andpackage.json, and check which version of zod we use.” - Allow “I don’t know”. “If you are not sure an API exists, check the types in
node_modulesor the docs. Do not make it up.” - Use the docs that ship with your code. Type declarations in
node_modules(.d.tsfiles) show the real signatures of the version you have installed. The agent can open them like any other file. - Fetch current docs when needed. Claude Code’s
WebFetchtool fetches a URL, such as the official docs page for your library version. An MCP server such as Context7 pulls version-specific documentation and code examples into the session.
Give it a check it can run
- Type-check.
npx tsc --noEmitruns the TypeScript compiler as a checker only, without writing output files. Most invented methods and fields fail here immediately, which is why TypeScript and agents work so well together. - Write the failing test first. With vitest or jest, ask for a test that reproduces the bug, watch it fail, then fix the code until it passes.
- Lint. Run eslint as part of the same check.
- Run the real thing. For a backend,
curlthe endpoint. For a frontend, let the agent open the page: Claude in Chrome lets Claude Code open your local app, try a form, read console errors and fix what it finds. - Make it a standing rule. Put it in CLAUDE.md, for example “After every change, run
npm run typecheck && npm test.” - Ask for evidence, not claims. Do not accept “everything works” without the command and its output. Reviewing the output is faster than re-running it yourself.
- Review new dependencies by eye before
npm install: check that the package exists, is the one you meant, and is maintained. Invented package names are a real attack vector (slopsquatting).
Example
A package.json script the agent can run in one go:
{
"scripts": {
"typecheck": "tsc --noEmit",
"lint": "eslint .",
"test": "vitest run",
"check": "npm run typecheck && npm run lint && npm test"
}
}And the line in CLAUDE.md:
## Verification
- After every change, run `npm run check` and show the output before saying it works.
- Never add a dependency without showing me the package name first.With that in place, when the agent writes await fs.promises.exists(path), the type-check fails, the agent reads the error, opens the Node types and switches to fs.promises.access, all before you look at the diff.
Common mistakes
- Trusting “tests pass” without output. Ask to see the run.
- No check at all. Without something that returns pass or fail, the agent stops when the code looks done, and you become the test suite.
- Letting the agent install packages unreviewed. That removes the one point where a fake package gets caught.
- Asking from memory about fast-moving libraries. Point it at the installed version or the current docs instead.
Related
- Hallucinations: what this practice protects against.
- Agentic loop: why a runnable check lets the loop fix its own mistakes.
- Managing context: a lean context also hallucinates less.