Architecture decision records for AI coding agents

· by

Architecture decision records for AI coding agents work best when they are short and tied to files. An ADR is a small document that records one decision, why it was made, and what it costs. The usual place for them, a docs/adr/ folder, is written for people. An agent that never opens the right record at the right moment does not follow it. An agent needs the rule, the reason, the files it governs, and a message when it changes.

What an ADR is

Michael Nygard proposed the format in 2011: one short file per architecturally significant decision, kept with the code. The sections are:

  • Title: a short noun phrase, such as “Use signed cookies for sessions”.
  • Status: proposed, accepted, or superseded by a later record.
  • Context: the forces at play, including the constraints and the alternatives.
  • Decision: what you chose, in full sentences.
  • Consequences: what becomes easier and harder as a result.

Two habits make the format work. Records are numbered and never rewritten. If you change your mind, you write a new record and mark the old one superseded. The history of why the system looks the way it does stays readable.

Why ADRs in docs/adr/ do not reach agents

The format is good. The delivery is the problem. A folder of ADRs is a library, and a library only helps if someone walks in and pulls the right book.

  • Nothing loads them. An agent starts from its instruction file, such as CLAUDE.md or AGENTS.md, and from the files it opens. It will not scan thirty records to find the one about cookies unless told to.
  • They are long by design. Context and consequences are what make an ADR useful to a new teammate. To an agent about to edit one file, they are mostly noise around a single sentence.
  • They are not tied to files. A record says “sessions use cookies”. It does not say which paths that governs, so there is no trigger at the moment an agent edits src/auth/.
  • Superseding is silent. Marking a record superseded updates a document. It tells no agent that is halfway through a task built on the old one.

None of this is a flaw in ADRs. They were written to be read by a person who is deciding whether to change something. An agent does not read like that.

What an agent needs from a decision

Four things, in about two lines:

  1. The rule, stated so it can be followed: “Sessions use a signed cookie, not JWT.”
  2. The why, so it can handle a case the rule does not name.
  3. Which files it governs, so it can be shown at the moment of an edit.
  4. To be told when it changes, including while it is mid-task.

The first two are what CLAUDE.md or AGENTS.md already carry. The last two are where a static file stops. See CLAUDE.md vs AGENTS.md for how those files load and why a change on main can miss an agent in another worktree.

The same decision as a ledger entry

trailstone keeps decisions in .trailstone/decisions.yml, a YAML file in your repo. This is the pair from the home page, with the timestamp field trailstone also writes:

- id: d_6d0bf686
  at: 2026-09-01T09:14:00.000Z
  by: Dana
  decision: Sessions use JWT headers, not cookies
  why: a CLI calls the API too
  scope: [src/auth/]

- id: d_259ab7a1
  at: 2026-09-12T15:40:00.000Z
  by: Dana
  decision: Sessions use a signed cookie, not JWT
  why: XSS token theft; the CLI gets a PAT
  scope: [src/auth/]
  supersedes: d_6d0bf686

The fields are id, at, by, decision, why, scope and supersedes. An entry can also carry a status of proposed or rejected. The two timestamps above are illustrative. You record the entries with:

trailstone decide "Sessions use JWT headers, not cookies" \
    --why "a CLI calls the API too" --scope src/auth/

trailstone reverse d_6d0bf686 "Sessions use a signed cookie, not JWT"

How the ADR statuses map

  • Proposed maps to status: proposed, an entry that is not binding until someone confirms it. trailstone ratify confirms it and trailstone reject refuses it.
  • Accepted is an entry with no status. There is no separate “accepted” value.
  • Superseded is a reversal: a new entry with supersedes: pointing at the old one. Nobody edits the old entry, which is the same rule Nygard’s format uses.

What a reversal adds is action. The files in the old decision’s scope are flagged as built on a decision that has since been replaced. A running agent is told at its next edit of one of them, and the push of a file last committed before the reversal is blocked until someone re-checks it. Staleness is worked out from git history and scope each time, never stored.

Where a CLAUDE.md is enough

If a rule never changes, write it in CLAUDE.md or AGENTS.md and stop. In our own runs, with up to 100 rules, a plain CLAUDE.md delivered them about as well as trailstone and costs less. Those were small samples that we ran ourselves.

The case a file cannot reach is a decision reversed while agents are running. With agents in separate git worktrees, trailstone reached 15 of 15 running agents. In separate clones, a teammate’s pushed CLAUDE.md edit reached 0 of 3 clones that had not pulled, and trailstone reached 3 of 3. We also found that an interactive Claude Code session noticed a CLAUDE.md edit in its own checkout, 4 of 4 times. The gap is checkouts that never see the change.

Keep your ADRs

trailstone does not replace long-form ADR prose. A ledger entry has a why, and that is a sentence, not the context, alternatives and consequences that a good ADR holds. Blocking works only on an exact match of a path, directory or glob, and a flag means “built on”, not “broken”. It flags and blocks. It does not fix code, and it does not follow renames.

The split we suggest if you already have ADRs:

  • Keep the ADRs. They are the long record for people who need the whole argument.
  • Put the enforceable line in the ledger: the rule, one sentence of why, and the paths.
  • Link from the why to the ADR file if you want the agent’s reader to find the full text.
  • When you supersede an ADR, run trailstone reverse in the same commit.

There is no server, no account and no telemetry. Try it on a throwaway repo with npx trailstone demo, which needs Node.js 20.17 or later, and see the README for what installing changes.