#Ensuring a custom Openclaw plugin loads at gateway start / restart?

1 messages · Page 1 of 1 (latest)

pearl oasis
#

I'm developing a plugin that uses hooks so I can log LLM calls Openclaw makes. The plugin is starting simple but will evolve to something more complex. It seems, however, that new versions of the plugin don't always get loaded when I do a gateway restart or stop/start sequence. How can I ensure that restarts, or stop/start sequences, always load the latest version of the plugin?

swift breachBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> âś… Mark Solution

quiet ploverBOT
tender kilnBOT
# pearl oasis I'm developing a plugin that uses hooks so I can log LLM calls Openclaw makes. T...

For local plugin development, the least surprising path is to install it as a linked plugin, not as a copied install:

openclaw plugins install --link /absolute/path/to/your-plugin
openclaw plugins enable <plugin-id>
openclaw plugins list --enabled --verbose
openclaw gateway restart

A normal openclaw plugins install /path/to/plugin copies the plugin into OpenClaw’s managed extensions dir, so editing your source tree later will not necessarily change what the gateway loads. --link adds the source dir to plugins.load.paths, so restarts discover that directory directly.

A few gotchas:

  • If your manifest/package points at dist/index.js, rebuild before restarting. The gateway will load the built file, not your edited src/index.ts.
  • If you are testing an installed/copy-based plugin instead of a linked one, reinstall/update it before restart: openclaw plugins install /path/to/plugin --force or openclaw plugins update <id>.
  • Verify what OpenClaw thinks it loaded with openclaw plugins inspect <plugin-id> --json or openclaw plugins list --verbose; check the shown source/path/version.

Docs: https://docs.openclaw.ai/cli/plugins and https://docs.openclaw.ai/plugins/building-plugins

tender kilnBOT
pearl oasis
#

Thanks, that's helpful.

I tried

openclaw plugins install --link

and it told me the plugin was already installed, which makes sense since it's already in plugins.load.paths.

However, when I run

openclaw plugins list --enabled --verbose

the plugin doesn't appear in the list even though it's in plugins.load.paths, plugins.allow, and plugins.entries with enabled: true. I can verify the plugin works correctly — when I issue a gateway config.get tool call from within the session, it triggers a config re-read and the plugin activates and starts logging perfectly.

What could cause a workspace plugin (kind: workspace) to be silently skipped during auto-enable on boot when it loads fine after a config re-read? The plugin only uses hooks (model_call_started/model_call_ended) and doesn't need any plugin slot — is that relevant?

Follow-ups I'm wondering about:

  1. Does a plugin need to be referenced by a plugins.slots entry to be guaranteed to load on every boot?
  2. If so, is there an alternative way to ensure a hooks-only workspace plugin loads reliably on gateway start/restart?
  3. Does openclaw plugins inspect <id> --json work for plugins in plugins.load.paths, or does it only inspect plugins installed via openclaw plugins install?
tender kilnBOT
# pearl oasis Thanks, that's helpful. I tried openclaw plugins install --link and it tol...

I checked the current plugin startup path. Short version: no, a hooks-only plugin should not need a plugins.slots entry.

Answers:

  1. plugins.slots is only for exclusive plugin kinds like memory / context-engine. It is not the general “load this plugin” mechanism.
  2. For a hooks-only local plugin, the intended reliable boot path is: discoverable via plugins.load.paths, allowed if you use plugins.allow, and explicitly enabled via plugins.entries.<id>.enabled: true. Current source has a startup planner path for explicitly enabled non-channel “sidecar” plugins, which is exactly the bucket a hooks-only plugin should fall into.
  3. openclaw plugins inspect <id> --json should work for discoverable plugins from plugins.load.paths; it is not limited to managed installs. For linked/path plugins the install field may be null, but the plugin should still inspect.

The part that smells off is “loads after config.get”. config.get builds the runtime config schema with plugins, so it can cause plugin discovery/loading through a different path than gateway startup. If startup skips it but schema/config reload sees it, I’d check these first:

openclaw --version
openclaw plugins inspect <plugin-id> --json
openclaw plugins list --json

In the JSON, look for the plugin’s exact canonical id, origin, status, source, and any diagnostics. Also make sure the id in plugins.allow and plugins.entries.<id> exactly matches the manifest id.

tender kilnBOT
# pearl oasis Thanks, that's helpful. I tried openclaw plugins install --link and it tol...

One nuance: if you literally put kind: "workspace" in openclaw.plugin.json, I’d remove that. “workspace” is an origin, not a documented manifest kind; documented kind values are slot kinds like memory / context-engine. A normal hooks-only plugin can omit kind entirely.

For clarity I’d configure it like this:

plugins: {
  enabled: true,
  allow: ["your-plugin-id"],
  load: {
    paths: ["/absolute/path/to/your-plugin"],
  },
  entries: {
    "your-plugin-id": {
      enabled: true,
    },
  },
tender kilnBOT
pearl oasis
#

Thanks for the excellent insights and tips.

I tried the suggestions, but I'm still hitting the same problem. Here's what I did and what I found (note: the plugin is called "llm-monitor"):

Changes made:

  • Removed "kind": "workspace" from the manifest (as advised — it's not a valid manifest kind)
  • Verified the plugin is already in plugins.load.paths, plugins.allow, and plugins.entries.<id>.enabled: true

What happened after a cold stop/start:

  • Gateway started with http server listening (2 plugins: browser, ctx-engine; 12.5s) — llm-monitor was not loaded
  • No [plugins] [llm-monitor] message in the journal at all
  • The CSV log file has no entries from the new session

What openclaw plugins list --json shows:

  • llm-monitor is listed with origin: "config", enabled: true, status: "loaded"
  • But the diagnostics section at the top warns:

"Persisted plugin registry policy does not match current config; using derived plugin index. Run openclaw plugins registry --refresh to update the persisted registry."

This suggests a stale persisted registry might be the root cause. The config-derived index knows about the plugin (it shows in list --json), but the startup planner might be loading from the stale registry instead.

Also notable: openclaw plugins inspect <id> --json and openclaw plugins list --json hang when run from the CLI while the gateway is running — they seem to wait for a gateway response that times out. I got the output through the tool's exec instead.

Questions:

  1. Could the stale persisted registry explain why the plugin isn't loaded on cold boot despite being in plugins.load.paths + plugins.allow + plugins.entries?
  2. Is openclaw plugins registry --refresh safe to run while the gateway is running, or does it require a stopped gateway?
  3. If a stale registry is the issue, is there a way to trigger a full config-aware boot that disregards the persisted registry?

Running Openclaw v2026.5.12 .

tender kilnBOT
# pearl oasis Thanks for the excellent insights and tips. I tried the suggestions, but I'm st...

That warning is relevant, but I think there are two separate things in play on v2026.5.12:

  1. v2026.5.12 uses a cold persisted plugin registry for startup planning. plugins list --json can fall back to a derived index and show the plugin correctly while also warning that the persisted registry is stale. So yes, refresh it.

  2. For startup loading, plugins.entries.llm-monitor.enabled: true is not always enough for a hooks-only plugin anymore. The manifest should declare startup intent. The current manifest docs say: “Omitting activation.onStartup no longer startup-loads the plugin implicitly.”

For a plugin that must observe all model calls after gateway boot, I’d set this in openclaw.plugin.json:

{
  "id": "llm-monitor",
  "name": "LLM Monitor",
  "configSchema": {
    "type": "object",
    "additionalProperties": false
  },
tender kilnBOT
# pearl oasis Thanks for the excellent insights and tips. I tried the suggestions, but I'm st...
  "activation": {
    "onStartup": true,
    "onCapabilities": ["hook"]
  }
}

Then rebuild if your manifest/runtime is copied into dist, refresh the registry, and restart:

openclaw plugins registry --refresh
openclaw plugins registry --json
openclaw gateway restart

openclaw plugins registry --refresh is intended as the repair path and writes the generated registry state. It should be safe to run while the gateway is up, but it will not mutate the already-running gateway’s active plugin registry; restart afterward. If your CLI hangs while the gateway is running, run the refresh with the gateway stopped, then start it again. The hang itself is worth filing if reproducible, because plugins list / registry inspection is supposed to be local registry/config work, not a long gateway RPC dependency.

tender kilnBOT
# pearl oasis Thanks for the excellent insights and tips. I tried the suggestions, but I'm st...

For #3: the break-glass env is OPENCLAW_DISABLE_PERSISTED_PLUGIN_REGISTRY=1, but the code marks it deprecated and points people back to openclaw plugins registry --refresh / openclaw doctor --fix. I’d only use that briefly to confirm the diagnosis, not as the fix.

Also: model_call_started / model_call_ended are the right hooks for telemetry without raw prompt/response content. allowConversationAccess=true is only needed for raw conversation hooks like llm_input / llm_output.

Docs: https://docs.openclaw.ai/plugins/manifest and https://docs.openclaw.ai/cli/plugins

pearl oasis
#

Follow-up — resolved.

The fixes worked. Summary of what it took:

  1. Added activation.onStartup: true and activation.onCapabilities: ["hook"] to the manifest. That was the main fix — without it, the startup planner wasn't pulling in the hooks-only plugin on cold boot.

  2. Ran openclaw plugins registry --refresh to fix the stale persisted registry. Without this, even the corrected manifest was ignored because the startup planner was using cached metadata.

  3. After those two changes, a cold stop/start brought up the plugin cleanly: http server listening (XX plugins: ... llm-monitor). The plugin is fully functional.

Also verified that code changes to the entrypoint (index.js) are picked up on restart without any extra steps — only manifest changes require the registry refresh.

Thanks for the help — I wouldn't have found the activation.onStartup: true requirement in the docs on my own.

tender kilnBOT
# pearl oasis **Follow-up — resolved.** The fixes worked. Summary of what it took: 1. **Adde...

Nice, glad we pinned it down.

That summary is the right takeaway for future folks:

  • hooks-only plugin that must be active from boot: activation.onStartup: true
  • hook capability hint: activation.onCapabilities: ["hook"]
  • after manifest/policy changes: openclaw plugins registry --refresh
  • after runtime/entrypoint code changes: gateway restart is enough for linked/path plugins

If this fixed the thread, please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow indexes it cleanly.