The AGENTS.md Specification: Anatomy of a Repository Context File
Twenty tools now read the same context file. Here is what to put in it, what to leave out, and why the comprehensive version performs worse than the short one.
What the file is for
A coding agent starts every session knowing nothing about your repository
beyond what it can read. It does not remember yesterday. It does not know that
make test has been broken since March and everyone uses
pytest -x instead, or that the legacy/ directory is
scheduled for deletion and should never be extended. Left to itself it will
infer conventions from whatever files it happens to open, and it will infer
them wrong often enough to be annoying.
AGENTS.md is the answer the industry converged on: a markdown
file at the repository root holding the operational context an agent needs.
The format was formalised as an open specification in August 2025, in an effort
led by OpenAI with participation from Google, Cursor and Factory. By December
2025 more than 60,000 open-source projects had adopted it and more than twenty
tools read it natively — Claude Code, OpenAI Codex CLI, Cursor, Aider,
Devin, GitHub Copilot, Gemini CLI, Windsurf and Amazon Q among them.
That convergence matters more than the format's particular merits. Before
it, every tool had its own file: .cursorrules,
CLAUDE.md, .aider.conf.yml, a half-dozen others. A
team using three tools maintained three copies of the same instructions and
they drifted apart within weeks. A single file that twenty tools agree to read
is worth more than a better-designed file only one tool reads.
The specification calls this a context file rather than a config
file, and the distinction is real. Configuration is read by a program that
executes it deterministically. Context is read by a model that weighs it
against everything else in the window. Instructions in an
AGENTS.md are strong suggestions, not guarantees — a point
this article returns to at the end.
The six sections that carry the weight
The spec is deliberately loose about structure, but practice has settled on six sections. Each answers a question the agent would otherwise have to guess at.
| Section | Answers | Failure if omitted |
|---|---|---|
| Code style | Formatter, linter, naming, file organisation | Agent writes in its own house style; diff noise on every PR |
| Testing instructions | Exact command, coverage expectations, naming | Agent runs the wrong command, sees failure, "fixes" working code |
| Architecture notes | Patterns in use, folder logic, module boundaries | New code lands in the wrong layer and violates boundaries |
| PR and commit guidelines | Branch naming, commit format, description template | Commits that fail your CI lint before a human ever sees them |
| Security considerations | Secrets handling, banned dependencies, auth patterns | Credentials in logs; a dependency your legal team rejected |
| Things to avoid | Anti-patterns, deprecated paths, dead directories | Agent extends the code you are trying to delete |
The last row is the one teams most often skip and most often regret. An
agent has no way to know which parts of your codebase are aspirational and
which are load-bearing. If legacy/ and core/ both
contain working code, both look equally like good examples to follow.
A file that actually works
Here is a root file for a Python service. It is short on purpose; the next section explains why.
# AGENTS.md
## Commands
- Install: `uv sync`
- Test: `pytest -x -q` (NOT `make test` — that target is broken)
- Lint: `ruff check --fix . && ruff format .`
- Type check: `mypy src/` — must pass with zero errors before commit
## Style
- Line length 100. Ruff config in pyproject.toml is authoritative.
- Type hints on every public function. Internal helpers may omit them.
- No `from x import *`. No relative imports above one level.
## Architecture
- `src/api/` HTTP layer only — no business logic, no DB calls
- `src/domain/` pure functions, no I/O, fully unit-testable
- `src/adapters/` all I/O: database, HTTP clients, queues
- Dependencies point inward. `domain/` imports nothing from the other two.
## Do not touch
- `src/legacy/` — frozen, scheduled for deletion Q4. Do not extend.
- `migrations/` — generated by alembic. Never hand-edit.
- Anything matching `*_pb2.py` — generated from protobufs.
## Security
- Secrets come from env vars via `src/config.py`. Never inline, never in tests.
- No new dependencies without asking. The lockfile is reviewed.
Twenty-eight lines. Every line tells the agent something it could not have worked out by reading the code, and nothing tells it something it could.
Why short beats comprehensive
The instinct on first writing one of these is to be thorough — to explain the project, its history, its module structure in detail. That instinct is wrong, and there is now measurement behind saying so. Practitioner guidance converged during 2026 on keeping the root file near 20 to 30 lines, on the specific finding that content duplicated from the README measurably degrades agent performance rather than improving it.
The mechanism is straightforward once stated. The context window is finite and shared. Every token spent restating what the agent can read directly from the codebase is a token not available for the actual task. Worse, duplication creates the opportunity for contradiction: your README says the project uses Poetry, you migrated to uv six months ago, and now the agent has two conflicting claims with no way to adjudicate between them. It will sometimes pick the wrong one, and it will do so with complete confidence.
If a fact is discoverable by reading a file in the repo, it does not belong
in AGENTS.md. Put the exception in, not the rule. "Test
with pytest" is discoverable from pyproject.toml. "The
make test target is broken, use pytest directly" is not
discoverable from anywhere, and is worth ten lines of project overview.
Precedence and nesting
Most tools that read AGENTS.md support nested files: one at the
root, others deeper in the tree, with the nearest file to the code being edited
taking precedence. This is the mechanism that makes monorepos tractable, and it
deserves its own treatment — the short version is that the root file
should carry only what is true everywhere, and everything package-specific
belongs in a package-level file.
Precedence is by proximity, not by specificity. A rule in
packages/api/AGENTS.md overrides the root file for anything under
packages/api/, regardless of which rule is more detailed. If you
find yourself writing "except in the API package" in your root file, that
exception belongs one directory down.
Treat it as source, not documentation
Three practices separate teams whose context files stay useful from teams whose files rot within a quarter.
Version it and review it
The file lives in the repository and goes through code review like anything
else. A change to AGENTS.md changes the behaviour of every agent
session across the team; that is at least as consequential as a change to CI
config, and deserves the same scrutiny.
Update it when it is wrong, immediately
The failure mode is silent. A stale instruction does not throw an error, it produces subtly worse output that nobody traces back to the file. When you notice an agent doing something the file told it to do and the file is wrong, fix the file in that moment. It takes ninety seconds and you will not remember later.
Test it
Give a fresh agent session a representative task and read what it produces before reading your own code. If it reaches for the wrong test command or puts a file in the wrong directory, that is a defect in the context file, not in the model. This is a cheap, repeatable check and almost nobody runs it.
What it cannot do
A context file is read by a language model that weighs it against the task,
the code it has open, and its own priors. It is not a policy engine. An
instruction not to touch src/legacy/ reduces the probability the
agent touches src/legacy/; it does not reduce it to zero.
This matters most for anything with real consequences. "Never commit
secrets" in AGENTS.md is worth writing, and is not a substitute
for a pre-commit hook that scans for them. "Do not modify migrations" is worth
writing, and is not a substitute for a CI check that fails the build if
migration files changed. Use the context file to make good behaviour likely and
mechanical controls to make bad behaviour impossible. The two are complements,
and treating the first as if it were the second is how teams end up surprised.
Write down what the agent cannot discover from the code, keep it near thirty lines, push exceptions into nested files, review it like source, and back anything consequential with a mechanical control that does not depend on a model choosing to comply.