Kousigan A

Coding agents forget the why: architecture decision records

Write architecture decision records a coding agent can use: the parts to include, where to keep them, how to supersede one, and a prompt to check a plan.

Last verified against official docs on

Write each significant design decision as an architecture decision record (ADR), a short file with the decision, its reasons and the options that lost. Keep them in the repository and point your coding agent’s instructions file at the index, so each new session reads the reasons first. When a decision changes, write a new record that supersedes the old one.

The ADR format below comes from Michael Nygard’s original post and the MADR template, and the agent behaviour from each tool’s official docs. All of it was last verified on 11 October 2026; none of it was tested for this post.

This is part 23 of the series. Part 1 put a short, dated DECISIONS.md among the project docs, and Part 14 moved lasting decisions out of task notes and into that log. This part is about that log and how a coding agent uses it.

A new session sees the code without the reasons

A coding agent starts most sessions with the code and its instructions files. The code shows what was built. The reason it was built that way often lives in a chat that has since been compacted, or in a pull request nobody will reopen.

Michael Nygard described the same problem for people in 2011, in Documenting Architecture Decisions. Without the rationale, a newcomer “has only two choices”. One is to “Blindly accept the decision”, and the other is to “Blindly change it”.

A coding agent without the reasons is in that spot at the start of every session. Nygard’s warning about the second choice fits it well: “changing the decision without understanding its motivation or consequences could mean damaging the project’s overall value without realizing it.”

Microsoft’s Azure Well-Architected guide to ADRs names the cost of skipping the record. “A decision that’s made but never recorded will likely be forgotten, leading to repeated debates or later changes that unknowingly contradict the original intent.” With an agent, that later change can arrive in the next session.

Not every choice needs a record. Nygard keeps ADRs for “architecturally significant” decisions: “those that affect the structure, non-functional characteristics, dependencies, interfaces, or construction techniques.” The Azure guide adds choices that “are difficult to reverse”.

A naming rule belongs in the instructions file. A choice with a trade-off belongs in an ADR.

The parts of an architecture decision record

Nygard’s format has five parts: title, context, decision, status and consequences. MADR, the Markdown Architectural Decision Records template, keeps those ideas and adds named sections for the options you weighed and how the decision gets confirmed. The ADR organisation on GitHub calls the collection of a project’s ADRs its “decision log”.

Part In Nygard’s post (2011) In the MADR template What it gives the agent
Title “short noun phrases” “short title, representative of solved problem and found solution” One line to scan in the index
Status “proposed”, “accepted”, “deprecated” or “superseded” A status field: proposed, rejected, accepted, deprecated, or “superseded by ADR-0123” Which records still apply
Context “the forces at play”, in value-neutral language Context and Problem Statement The situation the decision assumed
Constraints Part of the context Decision Drivers: “a desired software quality, faced concern, constraint or force” What any change must keep true
Rejected options No separate part Considered Options, then Pros and Cons of the Options What was already weighed, and why it lost
Decision Full sentences, “We will …” Decision Outcome: the chosen option “because” a justification The rule to follow
Consequences “positive, negative, and neutral” Consequences, as “Good, because” and “Bad, because” The costs accepted on purpose
Confirmation No separate part Confirmation: how compliance “can/will be confirmed” A check that holds even when the agent misses the record
Open questions No separate part More Information, including “if/when it should be re-visited” Where to stop and ask

Each row comes from Nygard’s post and the MADR template, last verified on 11 October 2026.

Nygard wanted each record to be “one or two pages long”, and each written “as if it is a conversation with a future developer”. These days that future developer may be a coding agent with no memory of last week. He also asked for full sentences, and put it bluntly: “Bullets kill people, even PowerPoint bullets.”

Rejected options, constraints and open questions

Rejected options earn their place when an agent reads the log. An agent that sees a design with an obvious alternative may propose that alternative as new. A record that lists it, with the reason it lost, shows the idea was already weighed. AWS’s ADR process guide asks for a reason even on a rejected ADR, “to prevent future discussions on the same topic”.

Constraints are what any later change must keep true: a format another system reads, a contract a client depends on. Write them as plain, checkable sentences, so the agent can test its plan against them.

Open questions are the parts of a decision nobody has settled yet. Neither Nygard nor MADR gives them a heading of their own, so put them under More Information. The Azure guide makes a related point: “Record the confidence level of the decision.” An open question tells the agent where guessing is not allowed.

An example ADR in the MADR shape

A made-up example, for a shop that stores order amounts. It follows the MADR template with the optional parts kept short:

docs/decisions/0007-store-money-as-integer-minor-units.md
---
status: accepted
date: <YYYY-MM-DD>
decision-makers: <names>
---

# Store money as integer minor units

## Context and Problem Statement

Order totals are calculated in the API, stored in the database and
exported to the finance report. All three must give the same total.

## Decision Drivers

* Totals must match the finance report exactly
* Constraint: the finance export reads amount columns as integers
* Constraint: the public API's `amount` field keeps its type in v2

## Considered Options

* Integer minor units (cents) everywhere
* Floating-point numbers
* A decimal column, sent as a string in the API

## Decision Outcome

Chosen option: "Integer minor units", because it is the only option
that keeps the export and the v2 API unchanged and adds no rounding error.

### Consequences

* Good, because sums are exact and match the export
* Bad, because every display needs a conversion using the
  currency's decimal places

### Confirmation

A test fails if a money column or API field uses a float type.
Reviewers check new money code against this record.

## Pros and Cons of the Options

### Floating-point numbers

* Bad, because binary floats cannot hold 0.1 exactly, so sums drift

### A decimal column, sent as a string in the API

* Good, because it is exact
* Bad, because it changes the type of `amount` in the public API

## More Information

Open questions: currencies with no minor unit, or with three decimal
places. Not decided. Ask before adding one.
Revisit when the API gets a new major version.

An agent asked to “tidy up the money maths” can read that floats were considered and why they lost. It can also see the finance export constraint and the open question about currencies, which is where it should stop.

Keep decisions in the repository, and point the instructions file at them

Decision records belong next to the code they explain. Nygard kept them “in the project repository under doc/arch/adr-NNN.md”, in Markdown, and the MADR docs suggest docs/decisions/NNNN-title-with-dashes.md. A record in the repository travels with every branch and every clone, so each agent session and each teammate can read it.

One file per decision, plus an index

A single DECISIONS.md works while it is short. Once it grows, move to one file per decision. Nygard’s rule for the numbers is that ADRs are “numbered sequentially and monotonically. Numbers will not be reused.” That keeps a reference like “ADR-0007” valid for good.

Many teams also keep an index: one row per record, with its number, title and status. An example index file:

docs/decisions/README.md
# Decision log

| ADR | Title | Status |
| --- | --- | --- |
| 0003 | Use PostgreSQL for orders | Accepted |
| 0005 | Call the payment provider only from `payments/` | Accepted |
| 0006 | Send order events straight to the queue | Superseded by 0009 |
| 0007 | Store money as integer minor units | Accepted |
| 0009 | Write order events to an outbox table first | Accepted |

The index is what the agent reads every time. The full records are what it reads when a change touches one of them.

Task notes from Part 14 feed this log. When a task merges, its Decisions and Rejected approaches sections map onto an ADR’s Decision Outcome and Considered Options. Progress and next steps stay in the task notes.

A few lines in AGENTS.md and the tool files

The instructions file is read at the start of every session, so it is where the agent learns that the log exists. Put the pointer in the shared AGENTS.md and in any tool file your agents read, such as CLAUDE.md, GEMINI.md or .github/copilot-instructions.md. Part 1 has the table of which agent reads which file.

An example section for AGENTS.md:

AGENTS.md
## Decisions

- Accepted decisions are in docs/decisions/. The index is
  docs/decisions/README.md.
- Before changing structure, dependencies, interfaces, data formats
  or anything an ADR names, read the index and the accepted ADRs
  that apply.
- Treat superseded ADRs as history. Follow the ADR that replaced them.
- If a task conflicts with an accepted ADR, stop and tell me. Do not
  change the code or the ADR to make them agree.
- Never edit an accepted ADR. To change a decision, draft a new ADR
  with status "proposed" that supersedes it.

The second line borrows Nygard’s list of what makes a decision significant, so the trigger is concrete. Claude Code’s memory docs ask for instructions “concrete enough to verify”, and “read the ADRs when relevant” gives the agent nothing to check.

Pointing in words and importing behave differently. Claude Code’s import docs say imported files “are expanded and loaded into context at launch”, and that imports “don’t reduce its context cost”. Codex stops adding instruction files once their combined size reaches project_doc_max_bytes, “32 KiB by default” (AGENTS.md docs). So if you import anything, keep it to the index.

A pointer in words has the opposite trade-off. Claude Code’s docs cover a CLAUDE.md that tells Claude in words to read AGENTS.md. In that case, “Claude sees AGENTS.md only if it decides to open the file”.

A decision index named in words can be skipped the same way. That is why the example’s trigger names the kinds of change that need it.

Supersede a decision instead of editing it

A decision that changes gets a new record. Nygard’s rule: “If a decision is reversed, we will keep the old one around, but mark it as superseded.” His reason: “It’s still relevant to know that it was the decision, but is no longer the decision.”

The Azure guide calls the record “an append-only log” and says “Don’t go back and edit accepted records.” AWS’s process guide says that once accepted, an ADR “becomes immutable”.

The old record keeps its text. Its status line changes, the index changes, and the new record says which one it replaces. In the example index, ADR 0006 would carry this front matter:

docs/decisions/0006-send-order-events-straight-to-the-queue.md
---
status: "superseded by ADR-0009"
---

The adr-tools command line does this in one step. adr new -s 9 <title> creates a record “flagged as superceding ADR 9” and “changes the status of ADR 9 to indicate that it is superceded by the new ADR”. The spelling is the README’s.

