openclaw - ✅(Solved) Fix [Bug]: Slot plugin tools not exposed to Agent due to Rollup code-splitting state isolation [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#48919Fetched 2026-04-08 00:51:03
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
1
Participants
Timeline (top)
labeled ×2commented ×1cross-referenced ×1subscribed ×1

Plugin-registered tools from slot plugins (e.g., memory-lancedb-pro) are successfully added to the plugin registry but are not exposed as callable tools to the LLM agent during runs. The tools appear in openclaw plugins info <id> output, but the agent cannot invoke them. This is caused by Rollup code-splitting creating independent module instances with separate state variables, similar to issues #47625 and #47683.

Root Cause

This issue is identical in nature to reported issues #47625 (LINE webhook 404) and #47683 (plugin registerTool state loss).

The root cause is Rollup code-splitting creating independent module instances with separate state variables:

registry-DtTKJfN8.js → setActivePluginRegistry uses 'state'
auth-profiles-*.js → setActivePluginRegistry uses 'state$1'
discord-*.js → setActivePluginRegistry uses 'state$1'
model-selection-*.js → setActivePluginRegistry uses 'state$1'

When loadOpenClawPlugins() is called during session bootstrap from a different bundle chunk (e.g., auth-profiles-*.js), it calls setActivePluginRegistry() from its own chunk's copy — which updates state$1, not state. The agent runtime is linked to the registry-*.js chunk's state, so it sees a fresh empty registry while state$1 holds the new one with the registered tools.

Fix Action

Workaround

Use CLI commands as an alternative:

openclaw memory-pro search "query"     # Search memories
openclaw memory-pro list               # List all memories
openclaw memory-pro stats              # Show statistics

However, this bypasses the Agent's ability to proactively manage memories during conversations.

PR fix notes

PR #64859: fix(cli): stop misclassifying help/tool as plugin-gated

Description (problem / solution / changelog)

Summary

  • Problem: resolveMissingPluginCommandMessage() treated any missing primary token as plugin-backed under restrictive plugins.allow.
  • Why it matters: openclaw help broke outright, and openclaw tool ... returned a misleading allowlist error even though tool is not a manifest-backed plugin command on current main.
  • What changed: the missing-command guidance now only triggers for real plugin ids or manifest-backed aliases, and regression tests lock in the help/tool cases.
  • What did NOT change (scope boundary): this PR does not restore a tool CLI surface; it only stops blaming plugins.allow for non-plugin tokens.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #64732
  • Related #48919
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: the CLI only checked whether the primary token was still absent after lazy plugin registration, then assumed it must be a plugin-backed command.
  • Missing detection / guardrail: there was no manifest-backed existence check before emitting plugins.allow / plugins.entries.*.enabled guidance.
  • Contributing context (if known): Commander’s built-in help command is not represented in program.commands, and tool is also not a manifest-backed plugin id or alias on current main.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/cli/run-main.test.ts
  • Scenario the test should lock in: restrictive plugins.allow must not report help or tool as excluded plugins, while real plugin commands and manifest aliases still do.
  • Why this is the smallest reliable guardrail: resolveMissingPluginCommandMessage() is the exact decision point that converts a missing primary token into the startup error.
  • Existing test that already covers this (if any): the existing browser and dreaming cases already cover direct plugin ids and manifest-backed aliases.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

  • openclaw help works again under restrictive plugins.allow configs.
  • Non-plugin tokens like openclaw tool ... now fall through to Commander’s normal unknown-command handling instead of a false plugins.allow error.
  • Real plugin commands and manifest-backed aliases still return the existing allowlist guidance.

Diagram (if applicable)

Before:
[user types help/tool] -> [primary missing after lazy registration] -> [generic plugin-gated error]

After:
[user types command] -> [check manifest-backed plugin/alias?]
  -> yes -> [existing plugin guidance]
  -> no  -> [normal Commander parse/help path]

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local checkout via node scripts/run-node.mjs
  • Model/provider: N/A
  • Integration/channel (if any): none
  • Relevant config (redacted):
    {
      "plugins": {
        "allow": ["telegram", "matrix", "anthropic", "openai", "openrouter"]
      }
    }

Steps

  1. Use a restrictive plugins.allow that omits help / tool and excludes a real plugin command such as browser.
  2. Run openclaw help, openclaw tool image_generate --prompt test --filename test.png, and openclaw browser --help.
  3. Compare the startup behavior before and after this patch.

Expected

  • openclaw help should still print help.
  • Non-plugin tokens should not claim they were excluded by plugins.allow.
  • Real plugin commands should keep their existing allowlist guidance.

Actual

  • Before this PR, both help and tool failed with plugins.allow excludes "...".
  • After this PR, help prints root help, tool falls through to unknown command 'tool', and excluded real plugin commands like browser still surface the allowlist error.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: added the unit regression first, then reran it; manually reproed openclaw help under a restrictive allowlist; manually reproed openclaw tool image_generate ...; manually confirmed openclaw browser --help still reports the allowlist error when browser is excluded.
  • Edge cases checked: existing dreaming alias coverage still points at memory-core; direct bundled plugin ids like browser still return the plugin guidance path.
  • What you did not verify: I did not rerun the full pnpm test suite. The local pre-commit pnpm check hook still fails in unrelated extension lint surfaces (extensions/feishu/**, extensions/codex/**, extensions/msteams/**) on my checkout, both before and after this change.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: a workflow that depended on the old, misleading plugins.allow excludes "tool" text will now see Commander’s normal unknown command output instead.
    • Mitigation: actual plugin and alias cases still use the old guidance path; only non-plugin tokens change behavior.

AI Assistance

  • AI-assisted: Yes (Codex)
  • Testing degree: targeted unit + live CLI verification + build
  • Prompt/session summary: triaged recent issues and merged PRs for fit, reproduced #64732 on 2026-04-11, narrowed the bug to the missing-plugin guidance path, added the smallest regression coverage, verified the live CLI behavior, and attempted the repo’s local pnpm check / codex review protocol steps.
  • Understanding confirmation: I understand this only narrows when the CLI emits plugin-gating guidance; it does not add or restore a tool command surface.
  • Codex review note: I attempted codex review --base origin/main, but the local Codex CLI failed before review with invalid_grant during token refresh.

Verification Commands

  • pnpm exec vitest run src/cli/run-main.test.ts
  • pnpm exec oxlint src/cli/run-main.ts src/cli/run-main.test.ts
  • pnpm build
  • OPENCLAW_CONFIG_PATH=<tmp-config> OPENCLAW_STATE_DIR=<tmp-state> node scripts/run-node.mjs help
  • OPENCLAW_CONFIG_PATH=<tmp-config> OPENCLAW_STATE_DIR=<tmp-state> node scripts/run-node.mjs tool image_generate --prompt test --filename test.png
  • OPENCLAW_CONFIG_PATH=<tmp-config> OPENCLAW_STATE_DIR=<tmp-state> node scripts/run-node.mjs browser --help
  • Attempted: pre-commit pnpm check hook (failed in unrelated extension lint files already failing locally on 2026-04-11)

Changed files

  • src/cli/run-main.test.ts (modified, +20/-0)
  • src/cli/run-main.ts (modified, +9/-0)

Code Example

npm install memory-lancedb-pro@beta

---

{
     "plugins": {
       "slots": {
         "memory": "memory-lancedb-pro"
       },
       "entries": {
         "memory-lancedb-pro": {
           "enabled": true,
           "config": {
             "embedding": {
               "provider": "openai-compatible",
               "model": "bge-m3",
               "baseURL": "http://127.0.0.1:11434/v1",
               "apiKey": "ollama",
               "dimensions": 1024
             },
             "enableManagementTools": true,
             "autoCapture": true,
             "autoRecall": false
           }
         }
       }
     }
   }

---

openclaw gateway restart

---

openclaw plugins info memory-lancedb-pro

---

# Look for "Registered XXX tool" messages

---

[plugins] memory-lancedb-pro@1.1.0-beta.9: plugin registered (db: /root/.openclaw/memory/lancedb-pro, model: bge-m3, smartExtraction: ON)
[plugins] session-memory: hook registered for command:new as memory-lancedb-pro-session-memory
[plugins] feishu_doc: Registered feishu_doc, feishu_app_scopes
[plugins] feishu_chat: Registered feishu_chat tool          ← Normal plugin shows this
[plugins] feishu_wiki: Registered feishu_wiki tool          ← Normal plugin shows this
[adp-openclaw] Tool adp_upload_file registered successfully  ← Normal plugin shows this
# No "Registered memory_XXX tool" messages for slot plugin

---

Memory (LanceDB Pro)
id: memory-lancedb-pro
...
Status: loaded
Tools: memory_recall, memory_store, memory_forget, memory_update, memory_stats, memory_list
Hooks: memory-lancedb-pro-session-memory
CLI commands: memory-pro
Services: memory-lancedb-pro


**Missing tool registration logs:**
- Feishu plugin: `[plugins] feishu_chat: Registered feishu_chat tool`
- ADP plugin: `[adp-openclaw] Tool adp_upload_file registered successfully`
- Memory plugin: **No equivalent registration messages**

**Plugin source code confirms tools are registered:**

// From memory-lancedb-pro/src/tools.ts
export function registerAllMemoryTools(api, context, options) {
  // Core tools (always enabled)
  registerMemoryRecallTool(api, context);   // → api.registerTool()
  registerMemoryStoreTool(api, context);    // → api.registerTool()
  registerMemoryForgetTool(api, context);   // → api.registerTool()
  registerMemoryUpdateTool(api, context);   // → api.registerTool()
  
  // Management tools (optional)
  if (options.enableManagementTools) {
    registerMemoryStatsTool(api, context);  // → api.registerTool()
    registerMemoryListTool(api, context);   // → api.registerTool()
  }
}

---

registry-DtTKJfN8.js → setActivePluginRegistry uses 'state'
auth-profiles-*.js → setActivePluginRegistry uses 'state$1'
discord-*.js → setActivePluginRegistry uses 'state$1'
model-selection-*.js → setActivePluginRegistry uses 'state$1'

---

// src/plugins/registry.ts
const REGISTRY_KEY = Symbol.for('openclaw.pluginRegistry');
const globalState = globalThis as any;

if (!globalState[REGISTRY_KEY]) {
  globalState[REGISTRY_KEY] = { registry: null, key: null, version: 0 };
}
const state = globalState[REGISTRY_KEY];

export function setActivePluginRegistry(registry, cacheKey) {
  state.registry = registry;
  state.key = cacheKey ?? null;
  state.version += 1;
}

---

openclaw memory-pro search "query"     # Search memories
openclaw memory-pro list               # List all memories
openclaw memory-pro stats              # Show statistics
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Summary

Plugin-registered tools from slot plugins (e.g., memory-lancedb-pro) are successfully added to the plugin registry but are not exposed as callable tools to the LLM agent during runs. The tools appear in openclaw plugins info <id> output, but the agent cannot invoke them. This is caused by Rollup code-splitting creating independent module instances with separate state variables, similar to issues #47625 and #47683.

Steps to reproduce

  1. Install and configure a slot plugin (e.g., memory-lancedb-pro):

    npm install memory-lancedb-pro@beta
  2. Configure the plugin in openclaw.json:

    {
      "plugins": {
        "slots": {
          "memory": "memory-lancedb-pro"
        },
        "entries": {
          "memory-lancedb-pro": {
            "enabled": true,
            "config": {
              "embedding": {
                "provider": "openai-compatible",
                "model": "bge-m3",
                "baseURL": "http://127.0.0.1:11434/v1",
                "apiKey": "ollama",
                "dimensions": 1024
              },
              "enableManagementTools": true,
              "autoCapture": true,
              "autoRecall": false
            }
          }
        }
      }
    }
  3. Restart the gateway:

    openclaw gateway restart
  4. Verify the plugin is loaded and tools are registered:

    openclaw plugins info memory-lancedb-pro

    Expected output: Shows Tools: memory_recall, memory_store, memory_forget, memory_update, memory_stats, memory_list

  5. Check Gateway startup logs for tool registration:

    # Look for "Registered XXX tool" messages

    Actual output: No Registered memory_XXX tool messages appear (unlike Feishu/ADP plugins which show Registered feishu_chat tool, Tool adp_upload_file registered successfully)

  6. Attempt to use memory tools via Agent:

    • Send a message to the agent requesting memory storage or retrieval
    • The agent reports that memory tools are not available

Expected behavior

The slot plugin's tools (memory_recall, memory_store, memory_forget, memory_update, memory_stats, memory_list) should appear in the agent's available tool set and be callable by the LLM, just like tools from regular plugins (Feishu, ADP).

Actual behavior

  • The plugin is loaded successfully and shows Tools: memory_recall, memory_store... in openclaw plugins info
  • No Registered memory_XXX tool messages appear in Gateway startup logs
  • The agent cannot invoke memory tools; they are not present in the LLM's tool definitions
  • CLI commands (openclaw memory-pro search, openclaw memory-pro list) work correctly
  • Auto-capture and auto-recall hooks function normally

Gateway startup logs showing the discrepancy:

[plugins] [email protected]: plugin registered (db: /root/.openclaw/memory/lancedb-pro, model: bge-m3, smartExtraction: ON)
[plugins] session-memory: hook registered for command:new as memory-lancedb-pro-session-memory
[plugins] feishu_doc: Registered feishu_doc, feishu_app_scopes
[plugins] feishu_chat: Registered feishu_chat tool          ← Normal plugin shows this
[plugins] feishu_wiki: Registered feishu_wiki tool          ← Normal plugin shows this
[adp-openclaw] Tool adp_upload_file registered successfully  ← Normal plugin shows this
# No "Registered memory_XXX tool" messages for slot plugin

OpenClaw version

2026.3.12 (also tested on 2026.3.13)

Operating system

Linux VM-0-12-opencloudos 6.6.117-45.1.oc9.x86_64

Install method

npm global (via nvm, Node v22.22.0)

Model

Moonshot AI/kimi-k2.5

Provider / routing chain

openclaw → Moonshot AI (direct, token auth)

Config file / key location

~/.openclaw/openclaw.json ; plugins.slots.memory ; plugins.entries.memory-lancedb-pro

Additional provider/model setup details

  • Plugin: [email protected]
  • Backend: LanceDB with Ollama embeddings (bge-m3)
  • Smart extraction enabled with Moonshot AI/kimi-k2.5
  • plugins.allow: ["memory-lancedb-pro", "adp-openclaw", "feishu_doc", "feishu_chat", "feishu_wiki", "feishu_drive", "feishu_bitable"]

Logs, screenshots, and evidence

Memory (LanceDB Pro)
id: memory-lancedb-pro
...
Status: loaded
Tools: memory_recall, memory_store, memory_forget, memory_update, memory_stats, memory_list
Hooks: memory-lancedb-pro-session-memory
CLI commands: memory-pro
Services: memory-lancedb-pro


**Missing tool registration logs:**
- Feishu plugin: `[plugins] feishu_chat: Registered feishu_chat tool`
- ADP plugin: `[adp-openclaw] Tool adp_upload_file registered successfully`
- Memory plugin: **No equivalent registration messages**

**Plugin source code confirms tools are registered:**

// From memory-lancedb-pro/src/tools.ts
export function registerAllMemoryTools(api, context, options) {
  // Core tools (always enabled)
  registerMemoryRecallTool(api, context);   // → api.registerTool()
  registerMemoryStoreTool(api, context);    // → api.registerTool()
  registerMemoryForgetTool(api, context);   // → api.registerTool()
  registerMemoryUpdateTool(api, context);   // → api.registerTool()
  
  // Management tools (optional)
  if (options.enableManagementTools) {
    registerMemoryStatsTool(api, context);  // → api.registerTool()
    registerMemoryListTool(api, context);   // → api.registerTool()
  }
}

Impact and severity

Affected: All users of slot plugins (kind: "memory", kind: "context-engine") that register tools via api.registerTool()

Severity: High — blocks Agent from using memory management tools, forcing users to rely on CLI commands

Frequency: 100% reproducible on every gateway start

Consequence:

  • Agent cannot proactively store, retrieve, or manage memories
  • Users must use CLI commands (openclaw memory-pro search/list) for manual memory management
  • Auto-capture works (stores memories), but Agent cannot recall them via tools
  • Breaks the expected workflow of Agent-driven memory interaction

Additional information

Root Cause Analysis

This issue is identical in nature to reported issues #47625 (LINE webhook 404) and #47683 (plugin registerTool state loss).

The root cause is Rollup code-splitting creating independent module instances with separate state variables:

registry-DtTKJfN8.js → setActivePluginRegistry uses 'state'
auth-profiles-*.js → setActivePluginRegistry uses 'state$1'
discord-*.js → setActivePluginRegistry uses 'state$1'
model-selection-*.js → setActivePluginRegistry uses 'state$1'

When loadOpenClawPlugins() is called during session bootstrap from a different bundle chunk (e.g., auth-profiles-*.js), it calls setActivePluginRegistry() from its own chunk's copy — which updates state$1, not state. The agent runtime is linked to the registry-*.js chunk's state, so it sees a fresh empty registry while state$1 holds the new one with the registered tools.

Related Issues

  • #47625 — LINE webhook 404 (same root cause: Rollup state isolation)
  • #47683 — Plugin registerTool state loss (same root cause)

Suggested Fix

Per the analysis in #47625, Option B (process-global singleton) is the most robust fix:

// src/plugins/registry.ts
const REGISTRY_KEY = Symbol.for('openclaw.pluginRegistry');
const globalState = globalThis as any;

if (!globalState[REGISTRY_KEY]) {
  globalState[REGISTRY_KEY] = { registry: null, key: null, version: 0 };
}
const state = globalState[REGISTRY_KEY];

export function setActivePluginRegistry(registry, cacheKey) {
  state.registry = registry;
  state.key = cacheKey ?? null;
  state.version += 1;
}

This ensures setActivePluginRegistry, getActivePluginRegistry, and state live in exactly one place across all bundle chunks.

Workaround

Use CLI commands as an alternative:

openclaw memory-pro search "query"     # Search memories
openclaw memory-pro list               # List all memories
openclaw memory-pro stats              # Show statistics

However, this bypasses the Agent's ability to proactively manage memories during conversations.

extent analysis

Fix Plan

To resolve the issue of plugin-registered tools not being exposed to the LLM agent, we need to implement a process-global singleton for the plugin registry. This involves modifying the registry.ts file to use a global state.

Step 1: Modify registry.ts

// src/plugins/registry.ts
const REGISTRY_KEY = Symbol.for('openclaw.pluginRegistry');
const globalState = globalThis as any;

if (!globalState[REGISTRY_KEY]) {
  globalState[REGISTRY_KEY] = { registry: null, key: null, version: 0 };
}
const state = globalState[REGISTRY_KEY];

export function setActivePluginRegistry(registry, cacheKey) {
  state.registry = registry;
  state.key = cacheKey ?? null;
  state.version += 1;
}

export function getActivePluginRegistry() {
  return state.registry;
}

Step 2: Update loadOpenClawPlugins() to use the global registry

// src/plugins/loadOpenClawPlugins.ts
import { getActivePluginRegistry, setActivePluginRegistry } from './registry';

export function loadOpenClawPlugins() {
  // ...
  const registry = getActivePluginRegistry();
  if (!registry) {
    const newRegistry = createPluginRegistry();
    setActivePluginRegistry(newRegistry);
  }
  // ...
}

Step 3: Verify the fix

Restart the gateway and check the logs for the "Registered memory_XXX tool" messages. The agent should now be able to invoke the memory tools.

Verification

To verify that the fix worked, follow these steps:

  • Restart the gateway: openclaw gateway restart
  • Check the logs for the "Registered memory_XXX tool" messages
  • Attempt to use the memory tools via the Agent
  • Verify that the Agent can invoke the memory tools and that they are present in the LLM's tool definitions

Extra Tips

  • Make sure to test the fix thoroughly to ensure that it resolves the issue without introducing any new problems.
  • Consider implementing additional logging or debugging measures to help identify and resolve any future issues related to the plugin registry.
  • Review the related issues (#47625 and #47683) to ensure that the fix is comprehensive and addresses all aspects of the problem.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The slot plugin's tools (memory_recall, memory_store, memory_forget, memory_update, memory_stats, memory_list) should appear in the agent's available tool set and be callable by the LLM, just like tools from regular plugins (Feishu, ADP).

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: Slot plugin tools not exposed to Agent due to Rollup code-splitting state isolation [1 pull requests, 1 comments, 2 participants]