Skip to content
Domain 1Task 1.5

Agent SDK Hooks

Learn this interactively

What You Need to Know

An Agent SDK hook is code that intercepts a tool call or a tool result. A tool call is the model's request to run a tool. The tool result is what the tool returns. The model's choices are probabilistic. A hook is deterministic: it applies the same rule every time, inside an otherwise probabilistic system. Hooks run between the model and the tools it calls. There, they enforce business rules and normalise data (convert it to one consistent format). Hooks implement the programmatic enforcement described in 1.4.

This lesson uses one made-up example throughout: a furniture shop whose support agent finds customers, tracks deliveries, issues refunds and approves discounts. Some of the shop's rules must apply every time. The shop's data arrives from three systems in three different formats.

Two Types of Hooks

The Agent SDK provides hooks at two points in the tool execution lifecycle. A PostToolUse hook runs after a tool executes and before the model processes the result. It can transform the result, so the model receives clean, normalised data whichever tool produced it. A PreToolUse hook, sometimes described as tool-call interception, runs before a tool executes. It can block the outgoing call, modify it, or redirect it to an alternative workflow. A blocked tool never runs.

In the Agent SDK hooks guide (checked September 2026), a PreToolUse hook answers with a permissionDecision of allow, deny, ask or defer. A deny decision stops the tool call. An optional updatedInput rewrites the tool's arguments before the tool runs. A PostToolUse hook can set updatedToolOutput to replace what the model sees, for built-in and MCP tools alike. The older updatedMCPToolOutput covered MCP tools only. The docs say to prefer updatedToolOutput. By the time PostToolUse fires, the tool has already run. A block at that point stops the loop but does not undo the side effect. On the furniture shop's refund tool, a PostToolUse hook would fire after the money had left the shop.

Key Concept

PostToolUse hooks transform data after execution. PreToolUse hooks enforce policy before execution.

PostToolUse Hooks: Data Normalisation

Different MCP tools return data in different formats. The furniture shop's agent uses three:

  1. get_customer returns dates as Unix timestamps (1710489600) and status as numeric codes (200, 404, 500).
  2. lookup_order returns dates as ISO 8601 strings ("2024-03-15T12:00:00Z") and status as English strings ("active", "cancelled", "pending").
  3. check_shipping returns dates as "DD/MM/YYYY" and status as single-character codes ("S" for shipped, "P" for pending).

Without normalisation, the model interprets these mixed formats afresh on every iteration, so its readings vary. It might parse a Unix timestamp correctly once and misread it the next time. It might swap the day and month in "DD/MM/YYYY", or read "P" as "processed" instead of "pending".

A PostToolUse hook converts every result before the model processes it.

  • Unix timestamps to ISO 8601 dates, such as "2024-03-15T12:00:00Z"
  • Numeric and single-character status codes to human-readable strings, such as "shipped", "pending" and "delivered"
  • Currency values to a consistent decimal format with a currency code
  • Date strings in various regional formats to a single standard format

The interpretation errors then disappear entirely.

PreToolUse Hooks: Policy Enforcement

PreToolUse hooks implement the prerequisite gates described in 1.4. The hook checks an outgoing call against a business rule before the tool executes. The hook blocks a call that breaks the rule, so there is no side effect to undo.

Refund threshold. A hook intercepts all calls to process_refund. If the amount exceeds $500, the hook blocks the call and redirects it to a human escalation workflow, and the refund tool never executes. At the furniture shop, the hook sends a $900 refund on a returned dining table to staff.

Compliance prerequisite gate. A hook intercepts calls to transfer_funds. If the agent has not completed the required anti-money laundering (AML) check for this session, the hook blocks the call. The hook's error message tells the agent to complete the AML check first.

Manager approval. A hook intercepts calls to approve_discount for discounts above 20%. It pauses execution and routes the request to a manager approval queue. The tool executes only after a manager approves, so a 25% discount on a sofa waits for the shop manager.

Exam Trap

PostToolUse runs after execution, when the non-compliant action has already occurred, so it cannot stop that action. Use a PreToolUse hook to block an action before it happens.

The Decision Framework

RequirementMechanismGuarantee
Must be followed 100% of the timeHooksDeterministic
Preferred but occasional deviation is acceptablePromptsProbabilistic

If a single failure would lose the business money or expose it to legal risk, use a hook. For a formatting preference or style guideline, prompt-based guidance is fine. A prompt is probabilistic, so even a good one sometimes fails. The question is whether the consequence of one failure justifies a deterministic guarantee, not whether prompts are "good enough".

Hooks vs Prompts: Side-by-Side Comparison

Refunds above $500. A prompt can say "For refunds above $500, escalate to a human agent". The prompt works most of the time, but a single failure means that the agent processes a large refund without approval. The process_refund hook above blocks such a refund 100% of the time.

International transfers must pass AML checks. A prompt can say "Always complete AML verification before processing international transfers". The prompt works 95% of the time. The 5% failure rate means some transfers skip AML checks, which is a regulatory violation. A PreToolUse hook that blocks transfer_funds until aml_check returns a pass works 100% of the time. No transfer can execute without AML verification.

Markdown formatting. A prompt can say "Format all responses using markdown with headers and bullet points". The prompt works most of the time, and an occasional plain-text reply to a furniture shop customer is not a business risk. A hook would be unnecessary overhead, because formatting preferences do not need deterministic enforcement.

In the exam

The exam tests when each hook runs. The exam presents PostToolUse hooks as a way to block policy-violating actions. That option is wrong, because the action has already happened. The exam also consistently offers prompt-based solutions as wrong options for scenarios that need deterministic enforcement. For a 100% requirement, the right answer is a hook.

Beyond PreToolUse and PostToolUse

