Making Agents Read Only What They Should: Three-Layer Principles for Document Routing in Large Projects

In large projects, getting Agents to reach the right spec from their current task relies on routing, not reference connectivity.
The article extends the L0–L3 layering model and focuses on the question: which documents should an Agent read after receiving a task. The author first distinguishes "buried" from "unreachable" failures—the former fixed by formatting, the latter only by building a path. Routing failure has three forms—no path, path too wide, path broken midway—rooted in docs being organized by author categorization while Agents enter with only the current task. Three principles follow: entry routes only, no content; route by work type, not directory; every hop declares the next hop and its parent. Implementation covers an "operation → required reading" routing table, single entry via AGENTS.md, two-layer inheritance between shared and project layers, a hop-by-hop routing chain, and one-time handoff routing, with three typical breakpoints: routing table bloat, pointing to superseded docs, and project layer not declaring inheritance. The conclusion: reference connectivity isn't a path, and building a path beats bolding.
Making Agents Read Only What They Should: Three-Layer Principles for Document Routing in Large Projects
In large projects, an Agent's failure often isn't that "the documentation is badly written" but that "starting from the task at hand, there's simply no way to reach that document." Even if the reference chain is formally connected, if no signpost along the path bears the name of the current task, then for an Agent that loses memory every session, that document effectively doesn't exist.
This is the second article in the series "Agent-Facing Document Layering for Large Projects." The previous piece introduced the L0–L3 four-layer model: L0 is the entry file automatically loaded each session, L1 is the specification split by work type, L2 is module and change documentation, and L3 is execution evidence. This article answers only one question: for an Agent that has just received a task, which documents should it read?
The problem isn't "no specification" — it's "no path"
When reviewing an enterprise payment approval system, the original author first precisely distinguished two kinds of failure — whose fixes are completely different:
- Buried: The path exists, it's just covered by hundreds of lines of prose. The fix is to shorten, bold, and move it to a prominent place.
- Unreachable: Starting from the task at hand, the entry point has no signpost pointing to it. The only fix is — to build a path.
Their project fell into the second category. Strictly speaking, there actually was a two-hop path in the reference graph: the development process section of the entry pointed to the development process document, that document's related-documents table had a row pointing to the project testing specification, and the definition of "six full sets" was on line 154 of that specification. The path was connected. But for an Agent tasked with "release freeze," no signpost along the way mentioned "full set" or "release freeze." Another path did mention release freeze, but it stopped at the wrong place — it pointed to the requirements of some historical freeze, not the current definition.
For a reader with no cross-session memory, a document that cannot be reached from the current task is the same as nonexistent, no matter how complete it is.

