Skills vs subagents vs MCP vs hooks: which one should I use?
Use a hook for anything that must happen every time, MCP when the agent needs to reach a system it cannot otherwise touch, a skill when it needs to know how you do something it can already do, a subagent when the work would flood your main context, and an instruction file only for what every single turn needs — a plugin is how you ship any of these, not a sixth choice. The reason that rule holds is not the one most comparisons give. Context cost, the axis most of the existing advice was built on, is being engineered away; what is left is who pulls the trigger. Only a hook runs without the model choosing to run it; everything else, however firmly you word it, is a request.
The answer, as a procedure you can run.
Ask the questions in this order. The order matters: the first question that says yes decides it, and the early questions are the ones where picking wrong costs you a guarantee rather than a few tokens.
# Stop at the first yes. 1. Must it happen every time, whatever the model thinks? yes -> HOOK # lint after edit, block a path 2. Does the agent need a system it cannot reach today? yes -> MCP server # database, tracker, Slack 3. Would the work bury the main thread in output you will never read again? yes -> SUBAGENT # wide search, log triage 4. Is it a procedure or reference the agent needs only for some tasks? yes -> SKILL # release checklist, API guide 5. Does every turn of every task need it? yes -> AGENTS.md / CLAUDE.md / rules 6. Will another repo or team need the same setup? yes -> wrap the above in a PLUGIN
The same six, side by side. "Fired by" is the column the rest of this essay is about.
The real axis is who pulls the trigger.
Most comparisons sort these by what the content is — knowledge, capability, automation. That sorting is true and nearly useless, because the mistake people actually make is not putting knowledge in the wrong box. It is putting a requirement somewhere that only delivers a suggestion.
- Always. An instruction file is read on every turn. It is always present, which is not the same as always obeyed; the model weighs it against everything else in the window.
- The model's judgement. A skill loads when the model decides your task matches its description. An MCP tool runs when the model decides to call it. In Claude Code and Cursor a subagent starts when the model decides the task fits one. Three different mechanisms, one trigger: a prediction.
- An event. A hook fires because the harness reached
PreToolUseorPostToolUse, not because anyone chose it. It is the only mechanism on this list whose firing the model can neither choose nor skip. - A human. Typing
/deploy, @-mentioning a subagent, or naming a skill moves the trigger from the model to you. Both Claude Code (disable-model-invocation: true) and Codex (allow_implicit_invocation: false) let you make a skill human-only.
Anthropic's own feature guide states the consequence without hedging: an instruction like "never edit .env" in CLAUDE.md or a skill "is a request, not a guarantee", while a PreToolUse hook that blocks the edit is enforcement. That sentence is the whole decision for anything with a compliance, safety or data-loss flavour. If you would be unhappy to learn the model skipped it once in fifty runs, the model must not be the one deciding whether it runs.
The converse matters as much. A hook cannot reason. "Run the formatter after every edit" is a hook; "fix whatever the linter complains about" is a skill, because deciding how to fix is judgement. The common good setup is both: a PostToolUse hook that runs the linter and feeds its output back, and a skill that says what to do with it.
Context cost used to decide this. It mostly does not any more.
The familiar advice — "don't wrap a procedure in an MCP server, every tool definition sits in every request" — was correct when it was written. The harnesses have since moved the cost almost everywhere except the always-on rung.
- MCP schemas are deferred. Claude Code's documentation now says tool search is on by default: at session start it loads tool names and server instructions, and full JSON schemas stay out of the window until Claude needs a specific tool. An idle server is nearly free.
- Skill bodies are deferred. Claude Code and Codex both load a skill's name and description first and the body only when it is selected, and Cursor describes its skills as loaded "when relevant" — the progressive disclosure covered in agent skills.
- Subagents spend tokens elsewhere. They cost more in total — Codex's docs say plainly that subagent workflows consume more tokens than a comparable single-agent run — but the spend lands in a window you throw away, which is the point.
- Hooks cost nothing unless they return output. A hook that prints a 400-line lint report into the conversation has made itself an expensive instruction file.
- The instruction file is the exception. Its full text loads at session start and stays in every request. Anthropic's guidance is to keep CLAUDE.md under 200 lines and move reference material into skills — the only rung where line count is still the dominant cost.
What remains on every request is a list of descriptions — skill descriptions, subagent descriptions, tool names. That shifts the failure mode from cost to retrieval: a vague description means the model picks the wrong skill or none, which is the problem tool docs and discoverability works through. It is also a hint about scale; Claude Code warns at startup once combined subagent descriptions pass 15,000 tokens.
The same name does not mean the same trigger in every tool.
Because the trigger is what matters, check it per harness. The names have converged; the behaviour has not.
- Subagents. Claude Code delegates on its own when a task matches a subagent's
description, and Cursor says its agent "proactively delegates" on the same basis. Codex's local releases spawn agents only after a direct request or an instruction in a project file or skill that asks for one. Move the samecode-reviewerdefinition between them and it goes from something the model reaches for to something nobody calls unless told to. - Hooks are deterministic, not complete. They fire on their event every time, but only for the paths that pass through the hook. Codex documents that hosted tools such as web search do not use the local hook path and tells you to "treat tool hooks as a useful guardrail, not a complete enforcement boundary". Cursor's generic
preToolUseacceptsaskin its schema but does not enforce it. A hook guarantees it runs; it does not guarantee it sees everything. - Inheritance comes with the subagent. In Codex, subagents inherit the parent's sandbox and approval settings and a custom agent file cannot replace them; in Cursor they inherit every tool, MCP included. Isolation is of context, not of authority — the gap what a sub-agent inherits takes apart.
- Instruction files converge, mostly. Codex and Cursor read AGENTS.md; Claude Code reads CLAUDE.md. Which file is the least consequential choice on this page, as AGENTS.md vs CLAUDE.md vs Cursor rules vs skills argues.
Five placements that look reasonable and are wrong.
- A must-hold rule in an instruction file. "Never push to main" in AGENTS.md works until the long session where it does not. Keep the sentence for the model's benefit, and add a
PreToolUsehook that refuses the command. - A procedure wrapped as an MCP server. If the server's tools just return instructions, you have built a skill with a network hop, a process to keep running and a third-party trust boundary. MCP earns its place when there is something on the other side to reach — the rule in agent skills still stands, for a reason other than tokens now.
- A subagent for a persona. A "senior reviewer" subagent that reads three files and answers buys an extra context window you did not need and a summary you cannot check. A persona is a skill; a subagent is for when the reading would swamp you, as subagents argues.
- A side-effecting skill left model-invocable. A
/deployskill the model can trigger by matching its description is a deploy the model can decide to run. Make it human-only. - A plugin installed as if it were a skill. A plugin can carry hooks, and hooks run your commands with your privileges on events the model never observes. Claude Code merges hooks from every source rather than letting one override another, so a plugin's hook fires alongside yours. Installing a plugin is installing automation; lifecycle hooks and harness config covers why that path has the least change control, and Agent Plugins ships without a trust model covers what the shared format left out.
Real jobs usually take two mechanisms, split by trigger.
The useful pattern is to give each mechanism the part of the job that matches its trigger, rather than forcing the whole job into one.
- Lint and format. Hook: run the formatter and linter after every edit, return only the failures. Skill: how your team resolves the recurring ones.
- Talk to the database. MCP: the connection, with read-only credentials. Skill: the schema, the naming quirks, and the three queries everyone gets wrong. A hook on the MCP tool if writes must be refused rather than discouraged.
- Code review. Skill: the checklist, invoked by name. Subagent: run it over a large diff so the main thread gets findings, not 40 files of reading.
- Release. Human-only skill for the procedure; hooks for the steps that must never be skipped, such as refusing to tag when tests have not passed in this session.
- The second repository. Package the lot as a plugin — and review its hooks the way you would review a CI change, because that is what they are.
Audit what you have this week: list every sentence in your AGENTS.md or CLAUDE.md that starts with "never" or "always", and for each one ask whether a single miss would hurt. The ones that would become hooks; the long reference sections become skills; whatever needs a live system becomes an MCP server; and a task that keeps filling your context goes to a subagent. Then check the trigger for each in the harness you actually run, because the same file can be model-invoked in one tool and inert in another. Choose by who must decide that it happens — the model, an event, or you — and the right box follows.
Related: what is MCP for the protocol, MCP tool design for building the server side well, the instruction hierarchy for why written rules stay advisory, and context budgeting for the arithmetic behind the always-on rung.