Beyond the guide

The guide limits Task Statement 1.5 to PreToolUse and PostToolUse. Claude Code fires hooks at other points too. The practice questions cover one of those hooks, PreCompact. (Checked against the hooks reference, 16 September 2026.)

The same hook mechanism covers session events, not only tool calls. PreCompact runs immediately before Claude Code compacts the conversation (replaces it with a shorter summary). It runs in two cases: the user typed /compact (matcher manual), or the context reached the auto-compact window, the size at which Claude Code compacts automatically (matcher auto). The hook receives the transcript path, the trigger, and any custom instructions the user passed to /compact. The hook can therefore archive the full transcript to a log before the summary discards detail. Exit code 2, or "decision": "block" in the hook's JSON output, blocks the compaction. A PostCompact event fires afterwards. It carries the generated summary. The pattern matches the tool hooks: a Pre event can inspect and block, and a Post event can only observe what has already happened.

Exam Traps

Exam Trap

Using PostToolUse hooks to block policy-violating actions

PostToolUse hooks run after tool execution. By the time the hook fires, the non-compliant action has already been processed. Use PreToolUse hooks (pre-execution) to block actions before they happen.

Exam Trap

Enhanced prompt instructions as the solution for 100% compliance requirements

Prompts provide probabilistic compliance. If the business requires 100% enforcement (financial operations, regulatory compliance, security checks), a hook gives the deterministic guarantee that a prompt cannot.

Exam Trap

Leaving the model to normalise mixed data formats from different tools

Relying on the model to normalise heterogeneous data formats introduces inconsistency. PostToolUse hooks ensure clean, consistent data reaches the model every time, regardless of which tool produced it.

Exam Trap

Using a PreToolUse hook to convert or clean up the results a tool returns

PreToolUse fires before a tool runs and sees the outgoing call, not the result, so it has nothing to convert. Result transformation belongs in a PostToolUse hook, which runs after the tool executes and before the model processes the result.

Practice Scenario

An agent occasionally processes international transfers without required compliance checks. The compliance team requires 100% enforcement of anti-money laundering (AML) checks before any international transfer. What is the correct approach?

Build Exercise

Build Exercise

Implement Agent SDK Hooks for Normalisation and Policy Enforcement

Difficulty
60 minutes

What you'll learn

  • The distinction between PostToolUse hooks (after execution, data normalisation) and PreToolUse hooks (before execution, policy enforcement)
  • Why hooks provide deterministic guarantees that prompts cannot match
  • How to normalise heterogeneous data formats from multiple MCP tools into a consistent schema
  • How to implement threshold-based and prerequisite-based policy enforcement using pre-execution hooks
  • The decision framework: hooks for 100% requirements, prompts for preferences
  1. Create an agent with three MCP tools that return data in different formats: Tool A returns Unix timestamps and numeric status codes, Tool B returns ISO 8601 dates and string statuses, Tool C returns DD/MM/YYYY dates and single-character status codes

    Why: This recreates the exam’s example of mixed data formats. Without normalisation, the model must interpret three different date formats and three different status representations, leading to inconsistent parsing across iterations.

    You should see: Three tool implementations that each return data with distinct date and status formats. Tool A uses epoch seconds and numeric codes, Tool B uses ISO strings and English statuses, Tool C uses DD/MM/YYYY and single characters.

  2. Implement a PostToolUse hook that intercepts all tool results and normalises dates to ISO 8601 format and status codes to human-readable English strings

    Why: PostToolUse hooks run after execution but before the model processes the result. This is the correct hook for data normalisation — the exam tests whether you know that PostToolUse transforms data after execution, not before.

    You should see: A HookCallback registered under PostToolUse that reads tool_response and rewrites it: Unix timestamps and DD/MM/YYYY dates to ISO 8601, numeric and single-character status codes to English strings. The rewritten object comes back as updatedToolOutput inside hookSpecificOutput.

  3. Verify the model receives consistent data by testing with queries that require results from all three tools

    Why: Consistent data eliminates interpretation errors. Without normalisation, the model might confuse day/month order in DD/MM/YYYY or misinterpret status code P as processed instead of pending. Verification proves the hook works across all tool outputs.

    You should see: Three tool results that all use ISO 8601 dates and English status strings, whichever tool produced them. The model response should reference dates and statuses consistently.

  4. Add a PreToolUse hook that blocks process_refund when the amount exceeds $500 and redirects to a human escalation workflow

    Why: A PreToolUse hook runs before execution — the refund never processes. The exam specifically warns against using PostToolUse for blocking, because by that point the action has already occurred. Pre-execution interception is the only correct choice of hook for policy enforcement.

    You should see: A PreToolUse callback that inspects the refund amount and denies anything above $500, returning permissionDecision deny with a permissionDecisionReason. The refund tool never executes for denied calls.

  5. Add a second PreToolUse hook that blocks transfer_funds until aml_check has returned a pass result in the current session

    Why: This is the AML compliance scenario from the exam. Prompt instructions achieve 95% compliance, but regulatory requirements demand 100%. The hook provides deterministic enforcement that no prompt can match — a single missed AML check can result in legal penalties.

    You should see: Two callbacks: a PreToolUse hook on transfer_funds that denies until session state records a passing AML check, and a PostToolUse hook on aml_check that sets that state.

  6. Test both hooks by attempting to trigger the blocked operations and verify they are prevented before execution

    Why: Testing confirms that the hooks provide deterministic enforcement. The key verification is that blocked tools never execute — the hook prevents the call, not just logs a warning after the action has happened.

    You should see: The tool handlers for both denied operations do not run, and the model receives the permissionDecisionReason. Once the prerequisites are met, the same operations run.

Sources