AI Fieldcraft
FM-03 · AGENT OPERATIONS / BRIEFING DOCTRINELAST VERIFIED 2026-07 · FREE ISSUE

The AGENTS.md Template That Fixes 80% of Agent Failures

Purpose. Explain why coding agents fail on real codebases, and issue the briefing file — AGENTS.md — that prevents it. Includes the complete template and the rules for keeping it effective.

Section 1 — Why agents fail (it's boring)

1-1. When a coding agent wrecks a task, the post-mortem is almost never "the model is dumb." It is one of these:

1-2. Every one of those is a briefing failure, not an intelligence failure. You gave a capable contractor zero onboarding and are surprised they improvised. AGENTS.md is the onboarding. It's a plain Markdown file, placed in the repo root, that the major coding agents (Claude Code reads it natively alongside CLAUDE.md, Cursor, Codex-style CLIs, Cline, and others) load into context automatically on every task.

Section 2 — The template

2-1. Copy, fill in, delete what doesn't apply. Every section exists because its absence causes a specific, recurring failure — annotated in comments.

# AGENTS.md

## Project
<!-- 2 sentences max. What this is and the stack. Stops wrong-ecosystem guesses. -->
Invoice-processing API. Python 3.12 + FastAPI + Postgres. Frontend in /web (React + Vite).

## Commands
<!-- THE most valuable section. Exact commands, copy-paste runnable. -->
- Install:   uv sync
- Run dev:   uv run fastapi dev app/main.py
- Test:      uv run pytest -x -q          # run BEFORE and AFTER changes
- One test:  uv run pytest tests/test_x.py::test_name -x
- Lint/fix:  uv run ruff check --fix . && uv run ruff format .
- Types:     uv run mypy app/

## Conventions
<!-- Only rules a linter can't enforce or that differ from ecosystem defaults. -->
- Prefer plain functions over classes; no new classes without asking.
- All DB access through app/repo/*.py — never raw SQL in route handlers.
- Errors: raise domain exceptions from app/errors.py; never bare except.
- No new dependencies without asking. Especially not: pandas, requests (we use httpx).

## Definition of done
<!-- The agent stops when IT thinks it's done. Define done or inherit its guess. -->
A change is done only when:
1. `uv run pytest -x -q` passes
2. `uv run ruff check .` is clean
3. `uv run mypy app/` is clean
4. New behavior has a test

## Boundaries
<!-- Hard stops. Be blunt; agents respect explicit prohibitions well. -->
- NEVER edit: /migrations, *.lock, /web/dist, anything in .gitignore
- NEVER run: git push, deployment scripts, anything touching prod config
- Ask before: schema changes, deleting files, adding dependencies

## Map
<!-- Only the non-obvious. The agent can read a file tree by itself. -->
- app/routes/    HTTP layer — thin, no business logic
- app/services/  business logic lives here
- app/repo/      all database access
- tests/fixtures/ golden files — regenerate with `make golden`, never hand-edit

Section 3 — Doctrine (what makes it work)

3-1.Write commands, not prose. "We use pytest for testing" is decoration. uv run pytest -x -q is a briefing. Every claim in AGENTS.md should be either an exact command or an exact prohibition.

3-2.Keep it under ~150 lines. The file rides in the agent's context on every task; every line taxes attention, and models weight short, sharp documents better than long ones. If it can be discovered by reading the code (file tree, function names), it doesn't belong here. Decisions, commands, and boundaries do.

3-3.Nest in monorepos. Place one AGENTS.md at the root and additional ones inside subprojects (/web/AGENTS.md). Agents apply the closest file to the code being edited; the nested file overrides the root. This keeps each briefing short and local.

3-4.Treat failures as changelog entries. The file is a living document with a simple update rule: every time an agent does something wrong twice, that failure becomes a line. Agent used the wrong test runner? → Commands. Added a banned dependency? → Conventions. Six weeks of this produces a briefing tuned to your repo's actual failure modes — which is why a copied template is a starting point, never the finished artifact.

3-5.One source of truth. Some tools historically read their own file names (CLAUDE.md, .cursorrules). Keep the content in AGENTS.md and, where a tool wants its own name, symlink or point it there. Duplicate briefings drift, and a drifted briefing is worse than none — the agent can't tell which one is lying.

Section 4 — Anti-patterns

Anti-patternWhy it backfires
The novel (500+ lines, architecture essays)Dilutes the rules that matter; agents skim like tired humans. Move essays to /docs and link.
Vibes instead of rules ("write clean code", "be careful")Unactionable. The model already "intends" this. Only concrete commands and prohibitions change behavior.
Auto-generated and never touchedAn AGENTS.md that no failure has ever edited is a README with a different name. Its value comes from encoding your incidents (§3-4).
Stale commandsWorse than no file: the agent trusts the briefing over its own discovery, then confidently runs the wrong thing. Update it in the same PR that changes tooling.
Secrets or credentials in the fileIt's committed to the repo and pasted into model context. Never.

Section 5 — FAQ

What is AGENTS.md?
A plain Markdown briefing file in your repo that tells AI coding agents how to build and test the project, what conventions to follow, what "done" means, and what never to touch. Major coding agents read it automatically.
Where does it go?
Repo root; nested copies in monorepo subprojects override the root for their subtree.
How long should it be?
Under ~150 lines. It's loaded on every task — every line costs attention.
Does this help non-coding agents too?
Yes — the principle is universal: agents fail on missing operational context, and a short standing briefing (commands, conventions, done, boundaries) is the cheapest fix in all of agent engineering. The same doctrine powers the safety rules in FM-01 §4.
Cross-references

Build the agent this file briefs: FM-01. Run it on local models: FM-02 (Mac) and FM-05 (model choice).

Get the Field Kit (includes this template as a file)