What "Agent-facing documentation" and the "amnesiac reader" mean
Traditional documentation carries an implicit assumption: the reader is a persistent person who remembers the repository structure, which documents they've read, and what "full set" meant in the last project. Large language model-driven Agents lack this cross-session memory — each time a task begins, their context contains only the system prompt, the user's task, and the files they are asked to read. Document design must therefore treat "the reader is a newcomer" as the default premise rather than the exception. This differs fundamentally from "newcomer-friendly documentation": newcomers ask questions proactively, build mental models, and carry what they learn into the next session; Agents do not — they only follow explicitly given paths. The routing concept grows out of this difference — once you treat documents as nodes and references as directed edges, what actually determines whether an Agent can reach a document is not whether the document exists, but whether there's an explicitly marked path from the current task node.
Three forms of routing failure
Zooming out from a single freeze to the entire documentation system, there are three forms of routing failure, all of which appeared in the project:
- No path. The specification exists, but you can't reach it from the entry.
- The path is too wide. The entry file loads the detailed rules for every kind of work, and every session has to swallow it whole, diluting the truly critical line — this is the root of L0 bloat.
- The path breaks midway. The routing table sends the Agent to the project-level specification, but the project level never declares which shared specification it inherits from. The Agent finishes reading the project layer and thinks it has read everything.
All three forms share the same root cause: documentation is organized the way authors categorize things, while the Agent walks in with only one question — what should I do right now. Authors organize by directory, by document type, by time, which is natural for someone familiar with the repository; but the Agent is a newcomer every session, and it only knows that the user asked it to freeze, alter a table, or review a diff. The key of the route must be something the Agent already holds in its hand when it walks in.
Token budget and the quantified cost of "the path is too wide"
An Agent's context window is limited each session, and the L0 entry file is loaded in full, so the tokens it consumes crowd out space for subsequent reasoning. Suppose the entry file has 800 lines and averages 15 tokens per line — that's about 12,000 tokens burned before any work begins; if 80% of that content is irrelevant to the current task, you're spending the vast majority of the attention budget on rules that won't be used. This is why "the path is too wide" is not just a readability issue but an engineering one: it directly reduces the Agent's effective attention on the truly relevant rules. Moving the definition down from the entry into an L1 document and leaving only one routing line in the entry essentially converts a fixed cost into an on-demand cost — only sessions that actually perform "release freeze" pay tokens for the definition of "six full sets."
Three principles
Principle one: The entry file only routes; it doesn't carry content. The entry is loaded in full every session, so every line written into it is paid for by every session. Copy the definition of "six full sets" into the entry, and every session unrelated to freezing has to read it; turn it into a path, and only freeze sessions pay that cost.
Principle two: Route by work type, not by directory. A directory tree answers "where things are," premised on the reader knowing what things are called and which category they belong to — that premise itself is memory. The Agent walks in without that memory, only the task the user handed it. So the first column of the routing table is an action: release freeze, alter table structure, review code — not a directory name.
Principle three: Every hop declares the next hop and its own parent. A human reading "project database specification" naturally thinks "there's probably also a shared one." An Agent doesn't. If a document doesn't say "I am the implementation of that one," the Agent treats it as the entire rule set; if it doesn't say "where to go when you finish," the Agent stops. Routing isn't just the entry's job — every document along the way must answer these two questions.
Mechanism one: the "operation → required reading" routing table
The routing table looks like this (the source is the actual table in the project entry file, excerpted with redactions):
| Operation | Required reading | One-line key point |
|---|---|---|
| Release freeze / build / tag / say "full set green" | handbook/engineering/release-process.md | Only when all six sets pass by the established standard may you say "full set green" |
| DB schema / cross-environment data change | handbook/database/project-database-changes.md | Schema changes must have incremental scripts, and the scripts must have been run on the production executor |
| Writing / modifying / reviewing any test | testing/guides/project-testing.md | First select a layer from the "work type → test level" table; don't upgrade UI contracts to end-to-end |
| Verifying frontend behavior in a browser | Entry file section "Don't guess selectors" | Browser automation is for localization, not acceptance evidence |
| Code review / re-review | The change's handoff.md + test-cases.md | Conclusions must carry "path:line" evidence |
Which operations deserve a row: high risk, low frequency, easy to get wrong from memory. High risk means the cost of an error is expensive or irreversible; low frequency means things done once or twice a month, where the relevant specification won't happen to be in recent context; easy to get wrong from memory means the Agent's common sense will give a plausible but incorrect answer — "full set" is a textbook case: common sense says full set means "run all tests," but in this project it's a fixed six sets. Ordinary coding shouldn't get a row — that belongs in the development specification, and a single link in the entry suffices.
The value of the "one-line key point" column is that even if that hop isn't taken, the most important constraint has already been delivered. The routing table is at L0 and is read every session; the target document is at L1, still one hop away. The Agent may skip that hop due to context pressure or a judgment that "this change is small." The key-point column is the floor: even if the hop isn't taken, "schema changes must have incremental scripts" is already laid out before it. There's also a side effect — if a specification's key point can't be written in one line, it often means the specification itself has no core rule, and the target document should be cleaned up first.
"One-line key point" as degraded fault tolerance
The routing table's design implicitly encodes an engineering fact: routing won't succeed 100% of the time. The Agent may skip a hop due to context pressure, or subjectively judge that "this change is small, no need to read the spec." The value of the "one-line key point" column is that it provides a degraded path — even if a hop is skipped, the most critical constraint has already been loaded alongside L0. To achieve this, the key point must satisfy three conditions: decidable (one can clearly judge whether the current operation complies), non-derivable (it cannot be directly obtained from common sense, or it carries no information), single sentence (longer than one sentence and it degenerates into body text within the entry file). Conversely, if a specification can't produce such a line, it usually means it lacks a compressible core rule, and you should go back and clean up the target document rather than fabricate a key point for it.
Mechanisms two through five: a complete routing chain
Single entry, everything else forwards. The project entry was once called CLAUDE.md (the filename Claude Code expects), but as Codex and Kimi also joined the collaboration, an entry named after one tool's convention might not be loaded when the tool switches. After cleanup, all rules were centralized in AGENTS.md, and CLAUDE.md shrank to a 5-line forwarder — a forwarder must not contain a single rule; once one exists, the two entries will each grow, and different Agents will see different project rules.
Personal memory is the other half of a single entry. To decide where a piece of experience belongs, ask one question: if I switch Agents or machines, should this still take effect? If yes, it goes into the repository; only collaboration preferences (like replying in Chinese, or showing a human the diff before committing) stay in personal memory.
Shared layer → project layer, a two-layer inheritance. The shared layer writes rules that hold across projects and leaves placeholders; the project layer writes only four things: filled-in placeholders, the project's current state, exceptions to shared rules, and pitfalls the project has hit. The two layers are connected by an inheritance declaration, and the declaration must be placed at the top of the project layer — because the routing table points to the project layer, the Agent lands on the project layer, and if the project layer doesn't state its parent, the shared layer is unreachable from it, which is exactly the problem from the beginning replaying inside L1. The inheritance declaration must also clearly state "who wins on conflict," otherwise an Agent that executes literally will just pick a sentence at random to believe.
Hop-by-hop routing chain: entry → document home page (divided by responsibility) → top-level directory README (secondary routing + placement rules) → the AI Quick Path at the top of the document → body text. Each layer carries only the next hop, so each step costs only a few tokens; adding a new document only requires changing the README of the directory it lives in, and neither the entry file nor the routing table changes.
The handoff document is a one-time route. The routing table serves every session; the handoff document serves only once — a change passed from the current Agent to the next. It points in two directions at once: inward, explaining what to read first and in what order; outward, specifying "what evidence must accompany each handoff." Once the change is complete, it degrades to L2 history and no longer carries routing responsibility.
AGENTS.md as a cross-tool convention entry
Files like CLAUDE.md, .cursorrules, and GEMINI.md are entry conventions defined by various Agent tools. When a project is collaborated on by multiple tools at once, naming the entry after one tool causes other tools to "not see" the rules — not because the rules don't exist, but because that tool simply doesn't load that filename. The point of AGENTS.md is to consolidate this tool-layer difference onto a neutral filename, making the entry a single convention rather than a binding. CLAUDE.md is retained as a forwarder (usually just a few lines, content like "rules see AGENTS.md") because some tools still preferentially read the conventional filename; if the forwarder mixes in actual rules, it creates "dual entries" that each evolve and are seen by different Agents, ultimately leading to inconsistent behavior across tools. The discipline of not having a single rule in the forwarder is precisely to maintain a single source of truth.
Routing most easily breaks at three points
Breakpoint one: the routing table itself grows into an entry file. When rules were first written, 3 of 7 rows pointed back to the entry file itself; later, 5 of 12 rows pointed back to itself. The fix: if a row's target is "a section of the entry file," first ask whether it's in the L0 hard-rules list; if not, move that section down into an L1 document; the key-point column is allowed only one sentence; before adding a row, pass the three criteria first.
Breakpoint two: pointing to a document that has been superseded. A broken link at least exposes itself; the real danger is a link that's alive but whose target is no longer current fact. There are two forms of "superseded": formally replaced by a new version, and something that was always just a historical instance but is treated as the current definition. The original author's release-freeze path fell into the second — the specification's last hop landed on a historical delivery document, effectively writing "do it like last time" into the rules, causing handoff documents to drift generation after generation and several consecutive versions to lack the SHA-256 verification explicitly required by the specification. The fix: routes point only to "current definition" documents, or are written as pointers that change with the task (such as "the corresponding change's handoff"), not hard-coded to a specific instance.
Breakpoint three: the project layer doesn't declare what it inherits. This is the most complete counterexample in the project: before cleanup, the project testing specification and the project database specification each referenced the shared specification zero times, while the shared layer had long ago written an AI Quick Path at the top — the parent pointed to the child, but the path only went downward. The fix: the inheritance declaration at the top of the project layer is required, and it's also the easiest to check by machine — a single grep finds it. During cleanup, both project-layer specifications were given inheritance declarations, the shared database specification went from draft to final, and a missing inheritance declaration became a doc-lint error.
Closing thoughts
This experience lands not on "how to make the Agent remember the specification" but on: how to guarantee that every specification worth reading has a path from the entry, and that the Agent walks only the path it should. Whether it can be reached from the task at hand determines whether a document exists for the Agent; reference connectivity does not equal a path, and building a path beats bolding.
Related articles

Huberman's Rational Supplement Guide: A Five-Layer Health Framework and Scientific Decision-Making
Stanford neurobiology professor Huberman proposes a rational supplement framework: behavior and nutrition are the foundation, basic combination supplements serve as insurance, and sleep/hormonal/cognitive directions should stick to single-ingredient experiments. Omega-3 is the top single-ingredient choice, and melatonin is not recommended.

The Unsung Painter Behind Gilded Age Manhattan Interior Design
HN discussion highlights the painter behind Gilded Age Manhattan interiors: he created murals and decorative paintings but was long overlooked as his work was seen as architectural appendage.

Can AI Agents Be Socially Engineered? Understanding Prompt Injection and Tool Permission Risks
Through Invariant Lab's GitHub Issue injection and Brave's AI browser attack, this article analyzes how Prompt Injection induces AI Agents to perform unauthorized actions, and offers protection advice across three layers: least privilege, tool validation, and operation auditing.