Subagents vs Hooks in Claude Code: Picking the Right Tool for the Right Job
The Claude Code subagent and the Claude Code hook look similar at a glance — both let you add "behavior the model should follow" — but they answer different questions, and using the wrong one is one of the most common ways teams end up with a sprawling CLAUDE.md and a slow, leaky workflow.
A short way to remember the difference:
- Subagent = "do a separate scoped task and hand the result back." It is a worker with its own context, its own tool set, and a clean return path. It is good when the work is parallelizable or expensive to run inline.
- Hook = "before/after this tool call, do something." It is a wrapper around the model's tool use. It is good when the work is invariant enforcement — the same prep or cleanup every time.
Five questions to pick the right one for any new behavior you want to add:
- Does the work need a different context? If yes, subagent.
- Does the work need different tools (or sandboxing)? If yes, subagent.
- Is the trigger "the model called a tool"? If yes, hook.
- Is the work about enforcing a constraint the user can forget (formatting, file scope, secrets)? If yes, hook.
- Is the work about producing something the main thread will use? If yes, subagent.
Things that look like subagents but should be hooks:
- "Always run
pnpm formatafter every Edit." Hook. - "Always run the test suite before declaring done." Hook.
- "Always run
git statusbefore any commit." Hook.
Things that look like hooks but should be subagents:
- "Summarize a long PDF and put the summary in the chat." Subagent — it needs different tools and its own context.
- "Run a 5-step research plan in parallel and combine the answers." Subagent.
- "Find every place in the repo that uses a deprecated API." Subagent.
The place teams go wrong is using a hook to do a subagent's job. A "summarize this PDF" hook ends up reading the PDF inline in the main thread, blowing the context, and the user gets the first part of the summary truncated. Move it to a subagent and the main thread gets a clean pointer, and the summary can be a 200k-token scratchpad without polluting the per-run context.
The other way teams go wrong is using a subagent to do a hook's job. A "format the file after every edit" subagent that is invoked conditionally is the same job as a hook, but it is unreliable: the model can forget to invoke it, and the model can decide to skip the invocation. The hook runs deterministically, every time, on the tool event, not on the model's memory.
A good rule of thumb: if you find yourself writing "always remember to …" in CLAUDE.md, it is probably a hook. If you find yourself writing "sometimes ask X to do Y", it is probably a subagent.
Both pieces are part of the same toolbox. The forcing function for picking the right one is: what would happen if the model forgot? If the answer is "a small but consistent formatting bug", that's a hook's job. If the answer is "the model re-does an hour of work in the main thread", that's a subagent's job.
Shelf, the open-source desktop workspace we are building around Claude Code and Codex, is the project-level retrieval layer we use to find old sessions by project. The link is at
https://github.com/Harukaon/shelf if you want to compare it to your current workflow.
Tags: claudecode, codex, devtools, subagents, hooks, ai
Top comments (0)