Chapter 7

The Hook System

Lifecycle events — inject custom logic at key moments

What Is a Hook?

A Hook is a programming pattern: when a program reaches a specific moment, it automatically triggers a preset action. In OpenHarness, the Hook system provides 4 timing points: • SESSION_START — Triggered when a session begins • SESSION_END — Triggered when a session ends • PRE_TOOL_USE — Triggered before tool execution • POST_TOOL_USE — Triggered after tool execution PRE_TOOL_USE and POST_TOOL_USE are the most commonly used — they let you insert custom logic before and after each tool execution.

What Can Hooks Do?

Common use cases for hooks: 📝 Logging Record every tool call's parameters and results for auditing and debugging. 🛡️ Extra Security Checks For example, check if a Bash command contains dangerous operations — an extra layer of defense on top of the permission system. 🔄 Auto-Formatting Automatically run a code formatter after file writes. 📊 Analytics Track tool usage frequency, execution time, etc. 🚫 Blocking Operations PreToolUse hooks can prevent tool execution — for example, blocking deploys outside work hours.

Hook Execution Flow

openharness/hooks/executor.py
1async def execute_tool_with_hooks(tool_call, context):
2 # Step 1: Run PreToolUse hooks
3 pre_result = await run_hooks("pre_tool_use", {
4 "tool_name": tool_call.name,
5 "tool_params": tool_call.params,
6 })
7
8 # If a hook requests blocking, return immediately
9 if pre_result.should_block:
10 return ToolResult("Blocked by Hook", is_error=True)
11
12 # Step 2: Permission check (after hooks)
13 permission = await check_permission(tool_call)
14 if not permission.allowed:
15 return ToolResult("Permission denied", is_error=True)
16
17 # Step 3: Actually execute the tool
18 result = await tool.execute(tool_call.params)
19
20 # Step 4: Run PostToolUse hooks
21 await run_hooks("post_tool_use", {
22 "tool_name": tool_call.name,
23 "result": result,
24 })
25
26 return result

Every time a tool is called, hooks execute in this order:

Four Types of Hooks

OpenHarness supports four different hook implementations: 1. Command Hook Executes a shell command. The simplest and most direct approach. 2. HTTP Hook Sends an HTTP request to a specified URL. Ideal for integrating with external services. 3. Prompt Hook Lets the Agent process a prompt itself. Suitable for complex judgment logic. 4. Agent Hook Launches a full sub-agent to handle it. For scenarios requiring multi-step reasoning. In most cases, a Command Hook is sufficient.

How to Configure Hooks

settings.json
1{
2 "hooks": {
3 "pre_tool_use": [
4 {
5 "type": "command",
6 "command": "echo 'About to execute tool: $TOOL_NAME'",
7 "match_tools": ["Bash"]
8 }
9 ],
10 "post_tool_use": [
11 {
12 "type": "command",
13 "command": "echo 'Tool execution complete: $TOOL_NAME'"
14 }
15 ]
16 }
17}

Hooks are configured in settings.json:

📌 Key Takeaway
Hooks Make the Harness Observable and Extensible
The core value of the Hook system: inject custom logic at key moments without modifying engine code. This makes OpenHarness not just a tool, but an observable, extensible platform.
🧠 Check Your Understanding
What is the most important special ability of PreToolUse hooks?