Skip to content

Agent SDK Hooks

Prompts guide behavior. Hooks, Permissions, Callbacks, and Application logic enforce behavior.

1. Core Concept

Where to enforce rules in an agentic system.

A weak answer says:

Tell Claude not to do dangerous things.

A strong answer says:

Use hooks, permission rules, approval callbacks, validators, and deterministic application logic to block, modify, approve, or audit actions at runtime.

Anthropic’s Agent SDK docs describe hooks as callback functions that run on agent events such as tool calls, session start, subagent start/stop, compaction, or execution stop.

Hooks can block dangerous operations, log/audit tool calls, transform inputs or outputs, require approval, and manage lifecycle state. (Claude Code)


2. Mental Model

Hook = Lifecycle Interception Point

A hook is code that runs automatically at a specific point in the agent lifecycle.

Example:

Claude wants to run:
Bash("rm -rf /tmp/build")

PreToolUse hook fires first.
Hook inspects command.
Hook returns deny.
Tool does not execute.
Claude receives the denial reason.

The important point:

Hooks run outside the model’s free-form reasoning. They are programmatic control points.

Claude can propose an action, but the hook can block or modify it before execution.


3. Hooks Vs Prompts

Requirement Is Prompt enough? Better enforcement
Preferred writing style Yes System prompt / instructions
“Be careful with files” No PreToolUse hook or permission rule
Block writes to .env No PreToolUse hook or deny rule
Log all tool calls No PostToolUse hook
Require human approval for deploy No canUseTool, ask rule, approval workflow
Run tests after edits No PostToolUse hook
Prevent completion until tests pass No Stop hook
Prevent subagent from finishing early No SubagentStop hook
Enforce regulated workflow No Application logic + hooks + approval gates

Heuristic:

If violation has real consequences, do not rely only on prompting.


4. Where Hooks Fit in the Permission Flow

When Claude requests a tool, the SDK evaluates permissions in a specific order. A hook can deny a call outright, but a hook returning allow does not skip later deny or ask rules. (Claude)

High-yield implications:

Situation Correct interpretation
Hook returns allow, but deny rule matches Tool is still denied
Deny rule matches in bypassPermissions Tool is still blocked
allowed_tools lists Read only, but mode is bypassPermissions Other tools can still run unless denied
dontAsk mode and unapproved tool Denied, not prompted
plan mode and file edit Prompts through approval callback; edits are not auto-approved

The exam will likely test precedence. Do not assume one allow setting overrides all other controls.


5. Programmatic Enforcement Layers

Think of enforcement as a stack.

Layer Best for Example
System prompt Behavioural guidance “Prefer minimal changes.”
Allowed tools Pre-approve safe tools Auto-allow Read, Glob, Grep
Deny rules Static hard blocks Block Bash(rm *)
PreToolUse hook Dynamic runtime validation before execution Block writes outside /src
PostToolUse hook Audit or react after execution Run linter after file edit
Stop hook Prevent premature completion Continue until tests pass
Subagent hooks Track or constrain subagents Log subagent output or block early stop
canUseTool callback Human approval or UI-mediated decisions Ask user before deploy
Application logic Business-critical deterministic rules Refund > $500 requires manager approval

Use the lowest reliable enforcement layer. For example, “never delete production data” should be enforced in code or permission policy, not just in a model instruction.


6. Must-Know Hook Events

Anthropic’s hooks reference divides events across the session lifecycle, per-turn lifecycle, and tool-call lifecycle. Common exam-relevant events include UserPromptSubmit, PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, PostToolBatch, SubagentStart, SubagentStop, Stop, PreCompact, and SessionEnd. (Claude Code)

High-Yield Subset

Hook event Fires when Exam use case
UserPromptSubmit Before Claude processes user prompt Reject prompt containing forbidden data or inject context
PreToolUse Before a tool executes Block, allow, ask, defer, or modify tool input
PermissionRequest Permission dialog would appear External approval notification
PostToolUse After successful tool execution Logging, audit, post-edit checks
PostToolUseFailure After failed tool execution Error logging, recovery signal
PostToolBatch After a batch of parallel tool calls Inject conventions before next model turn
Stop Claude is about to stop Check completion criteria; prevent stopping
SubagentStart Subagent starts Track spawning
SubagentStop Subagent finishes Validate subagent completion
PreCompact Before compaction Archive transcript before summarization
Notification Status notification Send Slack/PagerDuty update

Shortcut:

Before execution → PreToolUse
After execution → PostToolUse
Before finishing → Stop
Before subagent finishes → SubagentStop
Before prompt enters model → UserPromptSubmit
Before compaction → PreCompact

6.1. PreToolUse: The Enforcement Workhorse

