docs: clarify api.on() vs api.registerHook() for plugin hooks#10680
docs: clarify api.on() vs api.registerHook() for plugin hooks#10680yassinebkr wants to merge 2 commits intoopenclaw:mainfrom
Conversation
Plugin developers using api.registerHook() will have their hooks silently dropped — handlers register without errors but never fire. The correct method is api.on() which registers typed hooks that the hook runner actually executes. - Add hook registration section to plugin.md with examples - Add cross-reference in hooks.md - Include warning about the silent-drop behavior
|
|
||
| ```ts | ||
| export default function register(api) { | ||
| // ✅ Correct — this handler will execute | ||
| api.on("gateway_start", async (event, ctx) => { | ||
| api.logger.info("Gateway started!"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Incorrect hook event name
The inline typed hook example uses api.on("gateway_start", ...), but the rest of the hooks docs list the gateway startup event as gateway:startup (colon), not gateway_start (underscore). If gateway_start isn’t a real typed hook key, this example will never fire and recreates the “silent failure” issue the section is trying to prevent. Please update the example (and the matching registerHook examples below) to the canonical event name used by the hooks system.
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/plugin.md
Line: 334:341
Comment:
**Incorrect hook event name**
The inline typed hook example uses `api.on("gateway_start", ...)`, but the rest of the hooks docs list the gateway startup event as `gateway:startup` (colon), not `gateway_start` (underscore). If `gateway_start` isn’t a real typed hook key, this example will never fire and recreates the “silent failure” issue the section is trying to prevent. Please update the example (and the matching `registerHook` examples below) to the canonical event name used by the hooks system.
How can I resolve this? If you propose a fix, please make it concise.
docs/hooks.md
Outdated
| ## Plugin hook registration (api.on vs api.registerHook) | ||
|
|
||
| If you're registering hooks **from a plugin** (not from a `HOOK.md` + `handler.ts` | ||
| directory), there are two different API methods — and choosing the wrong one | ||
| means your handler silently never fires. | ||
|
|
||
| - **`api.on(event, handler)`** — registers a typed hook that **actually | ||
| executes** when the event fires. This is what you want. | ||
| - **`api.registerHook(events, handler, opts)`** — registers hook **metadata** | ||
| for UI/diagnostics only. The handler is **not** called by the hook runner. | ||
|
|
||
| See [Plugins → Registering typed hooks](/plugin#registering-typed-hooks-inline) | ||
| for full details, code examples, and the common pitfalls. |
There was a problem hiding this comment.
Heading anchor contains parentheses
This heading includes parentheses: ## Plugin hook registration (api.on vs api.registerHook). Repo docs guidelines note Mintlify anchors can break with certain punctuation; parentheses are a common source of odd/unstable anchors. Consider simplifying the heading text (e.g. drop the parenthetical) and keep the clarification in the body so /hooks#... anchors remain stable.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/hooks.md
Line: 650:662
Comment:
**Heading anchor contains parentheses**
This heading includes parentheses: `## Plugin hook registration (api.on vs api.registerHook)`. Repo docs guidelines note Mintlify anchors can break with certain punctuation; parentheses are a common source of odd/unstable anchors. Consider simplifying the heading text (e.g. drop the parenthetical) and keep the clarification in the body so `/hooks#...` anchors remain stable.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.…n vs internal hook naming
bfc1ccb to
f92900f
Compare
This comment was marked as spam.
This comment was marked as spam.
|
This pull request has been automatically marked as stale due to inactivity. |
|
Closing due to inactivity. |
PR: Document
api.on()vsapi.registerHook()for plugin developersType: docs-only
Problem
OpenClaw exposes two hook registration methods in the plugin API:
api.on(event, handler)— registers a typed hook intoregistry.typedHooks. These are actually executed by the hook runner.api.registerHook(events, handler, opts)— registers hook metadata intoregistry.hooks. These are used for UI/diagnostics only and are never executed by the hook runner.The names are similar enough that plugin developers naturally reach for
registerHookfirst. When they do, registration succeeds without errors, the hook appears to be set up correctly, but the handler never fires. There is no warning logged. This leads to hours of silent-failure debugging.An additional footgun:
registerHook()silently drops entries whenopts.nameis missing — again, no error, no warning.What this PR does
docs/plugin.md: Adds a "Registering typed hooks (inline)" section with a clearapi.on()example, and a prominent warning callout explaining the difference between the two methods, including a comparison table and code examples showing correct vs incorrect usage.docs/hooks.md: Adds a "Plugin hook registration" section that summarizes the distinction and links to the plugin docs for full details.Who this helps
Any developer writing an OpenClaw plugin that needs event-driven hooks. This is the kind of trap you only fall into once — but it costs hours when you do. The docs now make the correct path obvious.
Greptile Overview
Greptile Summary
This docs-only PR clarifies the distinction between plugin hook registration APIs:
docs/hooks.mdthat explains whyapi.on()is the correct choice for executable typed hooks, whileapi.registerHook()only records metadata for UI/diagnostics.docs/plugin.mdunder Plugin hooks with separate guidance for registering hooks from a directory vs registering typed hooks inline, including a comparison table and examples.Confidence Score: 5/5