Route ADRs to coding agents by giving each live decision explicit code scope, resolving the task's intended and changed paths against that scope, and delivering only the matching records with stable IDs and provenance. Run the lookup before implementation and again against the final diff. Keep enforcement separate: routing tells the agent what governs the work, while deterministic checks establish whether the result complies.

What does it mean to route ADRs to coding agents?

Routing an architecture decision record means selecting the decisions that govern a specific coding task and placing them in the agent's working context before the agent makes the affected choice. The input is the work being proposed: paths, components, capabilities and the question being answered. The output is a small, cited decision brief, not a dump of the repository's entire ADR directory.

For a change under apps/desktop/src/storage/, the router should return accepted decisions whose declared scope covers desktop storage. It should not return every decision containing the word database, and it should not omit a governing decision merely because the task description used different vocabulary. Scope provides the authoritative match; topic search helps when the paths are not known yet.

This is a delivery problem. Writing an ADR preserves the decision, but routing makes the relevant ADR participate in planning, implementation and review.

The minimum routing contract

A practical router needs a small amount of structured information on both sides. The decision supplies identity, lifecycle and scope. The task supplies intended or actual code paths and, where useful, a topic. The routing result preserves enough provenance for the agent and reviewer to inspect the source record.

Keep these fields explicit. If status, scope or provenance must be inferred from prose, the router is guessing at project authority.

  • Decision identity: a stable ID, title and canonical repository path.
  • Lifecycle: accepted decisions are live; superseded, deprecated or rejected records do not silently continue to govern.
  • Scope: repository-relative paths, directories or globs declared by the decision owner.
  • Task evidence: intended paths before coding and actual changed paths before review.
  • Routing evidence: the scope entry that matched each path.
  • Operative context: the decision, consequences and relevant constraints rather than an unbounded transcript.

Step 1: make code scope part of the ADR

An ADR cannot be routed reliably from a code path unless it says where it applies. Add a scope section to decisions that repeatedly matter during implementation. Use repository-relative paths so the same record works in local checkouts, remote agents and CI.

Prefer the narrowest scope that expresses the actual boundary. A directory is appropriate when every file beneath it is governed. A glob is useful for a file type spread across several directories. Do not declare the repository root simply to make a decision appear everywhere; that recreates the context-bloat problem routing is meant to solve.

The example below governs desktop workspace persistence and explicitly excludes hosted persistence through its wording and scope. Its status and consequences remain part of the source record, while the Applies To entries make path-based delivery possible.

# ADR-014: Use SQLite for desktop workspace state

## Status

Accepted

## Context

Desktop workspaces must remain usable without a network connection.
They are local to one user and do not require multi-host writes.

## Decision

Use SQLite for persistent desktop workspace state. This decision does
not govern hosted service persistence.

## Consequences

Do not add another database client to the governed desktop paths.
Features requiring concurrent multi-user writes belong in a hosted
service or require a superseding decision.

## Applies To

