DEV Community

Cover image for AGENTS.md, Kept True: Stop the Rot Step by Step (and Watch Your Agent Trust It)
wolfejam.dev
wolfejam.dev Subscriber

Posted on

AGENTS.md, Kept True: Stop the Rot Step by Step (and Watch Your Agent Trust It)

TL;DR — A good AGENTS.md isn't written, it's maintained — and the maintenance is where every one dies. Here's the exact discipline that keeps yours true: tie every line to a fact in the repo, verify it runs, and make it change in the same PR as the code. Six steps, one worked example, and an agent that stops guessing.

You've got an AGENTS.md — maybe you built one step by step. The problem now isn't writing it. It's that, as we covered, it goes stale the day you write it — it starts lying the moment your code moves, and your agent believes it anyway. So let's harden it. Open a repo and follow along.

Step 1 — Start from the truth, not a template

Before you write a line, list what's actually real:

cat package.json | jq .scripts     # your real commands
ls src/                            # your real entry points
ls .eslintrc* tsconfig.json 2>/dev/null   # your real conventions (the configs)
Enter fullscreen mode Exit fullscreen mode

Rule for the whole file: if it isn't in the repo, it doesn't go in the AGENTS.md. No aspirations, no "we should probably." Facts only.

Step 2 — Write the commands copy-pasteable, then RUN them

Don't type npm build from memory. Run it, and paste what actually works:

npm run build && npm test
Enter fullscreen mode Exit fullscreen mode

Put the exact strings in the file. If the command in your AGENTS.md doesn't run, your agent's first move fails — and it won't know why. Tests go above build: they're the agent's only way to check its work against reality.

And wrap every tool and command name in backticks — mypy, ruff, npm test. A formatted token reads as a literal to run, not a vague suggestion the model can paraphrase away when the context is saturated.

Step 3 — Point at the config; don't restate it

You already have a linter and a formatter. So don't write "use 2 spaces, prefer const, strict types." Write:

## Conventions
- Style is enforced — run `npm run lint`. Obey the config, don't hand-format.
- TypeScript strict mode (tsconfig.json).
Enter fullscreen mode Exit fullscreen mode

Restating a rule your linter owns is how the file goes stale (you change the config, the prose lies). Point at the source of truth instead. One line, can't rot.

Step 4 — Guardrails in three tiers + a Definition of Done

Give the agent a safety map and a finish line:

## Guardrails
- **Always:** read files, run the tests, build.
- **Ask first:** dependency installs, deletions, migrations.
- **Never:** force-push, push to `main`, commit secrets.

## Definition of Done
Done when: `npm run lint` exits 0 · `npm test` passes · committed with a conventional message.
Enter fullscreen mode Exit fullscreen mode

Now the agent can know it's finished, not guess — and it knows which moves need a human.

One phrasing note that punches above its weight: lead with the enable, not the prohibition. "Branch and open a PR" hands the agent the safe path; a bare "don't push to main" hands it only the landmine — and a naked negative can prime the very move it's warning against. Say what to do, then the boundary.

Step 5 — The anti-rot rule: it changes in the same PR as the code

This is the step everyone skips, and it's the whole game. Make drift a bug, not a someday:

  • Add it to your PR template: "Touched build/test scripts? Update AGENTS.md."
  • Or a CI check that fails if package.json scripts changed but AGENTS.md didn't.
  • Or — the honest endgame — regenerate the file from the repo so it can't drift (more on that below).

Treat AGENTS.md like code, because your agent already does.

Step 6 — Verify: point your agent at it and watch

Give the agent a small, real task ("add a tested /health endpoint"). Watch it: read the file, run the tests you listed, respect the guardrails, hit your Definition of Done. If it does the wrong thing — wrong command, ignored convention — your file lied. Fix the line, not the agent.

That loop — task, watch, fix the line — is how an AGENTS.md earns trust. A true one becomes the most reliable thing in your repo.

Where to go deeper

The series: 1 · the field guide2 · build one, hands-on3 · why it goes stale → you're on 4.

  • The AGENTS.md standardagents.md (the spec itself).
  • Section-by-section definitions + a field guidefaf.one/agents (what earns a line, ordering, length, and the anti-patterns).
  • Why "generated from truth" beats hand-writing and AI-slop — the research and the deeper dive, same place.

Keep it honest, and your agent stops guessing. That's the whole point of the file.

Top comments (0)