OpenClaw hooks: run scripts when your agent starts, resets, or speaks
Hooks are event scripts inside the Gateway, distinct from Automations (schedules), skills (instructions), and webhooks (inbound HTTP, confusingly under the same config key). The full map.
OpenClaw hooks are small scripts that run inside the Gateway when agent events fire: a /new or /reset command, session compaction, gateway startup and shutdown, messages arriving or being sent. They’re the event-driven leg of OpenClaw’s automation family: hooks react to events, Automations (cron) fire on schedules, and skills are instructions with no trigger at all. One confusion to clear early: the hooks config key also covers inbound webhooks, a different feature that happens to share the name.
What a hook is, concretely
A hook is a directory holding a HOOK.md (YAML frontmatter naming it and declaring which events it listens to) plus a handler written in TypeScript or JavaScript, run in-process by the Gateway. That’s worth noting if you’re arriving from Claude Code, whose hooks are shell commands: OpenClaw’s are code the Gateway loads. The documented events cover command lifecycle (command:new, command:reset, command:stop), session mechanics (session:auto-reset, compaction before/after), agent bootstrap, gateway lifecycle (gateway:startup, gateway:shutdown, gateway:pre-restart), and message flow (message:received, message:sent, transcription and preprocessing stages in between).
OpenClaw ships five bundled examples that show the shape of the tool: session-memory (saves session context into the workspace’s memory folder when a session resets: automatic memory at the exact moment it would be lost), bootstrap-extra-files, command-logger, compaction-notifier, and boot-md (runs your BOOT.md at gateway startup). Hooks live in four places with precedence: bundled, plugin-provided, managed (~/.openclaw/hooks/), and per-workspace (<workspace>/hooks/, disabled by default until explicitly enabled).
Enabling and managing them
The master switch is hooks.internal.enabled, with per-hook toggles under hooks.internal.entries.<name>.enabled. The Gateway loads internal hooks only once you’ve enabled the feature or configured at least one entry. The CLI does the day-to-day:
openclaw hooks list --eligible openclaw hooks info session-memory openclaw hooks enable session-memory openclaw hooks disable command-logger
Two operational facts to respect. Hook changes need a gateway restart. The docs say it plainly: “Restart your gateway process so hooks reload.” And a hook handler is operator-installed code running inside your Gateway process: install hook packs the way you’d install plugins: from sources you trust, because there is no sandbox between a hook and the process that holds your agent’s credentials.
Hooks vs Automations vs skills
- Hooks: when X happens, run this script. Deterministic code on lifecycle events; no model involved unless the script asks for one.
- Automations: at this time, do this. The Gateway’s persistent scheduler (one-shots, cron expressions, and more) that can wake the agent, covered separately.
- Skills: here’s how to do X, when you’re asked. Markdown instructions the agent loads; they never fire on their own.
The naming trap: “hooks” vs webhooks
The same top-level hooks config key also configures the Gateway’s inbound HTTP endpoints:
hooks: { enabled: true, token: "shared-secret", path: "/hooks" }That turns on authenticated webhook routes like POST /hooks/wake and POST /hooks/agent so external systems can poke your agent. That is a separate feature (event hooks are hooks.internal.*, inbound webhooks are the rest of the hooks block), and the docs themselves now file webhooks under the Automations pages. If you came here wanting “trigger my agent from an HTTP request,” that’s your path: set a strong token, and note the outbound direction (automations delivering to a webhook) has its own SSRF-guarded config. If you came here wanting “do something every time my agent resets,” that’s internal hooks, and session-memory is probably the first one worth turning on.