What a hook is
A hook is a small command — typically a shell command or script — that the worker runs automatically at a specific moment, instead of something you trigger by hand. You author hooks once, as a worker file, and every task that worker runs picks them up. Hooks live in ahooks.json file at the worker’s file scope, alongside its Skills, worker instructions, and memory. Because they’re worker files, you can edit them yourself through the Files panel, or ask the worker to write them for you.
This is the deliberate exception to how a worker’s definition otherwise works: a running task pins the worker’s instructions, model, and connections as a snapshot for its whole lifetime, but hooks are read live at the start of every turn instead. If you fix a broken hook mid-task, the very next turn picks up the fix. A worker-less task has no worker file scope, so it has no hooks.
When hooks fire
Hooks attach to named events in the loop. Each event fires at a precise point, and each has a different amount of power over what happens next.
A hook only reacts to the events and tools it’s configured to match — you point it at a tool name (or a pattern covering several) so it only runs where it’s relevant, for example only on
bash and write_file calls, or every web_* tool.
Every task gets its own isolated sandbox automatically, and each hook command runs inside it with a timeout, so a slow or hanging hook can’t stall the turn indefinitely.
Configuring hooks
Hooks are defined in ahooks.json file, grouped by event. Each entry pairs a matcher (which tool names it applies to) with one or more commands to run:
hooks.json
matcher above ("bash|write_file") limits that hook to two tools; an omitted matcher, like the Stop entry, matches everything for that event. Each hook command receives the details of the call — which tool, what arguments, and (for PostToolUse) the result — as JSON on standard input, and has to answer within its timeout (30 seconds by default, capped at 60) before the turn moves on.
A worker’s hooks are capped to keep them lightweight: up to 8 matchers per event and 4 commands per matcher, with the whole file limited to 16 KB. If
hooks.json is malformed, it’s ignored — with a warning — rather than breaking the task.What hooks are for
Validate input
Run a PreToolUse hook to check a tool’s arguments before they run — for example, rejecting a shell command that touches a protected path or a file write outside an approved directory.
Auto-format output
Run a PostToolUse hook that reformats or annotates a result — for example, running a linter or formatter after a file edit and feeding the outcome back to the worker.
Enforce guardrails
Use PreToolUse hooks as a second layer of policy on top of tool approvals — an org-specific rule a worker should never be allowed to break, regardless of what the model decides.
Audit and review
Use Stop or TaskCompleted hooks to log activity, or to kick off a review pass — for example, notifying an improvement-reviewer once a task settles, feeding self-improvement.
How a hook responds
A hook command reports back with an exit code:- Success — the call proceeds normally. The hook can still attach extra context for
PostToolUse. - Block — for
PreToolUse, the call is denied and the reason is shown to the worker as the tool’s result, so it can adjust course; forPostToolUseandStop, the call already happened and the reason is appended as context. - Anything else — treated as a non-blocking warning. The turn continues, and the warning is recorded so you can see it happened.
Hooks and human-in-the-loop
Hooks and approvals solve different problems, and it helps to keep them separate:- Human-in-the-loop approvals decide whether a call is allowed to happen at all — a person (or the permission classifier) says yes or no before execution.
- Hooks run after that decision, once a call has already been approved. A hook can only add a further restriction — it can block a call that was allowed, but it can never approve, skip, or auto-answer an approval on its own.
Next steps
The agentic loop
See where PreToolUse, PostToolUse, and Stop fit in a turn.
Human-in-the-loop
Understand approvals, the permission classifier, and decision memory.
Self-improvement & learning
Learn how a Stop hook can feed a worker’s review-and-learn loop.
Skills
See the other worker files that live alongside
hooks.json.