Skip to main content
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]
  • pre_tool_use: list[HookMatcher]
  • session_end: list[HookMatcher]
  • session_start: list[HookMatcher]
  • stop: list[HookMatcher]
  • user_prompt_submit: list[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 HookEvent

Bases: BaseModel Data passed to hook scripts via stdin as JSON.

Properties

  • event_type: 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

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 | 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’