# Loaded Obeyed: Why Your Agent Quotes Rules It Doesn't Follow

> Source: <https://dev.to/buildloops/loaded-obeyed-why-your-agent-quotes-rules-it-doesnt-follow-2256>
> Published: 2026-08-09 13:00:00+00:00

*The file was loaded. The rules just weren't followed. Here's the two-failure diagnostic that tells you which one you have — and what to do for each.*

My agent used to follow my rules. The output-format rules, written once into a `CLAUDE.md`

, were obeyed like law — for months, in Claude Code.

Then I migrated to OpenCode, and the rules quietly stopped meaning anything. The agent quoted them back flawlessly. It recited them every time I asked. And it ignored them, day after day, rule after rule. The file was loaded. The rules just weren't obeyed.

The fix wasn't stronger wording, and it wasn't a better prompt. It was re-declaring every rule, one by one, into a fresh `AGENTS.md`

— and it held.

That's the lesson this post is built on: a rule that isn't followed is one of two failures. Either it never loaded, or it loaded and lost. Here's how to tell which, and what to do for each.

I didn't run that test once. I ran it in fresh sessions, multiple times, for days. Every time, the same answer: a perfect recital. Every time, the same next output: the format rules broken.

In the middle of it, the token usage climbed — noticeably higher than expected. Not because the work was harder. Because the rules were being re-derived and re-explained instead of followed, every session, on top of a `MEMORY.md`

that was already bloated. Token waste and trust damage from the same root cause.

This is the exact state readers end up in with their own agents, and the reason most of them are on GitHub filing issues that never get answered.

So let's name what that means.

Here's the model that ended my guesswork. A rule that isn't followed is one of two failures:

| Lane A — never loaded | Lane B — loaded and lost | |
|---|---|---|
What it is |
A file/loading problem: wrong file, nested or path-scoped rule, compacted away, not read at all | A model-behavior problem: the rule reached the context window and still didn't steer |
The truth about it |
The harness never applied weight to this rule | Rules are context, not enforced configuration |
The fix |
Re-declare it into the file the harness actually reads, then verify | Redesign the rule's shape, or move it to a mechanism that can't lose |
Cost of guessing wrong |
You reword a rule that never mattered | You reword a rule forever, because wording was never the lever |

The whole point of the model is that these are two different problems with two different fixes. Most advice treats them as one problem — "write better rules" — which is why so much of that advice doesn't change anything.

My migration had both lanes in play. But the one that broke me was neither, exactly. It was the state in between.

Here's what my migration actually looked like. OpenCode reads `AGENTS.md`

as its first-class rules file, and it falls back to `CLAUDE.md`

if there's no `AGENTS.md`

— which is why the agent could quote my old rules at all. The fallback file was present enough to recite.

Present enough to quote. Not enough to act on.

The telling detail was what the agent *couldn't* do. It could recite the general rules. It couldn't tie them to a file or a plan — it couldn't tell me where they lived or what it would do to follow them. That's the gray zone's fingerprint: quoting without any load-bearing behind it.

I call that state **loaded but not load-bearing** — and it quietly breaks the most common piece of advice in this space: *"ask your agent what your rules are."* I asked, every single day. The answer was always a perfect recital. The recital proved a file existed. It proved nothing about whether the rule carried any weight.

That's the trap the two-lane model has to catch before it can help you: the gray zone — a rule that is loaded, quotable, and useless.

The reason "what are my rules?" failed me is that it's the bottom rung of a three-rung ladder:

The one line you can run today:

"Quote the exact rule, show me where it lives, and tell me what you'll do with it."

And what a passing answer looks like — this is the test I ran after the re-declaration:

"The output-format rule is the first block under

Output formatin`AGENTS.md`

. It requires a per-file summary (path, what changed, why) and a fenced, language-tagged code block for every diff. I'll apply it: every change in this session gets that summary and a tagged diff block."

That's quoted + located + plan statement — level 2 proven. Then you watch the next output for level 3.

The asymmetry matters here: Claude Code can show you loading proof directly — `/context`

lists what actually loaded. OpenCode doesn't have an equivalent shipped (there's an open issue asking for loading verification). Which means on OpenCode, this test isn't optional. It's the whole test.

This is the part that ended the blame-game for me, because the mechanism is documented.

Anthropic's own memory docs describe `CLAUDE.md`

as providing "context, not enforced configuration." And they're explicit about what that means: there's "no guarantee of strict compliance" — the wording is right there in the docs for anyone to read.

Your agent ignoring a rule you wrote is not a personal prompt failure. It's the documented behavior of a system where instructions are context rather than commands. That reframes the whole problem: the question isn't "why is my agent broken," it's "which lane is this rule in, and what does the fix look like when instructions aren't commands?"

And it's not just me saying it. The issue trackers are full of this exact failure — users reporting "my agent quoted my rules back and ignored them," and the admissions go further. In one thread, a user counted 14+ corrections on a single rule before anything stuck. The demand set is real, current, and cross-harness: it's the "I Told You" Developer's situation, at scale.

What finally fixed my migration wasn't a better prompt or stronger wording. It was re-declaring every rule, one by one, into a fresh `AGENTS.md`

— the file OpenCode actually applies weight to.

Copying files across hadn't worked. The old `CLAUDE.md`

came along, was read as a fallback, and was quotable without being load-bearing. The re-declaration was different because it moved the rules into the first-class file — and then I verified each one at level 2, and watched the output for level 3.

Here's the shape the rule needed to take. This is a faithful reconstruction of the kind of rule that lived in the fallback `CLAUDE.md`