- apps/desktop/**
- packages/local-store/**

Step 2: collect intended paths before implementation

The best time to route decisions is before the agent writes code. Turn the task into a provisional change surface: files likely to be edited, packages affected and interfaces crossed. This does not need to predict the final diff perfectly. It creates an initial decision boundary for planning.

Ask the agent to inspect the repository and list intended paths before proposing architecture. For an issue-driven workflow, the task author can supply known components. For an existing branch, Git can provide the current changed paths. Normalise paths to repository-relative POSIX form before matching so local operating-system details do not affect the result.

# Existing branch: collect the current change surface.
git diff --name-only origin/main...HEAD > changed-paths.txt

# New task: start with the paths the plan expects to touch.
cat > intended-paths.txt <<'PATHS'
apps/desktop/src/storage/workspace.ts
services/sync/src/push.ts
packages/protocol/src/workspace.ts
PATHS

Step 3: resolve only live decisions whose scope matches

For each path, resolve the live decisions whose declared scope covers it. Matching should be deterministic: a directory covers files beneath it, and a glob follows documented segment rules. An ungoverned path should produce an empty result rather than a fabricated recommendation.

AsDecided exposes this lookup through the decided decisions-for command. The JSON response includes the decision ID, title, status, source path and the exact scope entry that matched. The same path lookup is available to coding agents through the find_decisions MCP tool.

Deduplicate decisions that match several changed files, but retain the list of matched paths. A reviewer needs to know why each record appeared, especially for cross-cutting changes.

decided decisions-for   apps/desktop/src/storage/workspace.ts   decisions/ --json

# Repeat for every intended path, then deduplicate by decision ID.
# An empty decisions array is a valid result; it is not permission to
# invent a decision or claim the area is governed.

Step 4: turn matches into a focused decision brief

Do not paste every matched ADR in full without a budget. Build a brief that preserves authority and gives the agent the operative constraints. Include the stable ID, lifecycle state, why the record matched, its canonical path, the decision itself and any consequences relevant to the task.

The brief should distinguish source text from routing metadata. The decision remains authoritative in its repository file; the brief is a task-scoped projection. If the brief truncates a long record, link or cite the complete source so the agent can retrieve it before making a consequential choice.

## Applicable decisions

### ADR-014 — Use SQLite for desktop workspace state
- Status: Accepted
- Matched scope: apps/desktop/**
- Matched path: apps/desktop/src/storage/workspace.ts
- Source: decisions/decisions/adr-014-sqlite-desktop-state.md
- Governing constraint: keep desktop workspace persistence in SQLite.
- Boundary: hosted service persistence is outside this decision.

### ADR-027 — Synchronisation must be offline-first
- Status: Accepted
- Matched scope: apps/desktop/**
- Matched path: apps/desktop/src/storage/workspace.ts
- Source: decisions/decisions/adr-027-offline-first-sync.md
- Governing constraint: local writes must continue while disconnected.

Step 5: make retrieval part of the agent workflow

Give the coding agent a stable instruction to retrieve applicable decisions before planning, and make the retrieval mechanism available in every supported client. AGENTS.md is useful here because it can define the operating step without duplicating the decisions themselves.

If the agent can call an MCP server, expose path-scoped decision lookup and source retrieval as read-only tools. If it cannot, generate the decision brief before starting the session and attach it to the task. Both approaches should resolve the same repository records and preserve the same citations.

The instruction should also define the failure behaviour. When two live decisions conflict, a record cannot be retrieved, or the task appears to require violating a decision, the agent should stop and surface the conflict. It should not silently choose the instruction that best fits its proposed implementation.

# Agent instructions

Before planning or editing:
1. List the repository-relative paths the task is expected to change.
2. Retrieve the live decisions that govern each path.
3. Read the complete source record for every consequential match.
4. Cite the decision IDs in the implementation plan.

Before completion:
1. Re-run decision routing against the actual changed paths.
2. Report new, removed or unresolved matches.
3. Run the deterministic decision checks required by the repository.

Do not resolve conflicting live decisions yourself. Surface the conflict
with both IDs and ask for a human decision.

Step 6: use topic retrieval when the paths are not known

Some tasks begin before the implementation boundary is clear. A request such as “add enterprise single sign-on” may affect authentication, account provisioning, audit logging and deployment configuration. Use topic retrieval to discover candidate decisions during planning, then confirm applicability through explicit scope as paths become known.

Topic retrieval and path routing solve different problems. Search can find records whose language resembles the task. Path routing identifies records the team declared to govern the code. A mature workflow uses both: retrieve grounding for the problem domain, inspect related records, propose intended paths, then run path-scoped lookup.

  • At session start, inspect corpus health so invalid or ambiguous records are visible.
  • Search by the user's language, domain concepts and rejected alternatives.
  • Retrieve the complete record when an ID appears in a result.
  • Follow explicit relationships to requirements, superseding decisions and related constraints.
  • Confirm the final governing set from declared path scope rather than similarity alone.

Step 7: route the actual diff before review

Agents frequently change files that were not named in the initial plan. A migration appears, a shared package is edited, or a workflow file is added. Re-run routing against the actual diff so these newly crossed boundaries bring their decisions into review.

This second pass should be visible on the pull request. Report each live decision once, list the changed paths that caused the match and link to the source record. AsDecided Herald provides this as an advisory pull-request comment generated from decided decisions-for. It reports facts and does not turn the presence of a decision into a merge verdict.

Compare the final set with the planning brief. A new match may require additional tests or design review. A disappeared match may be harmless because the planned file was not changed, but the difference should be explainable rather than hidden.

git diff --name-only origin/main...HEAD > changed-paths.txt

decided herald decisions/   --paths-file changed-paths.txt   --link-base https://github.com/owner/repo/blob/HEAD   --out governing-decisions.md

Step 8: keep routing and enforcement separate

Routing tells the agent and reviewer which decisions apply. It does not prove that the patch complies. A decision may require judgement, or it may define a machine-checkable constraint. Keep those outcomes explicit.

Validate the decision corpus and its relationships independently of the code. For constraints that can be established mechanically, run deterministic architecture, dependency, pattern, import, schema or compatibility checks. AsDecided gate combines corpus checks into one policy-aware result, while Sentry evaluates explicitly classified code constraints without an LLM judge.

Do not use a model's statement that it followed an ADR as enforcement evidence. The model can explain its interpretation and cite the record; the repository's checks and human review determine whether the implementation is acceptable.

# Validate the decision system itself.
decided gate decisions/

# Include explicitly declared code constraints for the branch diff.
decided gate decisions/ --code --base origin/main

# Or run code enforcement directly.
decided sentry decisions/ --base origin/main

How to handle overlapping or conflicting ADRs

Cross-cutting work should match more than one decision. That is not a routing failure: a synchronisation feature can legitimately be governed by storage, protocol, conflict-resolution and background-job decisions at the same time. Return the complete live set within the response budget and preserve each match reason.

Conflict is different. If two accepted decisions prescribe incompatible outcomes for the same path, do not invent precedence from filename order, search score or whichever record is newer. Use explicit supersession relationships where the team has replaced an older decision. Otherwise mark the task blocked and ask the decision owner to reconcile the records.

  • Exclude records whose lifecycle explicitly makes them non-governing.
  • Do not assume the narrower path automatically overrides a broader decision unless the repository defines that rule.
  • Preserve every matching scope entry so accidental over-broad declarations can be corrected.
  • Treat an invalid or duplicate decision identity as a corpus problem, not a routing tie to break heuristically.
  • Record an approved exception as a visible, scoped and expiring artifact rather than an untracked prompt instruction.

Worked example: add cloud synchronisation

Suppose the task is “Add cloud synchronisation to desktop workspaces.” Planning identifies apps/desktop/**, services/sync/** and packages/protocol/**. Path routing returns five accepted decisions: desktop state remains in SQLite, hosted services use PostgreSQL, synchronisation is offline-first, conflicts require explicit user resolution, and background jobs are idempotent.

The agent receives those five records before designing the change. It can now separate local and hosted persistence correctly, preserve offline writes, avoid silent conflict resolution and design retries that do not duplicate effects. It cites the decision IDs in its plan so a reviewer can see which authority shaped each part of the implementation.

The final diff also touches .github/workflows/sync-integration.yml. Re-routing finds an additional decision governing integration-test credentials. That record was absent from the original brief because the workflow path was not anticipated. The second routing pass catches the crossed boundary before review.

  • Planning evidence: intended paths and the initial five-decision brief.
  • Implementation evidence: decision IDs cited beside the affected design choices.
  • Diff evidence: actual changed paths and the additional workflow decision.
  • Enforcement evidence: database dependency checks, offline integration tests, conflict tests and idempotency tests.
  • Human evidence: review of the user-facing conflict experience and any unresolved trade-offs.

Common routing failures

Most failed implementations are not caused by the absence of ADRs. They are caused by an unreliable connection between the records and the work. Watch for these patterns when introducing routing.

  • Loading every ADR into every session: high token cost, weak attention and no proof of applicability.
  • Using semantic similarity as authority: useful candidates are returned, but declared scope and lifecycle are ignored.
  • Copying ADR summaries into AGENTS.md: the summaries become stale and lose provenance or supersession state.
  • Routing only once: the implementation crosses new paths and their governing decisions never reach review.
  • Dropping empty results: an ungoverned area is mistaken for a successful governed match.
  • Treating retrieval as compliance: the agent cites a record, but no check or reviewer evaluates the resulting code.
  • Silently resolving conflicts: contradictory project authority is hidden inside an agent's implementation choice.

A practical adoption sequence

Do not begin by retrofitting scope onto every historical ADR. Start with the decisions that reviewers repeatedly explain or agents repeatedly violate. Add precise scope, validate it against the repository, and test the path-to-decision lookup on real changes.

Run the router in advisory mode first. Measure whether the returned set is relevant, whether important decisions are missing and whether broad scopes create noise. Tighten the records before using any result as an automated gate. Routing quality comes from maintained decision data, not from making the matching algorithm more mysterious.

  • Choose three to five accepted decisions with clear code boundaries.
  • Add repository-relative Applies To entries and validate literal paths.
  • Generate a brief for one real task before implementation.
  • Re-run the lookup on its final diff and compare the two sets.
  • Add an advisory pull-request summary once the signal is useful.
  • Automate only the consequences already classified as mechanically checkable.
  • Review routing misses and false positives as changes to the decision corpus.

Conclusion

Routing ADRs to coding agents is a concrete repository operation. Decisions declare where they apply. Tasks and diffs provide paths. A deterministic lookup returns the live governing records with provenance. The agent receives a focused brief before implementation, and the repository repeats the lookup before review.

That is enough to turn an ADR collection from a passive archive into working project context. Separate enforcement then gives objective consequences to the subset of decisions that can be checked, while conflicts and judgement stay visible to people.

Record the decision once. Route it wherever its scope is crossed. Check what the repository can prove.

Sources and further reading

  1. AGENTS.md Is Not a Decision System
  2. AsDecided code scope and relationships
  3. AsDecided decisions-for CLI reference
  4. AsDecided MCP server guide
  5. AsDecided decisions on pull requests
  6. AsDecided deterministic code enforcement
  7. Architecture Decision Records

Product claims should be checked against the AsDecided canonical source map.