# Why Adding More Rules Makes Your Agent Dumber - 268 Rules, 14 Always Loaded, and a Tool to Audit Yours

> Source: <https://dev.to/xinandeq/why-adding-more-rules-makes-your-agent-dumber-268-rules-14-always-loaded-and-a-tool-to-audit-4e8j>
> Published: 2026-07-11 01:43:54+00:00

A reader asked me a question I couldn't fully answer: "Do you retire rules, or does interception count keep them alive?" The honest answer was: mostly, I don't. And that's a problem.

*This article is co-authored with my AI agent. I handle real experience, judgment, and final sign-off; the agent handles architecture, drafting, and fact sourcing. The system this article describes also produced this article - including catching its own false claims during the writing process. The behind-the-scenes log at the end shows what happened.*

After I published [my last article](https://dev.to/xinandeq/i-built-an-error-notebook-for-my-ai-agent-266-rules-66-interceptions-and-a-demo-you-can-run-2lod) about building an error notebook for my AI agent, a reader named dipankar_sarkar left a comment:

"Do you retire rules, or does interception count keep them alive?"

I stared at that question for a while. Because the answer was uncomfortable.

I had 268 rules. (When I published my last article, it was 266 - the system keeps learning.) I'd been adding them for two months - every time the agent made a mistake, I'd extract a rule and file it away. But retire them? Almost never. The file only grew. And I'd started noticing something: the agent was following *fewer* rules, not more.

This article is about why that happens, what it costs you, and what to do about it.

Your CLAUDE.md is a ratchet wrench. It only tightens, never loosens.

Every time your agent makes a mistake, you add a rule. "Don't do X." "Always check Y." "When Z happens, execute W." The file grows. You never remove anything - because how do you know which rule is safe to delete?

I've been there. My rule file - called AGENTS.md, the equivalent of CLAUDE.md in [opencode](https://opencode.ai) - grew to **3,000+ characters**. My own system history diagnosed the root cause in six words:

"Rules only added, never removed. No exit mechanism."

After slimming it from 170 lines to 106, compliance improved in my workflow. This is an N=1 observation, not a benchmark - but the direction was clear: less noise, more signal.

This sounds counterintuitive. More rules should mean more guidance, right? In my experience, three things break:

**1. Attention dilution.** LLMs have finite context windows. Every rule in the context competes for the model's attention budget. When you have 10 rules, each gets a meaningful share. When you have 200, each gets noise-level weight. The signal-to-noise ratio drops. [Anthropic's memory best practices](https://docs.anthropic.com/en/docs/claude-code/memory) recommend keeping CLAUDE.md specific and structured, and reviewing it regularly - not making it exhaustive.

**2. Trigger conflicts.** Rules can contradict each other. "Always be concise" vs "Always explain your reasoning." "Use the fastest approach" vs "Always write tests first." You don't notice when you write them one at a time. But the agent has to follow all of them simultaneously - and when they conflict, it picks one. Usually the wrong one.

**3. Injection noise.** Rules that never fire still consume context budget. A rule about database migration patterns sits in your file, doing nothing, while the agent is trying to write a CSS fix. It's dead weight - but the agent still reads it, processes it, and allocates attention to it.

The result: your rule file becomes a graveyard of good intentions. The agent skims it, picks up a few rules, ignores the rest. You think you have 200 rules working for you. You actually have maybe 15.

I track every rule's effectiveness - how many sessions each rule actually fired in. After 175 sessions and 157 tracked rules, here's what the data looks like:

| Sessions where rule fired | Rules | Percentage |
|---|---|---|
| 11+ sessions | 8 | 5% |
| 4-10 sessions | 30 | 19% |
| 1-3 sessions | 119 | 76% |

**76% of my tracked rules fired in 3 or fewer sessions out of 175.** Only 8 rules (5%) fired in more than 10 sessions. My top rule - "don't skip the documentation before starting work" - fired in 23 sessions, about 13% of the time.

A note on what "fired" means: my system distinguishes between objectively verified interceptions (confirmed via tool-call logs or script output) and self-reported ones (the agent says "per rule X, I'm executing Y"). The session count above includes both. The self-reported numbers are a useful signal, but they're not independently verified - consistent with the theme of [my previous article](https://dev.to/xinandeq/i-built-an-error-notebook-for-my-ai-agent-266-rules-66-interceptions-and-a-demo-you-can-run-2lod): declaration ≠ fact.

The long tail is where retirement candidates live. These aren't bad rules. They're rules that worked once or twice, and then the context shifted - the model got updated, the project changed, the mistake stopped recurring. But the rule is still there, taking up space.

Out of 268 total rules, I've archived 165. That's 62% - retired, not deleted, but out of the active set. Only 14 rules are always loaded (Core). Another 89 load on demand when the task type matches (Task). **The rest must earn their way into the context when a task makes them relevant.**

Four mechanisms keep the system from drowning in its own rules:

**1. Three-layer architecture.**

```
Core:     14 rules  (always loaded - the non-negotiables)
Task:     89 rules  (loaded by task type - investment, coding, writing)
Archive:  165 rules (retired, searchable on demand)
```

Think of it like your phone. The home screen (Core) has your 14 most-used apps. The app library (Task) has apps organized by category. The cloud (Archive) has apps you rarely open but might need someday. You don't delete apps - you move them off the home screen.

**2. Core ≤ 15 hard cap.** When Core hits 16, the lowest-performing rule gets demoted. I use a rough heuristic - interception rate weighted by importance - to decide which goes. Safety-critical rules (like "backup before delete") are exempt. This isn't an optimized formula; it's a judgment call that works. Past 15, I see compliance drop.

**3. Hit/miss tracking.** Every rule's effectiveness is measured. Rules that fire rarely are retirement candidates. The tracking itself is a mix of objective signals (script logs, tool-call hooks) and self-reported signals (agent acknowledgments). Neither is perfect - but together, they surface the long tail.

**4. Cleanup cadence.** I borrow a principle from project governance: every 3 feature iterations, 1 cleanup sprint. The same rhythm applies to rules - every few rounds of adding rules, I do a retirement pass. This isn't a documented rule-level mechanism. It's a practice that works.

You don't need my full tracking system to start finding retirement candidates. Here are two ways to audit your own rule file right now.

Open your CLAUDE.md. For each rule, ask yourself:

"When was the last time this rule actually prevented a mistake?"

If you can't answer, or the answer is "months ago," it's a retirement candidate. But use judgment: safety-critical rules (like "backup before delete"), rare-but-high-impact rules, and seasonal rules should stay even with low hit rates. Archive low-risk rules with no recent hits. **Archive ≠ delete** - you can always bring a rule back.

Find 3 retirement candidates today. That's it. You'll be surprised how many rules are dead weight.

If you want a quick automated check, here's a script that scans any markdown rules file and flags rules worth reviewing. **It does not measure effectiveness** - it can't, because it doesn't have hit data. What it does is flag rules that are structurally weak: no trigger condition, too vague to be actionable, or near-duplicates of another rule.

``` bash
#!/usr/bin/env python3
"""Rule-file hygiene scanner - flags structurally weak rules."""
import re, sys

def scan(path):
    with open(path) as f: lines = f.readlines()
    rules = [(i+1, re.sub(r'^[-*]\s+|^\d+\.\s+', '', l.strip()))
             for i, l in enumerate(lines)
             if re.match(r'^[-*]\s+', l.strip()) or re.match(r'^\d+\.\s+', l.strip())]
    candidates, seen = [], {}
    for ln, text in rules:
        r = []
        if not re.search(r'\b(when|if|must|always|never|before)\b', text, re.I):
            r.append('NO_TRIGGER')
        if len(text) < 15: r.append('TOO_VAGUE')
        k = text.lower()[:30]
        if k in seen: r.append(f'DUP@L{seen[k]}')
        else: seen[k] = ln
        if r: candidates.append((ln, text[:60], r))
    total = len(rules)
    d = 'LOW' if total <= 10 else 'MEDIUM' if total <= 20 else 'HIGH'
    print(f'{total} rules found. Density: {d}')
    if candidates:
        print(f'{len(candidates)} rules worth reviewing:')
        for ln, t, r in candidates: print(f'  L{ln}: {t}... -> {", ".join(r)}')
    else: print('No structural issues found.')

if __name__ == '__main__':
    scan(sys.argv[1] if len(sys.argv) > 1 else 'CLAUDE.md')
```

Save it as `scan_rules.py`

and run it:

```
python scan_rules.py CLAUDE.md
```

Output:

```
26 rules found. Density: HIGH
8 rules worth reviewing:
  L3: Use TypeScript... -> NO_TRIGGER
  L7: Be concise... -> TOO_VAGUE
  L14: Always write tests... -> DUP@L11
```

Three flags: **NO_TRIGGER** (no "when/if/must" condition), **TOO_VAGUE** (under 15 characters), **DUP@L** (first 30 characters overlap another rule). Each is a review candidate - not an automatic retirement.

Think of it as a lint check for your rule file. It catches structural problems before you even start tracking effectiveness.

I need to be honest about what this system *doesn't* do. A reader on my last article also asked: "What happens with a genuinely new failure mode that has never tripped a rule before? Do you track novel slip-throughs vs known recurrences?"

The answer: no, I don't. Here's what's missing:

**Retirement is manual.** I review low-hit rules and decide. There's no automated degradation - no "rule auto-retires after 30 consecutive misses." I'm evaluating this, but it's not implemented.

**No conflict detection.** I can't detect when two rules contradict each other. If "be concise" and "explain thoroughly" are both in Core, the agent just picks one. I don't even know which one wins. This is a known gap in evaluation.

**No novel vs known tracking.** When a mistake happens, I can't tell if it's a known error recurring (rule failed to intercept) or a genuinely new failure mode (no rule exists). A reader pointed this out, and it's the most fundamental limitation - the system is reactive, not predictive.

**No risk-aware retirement.** The "last hit" test is crude. Safety-critical rules, rare-but-high-impact rules, and seasonal rules shouldn't be retired just because they haven't fired recently. The system doesn't currently distinguish between "low hit rate because the rule is useless" and "low hit rate because the failure is rare but catastrophic." I make this judgment manually; it should be systematized.

**This is still a 1-user system.** 175 sessions, one workflow, one agent platform. The patterns I see might not generalize. The hit distribution might look different for a team or a different model.

**1. Run the "last hit" test.** Open your rule file. For each rule, ask when it last prevented a mistake. If you can't answer and the rule isn't safety-critical, archive it. Find 3 today.

**2. Run the hygiene scanner.** `python scan_rules.py CLAUDE.md`

- 30 seconds, see your structural dead weight.

**3. Track hits for 30 days.** You don't need my full system. Just add a note next to each rule: "[hit 2026-07-10]" when it fires. After 30 days, the long tail will reveal itself. Then retire the bottom 20%.

The harder problem in agent governance isn't memory. It's forgetting. Your agent doesn't need more rules. It needs a metabolism - a way to break down and eliminate what no longer works.

Previous article:[I Built an Error Notebook for My AI Agent]- how to build the error notebook and intercept mistakes before they happen.

Next article:Giving LLM a body - why rules, memory, and verification are just organs of a larger control system.

**Behind the Scenes: How This Article Was Built** (click to expand)

> The system this article describes also produced this article. Here's what actually happened - including false claims caught during review.

| Stage | What happened | Why it matters |
|---|---|---|
| Source pack | Every claim was verified against raw data before writing began | Prevented false claims from reaching the draft |
| Data analysis | L2_Hits.csv was analyzed programmatically | Initially used the wrong column (self_reported instead of total) |
| Fact-checking | The "3:1 cleanup ratio" was searched in docs - found it's project-level, not rule-level | Prevented overclaiming a practice as a documented mechanism |
| External review | A reviewer caught 4 P0 issues that internal review missed | Including the wrong data column, demo overclaim, and metric naming |

| What the agent assumed | How it was caught | What happened |
|---|---|---|
Used `self_reported_hit_count` (67) but called it "hits" |
External review: CSV has `hit_count=1516` , `objective_hit_count=1449` , `self_reported_hit_count=67`
|
Switched to `sessions_hit` as primary metric; added caveat about self-reported vs objective |
| "Only 14 rules are active" (implying Task rules are inactive) | External review: Task rules load on demand, they're not inactive | Changed to "14 rules are always loaded"; Task described as "load on demand" |
| Demo "automates hit/miss tracking" | External review: script only does text heuristic scanning, doesn't read hit data | Reframed as "hygiene scanner"; explicitly states "it does not measure effectiveness" |
| Used "266" for series consistency while citing current session data | External review: mixing old total with current data is inconsistent | Changed to 268 (current actual); noted evolution from 266 in opening |
| "3:1 cleanup ratio for rules" (documented mechanism) | Source pack verification: 3:1 is project-level cadence, not rule-level | Reframed as practice, not documented mechanism |
`interception_rate × importance` presented as a real mechanism |
External review: no source in docs for this formula | Labeled as "rough heuristic" and "judgment call" |
| Anthropic guidance paraphrased as "short and specific" | External review: not the actual language used | Replaced with accurate description +
|

Three things emerged from writing this article:

These lessons are now in the error notebook. The system's own article production process is its own dogfood.
