AI-Native Updated 2026-09 10 min read View as Markdown

Writing an AGENTS.md for Python that agents actually follow

Most AGENTS.md files are 400 lines of advice the model already knew. Here is what earns its place in the context window, and a Python template you can copy.

AGENTS.md is a plain Markdown file in your repo root that coding agents read before they start work. Claude Code reads CLAUDE.md; Codex, Cursor, Aider, Cline and most newer tools read AGENTS.md. The contents are the same, so pick one file and symlink:

shell
printf 'CLAUDE.md\n' >> .gitignore   # or commit the symlink, your call
ln -s AGENTS.md CLAUDE.md

The file is not documentation. It is a standing correction list: the things a competent Python developer would get wrong on their first week in your repo, because they are specific to your repo rather than to Python.

The economics nobody mentions#

Every token in AGENTS.md is prepended to every request for the whole session. A 500-line file is not free advice — it is a permanent tax on the context available for your actual code, and it dilutes the instructions that matter.

Worse, models weight instructions roughly by salience, not by position in a list. Twelve rules get followed. Sixty rules get sampled. If you have written sixty, you have effectively randomised which of your rules apply.

The target

Under 100 lines. If it is longer, you are writing documentation. Move it to docs/ and link to it — agents can read a file on demand, and an on-demand read costs nothing when it is not needed.

What belongs in it#

1. How to run things. The single highest-value section, because it is unguessable and used every turn.

2. Conventions a linter cannot enforce. "Domain logic goes in src/core/, never in the route handlers." A model cannot infer this from the code, and ruff will not tell it.

3. Landmines. "sync_users() is called by a cron in production; changing its signature breaks the scheduler repo." This is the highest-value line in most files and almost nobody writes it.

4. Corrections you have made twice. If you have told the agent twice not to add try/except around everything, that is a line.

What does not belong in it#

Generic Python advice. "Use type hints. Follow PEP 8. Write docstrings." The model knows. You are spending context to teach it something it does better than most humans.

Anything a tool already enforces. If ruff sets your line length, do not also write the line length in prose. You now have two sources of truth and one of them will drift. Configure the tool; mention the tool.

Long architecture explanations. Put them in docs/architecture.md and write one line: "Read docs/architecture.md before changing anything under src/billing/." Agents follow pointers reliably.

Aspirations. "All code should have 100% test coverage." If it is not true today, it is a lie in the context window, and it makes every other line less credible.

A Python template worth copying#

AGENTS.md
# AGENTS.md

Python 3.12. Package management is `uv` — never `pip` or `poetry`.

## Commands
- Install:      `make install`   (uv sync)
- Test:         `make test`      (pytest -q)
- One test:     `uv run pytest tests/test_x.py::test_name -q`
- Lint + fmt:   `make lint`      (ruff check --fix, ruff format)
- Types:        `make typecheck` (mypy src, strict)
- All of it:    `make check`     <- must pass before you say you are done

## Layout
- `src/core/`      pure domain logic. No I/O, no framework imports, no `requests`.
- `src/adapters/`  everything that touches the outside world: db, http, queues.
- `src/api/`       FastAPI routers. Thin. Parse, call core, serialise. No logic.
- `tests/`         mirrors `src/`. Unit tests are offline; anything needing a
                   database is marked `@pytest.mark.integration`.

## Conventions
- Money is `Decimal`, never `float`. Serialise as a string.
- All datetimes are timezone-aware UTC. `datetime.now(UTC)`, never `utcnow()`.
- Public functions in `src/core/` are fully typed. `Any` needs a comment saying why.
- Errors: raise domain exceptions from `src/core/errors.py`. Do not catch broadly.
- New dependencies need a line in the PR description justifying them.

## Landmines
- `src/adapters/legacy_sync.py` is called by the `ops-scheduler` repo via CLI.
  Do not change its arguments or its exit codes.
- `tests/fixtures/prod_sample.json` is real, anonymised customer data. Do not
  print it in test output and do not paste it into commit messages.
- Alembic migrations are irreversible in production. Write the migration, do not
  run it. A human runs migrations.

## Working style
- Small commits. One behavioural change each.
- When a test is failing, fix the code, not the test — unless the test is
  provably wrong, in which case say so explicitly in the commit message.
- If a change needs more than ~150 lines of diff, stop and describe the plan first.

That is 40 lines and it does more than most 400-line files. Notice how much of it is specific facts about this repository rather than opinions about Python.

Nested files for big repos#

In a monorepo, a root AGENTS.md plus per-package files works better than one large file. Most tools read the nearest one and merge upward.

AGENTS.md                     # commands, global conventions
services/billing/AGENTS.md    # Decimal rules, the Stripe webhook landmine
services/etl/AGENTS.md        # pandas conventions, memory limits

The root file should then be almost entirely commands and layout, with the specifics pushed down to where they are relevant.

How to tell if yours is working#

Run the same non-trivial task twice: once with the file, once with it renamed away. If the diffs are meaningfully different, the file is earning its place. If they are the same, you have written 100 lines of ballast.

It is also worth deleting a third of the file periodically and seeing whether anything gets worse. Usually nothing does.

Common questions#

AGENTS.md or CLAUDE.md?#

Write AGENTS.md — it is the convention most tools now converge on — and symlink CLAUDE.md to it so Claude Code picks it up too. Maintaining two files by hand guarantees they drift apart within a month.

Should AGENTS.md be committed to the repo?#

Yes. It is a shared artefact: everyone on the team benefits from the same landmine list, and it should be reviewed in pull requests like any other change to how the project is built. Keep personal preferences in your user-level config instead.

Does a longer file mean better results?#

No, and the relationship reverses past a point. Every line competes for attention with every other line, and a long file dilutes the rules you care about most. Under 100 lines is a good target; the specific facts about your repository matter far more than the volume of general advice.

What if my team uses several different agents?#

That is the argument for AGENTS.md rather than tool-specific files. Keep one file with the substance, symlink the tool-specific names to it, and put anything genuinely tool-specific — permission allowlists, hooks, model choice — in that tool's own config where it belongs.

Get the Python agent pack

A battle-tested AGENTS.md, the review checklist, and the failure-mode cheat sheet for Python. One email, then occasional updates when the tooling shifts. No course pitch.

Unsubscribe in one click. We never sell the list. Or just take the AGENTS.md now — no email needed.

Disclosure: some links on this page are affiliate links. If you buy something through one, we earn a commission at no extra cost to you. We only list tools we would tell a friend to use, and we say so when we have not used something ourselves. This is how the site stays free and ad-light.