Your AGENTS.md Is Not a Fence
The most common thing I watch people do when an agent does something they didn't want is add a sentence to CLAUDE.md. The agent imported a module it shouldn't have, so they write "never import adapters from the domain layer." The agent skipped the tests, so they write "always run the tests before claiming done."
It feels like fixing the problem. It mostly isn't, and it's wrong in two directions at once — which is the whole point of this piece, the third in a series on building repos agents can maintain. The prose won't bind the agent the way you think it will, and the act of adding more prose makes the agent worse at everything else. Both of those are counter-intuitive, so let me take them one at a time.
Instructions Are Context, Not Enforcement
Here's the uncomfortable fact, and it comes straight from the people who build these tools: an instruction file is context. Anthropic's own documentation is careful to frame CLAUDE.md as memory that gets loaded into the model's context — not as a rule the runtime enforces. Same for AGENTS.md, same for Cursor rules. They are text the model reads and is influenced by. They are not fences. There is no part of the system that physically stops the agent from doing the thing the file told it not to do.
That distinction is easy to nod along to and hard to internalize, because the file looks authoritative. It's written in the imperative. It says "must" and "never." But "never import adapters from the domain layer," sitting in a markdown file, has exactly the enforcement power of a sticky note on a server rack that says "do not reboot." It works right up until someone — or some agent, mid-task, under context pressure, three tool calls deep into a refactor — has a reason to do it anyway. The model is a probabilistic system honoring a soft preference among many soft preferences. The more it's juggling, the more reliably the soft ones get dropped.
A README that says "core must not import adapters" while nothing in CI fails when core imports adapters is not a rule. It's a wish with good grammar. And the agent will eventually grant you the consequence of treating a wish like a rule: it'll do the forbidden thing, the prose won't stop it, and you'll find out in review — or worse, you won't.
The fix is to make the load-bearing rules executable. Anything that genuinely must hold needs a check that fails when it's violated, not a sentence that asks for compliance:
- A boundary rule — "domain stays pure, no framework or IO imports" — becomes a lint rule (
no-restricted-imports,no-restricted-globals) or an architecture test (ArchUnit, dependency-cruiser, a twenty-line script that greps the forbidden patterns and exits non-zero). - "No files over 300 lines" becomes a giant-file check in CI, with an allowlist that requires an owner and an expiry.
- "Don't hand-edit generated code" becomes a generated-clean check: regenerate,
git diff --quiet, fail if it moved. - "Run verification before claiming done" becomes one command the CI runs identically, so "done" is an exit code and not a vibe.
None of these trust the model. That's the entire value. A check is indifferent to how persuasive the prose was or how confident the agent feels. It's a wall, and the agent can run into it as many times as it likes without anything bad reaching main.
I learned this on my own setup, not in theory. I had a line in my global config telling the agent, in plain language, to stop asking me to review its work — I don't review long-form artifacts, that's its own job. It didn't stick. The agent kept ending turns with "want me to walk you through the plan?" because politeness-to-the-user is a strong prior and one sentence in a config file is a weak one. The thing that actually fixed it was a hook — a Stop hook that inspects the turn and blocks it when the review-asking pattern shows up. The prose had been there for weeks doing nothing. The hook worked the first day. Same rule, two completely different amounts of enforcement, and the difference was entirely whether a deterministic piece of code sat between the agent and the outcome.
That's the mental model: prose proposes, hooks dispose. The instruction file can describe intent all day. If the rule matters, something other than the model has to be the thing that makes it true.
More Instructions Make the Agent Worse
Now the second direction, which is the one people miss even after they accept the first.
Suppose you take the enforcement point seriously but keep the prose anyway — "can't hurt to also write it down." It can hurt. The instruction files are loaded into context on every session, and context is not free. It's a fixed budget the model spends attending to everything you've given it. Every sentence you add to an always-on file is a sentence competing for attention with the actual task, and with every other rule in the file.
The failure mode is real and documented by the labs as context pollution: past a certain size, more instructions reduce reliability instead of increasing it. A five-thousand-line root instruction file stuffed with every historical decision, every edge case, every "and also remember that one time" — that file doesn't make the agent more careful. It makes the agent more likely to lose the three rules that actually matter for this change in a sea of rules that don't. Rules also start contradicting each other as they accumulate, and the model has to guess which one wins, which is exactly the kind of guessing you were trying to eliminate.
So the reflex — agent misbehaved, add a rule — is doubly wrong. The new rule won't bind (it's prose), and it dilutes the rules around it (it's more prose). You've spent context to buy enforcement you didn't get.
The resolution is to treat the always-on instruction file like the hot path it is, and to use layers. Different things belong at different distances from the agent's attention:
- Global rules: a short list of universal working habits. Verification discipline, how you like commits. Not repo architecture.
- Repo
AGENTS.md: the architecture map, the commands, the boundaries, the definition of done. A routing map, not a knowledge dump. - Module-local files: the local exceptions, living next to the code they govern, loaded only when the agent is actually in that subtree.
- Skills: the long procedures — the multi-step runbooks — pulled in on demand instead of sitting in context permanently. This is progressive disclosure, and it's the release valve that lets the always-on text stay short.
- The task prompt: the current goal, scope, and acceptance criteria.
The guiding question for the top-level file isn't "what's true about this repo?" It's "what does an agent need in context every single time, for every task?" That set is much smaller than the set of true things. Everything else moves outward — into a scoped file, a skill, or, best of all, into a check that doesn't need to be in context because it runs anyway.
Write Less, Enforce More
Put the two halves together and you get a discipline that runs opposite to most people's instinct.
When an agent does something wrong, the move is almost never "add a paragraph." It's one of two things. Either the rule is load-bearing, in which case you write a check — a hook, a lint rule, an architecture test — and you can then make the prose shorter, because the wall is doing the work the words were failing to do. Or the rule is genuinely just guidance, in which case you put it in the smallest, most scoped place that will see it, and you keep the global file lean.
Both moves point the same way: the markdown gets shorter, the executable surface gets stronger. You stop trying to govern a fast, literal, amnesiac worker with politely-worded suggestions, and you start building the rails it physically can't leave. The prose becomes what it's actually good at — orientation, intent, where to look — and stops pretending to be a fence it was never able to be.
This is also why the verification command from the last piece and the next one matters so much: it's where all of this enforcement gets collected into a single gate the agent has to pass and doesn't get to argue with. The instruction file can be wrong, out of date, or ignored. The gate runs. Your AGENTS.md should tell the agent that the gate exists and how to run it — and then get out of the way, because the gate, not the file, is the thing keeping the repo honest.
Part three of four on agent-maintainable repositories. Previous: contracts, not tribal knowledge. Next: let the agent prove it's done. Related: the model isn't the product, the harness is — the hooks and gates here are exactly the harness, pointed at your own repo.