Follow Discord
Sweep 03 Nov 2026 · 22:27Z Build v2.1.318 536 read Stable v2.1.311 Latest v2.1.318 Next v2.1.318 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-code

Intercept and control agent behavior with hooks changedagent-sdk/hooks

Nearest release: v2.1.318, published an hour before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 3 Nov 2026 23:05 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 3 Nov 2026 23:07 UTC.

Upstream edited
Recorded here
Lines+49added
Lines−1removed
From line 220 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits22to this page, all time

### Block the action when a callback fails #### Events that behave differently #### Startup errors for `onFailure`

The whole hunk

from line 220, old and new numbered
/
lines
from line 220
220220| `matcher` | `string` | `undefined` | Pattern matched against the event's filter field, following the [rules for matchers in settings files](https://code.claude.com/docs/en/hooks.md#matcher-patterns). For tool hooks, that field is the tool name. Built-in tools include `Bash`, `Read`, `Write`, `Edit`, `Glob`, `Grep`, `WebFetch`, `Agent`, and others. See [Tool Input Types](https://code.claude.com/docs/en/agent-sdk/typescript.md#tool-input-types) for the full list. MCP tools use the pattern `mcp__<server>__<action>`, where `<server>` is the key you use in the `mcpServers` configuration, spelled as the [tool naming convention](https://code.claude.com/docs/en/agent-sdk/mcp.md#tool-naming-convention) describes. |
221221| `hooks` | `HookCallback[]` | - | Required. Array of callback functions to execute when the pattern matches |
222222| `timeout` | `number` | `undefined` | Timeout in seconds. When omitted, Claude Code applies the [event's default timeout](#hook-timeout). Your SDK callbacks follow the `command` hook defaults |
223| `onFailure` | `"continue" \| "block"` | `undefined` | What a failed callback does. Set `"block"` to [block the action when a callback fails](#block-the-action-when-a-callback-fails). In Python, use `on_failure` |
223224 
224225Use the `matcher` pattern to target specific tools whenever possible. A matcher with `'Bash'` only runs for Bash commands, while omitting the pattern runs your callbacks for every occurrence of the event.
225226 
from line 280
279280>
280281> Async outputs can't block, modify, or inject context into the operation since the agent has already moved on. Use them only for side effects like logging, metrics, or notifications.
281282 
283### Block the action when a callback fails
284 
285On most events, if a callback throws or returns output that fails validation, the action goes ahead and your app receives an [`SDKInformationalMessage`](https://code.claude.com/docs/en/agent-sdk/typescript#sdkinformationalmessage) warning whose `tag` is `hook_callback_failed`. A `PreToolUse` guard that crashes then lets the tool call reach the normal permission flow. A callback that returns nothing, such as a path with no `return`, also counts as failing. In Python, read `tag` from `SystemMessage.data`.
286 
287To block the action instead, set `onFailure: "block"` in TypeScript or `on_failure="block"` in Python on the matcher. Requires TypeScript Agent SDK v0.3.317 or later, or Python Agent SDK v0.2.177 or later. This example blocks a Bash call when `check_policy` in Python or `checkPolicy` in TypeScript fails:
288 
289```python Python theme={null}
290options = ClaudeAgentOptions(
291 hooks={
292 "PreToolUse": [
293 HookMatcher(matcher="Bash", hooks=[check_policy], on_failure="block")
294 ]
295 }
296)
297```
298 
299```typescript TypeScript theme={null}
300import type { Options } from "@anthropic-ai/claude-agent-sdk";
301 
302const options: Options = {
303 hooks: {
304 PreToolUse: [{ matcher: "Bash", hooks: [checkPolicy], onFailure: "block" }]
305 }
306};
307```
308 
309To test it, make the callback raise an error and ask Claude to run a Bash command. The tool result includes `failed; blocking because onFailure is "block"`, and Claude doesn't see your error text.
310 
311Return `{}` when the callback has no opinion. With `"block"` set, a path with no `return` blocks the action. A callback that catches its own error and returns `{}` isn't failing, so let the error propagate from a guard.
312 
313#### Events that behave differently
314 
315These events don't always block with `"block"` set:
316 
317* **`Stop`, `SubagentStop`, `TaskCompleted`, and `TeammateIdle`**: these events ignore the option, so the action goes ahead.
318* **`PermissionRequest`**: the block counts only if it arrives before your `canUseTool` callback answers.
319* **`PostToolUse`**: the tool has already run, so Claude receives the failure as feedback.
320 
321A callback that exceeds its timeout follows [Hook timeout](#hook-timeout). With `"block"` set, a timeout also blocks `PreCompact`, `Elicitation`, and `WorktreeCreate`.
322 
323#### Startup errors for `onFailure`
324 
325With `"block"` set, the query fails at startup and sends no prompt when it can't honor the option:
326 
327* **Claude Code doesn't support the option**: the error includes `does not honor`. Update Claude Code, or remove the option.
328* **The session was already running and didn't register your hooks**: the error includes `did not register your hooks`. Start a new session.
329 
282330## Examples
283331 
284332Several examples in this section show only the callback function. To run one, register the callback under the matching event in the `hooks` field of your options, as shown in [Configure hooks](#configure-hooks).
from line 823
775823* `Stop` and `SubagentStop`: the timed-out callback counts as returning no decision. The agent or subagent stops as if that callback had allowed it, and a decision from your other hooks on the event still applies. Before Claude Code v2.1.273, a timed-out `Stop` or `SubagentStop` callback counted as a failed hook run, and Claude Code discarded the decisions of your other hooks on the event.
776824* `SessionStart`: the timed-out callback counts as returning no output, and the session continues with the output of your other `SessionStart` hooks.
777825* `PreModelSwitch`: Claude Code blocks the model switch. A hook that doesn't answer hasn't approved the switch.
778* Other events, such as `Notification`, `PreCompact`, and `PostModelSwitch`: Claude Code logs the failure and continues.
826* Other events, such as `Notification`, `PreCompact`, and `PostModelSwitch`: Claude Code logs the failure and continues. With [`onFailure: "block"`](#block-the-action-when-a-callback-fails), a timeout on `PreCompact`, `Elicitation`, or `WorktreeCreate` blocks the action.
779827 
780828The first time a `Stop` or `SessionStart` callback times out in the main session, Claude Code also adds an [`SDKInformationalMessage`](https://code.claude.com/docs/en/agent-sdk/typescript#sdkinformationalmessage) to the message stream saying the app driving the session didn't respond. Later timeouts don't repeat that message while your app stays unresponsive.
781829 
Feedback