RAG Over ADRs: Architecture Decision Retrieval for Coding Agents

RAG Over ADRs: Architecture Decision Retrieval for Coding Agents

Coding agents love reinventing patterns seniors already rejected in an ADR three quarters ago. If Architecture Decision Records are not in the retrieval corpus — with status, date, and superseded-by links — agents will cheerfully propose the Kafka fan-out you abandoned for SQS, complete with confidence.

⚡ TL;DR: Index ADRs/RFCs as first-class documents with metadata (status, boundedContext, supersedes). Retrieve them on every design-affecting agent task. Require citations before approving architecture-shaped diffs. Prefer “accepted” ADRs over blog posts. Pair with Bedrock Knowledge Bases chunking and AI Migration Assistants: Strangler Fig Cuts.

ADR shape that retrieves well

# ADR-0142: Payments ledger writes go through DynamoDB transactional outbox

- Status: Accepted
- Date: 2026-03-12
- Bounded context: payments
- Supersedes: ADR-0098
- Deciders: @payments-arch

## Decision
All ledger mutations emit domain events via a DynamoDB transactional outbox.
Direct dual-writes to EventBridge from application code are forbidden.

## Consequences
- Agents must not introduce `eventBridge.putEvents` beside a ledger put
- New consumers read from the outbox stream mapping
{
  "docType": "adr",
  "adrId": "ADR-0142",
  "status": "accepted",
  "boundedContext": "payments",
  "supersedes": ["ADR-0098"],
  "path": "docs/adr/0142-ledger-outbox.md"
}

Chunk ADRs as whole decisions when short; split Context / Decision / Consequences only for long RFCs — see chunking guidance in Bedrock Knowledge Bases.

Force ADR retrieval on design tasks

export async function planWithArchitecture(opts: {
  ticket: string;
  boundedContext: string;
  retrieve: (q: string, filter: object) => Promise<{ path: string; text: string }[]>;
}) {
  const adrs = await opts.retrieve(opts.ticket, {
    andAll: [
      { equals: { key: "docType", value: "adr" } },
      { equals: { key: "status", value: "accepted" } },
      { equals: { key: "boundedContext", value: opts.boundedContext } },
    ],
  });

  // ✅ Accepted ADRs in system context — not optional "if relevant"
  const system = [
    "You are a senior engineer. Architecture changes must cite ADR IDs.",
    "If a proposal conflicts with an Accepted ADR, stop and propose an ADR amendment instead.",
    "ADRS:\n" + adrs.map((a) => `### ${a.path}\n${a.text}`).join("\n\n"),
  ].join("\n");

  return system;
}

❌ Dumping Confluence wiki noise without status filters (drafts and superseded ADRs fight accepted ones).
✅ Filter status=accepted and surface supersedes so the agent does not cite ghosts.

Gate PRs that smell like architecture

const ARCH_SMELLS = [
  /new\s+(kafka|kinesis|eventbridge|graphql|grpc)\s+topic/i,
  /introduce\s+shared\s+database/i,
  /cross-context\s+import/i,
];

export function requiresAdrCitation(prBody: string, diff: string): boolean {
  return ARCH_SMELLS.some((re) => re.test(prBody) || re.test(diff));
}

export function assertAdrCitation(prBody: string) {
  if (!/ADR-\d{3,}/.test(prBody)) {
    throw new Error("architecture_change_missing_adr_citation");
  }
}

Strangler migrations should point at the ADR that authorized the cut — AI Migration Assistants.

Keep the corpus honest

Job Cadence
Ingest new ADRs on merge to docs/adr/ webhook
Tombstone superseded ADRs (status flip) same pipeline
Eval: “should we dual-write ledger events?” must retrieve ADR-0142 weekly

Refresh discipline matches Codebase Embeddings refresh pipelines.

Closing checklist

  • [ ] ADRs carry status, boundedContext, supersedes metadata
  • [ ] Agent design prompts always retrieve accepted ADRs for the context
  • [ ] Superseded/draft ADRs filtered out of default retrieval
  • [ ] PR gate requires ADR-NNN citations on architecture-smelling diffs
  • [ ] Webhook sync on docs/adr/** merges
  • [ ] Offline eval queries assert the correct ADR is in top-k

Related reading

Last updated on September 11, 2026


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply