The Forge

Skills advise. Hooks enforce. Most agent setups break because the builder reaches for the wrong one.

You have four ways to shape how a coding agent behaves: CLAUDE.md, Skills, Subagents, and Hooks. They look interchangeable when you're setting up a project. They aren't. Three of them are advice the model can choose to ignore. One of them is law the model cannot break. Pick the wrong layer and you end up debugging behavior you thought you'd already handled.

Here's the mental model that sorts it out: some rules are advisory, and some are statutory. CLAUDE.md and Skills are advisory. They load context into the model and hope it pays attention. It usually does. It won't always. Subagents are structural, they draw a boundary around a task and hand it a clean context and a limited toolset. Hooks are statutory. They run deterministic code on lifecycle events, and they cannot hallucinate, forget, or decide to skip a step.

I've seen a lot of agent configs, and the same failure shows up over and over. Someone writes "never commit secrets" or "always run the tests before you stop" into CLAUDE.md, watches the agent follow it nine times, and then watches it skip the tests on the tenth run when the context gets long. The instruction was fine. The layer was wrong. A rule you can't afford to have broken does not belong in a file the model treats as a suggestion.

Let's sort the four layers by what they actually guarantee.

The Blueprint

Here's the decision table. Copy it, keep it next to your project config, and stop guessing.

Layer

What it is

Guarantee

Reach for it when

CLAUDE.md

Always-on project guidance loaded every session

Advisory. The model reads it and usually complies

It's short, stable, project-wide context. Keep it under ~200 lines and write it by hand

Skills

Instruction packs loaded on demand for a specific task

Advisory. Loaded only when relevant, so it doesn't bloat context

The knowledge is specialized and situational (a deploy runbook, a domain's rules, a house style)

Subagents

A delegated task with its own clean context and tool set

Structural. Isolates work, but the subagent still follows advice, not law

A task needs its own context, a limited toolset, or should run beside other work. Best at 3 to 5 concurrent

Hooks

Deterministic scripts that fire on lifecycle events

Statutory. Runs real code. Can block the action outright

A rule must hold every time: no writes outside the repo, tests must pass before stopping, secrets get redacted

The one line to remember: if it must be true every time, it's a hook. If it's guidance that's usually enough, it's a Skill or CLAUDE.md.

Now the part you can actually use. Here's a PreToolUse hook that blocks the agent from writing files outside your project directory, plus a Stop hook that refuses to end the session if the tests fail.

First, the guard script. Drop it at .claude/hooks/guard-writes.sh:

#!/usr/bin/env bash
# Block writes outside the project directory.
# Reads the tool call JSON on stdin, checks the target path.
path=$(jq -r '.tool_input.file_path // empty')

case "$path" in
  "$CLAUDE_PROJECT_DIR"/*) exit 0 ;;                       # inside the repo, allow
  *) echo "Blocked write outside project: $path" >&2; exit 2 ;;  # exit 2 blocks the call
esac

Then wire it up in .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/guard-writes.sh" }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "npm test --silent || exit 2" }
        ]
      }
    ]
  }
}

Two things make this work. The matcher targets the tools you care about (Write|Edit, pipe syntax for more than one). And exit code 2 is the magic number: it blocks the tool call before it runs and feeds your stderr message back to the model, so the agent sees why it was stopped and adjusts. Any other non-zero exit blocks too, but 2 is the one that talks back.

Copy, paste, customize. Change the matcher to Bash and the script to a secret scanner, and you've got a redact-on-every-command guard with the same shape.

The Anvil

Let's take a real scenario and watch the layer choice decide the outcome.

You're running an agent across a monorepo. Your rule: it should only touch files inside packages/checkout, because that's the service you're working on. The obvious move is to write it into CLAUDE.md: "Only edit files under packages/checkout."

That holds until it doesn't. The agent hits a failing import, traces it to a shared type two packages over, and "helpfully" edits packages/shared/types.ts to fix it. Reasonable-looking. Also exactly the blast radius you were trying to prevent. The instruction was clear. The model just decided this case was the exception, and there was nothing to stop it.

Swap the layer. Point guard-writes.sh at packages/checkout instead of the repo root, and the same edit exits 2 before a single byte is written. The agent gets told no, sees the reason, and routes around it, usually by flagging the shared-type problem instead of silently reaching into another package. You didn't make the model smarter. You made the boundary real.

That's the whole discipline. Advice for the things you want, enforcement for the things you can't afford to lose. Skills and CLAUDE.md shape the ninety-five percent where the model's judgment is fine. Hooks own the five percent where judgment isn't good enough.

Try this this week: find the one rule in your CLAUDE.md that would actually hurt if the agent broke it. Just one. Move it to a hook. See how it feels to have a rule that can't be argued with.

Sparks

Three things worth your attention this week.

MCP went stateless. The 2026-07-28 spec dropped the initialize handshake, the session ID, and server-initiated requests. A remote server that used to need sticky sessions and a shared store can now sit behind a plain round-robin load balancer. tasks/list is gone and Roots is deprecated, so if you shipped against the experimental Tasks API, you've got migrating to do. There's a formal 12-month deprecation window now, which is the adult-in-the-room move the protocol needed.

The maintenance trap has a number. 41% of enterprises reported at least one production rollback of an AI agent in the last twelve months. 80% of Q1 apps embed an agent, but only 31% of orgs have one actually running in production. The gap between "embedded an agent" and "runs reliably" is exactly the gap hooks close.

The Personal AI Agents Summit ran July 21 with builders from Anthropic, OpenAI, and Google covering agent security, permissions, and production deployment. Worth a scan if you missed it.

The Smith's Take

The reason your agent misbehaves is rarely that it's dumb. It's that you filed a must-never-break rule under advice. CLAUDE.md and Skills are how you teach an agent. Hooks are how you bind it. The best setups use both, and they never confuse the two.

Pick your single most dangerous instruction this week and promote it from advice to law. If you want the full decision framework plus more copyable hooks like the one above, join the Agentic Smith newsletter.

Build agents that actually work.

Keep Reading