Skip to content

Rules, skills and agents, which one you actually need

The same instruction behaves completely differently depending on where you put it. Rules are ambient constraints, skills are invoked procedures, agents are delegated scopes.

Next.js on Vercel5 min readships at docs/solutions/nextjs-vercel/rules-skills-agents-when-to-use-each.md

Tags: agents · skills · rules · claude-code · architecture

You have decided your team should always run an accessibility pass before merging UI work. Where does that instruction go?

Put it in a rule and it loads on every request that touches a component, adding noise to work that has nothing to do with accessibility, and it still will not happen reliably, because a rule is a constraint on how you work, not a procedure that gets run.

Put it in a skill and it happens exactly when someone invokes it, with the full checklist available, and nothing happens when nobody does.

Put it in an agent and it happens in a separate context with its own tools, returning a report, which is right if the pass is long and would otherwise crowd out the work being reviewed.

Three homes, three behaviours, one instruction. Getting this wrong is the most common reason a carefully written agentic setup does nothing.

The distinction, in one table

RuleSkillAgent
LoadedAutomatically, when a matching path is touchedWhen invoked by nameWhen delegated to
ShapeConstraints. "Always / never."A procedure. Numbered steps.A role and a standard. Judgement.
ContextShares the main conversationShares the main conversationIts own, separate
Toolsn/aWhatever the session hasIts own allowlist
CostsContext on every matching requestNothing until invokedA separate context window
Fails byBeing ignored when too long or too vagueNever being invokedBeing asked for a judgement it lacks the context to make

Rules: ambient constraints

A rule is what must be true whenever a matching file is touched. It is passive: nobody invokes it, and it does not describe a sequence.

---
title: Testing rules
paths:
  - src/**/*.test.ts
  - tests/**
---

- Every Route Handler under `src/app/api/**` has at least a happy-path test and
  an auth-failure test.
- Tests assert on behaviour, never on implementation details. No asserting that
  a mock was called with an object shape.
- No test depends on another test's leftover state.

The wrong content for a rule is a procedure. If your rule has numbered steps and words like "first" and "then", you have written a skill and filed it in the wrong place, where it will be loaded constantly and followed rarely.

Skills: procedures you invoke

A skill is a named procedure with steps, run on demand. /verify, /write-spec, /qa-feature, /deploy-to-vercel, /security-audit, /help, plus one per battery.

The mark of a good skill is that it contains the things people forget, in order, with the commands written out:

---
name: deploy-to-vercel
description: Ship this repo to Vercel, gates, env vars per scope, preview, promote, roll back.
---

## 1. Gates, locally
bun run typecheck && bun run lint && bun run test && bun run build

## 2. Environment variables, per scope
bunx vercel env ls
...

Two failure modes. A skill that only describes what a skill would do ("this skill helps you deploy") is useless; write the actual steps. And a skill that duplicates a rule pulls them out of sync: the rule says the constraint once, the skill links to it.

Agents: delegated scope

An agent is a specialist with its own context window and its own tool allowlist. Use one when the work is *large enough to pollute the main conversation or needs different permissions*.

---
name: security-auditor
description: Audits the repo or a diff for leaked secrets, broken auth boundaries, injection and unsafe deploy config.
tools: [Read, Grep, Glob, Bash]
---

You are the security auditor for this repository...

Note the tools list: no Edit, no Write. The auditor finds, you fix. That separation is deliberate: an agent that can both flag and silently repair is an agent whose findings nobody reads.

The four that ship here divide cleanly: pr-reviewer (reviews a diff against this repo's rules), security-auditor (finds, does not fix), documentarian (keeps docs true to the code), system-manager (maintains .claude/ itself).

The common mistake is creating an agent for something small. A "formatter agent" is a hook. A "commit message agent" is a skill. Every agent costs a context window and a round trip; earn it.

The fourth option people forget

Sometimes the answer is none of the three. If the cost of the mistake is unrecoverable (a dropped table, a leaked key, a force push over someone's work) put it in a hook. Hooks run in the harness, outside the model, and cannot be reasoned around at hour three of a long task.

Rules for what should be true. Hooks for what must never happen.

Deciding, in four questions

  1. Does this need to be true without anyone asking? → Rule. Scope it with paths so it loads only where it applies.
  2. Is it a procedure someone runs at a moment? → Skill. Write the real steps, with the real commands.
  3. Does it need its own context or its own tools? → Agent. Give it a narrow allowlist and a clear standard.
  4. Would the mistake be unrecoverable? → Hook, in addition to the above.

Worked example: the accessibility pass

Split it across all four homes, and each piece lands where it works:

  • Rule on src/components/**: interactive elements are real buttons and links; every image has alt text; colour is never the only signal. Ambient, checkable, loads only in component work.
  • Skill /a11y-audit: run axe against the changed routes, check keyboard order, check focus visibility, check at 200% zoom. Invoked before a UI PR.
  • Agent: only if the audit grows long enough to swamp the main conversation. Start without one.
  • Hook: none. A missing alt text is recoverable, and a hook that blocks edits over it would be turned off by Friday.

That split is the whole skill. When you can say which of the four a piece of guidance belongs in (and why the other three are wrong) your agentic layer starts doing what you wrote it to do.