The status line matters more with an agent reading the log. Claude Code’s memory docs warn: “if two instructions contradict each other, Claude may pick one arbitrarily.” An old record still marked Accepted next to its replacement is two contradicting instructions. An old record edited in place loses the history, and with it the reason the first choice once made sense.

A person changes a status. Nygard’s “proposed” fits anything an agent drafts: the decision is written down, and nobody has agreed to it yet. The example AGENTS.md above asks for exactly that.

Check a planned change against the accepted decisions

The cheapest place to catch a conflict with an ADR is the plan, before any code exists. Part 2 made planning a step of its own. Add one question to that step: which accepted ADRs does this change touch, and does it break any of them?

AWS’s process guide describes the same check in code review: “a code reviewer might find changes that violate one or more ADRs.” The reviewer then asks for a code change and “shares a link to the ADR”. Asking the agent to run that check on its own plan moves it earlier.

A conflict has two honest outcomes. The plan changes to fit the decision, or a person decides the decision is wrong and a new ADR supersedes it. The agent picks neither on its own.

Two prompts for decision records

Neither prompt depends on one tool’s features.

Prompt 1: check a plan against the decision log

An example prompt to use after the agent has a plan and before it edits anything.

Prompt 1: check a plan against the decision log
Task: <describe the task>
Plan: <paste the plan, or "the plan above">

Before changing any code, check the plan against our decisions.

1. Read docs/decisions/README.md. Ignore superseded records.
2. Open each accepted ADR this plan could touch: structure,
   dependencies, interfaces, data formats, or anything an ADR names.
3. For each one, report:
   - the ADR number and title
   - the decision and its constraints, quoted
   - whether the plan follows it, conflicts with it, or reaches
     one of its open questions
   - for a conflict, the plan step and the exact line it breaks
4. List any rejected option from those ADRs that the plan uses.

If anything conflicts or reaches an open question, stop and ask me.
Do not change the plan, the code or any ADR to make them agree.
Read only what this check needs. Do not edit files.
Never print, expose or commit secret values.
Do not commit, push, deploy, run destructive commands or make
external changes unless I explicitly authorise it.
If two reasonable attempts fail, stop and report the failure
rather than repeatedly guessing.

A report with no ADRs listed is worth a second look: either the change is small, or the index is out of date.

Prompt 2: draft an ADR from a finished task

An example prompt for when a task made a decision that should outlive it, such as one in the task notes.

Prompt 2: draft an ADR from a finished task
Task: draft an ADR for this decision: <one line>
Sources: <task notes file, pull request, or "this session">

Write a new file docs/decisions/NNNN-title-with-dashes.md, using
the next unused number. Use these sections: Context and Problem
Statement, Decision Drivers (including constraints), Considered
Options, Decision Outcome, Consequences (good and bad),
Confirmation, Pros and Cons of the Options, More Information
(open questions and when to revisit).

Set status to "proposed". If it replaces an accepted ADR, say
"Supersedes ADR-NNNN" in More Information, but do not edit
the old ADR or the index. I will do that after I accept it.

Use only what the sources say. Mark anything you inferred as
"unverified". Keep it to one or two pages.
Change no file other than the new ADR.
Never print, expose or commit secret values, and never copy
them into the ADR.
Do not commit, push, deploy, run destructive commands or make
external changes unless I explicitly authorise it.
If two reasonable attempts fail, stop and report the failure
rather than repeatedly guessing.

Check the reasons under Considered Options against the sources before you accept the record.

Quick answers

What is an architecture decision record?

An architecture decision record (ADR) is a short file about one significant decision: its context, the decision, its status and its consequences. Michael Nygard proposed the format in 2011. Templates such as MADR (Markdown Architectural Decision Records) add the options considered and how compliance is confirmed.

Do AI coding agents follow architecture decision records?

AI coding agents read architecture decision records (ADRs) as context, so they can still miss or misread one. Claude Code’s docs give no guarantee of strict compliance with instruction files. A test or a human review confirms that an important decision held.

Where should ADRs live in a project?

Architecture decision records (ADRs) live in the repository, usually one Markdown file per decision in a folder such as docs/decisions or doc/arch. A short index lists each record’s number, title and status, and the agent’s instructions file points to that index.

How do you change an accepted ADR?

An accepted architecture decision record (ADR) is changed by writing a new ADR that supersedes it. The old record keeps its text, and its status changes to superseded, with a link to the record that replaced it.

What is the difference between task notes and a decision log?

Task notes hold the state of one coding task: goal, progress, next step and checks. A decision log holds the decisions that outlive the task, with their reasons and rejected options, for every later session and teammate.

More on AI coding is in the AI category.

Cartoon of Kousigan making a heart with his hands

Kousigan A

Build with AI. Ship with care.

Software engineer building real products with AI assistants. I write down what works: prompts, rules, skills and agents, and how to ship safely.