BACK TO ARTICLES

How to Make Coding Agents Remember Architectural Decisions

Your repository records what the team decided, not why, so a coding agent keeps proposing the approach you rejected last spring. Here is where decision rationale lives and how to make it reachable.

Dosu
/
Sep 23, 2026/12 min read

Your team pulled out a Redis response cache six months ago. Invalidation lagged behind permission changes, and for a few minutes after every deploy some users could see records they no longer had access to. The fix was to go back to direct reads and eat the latency.

This morning a coding agent looked at those repeated reads, correctly identified them as the hot path, and proposed adding a cache. It is a reasonable suggestion from the evidence in front of it. The repository contains the direct reads. It does not contain the incident.

Code records what a team decided. The reasoning that produced the decision, the alternatives weighed, and the thing that went wrong the last time someone tried the obvious approach usually live somewhere else, and an agent that cannot reach them treats a rejected option as an unexplored one.

What your repository tells an agent

Fewer sources carry rationale than most teams assume.

The current implementation tells the agent what survived. It says nothing about what was tried. A file tree shows how the code is organized today, with no trace of the structure that was abandoned two refactors ago.

Git history looks more promising than it is. A diff records changed lines, and a commit message records whatever the author had energy to write at the time. revert caching layer is accurate and nearly useless. It leaves open whether the team rejected caching as a strategy or backed out one broken implementation, and those two facts point an agent in opposite directions. The explanation is usually a paragraph in the pull request, written by whoever found the invalidation bug.

Instruction files hold only what somebody deliberately put there. AGENTS.md and CLAUDE.md are good places to state a convention the team wants followed. They are a poor archive, because every historical exception copied into them competes for the same context budget as the task, and because nobody adds an entry for a decision they have stopped thinking about.

So the agent proposes the cache. Its reasoning is sound and its conclusion is wrong, and the only thing that would have changed the outcome is a record it never saw.

Capture, retrieval, reachability, and staleness are four different problems

Teams tend to treat this as one documentation problem and then stall, because the fixes do not overlap.

Capture asks whether anyone wrote the reasoning down at all. Retrieval asks whether a search can find the right record among the ADRs, pull requests, and design docs that exist. Reachability asks whether that record lands in the agent's context during the task that needs it. Staleness asks whether a newer decision has replaced it.

A team can solve capture completely and still fail, because a perfect decision record nobody retrieves changes nothing. Keep the four separate as you read the rest of this, because the sections below fix different ones.

Architecture decision records are the floor

An ADR is a short document for one decision. The convention Michael Nygard introduced gives each decision a numbered Markdown file with a status and three sections: the context and constraints in play, the decision itself, and the consequences the team accepted. The adr-tools implementation is the reference for how this works in practice.

For the failure this article is about, MADR is the better template, because it makes the rejected options a first-class part of the record rather than something you hope made it into a context paragraph. Its template defines a Considered Options section and a Pros and Cons of the Options section alongside decision drivers, the outcome, and consequences. An ADR that says "we considered Redis and rejected it because invalidation lag exposed stale authorization data after deploys" is exactly the artifact that stops the suggestion from coming back.

Keep the files in the repository, conventionally under doc/adr, so they move with the code and go through the same review.

ADRs only ever capture decisions somebody remembered to write up, and ADR practices lapse. The usual reasons are structural rather than cultural: no agreed trigger for when a record is required, no owner, or a directory that fills with trivia while the consequential arguments stay in Slack. A policy that survives names both a trigger and an owner. Require a record when a change crosses a durable system boundary, reverses an earlier decision, or rejects an option a reasonable engineer will suggest again. The person proposing the change writes it, and the reviewers who approve the code approve the rationale.

A new ADR practice still leaves every decision your team made before this week.

The rationale you wrote down and never indexed

Pull request reviews and issue threads are the highest-yield source available to most teams, because the reasoning was written down while the work happened. Somebody explained why the migration had to stay reversible while they were reviewing the migration. Nobody has to reconstruct anything. The work is indexing, not authoring.

Compare the effort. An ADR practice asks every engineer to recognize a decision as a decision and then write a document after the discussion ends, which is a durable behavior change. Mining existing threads asks nothing of anyone and works on text the team wrote during the work.

Be selective about what you extract. The comments worth keeping are the ones that changed an outcome: the reviewer objection that killed a pull request, the issue comment that ruled out a library, the note attached to a revert explaining what broke. Keep enough surrounding context to identify the component and the final resolution. A stranded "we tried this before" helps nobody.

Start with the two or three arguments your team keeps having. Ask a couple of senior engineers which ones those are, find the original threads, and write each one up as a record that links back to the source so a reviewer can check the summary against what was said.

Pointing at a directory is not the same as reaching it

A line in CLAUDE.md reading "see doc/adr" delegates to the agent the job of guessing which of forty files matters. Naming the trigger works better: "before changing cache invalidation, check for active ADRs about caching and follow their linked pull request discussions."

But there is a limit you should understand before you design around instruction files. Claude Code supports importing other files into CLAUDE.md with @path syntax, and those imports resolve recursively up to four hops. The catch is in Anthropic's own documentation: imported files "still load and enter the context window at launch." An import is not lazy loading. Importing every ADR file means paying for every ADR in every session, including the thirty-nine irrelevant ones. The same page recommends keeping a CLAUDE.md under 200 lines, noting that longer files both consume more context and reduce how reliably the instructions get followed.

The launch-time cost rules out the obvious approach. You cannot solve reachability by importing the archive, and the archive only grows.