Use PreToolUse when you must decide before a tool runs.

Best for:

  • Blocking destructive shell commands
  • Preventing writes to protected files
  • Validating API request parameters
  • Enforcing path restrictions
  • Requiring approval for sensitive tools
  • Sanitizing or redirecting tool inputs
  • Controlling MCP tool calls.

Example policy:

If tool_name == "Bash" and command contains "rm -rf":
    deny with reason

Anthropic’s hook docs show a PreToolUse hook that blocks writes to .env files by returning permissionDecision: "deny" with a reason. (Claude Code)

Trap:

Do not use PostToolUse to block dangerous execution. By then, the tool already ran.

6.2. PostToolUse: Audit and Reaction, Not Prevention

Use PostToolUse after the tool succeeds.

Best for:

  • Logging tool use
  • Recording audit trails
  • Running lint/test checks after edits
  • Sending webhook notifications
  • Adding context after a tool result
  • Detecting tool output anomalies

But PostToolUse cannot prevent the original action because it has already happened. Claude Code’s hook reference explicitly distinguishes events that can block from those that cannot; PostToolUse cannot block the action and can only show feedback after the fact. (Claude Code)

Good use:

After Write/Edit, run formatter or test suite.
Bad use:
After Bash("delete-prod-db"), decide whether deletion was allowed.

6.3. Stop Hook: Completion Enforcement

A Stop hook runs when Claude is about to finish. Use it to enforce completion criteria.

Good cases:

  • Tests must pass before Claude stops
  • Required checklist must be complete
  • Output must include required sections
  • All requested files must be updated
  • No unresolved TODOs remain

Anthropic’s hooks reference gives an example of a multi-criteria Stop hook that checks whether all user-requested tasks are complete, whether errors need addressing, and whether follow-up work is needed; if not OK, Claude continues working. (Claude Code)

Trap:

A Stop hook is not the same as stop_reason.
stop_reason controls the API agentic loop. A Stop hook can intercept Claude Code / Agent SDK lifecycle completion and enforce additional criteria.

6.4. SubagentStart And SubagentStop

From D1.2, subagents are isolated workers and all coordination should flow through the coordinator. For D1.5, hooks let you observe or enforce subagent lifecycle behavior.

Use subagent hooks for:

  • Logging spawned subagents
  • Tracking parallel work
  • Preventing premature subagent completion
  • Validating subagent output
  • Auditing subagent tool usage

Anthropic’s Agent SDK hook docs list SubagentStart and SubagentStop and show a SubagentStop example that logs subagent completion, transcript path, and tool-use ID. (Claude Code)

Important trap:

Subagents do not automatically inherit every permission assumption safely. Be careful with broad permission modes.

Anthropic’s permission docs warn that when a parent uses bypassPermissions, acceptEdits, or auto, subagents inherit that mode and it cannot be overridden per subagent; in particular, inherited bypassPermissions can give subagents full autonomous system access. (Claude)

6.5 Hook Decisions

For SDK callback hooks, a PreToolUse hook can return:

Decision Meaning
allow Approve the operation
deny Block the operation
ask Escalate to user approval
defer End query so it can be resumed later
updatedInput Modify tool input before execution
permissionDecisionReason Tell Claude why a tool was denied
additionalContext Add context after a tool result
updatedToolOutput Replace tool output before Claude sees it

Anthropic documents these fields under hook outputs and notes that updatedToolOutput replaces tool output before Claude sees it, while additionalContext can append information to tool results. It also states that when multiple hook or permission results apply, the priority is deny > defer > ask > allow. (Claude Code)

Implication:

If any matching hook denies, the operation is blocked even if another hook allows.

6.6 Command Hook Exit Codes

For Claude Code command hooks, exit codes matter.

Exit code / output Meaning
0 with no JSON No decision; normal flow continues
0 with valid JSON Structured control decision
2 Blocking error for blockable events
Other non-zero Usually non-blocking error

The hooks reference says exit 2 is the “stop, don’t do this” signal for blockable events such as PreToolUse, PermissionRequest, UserPromptSubmit, Stop, SubagentStop, and PreCompact; it also says PostToolUse cannot block because the tool already ran. (Claude Code)

Exam trap:

Exit code 1 is not the standard enforcement signal in Claude Code hooks. Use exit 2 or structured JSON for blocking.


7 Permissions: Allow, Deny, Ask, and Modes

Hooks are only one enforcement mechanism. Permission rules and modes are equally relevant.

7.1 Allow and Deny Rules

Rule Meaning
allowed_tools=["Read", "Grep"] Auto-approve these tools
disallowed_tools=["Bash"] Remove Bash tool from Claude’s available tools
disallowed_tools=["Bash(rm *)"] Keep Bash available, but block matching rm calls
disallowed_tools=["*"] Remove every tool

