Skip to content

docs: clarify api.on() vs api.registerHook() for plugin hooks#10680

Closed
yassinebkr wants to merge 2 commits intoopenclaw:mainfrom
yassinebkr:docs/hook-registration-guide
Closed

docs: clarify api.on() vs api.registerHook() for plugin hooks#10680
yassinebkr wants to merge 2 commits intoopenclaw:mainfrom
yassinebkr:docs/hook-registration-guide

Conversation

@yassinebkr
Copy link
Copy Markdown
Contributor

@yassinebkr yassinebkr commented Feb 6, 2026

PR: Document api.on() vs api.registerHook() for plugin developers

Type: docs-only

Problem

OpenClaw exposes two hook registration methods in the plugin API:

  • api.on(event, handler) — registers a typed hook into registry.typedHooks. These are actually executed by the hook runner.
  • api.registerHook(events, handler, opts) — registers hook metadata into registry.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 registerHook first. 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 when opts.name is missing — again, no error, no warning.

What this PR does

  • docs/plugin.md: Adds a "Registering typed hooks (inline)" section with a clear api.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:

  • Adds a new “Plugin hook registration” section to docs/hooks.md that explains why api.on() is the correct choice for executable typed hooks, while api.registerHook() only records metadata for UI/diagnostics.
  • Expands docs/plugin.md under Plugin hooks with separate guidance for registering hooks from a directory vs registering typed hooks inline, including a comparison table and examples.
  • Also documents the naming convention difference between plugin typed hook keys (underscored) and workspace internal hook events (colon-separated) to reduce confusion.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk.
  • Docs-only changes are internally consistent, follow existing linking conventions, and address the previously noted anchor/event-name concerns without introducing new broken references or contradictory guidance.
  • No files require special attention

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
@openclaw-barnacle openclaw-barnacle bot added the docs Improvements or additions to documentation label Feb 6, 2026
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +334 to +341

```ts
export default function register(api) {
// ✅ Correct — this handler will execute
api.on("gateway_start", async (event, ctx) => {
api.logger.info("Gateway started!");
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Comment on lines +650 to +662
## 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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@mudrii

This comment was marked as spam.

@openclaw-barnacle
Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added the stale Marked as stale due to inactivity label Mar 8, 2026
@openclaw-barnacle
Copy link
Copy Markdown

Closing due to inactivity.
If you believe this PR should be revived, post in #pr-thunderdome-dangerzone on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants