> ## Documentation Index
> Fetch the complete documentation index at: https://allhandsai-extend-api-reference-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# openhands.sdk.hooks

> API reference for openhands.sdk.hooks module

OpenHands Hooks System - Event-driven hooks for automation and control.

Hooks are event-driven scripts that execute at specific lifecycle events
during agent execution, enabling deterministic control over agent behavior.

***

### class HookConfig

Bases: `BaseModel`

Configuration for all hooks.
Hooks can be configured either by loading from .openhands/hooks.json or
by directly instantiating with typed fields:

# Direct instantiation with typed fields()

config = HookConfig(

pre\_tool\_use=\[
: HookMatcher(
: matcher=”terminal”,
hooks=\[HookDefinition(command=”block\_dangerous.sh”)]
)

]

)

# Load from JSON file:

config = HookConfig.load(“.openhands/hooks.json”)

#### Properties

* `model_config`: = (configuration object)
  Configuration for the model, should be a dictionary conforming to \[ConfigDict]\[pydantic.config.ConfigDict].
* `post_tool_use`: list\[[HookMatcher](#class-hookmatcher)]
* `pre_tool_use`: list\[[HookMatcher](#class-hookmatcher)]
* `session_end`: list\[[HookMatcher](#class-hookmatcher)]
* `session_start`: list\[[HookMatcher](#class-hookmatcher)]
* `stop`: list\[[HookMatcher](#class-hookmatcher)]
* `user_prompt_submit`: list\[[HookMatcher](#class-hookmatcher)]

#### Methods

#### classmethod from\_dict()

Create HookConfig from a dictionary.

Supports both legacy format with “hooks” wrapper and direct format:
: # Legacy format:
(JSON configuration object)

# Direct format:

(JSON configuration object)

#### get\_hooks\_for\_event()

Get all hooks that should run for an event.

#### has\_hooks\_for\_event()

Check if there are any hooks configured for an event type.

#### is\_empty()

Check if this config has no hooks configured.

#### classmethod load()

Load config from path or search .openhands/hooks.json locations.

* Parameters:
  * `path` – Explicit path to hooks.json file. If provided, working\_dir is ignored.
  * `working_dir` – Project directory for discovering .openhands/hooks.json.
    Falls back to cwd if not provided.

#### classmethod merge()

Merge multiple hook configs by concatenating handlers per event type.

Each hook config may have multiple event types (pre\_tool\_use,
post\_tool\_use, etc.). This method combines all matchers from all
configs for each event type.

* Parameters:
  `configs` – List of HookConfig objects to merge.
* Returns:
  A merged HookConfig with all matchers concatenated, or None if no configs
  or if the result is empty.

#### save()

Save hook configuration to a JSON file using snake\_case field names.

***

### class HookDecision

Bases: `str`, `Enum`

Decisions a hook can make about an operation.

#### Methods

#### ALLOW = 'allow'

#### DENY = 'deny'

***

### class HookDefinition

Bases: `BaseModel`

A single hook definition.

#### Properties

* `async_`: bool
* `command`: str
* `model_config`: = (configuration object)
  Configuration for the model, should be a dictionary conforming to \[ConfigDict]\[pydantic.config.ConfigDict].
* `timeout`: int
* `type`: [HookType](#class-hooktype)

***

### class HookEvent

Bases: `BaseModel`

Data passed to hook scripts via stdin as JSON.

#### Properties

* `event_type`: [HookEventType](#class-hookeventtype)
* `message`: str | None
* `metadata`: dict\[str, Any]
* `model_config`: = (configuration object)
  Configuration for the model, should be a dictionary conforming to \[ConfigDict]\[pydantic.config.ConfigDict].
* `session_id`: str | None
* `tool_input`: dict\[str, Any] | None
* `tool_name`: str | None
* `tool_response`: dict\[str, Any] | None
* `working_dir`: str | None

***

### class HookEventProcessor

Bases: `object`

Processes events and runs hooks at appropriate points.

Call set\_conversation\_state() after creating Conversation for blocking to work.

HookExecutionEvent is emitted for each hook execution when emit\_hook\_events=True,
providing full observability into hook execution for clients.

#### Methods

#### **init**()

#### is\_action\_blocked()

Check if an action was blocked by a hook.

#### is\_message\_blocked()

Check if a message was blocked by a hook.

#### on\_event()

Process an event and run appropriate hooks.

#### run\_session\_end()

Run SessionEnd hooks. Call before conversation is closed.

#### run\_session\_start()

Run SessionStart hooks. Call after conversation is created.

#### run\_stop()

Run Stop hooks. Returns (should\_stop, feedback).

#### set\_conversation\_state()

Set conversation state for blocking support.

***

### class HookEventType

Bases: `str`, `Enum`

Types of hook events that can trigger hooks.

#### Methods

#### POST\_TOOL\_USE = 'PostToolUse'

#### PRE\_TOOL\_USE = 'PreToolUse'

#### SESSION\_END = 'SessionEnd'

#### SESSION\_START = 'SessionStart'

#### STOP = 'Stop'

#### USER\_PROMPT\_SUBMIT = 'UserPromptSubmit'

***

### class HookExecutor

Bases: `object`

Executes hook commands with JSON I/O.

#### Methods

#### **init**()

#### execute()

Execute a single hook.

#### execute\_all()

Execute multiple hooks in order, optionally stopping on block.

***

### class HookManager

Bases: `object`

Manages hook execution for a conversation.

#### Methods

#### **init**()

#### cleanup\_async\_processes()

Cleanup all background hook processes.

#### get\_blocking\_reason()

Get the reason for blocking from hook results.

#### has\_hooks()

Check if there are hooks configured for an event type.

#### run\_post\_tool\_use()

Run PostToolUse hooks after a tool completes.

#### run\_pre\_tool\_use()

Run PreToolUse hooks. Returns (should\_continue, results).

#### run\_session\_end()

Run SessionEnd hooks when a conversation ends.

#### run\_session\_start()

Run SessionStart hooks when a conversation begins.

#### run\_stop()

Run Stop hooks. Returns (should\_stop, results).

#### run\_user\_prompt\_submit()

Run UserPromptSubmit hooks.

***

### class HookMatcher

Bases: `BaseModel`

Matches events to hooks based on patterns.

Supports exact match, wildcard (\*), and regex (auto-detected or /pattern/).

#### Properties

* `hooks`: list\[[HookDefinition](#class-hookdefinition)]
* `matcher`: str

#### Methods

#### matches()

Check if this matcher matches the given tool name.

#### model\_config = (configuration object)

Configuration for the model, should be a dictionary conforming to \[ConfigDict]\[pydantic.config.ConfigDict].

#### model\_post\_init()

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

* Parameters:
  * `self` – The BaseModel instance.
  * `context` – The context.

***

### class HookResult

Bases: `BaseModel`

Result from executing a hook.

Exit code 0 = success, exit code 2 = block operation.

#### Properties

* `additional_context`: str | None
* `async_started`: bool
* `blocked`: bool
* `decision`: [HookDecision](#class-hookdecision) | None
* `error`: str | None
* `exit_code`: int
* `reason`: str | None
* `should_continue`: bool
  Whether the operation should continue after this hook.
* `stderr`: str
* `stdout`: str
* `success`: bool

#### Methods

#### model\_config = (configuration object)

Configuration for the model, should be a dictionary conforming to \[ConfigDict]\[pydantic.config.ConfigDict].

***

### class HookType

Bases: `str`, `Enum`

Types of hooks that can be executed.

#### Methods

#### COMMAND = 'command'

#### PROMPT = 'prompt'


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.