Anthropic’s permission docs distinguish allow rules from deny rules: allow rules pre-approve matching tools, while deny rules can remove a whole tool or block scoped patterns; scoped deny rules still apply even in bypassPermissions. (Claude)

7.2 Permission Modes

Mode Exam meaning
default Standard permission behaviour
dontAsk Deny anything not pre-approved
acceptEdits Auto-accept file edits/filesystem operations in scope
bypassPermissions Auto-approve tools unless denied/asked by earlier controls; dangerous
plan Explore and plan; file edits are not auto-approved

Use dontAsk for headless locked-down agents. Use plan when Claude should inspect and propose but not modify files. Use bypassPermissions only in isolated controlled environments, because it grants broad system access unless deny/ask/hooks stop it. (Claude)

7.3. canUseTool: Human Approval and User Input

Use canUseTool when your application needs to surface tool approval requests or clarifying questions to the user. Anthropic’s docs say Claude may need input when it wants permission for a tool or when it asks a clarifying question through AskUserQuestion; both trigger canUseTool, which pauses execution until the callback returns. (Claude Code)

Good use cases:

  • User approval before deletion
  • User approval before deployment
  • User selects which database/environment to use
  • User confirms an irreversible action
  • UI-mediated “allow / deny / modify” decision

Anthropic documents that a callback can allow, deny, approve with changes, remember a permission update, reject with guidance, or redirect Claude through application logic. (Claude Code)

Exam distinction:

Need Use
Automatically block every .env write Hook or deny rule
Ask user whether to allow a specific file delete canUseTool
Ask user which output format they want AskUserQuestion via canUseTool
Send Slack message when approval is needed PermissionRequest or notification hook

7.4 Async Hooks

Async hooks are useful for side effects that should not block Claude.

Examples:

  • Logging
  • Sending metrics
  • Starting background tests
  • Notifying Slack
  • Firing analytics

Async hooks cannot block, modify, or inject context into the current operation because Claude continues immediately. Anthropic’s docs explicitly state that async hook decisions such as permissionDecision and continue have no effect after the triggering action has proceeded. (Claude Code)

Trap:

Do not use an async hook for a mandatory security check.

Use synchronous PreToolUse or permission rules for enforcement.


8. Hook Types

Claude Code hooks can be implemented as command hooks, HTTP hooks, MCP tool hooks, prompt hooks, or agent hooks.

  • Command hooks run shell commands;
  • HTTP hooks call endpoints;
  • MCP tool hooks call connected MCP tools;
  • Prompt hooks use an LLM for single-turn evaluation;
  • Agent hooks spawn a subagent to verify conditions.

(Claude Code)

Hook type Best use
Command Deterministic local scripts, validation, linting
HTTP Centralized policy service or audit endpoint
MCP tool Use connected MCP capability as validator
Prompt Soft judgement / rubric check
Agent Richer verification requiring file inspection
Async command Logging or long-running side effect

Anthropic marks agent hooks as experimental and says production workflows should prefer command hooks. (Claude Code)


9. Security Best Practices

Hooks can be powerful and dangerous. Command hooks run with the user’s system permissions, so hook scripts must be reviewed and tested. Anthropic’s hooks reference recommends validating and sanitizing inputs, quoting shell variables, blocking path traversal, using absolute paths, and skipping sensitive files like .env, .git, and keys. (Claude Code)

Traps:

  • Do not pass raw tool input into shell commands without quoting
  • Do not trust hook input blindly
  • Do not assume hooks run in a sandbox unless your environment enforces one
  • Do not use a prompt hook as a hard security boundary
  • Do not let bypassPermissions run outside a controlled environment
  • Do not assume allowed_tools constrains bypassPermissions

10. Decision Table

Scenario wording Best answer
“Block dangerous command before execution” PreToolUse hook or deny rule
“Log every file change” PostToolUse hook
“Prevent Claude from stopping before tests pass” Stop hook
“Validate subagent output before accepting it” SubagentStop hook
“Ask user before deleting files” canUseTool callback / ask rule
“Headless agent with only Read/Grep allowed” allowed_tools + dontAsk
“Claude should plan but not edit” plan mode
“Need auto-approve file edits in isolated repo” acceptEdits
“Need full speed in isolated sandbox but still block rm” bypassPermissions + deny rules/hooks
“Need security policy to apply to all developers” Managed policy settings / project hooks
“Need external approval service” HTTP hook or canUseTool integration
“Need non-blocking analytics” Async hook

Test yourself on this topic Interactive questions for Task 1.5 — Agent SDK Hooks, with instant explanations and scoring.
Start quiz →