ADRs for AI coding agents: how to make every agent read architecture decisions
Architecture decision records only help AI coding agents when the right record enters context at the right time. Use this setup for Cursor, Claude Code, and other agents.
An AI coding agent opens the billing service and finds a synchronous call followed by a queue publish.
The direct call looks redundant. The agent proposes deleting it and relying on the queue. The refactor is smaller, the tests pass, and the code looks cleaner.
Six months earlier, the team made the direct call intentional. One enterprise customer needs an immediate confirmation, while the queue supports downstream work. That choice is written in docs/adr/0017-immediate-billing-confirmation.md.
The ADR exists. The agent never reads it.
This is the gap teams hit after they start writing architecture decision records. A record in the repository is available to an agent, but availability is not the same as context. The agent needs a predictable place to look, a rule that tells it when to look, and a current status it can trust.
The short answer
Use this structure:
repo/
AGENTS.md
CLAUDE.md
.cursor/
rules/
architecture-decisions.mdc
docs/
adr/
README.md
0017-immediate-billing-confirmation.md
0018-retry-policy.md
Each ADR should hold one significant decision with:
- title
- status: proposed, accepted, deprecated, or superseded
- context and constraints
- the decision in active language
- consequences and tradeoffs
- owner and decision date
- links to a replacement when superseded
Then keep the agent rule short:
Before changing service boundaries, persistence, messaging, authentication,
or public API behavior, search `docs/adr/` for relevant accepted decisions.
Read the full matching ADR and any ADR that supersedes it.
If the proposed change conflicts with an accepted ADR, stop and name the
conflict instead of silently rewriting the architecture.
That is enough to create the retrieval habit without loading every ADR into every conversation.
Why ADRs fit AI coding agents
Michael Nygard's original ADR format was designed as a short conversation with a future team member. It separates the forces around a choice from the choice itself and its consequences. A decision stays in the log when it is reversed, but its status changes to superseded and points to the replacement.
That structure is unusually useful for agents. Code shows what the system does now. An ADR can explain:
- which constraint shaped the design
- which alternatives were considered
- which option the team accepted
- what downside the team knowingly took on
- whether the choice is still current
Without those fields, an agent may treat an intentional compromise as an accident. With them, the agent can compare a proposed edit against the reason the code exists.
Sources: Documenting Architecture Decisions and ADR guidance
Step 1: give every ADR a stable shape
Do not make the agent infer status from prose. Put it near the top.
# ADR 0017: Immediate confirmation before billing events
- Status: Accepted
- Owners: Payments team
- Decided: 2026-02-12
- Scope: services/billing, packages/payments
- Replaces: ADR 0009
## Context
One enterprise flow must receive confirmation inside the request window.
The event queue may be delayed and cannot satisfy that contract.
## Decision
We will keep the synchronous confirmation call. We will publish the billing
event after confirmation for downstream work.
## Consequences
Requests depend on the confirmation service. The queue cannot become the only
path without changing the enterprise contract.
## Rejected options
- Queue-only confirmation: rejected because delivery time is not bounded.
- Polling: rejected because it increases client complexity and load.
The exact template matters less than consistency. One record should describe one significant choice. Keep it short enough that a person and an agent can read the full record before changing code.
Step 2: keep old ADRs, but make replacement explicit
Deleting or rewriting an old ADR destroys useful history. Leaving it unchanged creates a different failure: search may return the old and new decisions as if both are current.
Use a visible status and reciprocal links:
- Status: Superseded by [ADR 0024](./0024-event-driven-confirmation.md)
The new ADR should say what it replaces. This gives agents a deterministic path from an old search result to the current decision.
adr-tools supports this workflow directly: creating a superseding ADR marks the old one as superseded and links the replacement. You do not need the tool, but you do need the behavior.
Source: adr-tools
Step 3: index the decision log for fast scanning
A large repository may have hundreds of records. Give humans and agents a small index in docs/adr/README.md:
| ADR | Status | Area | Decision |
|---|---|---|---|
| 0017 | Accepted | Billing | Keep synchronous confirmation |
| 0018 | Accepted | Billing | Retry only idempotent operations |
| 0024 | Proposed | Billing | Move confirmation to bounded stream |
The index is a search aid, not the source of truth. The agent still reads the full matching ADR and checks replacement links. Regenerate the index in CI if manual upkeep becomes unreliable.
Step 4: point Claude Code to ADRs without bloating CLAUDE.md
Claude Code reads project CLAUDE.md files at the start of a session. Its current guidance recommends keeping instructions concrete and concise, targeting fewer than 200 lines because larger files consume more context and reduce adherence.
Do not paste your decision history into CLAUDE.md. Add a durable retrieval rule:
## Architecture decisions
Accepted architecture decisions live in `docs/adr/`.
Before changing boundaries, storage, messaging, security, or public APIs:
1. search `docs/adr/README.md` and `docs/adr/` for the affected area;
2. read matching ADRs and their replacement links;
3. name any conflict with an accepted ADR in the plan.
For a monorepo, use path-scoped files in .claude/rules/ so billing decisions load for billing work and frontend decisions load for frontend work. Claude Code also supports importing an AGENTS.md file from CLAUDE.md, which avoids duplicating the common instruction across tools.
Source: Claude Code project memory and CLAUDE.md
Step 5: make Cursor apply the same retrieval rule
Cursor project rules live in .cursor/rules as version-controlled .mdc files. They can be scoped by file patterns or included based on relevance. Cursor recommends focused, actionable rules and explicitly suggests referencing files instead of copying their contents so rules stay short and do not go stale.
A path-scoped rule can look like this:
---
description: Read accepted billing ADRs before changing billing architecture
globs: services/billing/**,packages/payments/**
alwaysApply: false
---
Before planning architecture changes, read `docs/adr/README.md` and matching
records in `docs/adr/`. Follow accepted decisions. If a change conflicts with
one, name the ADR and ask for a new decision rather than ignoring it.
For simple cross-agent instructions, Cursor also reads a root AGENTS.md. Use it as the common pointer, then keep client-specific mechanics in the client-specific rule file.
Source: Cursor Rules documentation
Step 6: separate accepted decisions from proposed ideas
An agent should be allowed to suggest a better design. It should not silently treat its suggestion as the new architecture.
Use a clear flow:
- The agent finds the current accepted ADR.
- It names the conflict and proposes a replacement.
- A human owner reviews the new decision.
- The new ADR moves from proposed to accepted.
- The previous ADR becomes superseded.
- Every agent retrieves the new current record.
This preserves agent initiative without letting the latest generated plan outrank the team's decision.
Step 7: test with a fresh agent, not the session that wrote the ADR
The authoring session already knows the answer. It is a weak test.
Open a new Cursor or Claude Code session and ask:
- Why is the synchronous billing confirmation still here?
- Which ADR governs retry behavior in
services/billing? - Is queue-only confirmation accepted, proposed, or rejected?
- What would need a new ADR before this refactor can proceed?
A passing setup returns the current decision, rationale, and status. It follows supersession links. It does not quote an old ADR as current or pretend the instruction file is a hard security control.
Claude's own documentation makes the last point clear: CLAUDE.md shapes behavior but is not guaranteed enforcement. Cursor gives a similar warning that AI guidance should not be the only security control. Use tests, permissions, and policy checks for hard boundaries.
Common mistakes
Loading the full ADR directory into every prompt
This burns context and makes unrelated decisions compete for attention. Load a short index and retrieve the matching records.
Recording only the final choice
"Use Kafka" does not tell a future agent which constraint mattered. Include the forces, rejected options, and consequences.
Mixing proposals with accepted decisions
If both are plain Markdown with no status, search cannot establish authority. Status is part of the data, not decoration.
Updating old ADR text in place
This makes historical links lie and hides why the system changed. Supersede the old record and connect the two.
Assuming a repository file reaches every tool
Claude Code, Cursor, Codex, and other agents load instructions differently. Keep one common record, then add a tested pointer in each client's supported instruction path.
Connect ADRs to the rest of your agent context
ADRs solve one part of the context problem. Stable commands and conventions still belong in project instructions. Temporary work state belongs in a task handoff. Personal preferences belong in personal memory.
For the broader stack, compare the best tools for AI coding agent context, the best MCP servers for engineering teams, and decision log tools for product and engineering.
If teams use both Cursor and Claude Code, the companion guide on sharing memory between Cursor and Claude Code shows where the common pointer and handoff files fit.
Where Lockstep fits
Repository ADRs work well when one codebase and one review flow define the decision boundary. The harder case starts when product, engineering, and several agents must use the same decision across repositories and tools.
Lockstep keeps accepted decisions, rationale, rejected options, owner, and status in one shared record, then makes the current decision available through MCP. The ADR can stay close to code while Lockstep carries the team-level choice to Cursor, Claude Code, and the people reviewing their work.
The goal is simple: a new agent should not merely find architecture documents. It should know which decision is current, why the team made it, and when to stop before changing it.
Keep reading