Agent SDK Hooks
Hooks inject deterministic behavior into a probabilistic model. Learn when to use PreToolUse to block actions and PostToolUse to normalize data - and never mix them up.
Agent SDK hooks inject deterministic behavior into an otherwise probabilistic system. They sit at the boundary between the model's decisions and real-world execution, intercepting tool calls and tool results to enforce business rules and normalize data. Two hook types dominate the exam, and the entire trick is knowing which runs before execution and which runs after.
PreToolUse: block before execution
A PreToolUse hook runs *before* a tool executes. It can block, modify, or redirect the outgoing call, which makes it the tool for policy enforcement and prerequisite gates. Because it fires first, a non-compliant action never happens. Typical uses:
- Block
process_refundwhen the amount exceeds $500 and redirect to human escalation. - Block
transfer_fundsuntil an AML check has returned a verified pass. - Pause
approve_discountabove 20% and route it into an approval queue.
PostToolUse: normalize after execution
A PostToolUse hook runs *after* the tool completes but *before* the model sees the result. Its main job is data normalization - guaranteeing clean, consistent data reaches the model no matter which tool produced it. For example, three MCP tools might return Unix timestamps, ISO 8601 dates, and DD/MM/YYYY dates, plus numeric, English, and single-character status codes. Without normalization the model re-interprets that chaos every iteration and makes parsing errors; a PostToolUse hook converts everything to one format first.
| Concern | Hook | Timing | Purpose |
|---|---|---|---|
| Policy / compliance | PreToolUse | Before execution | Block or redirect non-compliant calls |
| Data consistency | PostToolUse | After execution, before model | Normalize heterogeneous tool output |
// PreToolUse: enforce a refund ceiling BEFORE the tool runs.
const preToolUse = async (toolName: string, input: any) => {
if (toolName === "process_refund" && input.amount > 500) {
return { decision: "block", reason: "Refunds over $500 need approval." };
}
return { decision: "allow" };
};
// PostToolUse: normalize timestamps AFTER the tool runs.
const postToolUse = async (toolName: string, output: any) => {
if (output.created_at && typeof output.created_at === "number") {
output.created_at = new Date(output.created_at * 1000).toISOString();
}
return { updatedToolOutput: output };
};If a requirement must hold 100% of the time - a financial ceiling, an AML check - use a hook. If it is a preference where occasional deviation is fine, such as a formatting style, a prompt is sufficient and a hook is needless overhead.
Enforcing the ceiling in a PostToolUse hook. It fires *after* the tool runs, so the refund has already been issued - "blocking" here only reacts to a violation that already happened.
// PostToolUse - too late, money already moved
if (output.amount > 500) return { decision: "block" };Enforce it in a PreToolUse hook, which runs *before* execution, so the non-compliant call never happens.
// PreToolUse - blocks before the tool runs
if (input.amount > 500) return { decision: "block" };Using PostToolUse to "block" a bad action is a classic trap: it runs AFTER the tool already executed, so the transfer or refund has happened and the violation already occurred. Pre-execution blocking requires PreToolUse. Memorize the direction: PreToolUse before, PostToolUse after.
Relying on the model to reconcile three date formats every turn invites inconsistent parsing. A PostToolUse hook transforms the data once, deterministically, so the model always sees the same clean shape.
How the exam will try to trick you
The distractors below look right under time pressure — learn the tell.
- The trap
Block a non-compliant
transfer_fundsorprocess_refundcall with a PostToolUse hook.Correct answerBlock it with a PreToolUse hook that fires before execution.
Why: PostToolUse runs after the tool already executed - the transfer or refund has already happened.
- The trap
Use stronger prompt instructions to guarantee a 100% financial or regulatory rule.
Correct answerEnforce the rule with a hook for deterministic guarantees.
Why: Prompts are probabilistic; only hooks provide the 100% enforcement compliance operations require.
- The trap
Let the model reconcile heterogeneous date and status formats each turn.
Correct answerNormalize with a PostToolUse hook so clean, consistent data reaches the model.
Why: Re-interpreting mixed formats every iteration invites inconsistent parsing errors.
- The trap
Treat PreToolUse and PostToolUse as interchangeable on timing.
Correct answerPreToolUse enforces before execution; PostToolUse transforms after it.
Why: The wrong direction either misses the chance to prevent an action or needlessly blocks completed work.
Key takeaways
- Hooks inject deterministic behavior at the boundary between model decisions and execution.
- PreToolUse runs before execution - use it to block, modify, or redirect calls for policy enforcement.
- PostToolUse runs after execution but before the model - use it to normalize heterogeneous data.
- PostToolUse cannot block a violation because the action already happened - only PreToolUse blocks.
- Use hooks for 100% requirements (financial, regulatory); use prompts for preferences like formatting.
- Do not rely on the model to normalize inconsistent tool output - a PostToolUse hook does it deterministically.
Frequently asked questions
What is the difference between PreToolUse and PostToolUse hooks in the Claude Agent SDK?+
PreToolUse runs before a tool executes and can block, modify, or redirect the call - ideal for policy enforcement. PostToolUse runs after the tool executes but before the model sees the result - ideal for normalizing data so the model receives consistent output.
Can a PostToolUse hook stop a non-compliant tool call?+
No. PostToolUse runs after the tool has already executed, so any financial or compliance violation has already occurred. To prevent a call from running you must use a PreToolUse hook, which fires before execution.
When should I use a hook instead of a prompt instruction?+
Use a hook when a rule must be followed 100% of the time, such as a refund ceiling or an AML check, because hooks are deterministic. Use a prompt for preferences where occasional deviation is acceptable, such as response formatting, where a hook would be unnecessary overhead.