slowlp
← Blog
Method 2026.06.11 · 11 min read

4 Control Levers When Your Agent Won't Listen

Why it's not the model's fault, and what each of the 4 control levers actually does

Method

When Your Agent Won’t Listen — Building 100% Reliability with 4 Control Levers: CLAUDE.md, Skills, Commands, and Hooks

Why missed instructions aren’t the model’s fault, and a hands-on methodology for understanding the reliability differences between 4 control levers


Opening: “I wrote everything in CLAUDE.md — why isn’t it following the rules?”

I lived with that question for a while myself. I’d packed maybe 20 rules into CLAUDE.md, and fewer than half were actually being followed. I couldn’t figure out whether the model was just bad, or whether I was writing bad prompts.

Now the answer is clear to me. The problem wasn’t the model, and it wasn’t the prompts. I was choosing the wrong control lever.

Claude Code has 4 control surfaces for shaping agent behavior, and each one has completely different reliability and cost profiles. If you don’t distinguish between them and just dump everything into CLAUDE.md, missed instructions become structurally unavoidable.


Lever 1: CLAUDE.md — Always On, Which Is Exactly Why It’s Dangerous

The biggest thing about CLAUDE.md is that it’s always loaded. The model reads it every session, every message. That means every character you write there gets added to the cost of every request throughout the session.

The problem is that compliance with individual rules drops as the content gets longer. As the model’s attention spreads across the growing context, specific rules get deprioritized. “It’s there but being ignored” is the classic symptom of an overloaded CLAUDE.md.

There’s one simple test: “Is this worth carrying around on every single message?” If yes, it belongs in CLAUDE.md. If not, it should be moved to a different lever. Package manager settings, code style, always-on rules — those are the things that should stay.


Lever 2: Skills — Almost Free Until Triggered

Skills are set up with a .claude/skills/<name>/SKILL.md structure, and only the description floats around in the background — the full content loads at trigger time. If a skill never triggers, the cost is nearly zero.

Once I understood this and moved the heavy procedures out of CLAUDE.md into skills, two things improved at the same time. The separated procedures got handled cleanly by their skills, and the remaining CLAUDE.md rules saw less dilution, so their compliance rate went up too. An unexpectedly big win.

The most important part of a skill is the description. If the trigger conditions aren’t specific about “when to activate,” the skill just won’t show up when you actually need it. Instead of “anything stock-related,” write something like “when writing or modifying P&L calculations or profit/loss logic” — that’s what lets Claude match the right context.

Skills also have their own unique failure mode. CLAUDE.md gets diluted but at least it’s always there. A skill that fails to trigger is completely absent. That’s why description quality is directly equal to miss rate.


Lever 3: Commands — Manual Means 100% Reliable

Commands require you to type /name yourself. There’s no model judgment involved — a person intentionally fires it, so reliability is 100%.

This makes commands great for testing a process before turning it into a skill, or for work where automatic triggering would actually get in the way. Things like /review, /simplify — convenience tools that let you invoke a well-crafted prompt with a single word.


Lever 4: Hooks — Bypasses Model Judgment Entirely

Hooks are a completely different animal. There’s no step where the model decides whether or not to do something. Shell commands embedded around tool call events execute deterministically.

You define them under the hooks key in settings.json as an event → matcher → handler structure. Three core events matter most:

  • PreToolUse: Intercepts before a tool runs. Exit code 2 blocks it, 0 lets it through.
  • PostToolUse: Cleanup after a tool runs.
  • Stop: A gate for when Claude tries to finish.

The most striking thing I personally witnessed was a PreToolUse secret scan. High-confidence patterns like sk-ant- and ghp_ get detected and blocked with exit 2 — before the model even gets to make a judgment call. That was the moment I really felt: “okay, this one genuinely cannot miss.”

Forcing tests via a Stop hook is also powerful. When Claude tries to wrap up, tests run, and if they fail, exit 2 prevents it from ending. The tester agent is model-based, but the Stop hook is a deterministic gate.


The 4-Lever Decision Tree

Here’s the actual framework I use to decide how to distribute things across the 4 levers.

SituationLever
Frequent + must trigger automaticallySkill
Occasional + best-effort is fineCLAUDE.md pointer (one line + file path)
Rare + needs to be certain in that momentDirect @filename mention on the spot
Absolutely cannot be missedHook (deterministic)

To put it simply: “Does this need to happen all the time? Does it need to surface automatically? Can it absolutely never be skipped?” — once you separate those three questions, the lever choice almost picks itself.


An Actionable Takeaway

Open your CLAUDE.md right now and skim your rule list. Try separating “things you only need once in a while” from “things that absolutely must always be followed.”

Move the former to commands, move the latter to hooks. Your CLAUDE.md shrinks in half, and the compliance rate of what’s left goes up. That’s the real change I experienced after understanding the control levers.

If you want to dig deeper into skills and the Claude Code world, The Secret of Skills: When Natural Language Becomes Logic and Cutting Dev Time with the Build-Plan Skill connect the context well.

COMMENTS