Skills, hooks, agents, CI: what enforces what
A rule that lives only in a skill is a wish. It reads like policy (“never commit to main”, “always run the migration check”) but nothing makes it happen. The model may load it, may weigh it, may follow it. Anthropic’s engineering guidance on steering agents is blunt about the failure mode: advisory rules give way under pressure (a long session, a crowded context, a prompt injection), while hooks and permissions hold because they don’t ask the model’s opinion. So before you write another rule, ask: what enforces this?
There are five places a rule can live. They differ on one axis: the guarantee they give.
Five mechanisms, one axis
Section titled “Five mechanisms, one axis”| Mechanism | What it is | Guarantee |
|---|---|---|
| Always-loaded convention | CLAUDE.md, AGENTS.md: standing instructions read at session start | Advisory. The model can ignore it |
| Skill / on-demand knowledge | Packaged know-how, loaded only when judged relevant | Advisory, and conditional on being loaded at all |
| Hook | A script that fires at a lifecycle point, blocks or passes | Deterministic. Always fires; exercises no judgment |
| Agent | A fresh model with a mandate: review this diff, refute this claim | Judgment. Catches what scripts can’t; guarantees nothing |
| CI / platform policy | Branch protection, pipeline gates, permission boundaries | Real enforcement. Binds human and agent alike |
Read the table bottom-up and it’s a chain of custody: the further down, the less the outcome depends on anyone (human or model) behaving well.
- Skill (on-demand) advisory
- Convention (always loaded) advisory
- Agent judgment, not a guarantee
- Hook deterministic
- CI / platform policy enforced
Advisory: conventions and skills
Section titled “Advisory: conventions and skills”Standing instructions and skills are the same substance, text a model reads; they differ only in when they load. Conventions cost context on every turn; skills cost almost nothing until triggered. Both are the right home for knowledge: your stack, your naming, how deploys work here. Neither is enforcement. An advisory rule fails in four ordinary ways: it wasn’t loaded, it was crowded out, a conflicting instruction outranked it, or an injected prompt overrode it. None of these are exotic. All of them happen on normal Tuesdays.
Deterministic, no judgment: hooks
Section titled “Deterministic, no judgment: hooks”A hook is code at a lifecycle point: before an action, after an edit, at the end of a turn. It fires every time, whatever the model believes. A pre-action hook can refuse any write to migrations/; a stop hook can run the test suite and refuse to end the turn until it’s green. This is the 12-factor agents principle of owning your control flow: a production agent is mostly deterministic code with model steps placed where reasoning is needed, not a model improvising the loop. The trade is symmetrical: a hook never forgets, and it never understands. It cannot tell a safe migration from a destructive one. It can only tell migrations/ from everywhere else.
Judgment, no guarantee: agents
Section titled “Judgment, no guarantee: agents”Some rules can’t be checked by pattern-matching: “is this error message actually helpful?”, “does this change match the spec’s intent?” That’s judgment work, and a fresh reviewer agent that didn’t write the code is the right tool: it reads the diff without the author’s attachment to it. But be precise about what you bought. A model grading a model is a strong opinion, not a gate. It raises the odds of catching what a script can’t see, and guarantees nothing. Use agents as a net above your deterministic layer, never as the floor.
Real enforcement: CI and platform policy
Section titled “Real enforcement: CI and platform policy”Branch protection, required pipeline checks, permission boundaries, deploy gates: these bind at the platform, so they don’t care who’s asking. A human at 23:00 and an agent in an unattended run hit the same wall. That symmetry is the point: any control that only worked because humans were slow was never a control. The research direction agrees. Written policy can be compiled into runtime guardrails rather than left as prose. Your “must never” rules belong here, stated once, enforced for everyone.
The decision table
Section titled “The decision table”| You need | Reach for |
|---|---|
| Knowledge the model should apply | A skill (or standing instructions) |
| Something that must happen every time | A hook |
| A judgment call on ambiguous output | An agent |
| A “must never”, whatever the actor | CI / platform policy |
Most real rules decompose across rows. “Migrations are reviewed before they ship” becomes: a skill explaining how migrations work here, a hook blocking direct writes to the folder, a reviewer agent reading the SQL, and branch protection making the human sign-off non-optional. Four layers, one rule, and only the last one is a guarantee.
Enforcement lives downstream of definition
Section titled “Enforcement lives downstream of definition”Writing the rule is the cheap step. The decision that matters is where the rule lives: which row of the first table it lands on, and therefore what its violation costs. Audit your current rules against that axis. If everything sits in the top two rows, you don’t have a policy. You have a wish list with good formatting.
Next step
Section titled “Next step”Rules are one half of what persists across sessions. The other half is memory, and most of it is not where you’d expect.