Skip to content

Commit 9e39fb7

Browse files
authored
docs: add a case study of the org's agent-ready setup (#144)
1 parent cabf462 commit 9e39fb7

2 files changed

Lines changed: 90 additions & 0 deletions

File tree

‎docs/agent-ready.md‎

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# How the modern-python repos are set up for coding agents
2+
3+
modern-python is about thirty repositories, maintained by one person, with coding agents working
4+
in every one of them. This page describes the setup that makes that workable, using the same four
5+
parts as the [agent-ready backend](services.md#agent-ready) offer. Everything here is public and
6+
linked, so you can check it.
7+
8+
## Context the agent can use { #context }
9+
10+
Every repo has an `AGENTS.md` at the root. It holds what an agent can't learn by reading the code:
11+
the commands, where each concern lives, and the rules that leave no trace in the code that follows
12+
them. [lite-bootstrap's](https://github.com/modern-python/lite-bootstrap/blob/main/AGENTS.md)
13+
is a typical one. It explains why every link in `README.md` must be absolute (the README is also
14+
the PyPI description, and PyPI doesn't rewrite relative links), and it lists four code style rules,
15+
each with the reason behind it.
16+
17+
Most repos also carry a `CONTEXT.md`, a glossary limited to terms with a synonym to reject or a
18+
meaning subtle enough that code and docs have to agree on it. Each entry names the words to avoid.
19+
In [lite-bootstrap's](https://github.com/modern-python/lite-bootstrap/blob/main/CONTEXT.md), an
20+
instrument being *configured* and a bootstrapper being *ready* are separate terms, and the agent is
21+
told to use them exactly.
22+
23+
Decisions go into architecture decision records under `docs/adr/`, 88 of them across the repos. A
24+
short [domain doc](https://github.com/modern-python/lite-bootstrap/blob/main/docs/agents/domain.md)
25+
tells the agent to read the ADRs for the area it is changing, and to say so when its change
26+
contradicts one instead of quietly overriding it. Two more docs in the same folder describe the
27+
issue tracker and the triage labels, so an agent can pick up and file GitHub issues through `gh`.
28+
29+
Above the repos sits the [standard](standard.md): numbered requirements, each with a stable ID and
30+
usually a *Why* line. An agent can cite [CI9](standard.md#CI9) in a pull request the same way a
31+
person would.
32+
33+
## Checks for agent-written code { #checks }
34+
35+
An agent's change goes through the same checks as anyone's, and the commands are identical
36+
locally and in CI:
37+
38+
- The `justfile` has a fixed set of recipes ([JF1](standard.md#JF1)). `just lint` rewrites files,
39+
and `just lint-ci` runs the same checks read-only.
40+
- ruff, ty and eof-fixer, required by the standard ([TL2](standard.md#TL2)), with a 100% line
41+
coverage gate ([TS2](standard.md#TS2)). A `pragma: no cover` should carry its reason on the same
42+
line ([TS6](standard.md#TS6)).
43+
- The `floors` job installs every dependency at its lowest declared version and runs the suite
44+
([CI10](standard.md#CI10)), which catches code that only works on the latest release.
45+
- A links job fails on any relative link or file path the diff broke ([CI7](standard.md#CI7)), and
46+
docs sites build with `mkdocs build --strict` ([CI8](standard.md#CI8)).
47+
- A shared check fails when a file cites an ADR that doesn't exist ([CI9](standard.md#CI9)).
48+
49+
Some rules are tests. The org repo's
50+
[`tests/test_site.py`](https://github.com/modern-python/.github/blob/main/tests/test_site.py)
51+
asserts that the site's project lists match the brand manifest, and each test's docstring opens
52+
with `INVARIANT:` and explains what breaks without it. An agent that removes the check has to argue
53+
with the reason in front of it.
54+
55+
## Signals from outside the diff { #signals }
56+
57+
Libraries don't have a production environment, so this part is thin here. The closest thing is a
58+
daily scheduled run of each published repo's checks ([CI2](standard.md#CI2)). When a dependency release or a
59+
new Python breaks a repo, a
60+
[shared workflow](https://github.com/modern-python/.github/blob/main/.github/workflows/report-scheduled-failure.yml)
61+
opens or updates an issue linking the failing run, and an agent can pick that issue up like any
62+
other.
63+
64+
## Telemetry { #telemetry }
65+
66+
The same applies to telemetry: a library has none of its own. For services, the org's answer is
67+
[`lite-bootstrap`](https://github.com/modern-python/lite-bootstrap), which wires OpenTelemetry,
68+
Prometheus, Sentry and structlog into FastAPI, Litestar or FastStream. In a client's service, this
69+
part and the one above carry more weight than they do here.
70+
71+
## What we learned { #lessons }
72+
73+
Copies drift, even byte-identical ones. Twenty-five copies of the ADR citation test drifted within
74+
a month of being written, so the repos now fetch one shared file from the org repo, unpinned
75+
([CI9](standard.md#CI9)). Per-repo scripts that reported scheduled failures drifted the same way,
76+
and several named a dependency their repo didn't have. They were replaced by one shared workflow
77+
([CI2](standard.md#CI2)).
78+
79+
Not everything should be shared. A single CI workflow for all repos was built and rejected
80+
([#95](https://github.com/modern-python/.github/issues/95)): reusable workflow inputs are plain
81+
strings, so service containers and environment maps had to be flattened into them. Each repo keeps
82+
its own `_checks.yml` ([CI3](standard.md#CI3)), and a change to the jobs is a sweep across repos.
83+
84+
Write down only what the code doesn't show. Agents read code well. What they miss is the reason a
85+
link must be absolute, why a type checker's warning is noise, or which word the project has already
86+
rejected, and that is what the `AGENTS.md` and `CONTEXT.md` files hold.
87+
88+
If you'd like the same setup in your own codebase, see [services](services.md#agent-ready).

‎docs/services.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ merged pull requests in your repositories:
2525
[`lite-bootstrap`](https://github.com/modern-python/lite-bootstrap), so people and agents can
2626
debug from the same data.
2727

28+
The [modern-python repos](agent-ready.md) run on the same setup, minus the production parts.
29+
2830
## Delivery health check { #audit }
2931

3032
A short, fixed-scope review, and a good first step before a sprint. Automated scanners for

0 commit comments

Comments
 (0)