Introduction
Beyond basic event handling, hooks support advanced patterns like chaining multiple handlers, distributing hooks as npm packages, and configuring per-hook environment variables. These patterns let you build reusable, composable automation layers that can be shared across teams and projects.
Key Concepts
- Hook Chaining: Running multiple hook handlers for the same event in sequence
- Hook Packs: npm packages that bundle reusable hook collections, configured via
openclaw.hooksin package.json - Per-Hook Configuration: Setting environment variables and parameters for individual hook handlers
- Composability: Building complex automation by combining simple, focused hooks
- Hook Middleware: Treating hooks as middleware that transforms data as it flows through the pipeline
Real World Context
A company's platform team creates an npm package called @company/openclaw-hooks that bundles their standard compliance hooks: message logging, PII detection, and rate limiting. When a new team onboards to OpenClaw, they simply install the package and add it to their configuration. The hooks are maintained centrally and updates roll out across all teams through normal npm version bumps.
Deep Dive
Hook Chaining
You can attach multiple handlers to the same event using an array:
json{ "hooks": { "message": { "received": [ "./hooks/log-message.js", "./hooks/filter-pii.js", "./hooks/rate-limit.js" ] } } }
When a message is received, all three handlers run in order: first the message is logged, then PII is filtered, then rate limiting is checked. If any handler in the chain fails, subsequent handlers are skipped.
Hook Packs via npm
Hook packs are npm packages that export hook configurations:
json{ "openclaw": { "hooks": [ "@company/openclaw-compliance-hooks", "@company/openclaw-analytics-hooks" ] } }
Each package exports a hooks configuration object that OpenClaw merges with your local hooks. This enables a library ecosystem where common patterns are packaged and shared.
Per-Hook Configuration
Individual hooks can receive configuration through environment variables:
json{ "hooks": { "message": { "received": { "handler": "./hooks/notify-slack.js", "env": { "SLACK_WEBHOOK_URL": "${SLACK_ALERTS_URL}", "NOTIFY_THRESHOLD": "high" } } } } }
The env block sets environment variables available to the hook at runtime. This lets you reuse the same hook script with different configurations across agents.
Composable Patterns
Combine chaining with per-hook config for sophisticated pipelines:
json{ "hooks": { "message": { "received": [ { "handler": "./hooks/classify-intent.js", "env": { "MODEL": "fast" } }, { "handler": "./hooks/route-by-intent.js", "env": { "DEFAULT_AGENT": "general" } } ] } } }
The first hook classifies the message intent. The second routes to the appropriate agent based on classification. Each hook has its own configuration, making the pipeline modular.
Common Pitfalls
- Creating circular hook chains: If hook A triggers an event that fires hook B, which triggers hook A again, you get an infinite loop.
- Over-relying on hook packs without auditing them: Third-party hook packs have access to all message data. Audit packages before adding them.
- Not versioning hook packs properly: Using floating npm versions can introduce breaking changes unexpectedly.
Best Practices
- Build hooks as focused, single-purpose handlers that compose through chaining.
- Pin hook pack versions in package.json to prevent unexpected changes.
- Document the hook chain order for each event so team members understand the pipeline.
Summary
- Hook chaining runs multiple handlers for the same event in a defined sequence
- Hook packs distribute reusable hook collections as npm packages
- Per-hook configuration passes environment variables to individual handlers
- Composable patterns combine chaining with configuration for modular pipelines
- Always audit third-party hook packs and pin their versions