Blog
Architecture decision records (ADRs) for AI coding agents
Published: September 23, 2026
An AI coding agent follows an ADR only if the decision is in its context while it writes the code. Keep ADRs as short markdown in the repo, with the decision in the first line and an explicit status, index them from AGENTS.md or CLAUDE.md, and mark superseded ones clearly. Otherwise the agent follows a decision the team already reversed.
What ADR format works best for AI coding agents?
The format you already know. Michael Nygard's 2011 post defined five parts: title, context, decision, status, consequences. MADR (4.0.0, released 2024-09-17) adds YAML front matter with status and date, and a status value of the form superseded by ADR-0123. Both are fine for an agent. Three habits make them better:
- Decision first. Put the rule in the title and the first sentence. An agent skimming an index sees titles, and a title like “Webhook retries” tells it nothing.
- Status in front matter. An agent can read
status: supersededon line two. It will not reliably infer it from a paragraph at the bottom. - Name the code it governs. A line saying which directory or module the decision is about lets you scope it later.
--- status: accepted date: 2026-08-14 --- # ADR-0017: Retry provider webhooks on 5xx and timeouts only ## Decision Retry on 5xx and timeouts. Never on 4xx. Max 3 attempts, exponential backoff, same idempotency key on every attempt. Applies to: services/payments/webhooks/ ## Context A 4xx means our request is wrong; retrying repeats it. Decided in #eng-payments after the August incident. ## Consequences Consumers must be idempotent on the provider event id.
Where should ADRs live?
In the repository, next to the code they govern, so they version and review with it. Nygard used doc/arch/adr-NNN.md; MADR uses docs/decisions/. Pick one and keep numbers monotonic. Nygard's rule still holds: when a decision is reversed, keep the old record and mark it superseded. The history is the point.
A wiki page is worse for agents on every count. It is not on disk, it is not in the PR that changed the behaviour, and no agent reads it unless someone connects the wiki.
How do I make Claude Code, Cursor or Codex read my ADRs?
There are five ways to get an ADR in front of an agent. They differ in when the text loads and who decides to load it. Claude Code details are from its memory docs and skills docs, checked 2026-09-23.
| Method | When it loads | Who decides | Catch |
|---|---|---|---|
| @import in CLAUDE.md or AGENTS.md | At launch, in full, every session | Nobody; always on | Every ADR costs context in every session, relevant or not |
| An index in AGENTS.md (title and path per ADR) | Index every session; ADR when opened | The agent, from the title | Only as good as the titles |
| Path-scoped rule (.claude/rules with paths:) | When Claude reads a matching file | The file path | Claude Code only; the decision must map to paths |
| A skill wrapping the ADRs | Name and description at start; body when invoked | The agent | The agent may never invoke it |
| An MCP server that searches docs | When the agent calls it | The agent | The agent has to know to ask |
The index is the cheapest good default. Vercel's agent evals (January 2026) found a compressed docs index in AGENTS.md reached a 100% pass rate, while a skill with the same material went uninvoked in 56% of cases. A minimal index:
## Architecture decisions (docs/decisions/) Read the ADR before changing code it names. Skip superseded ones. - ADR-0017 Retry provider webhooks on 5xx and timeouts only (services/payments/webhooks) - ADR-0012 [superseded by 0017] Retry all failed webhooks - ADR-0009 Postgres advisory locks for the ledger writer (services/ledger)
Avoid @-importing the whole directory. Claude Code's docs note that imported files “still load and enter the context window at launch”, so twenty ADRs become twenty ADRs of standing context. How much that costs is covered in how long should CLAUDE.md be.
Why do agents still ignore architecture decisions?
Two reasons, and neither is the format.
Available is not in context. Every method above except the import depends on a choice made mid-task: a file path, a title, the agent's judgment that it should look. The agent adding a webhook consumer in a new directory reads no matching path, sees an index line it does not connect to the task, and writes the retry loop from general knowledge. The ADR was one command away the whole time.
ADRs go stale. ADR-0012 said retry everything. ADR-0017 reversed it. If 0012's status was never updated, both records look current. If the reversal happened in Slack and 0017 was never written, the only record on disk is the wrong one. Claude Code's docs are candid about the result: if two rules contradict each other, Claude may pick one arbitrarily. The same goes for an ADR describing a module that was deleted last quarter; it keeps being served to anyone who asks. More on that in context rot and stale rules.
Should AI agents write ADRs?
They can draft them, and it is a good use of the end of a session. The agent that just implemented the retry change knows the context, the options it rejected, and the files it touched. Ask it for an ADR in your template and open it as part of the same PR.
Two conditions. A person reviews the draft like any other change, because a model will happily record a guess as a decision. And the draft must name the ADR it supersedes, if any, and update that record's status in the same commit. An agent writing ADR-0017 without touching ADR-0012 leaves both looking current, which is the staleness failure described above.
The inverse matters too. Plenty of real decisions never become ADRs, because they were settled in a Slack thread or a review comment and nobody wrote the record. An ADR practice covers the decisions someone chose to write down, not all the ones the code depends on.
How Harbor serves ADRs to coding agents
Harbor reads repo markdown from GitHub and GitLab, including ADRs, RFCs and docs/, alongside the places the decision was argued: Slack channels you opt in, and PR review threads. The decision in ADR-0017 becomes a fact with the file as its source, and passes the review gate you set.
Then it is served on turn one. When an engineer asks Claude Code, Cursor or Codex to add a webhook consumer, the hooks harbor init installed give the agent the facts that apply to that task, and the retry decision is among them. The agent does not have to guess that an ADR exists.
Supersession is handled as a decision, not a file edit. When a newer decision conflicts with an existing fact, Harbor proposes the supersession to an owner instead of serving both. When a repo change removes what a fact is about, Harbor can retire it. Retired facts are archived, not deleted, which keeps Nygard's history intact. Each fact is counted served and cited, so an ADR nobody's answers ever rely on is visible. Start with the quickstart, and see the knowledge docs for how facts are kept.
Related: is AGENTS.md useful and Slack decisions for AI coding agents.
Questions
How do I make Claude Code read my ADRs?
Add an index to CLAUDE.md or AGENTS.md with each ADR's title, path and status, so Claude sees the list every session and opens the one it needs. Importing every ADR with @path also works but loads all of them into every session.
What ADR template should I use for AI agents?
Nygard's format or MADR both work. Put the decision in the title and first sentence, keep the status in front matter, and name the code the decision governs.
Where should architecture decision records be stored?
In the repository, next to the code they govern, for example docs/decisions/ as MADR suggests. That way they are versioned and reviewed with the code and are on disk where agents can read them.
What happens when an ADR is superseded?
Keep the old record and set its status to superseded with a pointer to the new one. If both look current, an agent can follow either, and Claude Code's docs say it may pick one of two contradictory rules arbitrarily.