Context Architecture

The AGENTS.md Specification: Anatomy of a Repository Context File

David Guzenburg/ / 9 min read

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.

AGENTS.mdcontext filesspecificationrepository setup

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.

Terminology

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.

SectionAnswersFailure if omitted
Code styleFormatter, linter, naming, file organisation Agent writes in its own house style; diff noise on every PR
Testing instructionsExact command, coverage expectations, naming Agent runs the wrong command, sees failure, "fixes" working code
Architecture notesPatterns in use, folder logic, module boundaries New code lands in the wrong layer and violates boundaries
PR and commit guidelinesBranch naming, commit format, description template Commits that fail your CI lint before a human ever sees them
Security considerationsSecrets handling, banned dependencies, auth patterns Credentials in logs; a dependency your legal team rejected
Things to avoidAnti-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.

The duplication trap

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.

Takeaway

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.

Keep reading
Context Architecture

Scoping Agent Context in Monorepos: Nested Files and Precedence

How to split AGENTS.md across a monorepo so each package carries its own rules, why precedence follows proximity, and how to verify your tooling actually reads nested files.

Context Architecture

Why Duplicating Your README Into AGENTS.md Makes Agents Worse

Copying project overview into a context file measurably degrades agent performance. The three mechanisms behind it, and a discoverability test for deciding what to cut.

Context Architecture

AGENTS.md vs CLAUDE.md vs .cursorrules: When One File Isn't Enough

Whether to keep one context file or several, the three cases where a second file is justified, and why the symlink workaround usually disappoints.

Context Architecture

Encoding Architectural Constraints and Module Boundaries for Agents

Why naming your architecture pattern doesn't work, how to state dependency directions as checkable rules, and why every prohibition needs an escape hatch.

← Writing Build and Test Instructions an Agent Can Actually Execute  ·  Agent Memory: Four Layers, and Which One Is Worth Building →

All context architecture articles  ·  Every article