Skip to content

Architecture Decision Records with Agents ​

Agents do not remember last quarter's debate about "why we don't use an ORM in the payment path." If the decision isn't in the repo, every session re-opens it — often picking the option you rejected. ADRs are the durable "we decided X because Y" layer. Specs say what a feature must do; ADRs say which structural bets the system is allowed to make.

ADR vs spec vs CLAUDE.md ​

ArtifactAnswersLifespanAgent use
SpecWhat this feature must do / not doUntil feature evolvesImplementation acceptance
ADRWhich option we chose for a cross-cutting design problemUntil supersededAvoid re-proposing rejected options
CLAUDE.mdHow to work in this repo day-to-dayContinuous pruneCommands, never-dos, pointers to ADRs

Rule of thumb: if you find yourself pasting the same architectural rationale into prompts twice, write an ADR and link it from CLAUDE.md ("Payment path: see docs/adr/00xx-no-orm-payments.md").

See What Not to Delegate — many ADR topics are human-owned decisions the agent may only research.

When to write an ADR ​

Write an ADR when…Skip when…
Two+ viable options with lasting consequencesTrivial library choice with no coupling
You rejected an option agents love (ORM, rewrite, new queue)Purely local naming inside one file
Cross-cutting constraint (authn, tenancy, money, idempotency)Feature-only behavior → use a spec
Migration / strangler strategyOne-line bug fix
Multi-agent work needs a shared north starTemporary spike (mark spike explicitly if recorded)

Decision tree — research vs decide vs record ​

Template (fill-in) ​

markdown
# ADR <nnnn>: <short title>

- Status: Proposed | Accepted | Superseded by ADR-<nnnn>
- Date: <YYYY-MM-DD>
- Deciders: <names>
- Agent involvement: research only | drafted | n/a

## Context
<What forces this decision? Constraints, symptoms, scale.>

## Decision
<One paragraph: we will X.>

## Consequences
### Positive
- <...>
### Negative / accepted costs
- <...>
### Follow-ons required
- <docs, migrations, CLAUDE.md never-dos>

## Options considered
### Option A — <name>
- Pros: ...
- Cons: ...
- Why rejected / accepted: ...

### Option B — <name>
- ...

## Agent instructions
- DO: <how to comply in code>
- DO NOT: <rejected approaches to stop proposing>
- See also: <paths, specs>

The Agent instructions section is the load-bearing addition for agentic teams — classic ADRs omit it and agents keep offering Option B.

Example (abridged) — no ORM in payment path ​

markdown
# ADR 0014: No ORM in the payment path

- Status: Accepted
- Date: 2026-03-02
- Deciders: platform + billing leads
- Agent involvement: researched options; did not decide

## Context
Invoice settlement and Stripe webhook handlers must be auditable line-by-line.
Prior ORM usage hid transactional boundaries and generated N+1s under list+settle.

## Decision
Payment and settlement code under `src/domain/payments/` and `src/api/webhooks/stripe/`
uses hand-written SQL via our `db.query` helper. No Prisma/Drizzle/etc. in these trees.

## Consequences
### Positive
- Explicit transactions; easier audit
### Negative
- More boilerplate; agents will try to "clean up" with an ORM
### Follow-ons
- CLAUDE.md never-do; import lint boundary

## Options considered
### ORM everywhere
Rejected: auditability and surprise queries.
### Hybrid (ORM read, SQL write)
Rejected: still leaks into write path via convenience.

## Agent instructions
- DO: extend `db.query` helpers; add characterization tests for SQL
- DO NOT: add an ORM dependency or import ORM clients into payments/webhooks
- See also: `src/lib/db.ts`, ADR 0009 tenancy

Prompt: agent drafts, human decides ​

text
Research options for: <decision question>.
Constraints: <list>. Read ARCHITECTURE.md and existing docs/adr/*.

Output:
1. Context summary (evidence from this repo, not generic blog advice)
2. 2–4 options with pros/cons FOR THIS codebase
3. Recommendation with risks — clearly labeled as recommendation only
4. A draft ADR in our template (Status: Proposed)

Do not edit application code. Do not mark Accepted.

You set Status to Accepted (or reject). Never let the agent self-accept architectural ADRs. Related: Exploring Options, Constraints and Validation.

Making ADRs executable for agents ​

PracticeWhy
Store under docs/adr/ with numeric prefixesStable greppable paths
Link hot ADRs from CLAUDE.md (≤5 pointers)Loaded every session
Import lint / path ownership where possibleTurns "DO NOT" into a red gate
Supersede, don't silently edit Accepted meaningAgents and humans need history
Mention ADR in feature specs when relevantCloses spec-code + architecture loop

CLAUDE.md fragment:

text
## Architecture decisions (do not re-litigate)
- Payments SQL only: docs/adr/0014-no-orm-payments.md
- Tenancy: docs/adr/0009-tenant-context.md
If a task conflicts with an ADR, STOP and ask — do not invent a v2 path.

Review checklist for new ADRs ​

markdown
- [ ] Decision stated in one paragraph without hedging
- [ ] Rejected options include ones agents commonly propose
- [ ] Agent instructions DO / DO NOT are concrete (paths, deps)
- [ ] Status and deciders set by a human
- [ ] CLAUDE.md pointer added if this will be hit weekly
- [ ] Enforcement noted (lint, review, test) or explicitly "honor system only"
- [ ] Related specs updated if feature work assumed the old world

Failure modes ​

SymptomRoot causeFix
Agent proposes rejected ORM againNo ADR or no CLAUDE.md pointerWrite/link ADR; add never-do
ADR novel-length, unreadToo much essayCompress; move narrative to wiki; keep decision + agent instructions
ADR edited in place to flip meaningNo supersessionNew ADR; mark old Superseded
Agent "Accepted" an ADR in a PRDelegated decisionReject; human status only
Specs contradict ADRDriftReconcile in one PR — Keeping Specs Alive

A field manual for AI-native software engineering.