HOOK.md script for command and Gateway events such as
/new, /reset, /stop, agent:bootstrap, or gateway:startup.
Quick start
Register typed plugin hooks withapi.on(...) from your plugin entry:
priority. Same-priority hooks
keep registration order.
Hook catalog
Hooks are grouped by the surface they extend. Names in bold accept a decision result (block, cancel, override, or require approval); all others are observation-only. Agent turnbefore_model_resolve— override provider or model before session messages loadbefore_prompt_build— add dynamic context or system-prompt text before the model callbefore_agent_start— compatibility-only combined phase; prefer the two hooks abovebefore_agent_reply— short-circuit the model turn with a synthetic reply or silenceagent_end— observe final messages, success state, and run duration
llm_input— observe provider input (system prompt, prompt, history)llm_output— observe provider output
before_tool_call— rewrite tool params, block execution, or require approvalafter_tool_call— observe tool results, errors, and durationtool_result_persist— rewrite the assistant message produced from a tool resultbefore_message_write— inspect or block an in-progress message write (rare)
inbound_claim— claim an inbound message before agent routing (synthetic replies)message_received— observe inbound content, sender, thread, and metadatamessage_sending— rewrite outbound content or cancel deliverymessage_sent— observe outbound delivery success or failurebefore_dispatch— inspect or rewrite an outbound dispatch before channel handoffreply_dispatch— participate in the final reply-dispatch pipeline
session_start/session_end— track session lifecycle boundariesbefore_compaction/after_compaction— observe or annotate compaction cyclesbefore_reset— observe session-reset events (/reset, programmatic resets)
subagent_spawning/subagent_delivery_target/subagent_spawned/subagent_ended— coordinate subagent routing and completion delivery
gateway_start/gateway_stop— start or stop plugin-owned services with the Gatewaybefore_install— inspect skill or plugin install scans and optionally block
Tool call policy
before_tool_call receives:
event.toolNameevent.params- optional
event.runId - optional
event.toolCallId - context fields such as
ctx.agentId,ctx.sessionKey,ctx.sessionId, and diagnosticctx.trace
block: trueis terminal and skips lower-priority handlers.block: falseis treated as no decision.paramsrewrites the tool parameters for execution.requireApprovalpauses the agent run and asks the user through plugin approvals. The/approvecommand can approve both exec and plugin approvals.- A lower-priority
block: truecan still block after a higher-priority hook requested approval. onResolutionreceives the resolved approval decision —allow-once,allow-always,deny,timeout, orcancelled.
Prompt and model hooks
Use the phase-specific hooks for new plugins:before_model_resolve: receives only the current prompt and attachment metadata. ReturnproviderOverrideormodelOverride.before_prompt_build: receives the current prompt and session messages. ReturnprependContext,systemPrompt,prependSystemContext, orappendSystemContext.
before_agent_start remains for compatibility. Prefer the explicit hooks above
so your plugin does not depend on a legacy combined phase.
before_agent_start and agent_end include event.runId when OpenClaw can
identify the active run. The same value is also available on ctx.runId.
Non-bundled plugins that need llm_input, llm_output, or agent_end must set:
plugins.entries.<id>.hooks.allowPromptInjection=false.
Message hooks
Use message hooks for channel-level routing and delivery policy:message_received: observe inbound content, sender,threadId,messageId,senderId, optional run/session correlation, and metadata.message_sending: rewritecontentor return{ cancel: true }.message_sent: observe final success or failure.
ctx.sessionKey, ctx.runId, ctx.messageId, ctx.senderId, ctx.trace,
ctx.traceId, ctx.spanId, ctx.parentSpanId, and ctx.callDepth. Prefer
these first-class fields before reading legacy metadata.
Prefer typed threadId and replyToId fields before using channel-specific
metadata.
Decision rules:
message_sendingwithcancel: trueis terminal.message_sendingwithcancel: falseis treated as no decision.- Rewritten
contentcontinues to lower-priority hooks unless a later hook cancels delivery.
Install hooks
before_install runs after the built-in scan for skill and plugin installs.
Return additional findings or { block: true, blockReason } to stop the
install.
block: true is terminal. block: false is treated as no decision.
Gateway lifecycle
Usegateway_start for plugin services that need Gateway-owned state. The
context exposes ctx.config, ctx.workspaceDir, and ctx.getCron?.() for
cron inspection and updates. Use gateway_stop to clean up long-running
resources.
Do not rely on the internal gateway:startup hook for plugin-owned runtime
services.