Two mechanisms load conditionally instead. Claude Code loads CLAUDE.md files from subdirectories on demand when it reads files in those directories, and path-scoped rules under .claude/rules/ load only when the agent works on matching files. A caching decision attached to the directory that holds the caching code reaches the agent exactly when it is relevant and costs nothing the rest of the time. Where your decisions map cleanly onto directories, this is the cheapest reachability fix available.

Where they do not, you need retrieval: search over your ADRs, design docs, and selected discussions, exposed to the agent during the session, often through an MCP server. Treat this as an engineering choice you have to test rather than a solved feature. Similarity search will happily return a discussion that uses the same words as the query but describes an approach the team abandoned, and rank it above the decision that replaced it, a blind spot covered in agent memory vs. RAG vs. the context window. Store status, affected component, date, and the link to any replacement record alongside the text, and make the search use them.

Test it with real cases. Take a decision your team relitigates, give the agent a task that touches the affected code, and inspect what it received before it proposed anything. No other measurement tells you whether any of this is working.

A superseded decision is more dangerous than a missing one

When retrieval surfaces a three-year-old ADR still marked Accepted, the agent does not merely lack context. It now has documented rationale for the wrong answer and will argue for it. A missing record at least leaves the agent uncertain enough to look at the current code.

So when a decision is reversed, do not rewrite the old record. Write a new ADR for the replacement, change the old one's status to superseded, and link the two. adr-tools does this directly: adr new -s 9 creates a record flagged as superseding ADR 9 and updates ADR 9's status to point at its replacement. Rewriting the original would destroy the dated account of what governed the codebase at the time, and would quietly invalidate every pull request that cited it.

Your retrieval layer has to respect that status, or the convention buys you nothing. Current records should rank first, superseded ones should surface only when the history explains a rejected alternative or an old piece of code, and a conflict between two records with no clear status is something the agent should flag rather than silently resolve by relevance score.

How to evaluate a tool for this job

Agent memory products are frequently suggested for this problem. Mem0, Zep, Cognee, Falconer, and Unblocked all sit somewhere near it, and so does Dosu.

This article does not rank them. What these products do changes quickly, and the useful question is not which is best in general but which one passes the test below against your repository. Read each vendor's current documentation, then test rather than trust the summary.

The test is the same regardless of the product. Does it ingest the places your rationale lives, which for most teams means pull requests and issues rather than a wiki? Does it preserve decision status and supersession, so a replaced decision cannot be returned as current? Does it deliver the controlling record into the agent's context during the task, rather than into a search box a human has to remember to open? Run it against a rejected library, a reverted migration, and a superseded ADR before you connect it to anything.

A sequence you can run this quarter

  1. Set the convention. Add doc/adr to your active repositories, pick the Nygard format or MADR, and write the trigger and owner down. Point AGENTS.md or CLAUDE.md at it with a specific instruction, not a bare directory reference.
  2. Recover the arguments you keep having. Get two or three from your senior engineers, find the original pull request or issue threads, and write each up as a record that links to its source. Mark these as reconstructed. Do not present them as contemporaneous.
  3. Fix reachability for one case. Take the decision from step two that maps most cleanly onto a directory, attach it there, and confirm the agent picks it up. Then decide whether the rest needs retrieval.
  4. Put supersession on a schedule. Review status quarterly and whenever a migration lands. Replace, link, and never rewrite.

The order matters. Decision recall is a retrieval and discipline problem before it is a tooling problem, and a team that adds a memory product before step one has bought a search index over an empty shelf.

FAQ

How is an ADR different from a design doc?

A design doc describes a proposed system, often in detail, and usually drifts from what got built. An ADR records one decision, its constraints, and its consequences, and then stops changing. The immutability is the point, because it is what lets a record from 2024 still be evidence about 2024.

Can CLAUDE.md or AGENTS.md just reference my ADR directory?

You can reference it, and Claude Code can import files with @path syntax, but imports load at launch rather than on demand, so importing every ADR costs context in every session. Subdirectory instruction files and path-scoped rules under .claude/rules/ load conditionally, which is usually what you want.

How often should we write an ADR?

Write one when a decision constrains future work or rejects an option somebody will propose again. Database strategy, service boundaries, and caching policy usually qualify. A local refactor does not. If your directory is filling with entries nobody would ever relitigate, the trigger is too loose.

What about decisions with no written trace at all?

Interview the people who were there, while they are still there, and write down the constraints and the rejected alternatives as they remember them. Mark the record as reconstructed and note where you are uncertain, so nobody later mistakes a recollection for a contemporaneous record.

Find out what your agent is working from

Before changing any tooling, run the test. Pick a decision your team has relitigated at least twice. Open a session in that repository, ask the agent to change the affected code, and read what it proposes. If it suggests the thing your team rejected, you have located a gap, and you now know which of the four problems caused it: nobody wrote it down, nothing indexed it, it never reached the session, or a stale record outranked the current one.

Often the rationale existed the whole time, sitting in a pull request thread nobody indexed. Dosu is built to close that gap. It captures from the work itself, including coding sessions and pull requests alongside connected Sources like GitHub, Slack, and Notion, keeps the files your agents load current as the code moves, and serves the rest over MCP and the Dosu CLI. Monitors flag Documents that have stopped matching their Sources, which is the staleness problem that makes a superseded decision dangerous.

Connect a repository to Dosu and let the next session start from the argument your team settled last time.

Ready to transform your workflow?

Join leading organizations using Dosu to automate documentation, streamline support, and empower development teams to focus on building great products.