Write for the Agent That Will Read Your Repo

I moved this blog from a self-hosted Ghost server to a static site with help from a coding agent. Along the way, the host’s deploy CLI failed with “Base directory does not exist”. The project config sets a base directory of site, and running the CLI from inside site made it apply that setting a second time. The fix was to deploy from outside the project and pass the build folder explicitly. That’s now a line in AGENTS.md, so no later session has to find it again.
AGENTS.md is a Markdown file at the root of a repo that coding agents read before they start work. The convention’s own site calls it “a README for agents”, and I think that undersells the difference, because this reader acts on what it reads. So it should hold only what an agent would get wrong without it: commands known to work, the traps that cost time, what never to touch, and not much more.
Confident mistakes
A stale line in a README costs a person a few minutes. They run the old command, see the error, and go read the code or ask someone. A stale line in AGENTS.md gets followed, and the convention’s FAQ says as much: list test commands and the agent will run them and try to fix what fails. When the command fails loudly that’s fine; the agent sees the error and investigates like anyone would. The damage is in instructions that fail quietly: a deploy that runs against the wrong directory, a converter that overwrites files, a “safe to rerun” that isn’t.
That makes a wrong instruction worse than a missing one. With nothing written, the agent reads the code, tries something, and maybe asks. With a wrong line, it skips that and does the wrong thing with confidence. AGENTS.md answers a narrower question than a README: what goes wrong here if you do the obvious thing?
The do-not-commit list
From this blog’s AGENTS.md, with one line left out:
## Do not commit
- `backup/` contains credentials, SSH keys, shell histories and a database dump.
- `static-build/` is the Ghost crawl and docker volumes.
...
These are in `.gitignore`. Check `git status` before committing, and never use `git add -f` on them.
The first line could have said “don’t commit backup/”. It says what’s inside instead, and that’s what lets the agent generalize: once it knows the folder holds credentials, it can treat a stray file with a token in it the same way.
The last line looks redundant, since .gitignore already keeps those folders out. But ask git to add an ignored path by name and it refuses with a hint: “Use -f if you really want to add them.” An agent trying to finish a task may well take that hint, so the rule is aimed at the workaround, not the original mistake.
The deploy line works the same way. It doesn’t only say “run it from another directory”; it says the config sets a base directory and the CLI applies it twice, so an agent can recognize the same failure in a preview deploy or a different command. The warning about the one-off Ghost converter, which would overwrite hand-edited pages if rerun, also says what to do instead: run it in a scratch copy and diff first.
What to leave out
Most agents load AGENTS.md at the start of every session, whether the task needs it or not. Each line takes room the agent could use for the work, and the more rules there are, the less weight each one carries. So the bar for a line is high: would the agent get this wrong without it?
The convention’s site suggests that anything you’d tell a new teammate belongs there too, and some tool vendors go further, with long files of coding conventions. I’d hold it to less. Those files read well to a person; the agent pays for every line, every session, and the line that prevents a disaster gets the same weight as the one about import order. A new teammate hears the onboarding talk once and forgets what doesn’t apply; the agent gets all of it every session. It can also read package.json for the scripts, list the folders and read the code, so none of that needs restating. My own file says the blog has 52 posts, which stops being true the next time I publish one.
Pointers help too. The deploy line ends with “See README.md for the full command”, and the tool-specific instruction file at the root of the repo is a single line pointing to AGENTS.md, so there’s one copy to keep true instead of two.
Untested commands
A command belongs in the file only after someone has run it as written, because one typed from memory with a wrong flag will be run exactly as typed. Then update it in the same change that makes it stale: rename a script or change how deploys work, and the AGENTS.md edit goes in that pull request. It’s closer to a script than to documentation, so give it the review a changed deploy command in CI would get.
What it can’t enforce
A short file leaves things out, and the agent will sometimes do the obvious wrong thing where nobody thought to warn it. You mostly learn what belongs there by watching an agent get it wrong, so the file grows one mistake at a time. When it drifts, nothing fails loudly; the agent just follows it. It also enforces nothing: a rule is a request the agent can still miss. When you can make the wrong thing impossible, do that instead: a deploy script that leaves the project directory itself, a pre-commit hook that rejects backup/, a converter that refuses to run outside a scratch copy. AGENTS.md is for what’s left, the reasons behind those guards and the traps you can’t cheaply build a guard for. For anything that must never happen, like committing credentials, it’s a second line of defense after .gitignore and access controls, never the only one.
Still, each session starts already knowing the traps, and nobody has to explain the same deploy quirk to every new agent.
Takeaways
- AGENTS.md has a reader that acts on it, so a wrong line does more harm than a missing one.
- Keep what an agent would get wrong without it: commands that work, the traps, and what never to touch. Leave out what the code already says.
- Write the reason next to each rule, so the agent can apply it to cases you didn’t list.
- Change it in the same pull request as the thing it describes, and review it like code.
The file is read by something that does what it says. Write it that way.