— a paragraph buried in a file that held rules, context, and everything else:

Always present your output in a clear and professional format. Use code blocks where appropriate and make sure diffs are easy to read. Pay attention to formatting quality in all responses.

Vague, not checkable, one paragraph competing with every other paragraph in the file.

And this is how the same rule reads re-declared in the fresh `AGENTS.md`

:

Output format (required, no exceptions):

- Every change is summarized as: file path, what changed, why.
- Every diff is a fenced code block tagged with the language.
- Never inline a diff without a code block.
- When in doubt about the format, ask before outputting — do not improvise.

Every line is checkable — the summary either has the three parts or it doesn't; the diff either is fenced or isn't. Self-verifying by observation.

It was a one-time fix. The rules went into a fresh `AGENTS.md`

once, and the loaded-but-not-load-bearing state never came back. Since that day I've been fully settled on OpenCode — the fixes since have been minor.

Here's the part I had to learn the hard way: **re-declaration fixes loading, not obedience.** If a rule is in Lane A, re-declaring it into the right file is the fix. If a rule is already in Lane B — loaded into the right file and still ignored — re-declaring it does nothing. Which brings us to the second fix.

Once you've confirmed a rule is genuinely loaded and still losing, the choice comes down to a single question:

**Can I afford for this rule to lose?**

If the answer is yes — and the output-format rule from the previous section is exactly this kind — keep it in prose, but make sure it's shaped well: short, specific, prohibition-framed, impossible to misread. You can see the output either follows it or doesn't, so it's the right fit for the load-bearing file.

If the answer is no, prose is the wrong home for it. The rule can't afford a single loss, so it moves to the mechanical floor: hooks, deny rules, permission configs. Mechanisms can't be ignored because they're not asking the model to comply; they're intercepting the action. (Reporails' line captures it: *prompts steer, hooks enforce.*)

Your own secrets rule is the perfect example — "don't push secrets to git repos." (GitHub's analysis of 2,500+ repos found it the single most common rule in `AGENTS.md`

files.) As prose, it's the weakest kind of rule:

Never push secrets to the repository. Check for API keys and credentials before every commit.

It's not self-verifying by observation — a leaked secret looks like a normal commit. It's catastrophic when lost even once. And the docs' "no guarantee of strict compliance" means the model is never forced to check. It's a rule that begs to be ignored in a rushed session — which is exactly when secrets leak.

So the mechanical version:

- A pre-push secret scan (a git-secrets / gitleaks style hook) that
blocks the pushif a secret pattern matches.- A deny rule on the harness side (e.g., deny reading
`.env`

, deny the push action until the scan passes).`.env`

in`.gitignore`

as defense-in-depth.

The mechanism intercepts the action — the model isn't being asked to comply, so there's no "strict compliance" gap to exploit. The choice stops being abstract: one rule earns shaped prose, the other earns the floor.

I'll be straight with you: I don't run a mechanical enforcement layer. My safety net is the memory loop — `AGENTS.md`

tells the agent to read `MEMORY.md`

at the start of every session and update it at the end ([the exact three-file system I built](https://dev.to/buildloops/i-built-a-session-log-that-survived-my-migration-heres-the-three-file-system-4bj6)), and that log is how I'd notice a rule starting to get ignored (the entries would begin to diverge from what the rules require). The escalation above is for rules you can't afford to lose, not the setup I run.

And the takeaway that ties the series together: **rules are another thing you have to re-declare, not carry.** When your agent keeps making the same mistakes, the fix is the file that tells it how to work — and knowing what that file can and can't enforce is the difference between a rule that steers and a rule that decorates.

One more thing, because it's the case that misleads everyone.

Compaction — when the context window gets rebuilt mid-session — re-injects the root `CLAUDE.md`

. What it does not re-inject is nested or path-scoped rules, or rules that lived in files outside the root. The same goes for nested files in general: if a rule lives in a subdirectory that only loads in certain paths, and you switch harnesses, it can quietly drop out of the bundle.

The result looks exactly like Lane B. "The agent just ignored my rule," you'll think, and start rewording a rule that never actually loaded — a Lane A costume on a Lane A failure. This is where the two-lane test matters most: diagnose before you reword. Quote-and-locate first. Only then decide whether the fix is re-declaration, redesign, or the mechanical floor.

The mystery at the top of this post — rules that worked, then quoted-and-ignored — resolved into something much simpler than I expected. Loaded ≠ obeyed. The file was loaded; the rules just weren't load-bearing. And once you see the failure as two lanes instead of one, the fix stops being a guessing game: re-declare if it never loaded; redesign or enforce if it loaded and lost.

The migration made both lanes visible at once. That's the only reason I can hand you the diagnostic instead of a longer list of things that didn't work. If your agent quotes your rules and ignores them, run the test — quote, locate, watch the output — and you'll know which lane you're in before you change a single word.

Rules are another thing you have to re-declare, not carry. If your agent keeps making the same mistakes, the fix is the file that tells it how to work — I wrote the playbook here: [Why Your Coding Agent Keeps Making the Same Mistakes — AGENTS.md Fixes It](https://dev.to/buildloops/agentsmd-is-programming-for-your-ai-agent-not-documentation-for-humans-1g4o).

This closes Break 1 of the migration diary ([what broke when I switched from Claude Code to OpenCode](https://dev.to/buildloops/i-migrated-my-claude-code-workflow-to-opencode-heres-what-broke-5ajc)). Next up: why skills silently degrade — the same failure class, different file.

Which of the two lanes are you stuck in? Quote the rule that still isn't obeyed in the comments and I'll tell you which one it is.
