Skip to main content
Hooks let you intercept and modify OpenClaw’s behavior at key lifecycle points. Hooks are registered via the Plugin API and called synchronously or asynchronously depending on the event type.

Registering Hooks

Use api.registerHook to register a hook handler:
You can register multiple events at once:

Available Hooks

Agent Lifecycle

before_model_resolve

Fired before resolving the model/provider for an agent run. Use this to override model selection based on the prompt.
Event: { prompt: string } Return: { modelOverride?: string, providerOverride?: string } or void

before_prompt_build

Fired before building the prompt for an agent run. Session messages are available at this point.
Event: { prompt: string, messages: unknown[] } Return: { systemPrompt?: string, prependContext?: string } or void

before_agent_start (legacy)

Fired before an agent run starts. Combines both before_model_resolve and before_prompt_build phases.
Event: { prompt: string, messages?: unknown[] } Return: { modelOverride?: string, providerOverride?: string, systemPrompt?: string, prependContext?: string } or void

llm_input

Fired before sending a prompt to the LLM. Use for logging, telemetry, or analytics.
Event:

llm_output

Fired after receiving a response from the LLM.
Event:

agent_end

Fired after an agent run completes (success or failure).
Event:

Session Management

session_start

Fired when a new session starts.
Event: { sessionId: string, resumedFrom?: string }

session_end

Fired when a session ends.
Event: { sessionId: string, messageCount: number, durationMs?: number }

before_compaction

Fired before session compaction (history summarization). Useful for archiving session history.
Event:

after_compaction

Fired after session compaction completes.
Event: { messageCount: number, tokenCount?: number, compactedCount: number, sessionFile?: string }

before_reset

Fired when a session is reset (/new, /reset commands).
Event: { sessionFile?: string, messages?: unknown[], reason?: string }

Message Flow

message_received

Fired when a message is received from a channel.
Event: { from: string, content: string, timestamp?: number, metadata?: Record<string, unknown> } Context: { channelId: string, accountId?: string, conversationId?: string }

message_sending

Fired before sending a message to a channel. Can modify or cancel the message.
Event: { to: string, content: string, metadata?: Record<string, unknown> } Return: { content?: string, cancel?: boolean } or void Context: { channelId: string, accountId?: string, conversationId?: string }

message_sent

Fired after a message is sent to a channel.
Event: { to: string, content: string, success: boolean, error?: string } Context: { channelId: string, accountId?: string, conversationId?: string }

Tool Execution

before_tool_call

Fired before a tool is called. Can modify parameters or block the call.
Event: { toolName: string, params: Record<string, unknown> } Return: { params?: Record<string, unknown>, block?: boolean, blockReason?: string } or void Context: { agentId?: string, sessionKey?: string, toolName: string }

after_tool_call

Fired after a tool completes.
Event: { toolName: string, params: Record<string, unknown>, result?: unknown, error?: string, durationMs?: number } Context: { agentId?: string, sessionKey?: string, toolName: string }

tool_result_persist

Fired before writing a tool result to the session transcript. Can modify or drop the message.
Event: { toolName?: string, toolCallId?: string, message: AgentMessage, isSynthetic?: boolean } Return: { message?: AgentMessage } or void

before_message_write

Fired before writing any message to the session transcript. Can block the write.
Event: { message: AgentMessage, sessionKey?: string, agentId?: string } Return: { block?: boolean, message?: AgentMessage } or void

Gateway Lifecycle

gateway_start

Fired when the gateway starts.
Event: { port: number } Context: { port?: number }

gateway_stop

Fired when the gateway stops.
Event: { reason?: string } Context: { port?: number }

Hook Files (Advanced)

OpenClaw also supports hook files with frontmatter metadata. These are typically used for bundled hooks in src/hooks/bundled/. Hook directory structure:
HOOK.md:
handler.ts:
Plugins can register hook directories:
See src/hooks/plugin-hooks.ts for details.

Example: Session Logger

Next Steps

  • Tools - Build custom agent tools
  • Channels - Create channel integrations
  • Examples - Real-world plugin examples