#Open Claw is super slow, and the bottleneck are extensions reads, how can I permanently disable?

1 messages · Page 1 of 1 (latest)

slender warren
#

This is relating to the bundled extensions, they essentially add an extra 5 to 12 seconds to every single call. Even when LLM step takes 0.5s

37,635 openat() calls on plugin files
29,957 successful reads, 7,666 ENOENTs (Node probing alternate paths)
Breakdown per extension dir: 315 opens each for 21 messaging plugins (bluebubbles, discord, feishu, line, matrix, slack, teams, signal, etc.), ~270 opens each for model provider plugins (deepseek, fireworks, groq, huggingface, minimax, stepfun…), 7,404 opens in openclaw core.

blazing dragonBOT
formal pollenBOT
#

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

blazing dragonBOT
drifting arrowBOT
#

Let me verify the actual config path in docs/source instead of guessing.

#

First, what does openclaw --version show?

Short answer, not completely via config today.

  • plugins.enabled: false is the only true global kill switch, but that turns all plugins off.
  • plugins.allow and plugins.entries.<id>.enabled: false can narrow what is eligible/activated, for example:
{
  plugins: {
    allow: ["discord", "anthropic"], // example, only keep what you really use
    entries: {
      slack: { enabled: false },
      signal: { enabled: false },
      matrix: { enabled: false },
    },
#
  },
}

But, from current docs/source, that does not fully stop bundled plugin discovery/manifest reads. It limits activation, not all scanning.

The big thing I found is the plugin caches are very short by default, 1s for both discovery and manifest registry. If your calls are spaced out more than that, you keep paying the scan cost again.

Best current mitigation is to raise these in the gateway service env:

OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS=60000
OPENCLAW_PLUGIN_MANIFEST_CACHE_MS=60000

Then restart the gateway.

slender warren
#

from the bundled ones, I literally only require telegram, edge-tts, openrouter, groq-stt, and my custom ones of bt-remote, ir-remote, note-taker,

OpenClaw 2026.4.15 (041266a)

drifting arrowBOT
#

Nice, that helps.

For the bundled ones, the plugin ids you want are:

  • telegram
  • microsoft (this is the Edge TTS one)
  • openrouter
  • groq (the bundled Groq transcription/media plugin)

So your minimal allowlist should be something like:

{
  plugins: {
    allow: [
      "telegram",
#
      "microsoft",
      "openrouter",
      "groq",
      "bt-remote",
      "ir-remote",
      "note-taker",
    ],
    slots: {
      memory: "none",
    },
  },
}

A couple of gotchas:

#
  • edge-tts is not the plugin id, it is microsoft
  • groq-stt is not the plugin id, it is groq
  • remove/disable any stale channels.* configs for other chat channels too, because configured bundled channels can still auto-activate

Then I would also bump the plugin cache TTLs in the gateway env, because the defaults are only 1s:

OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS=300000
OPENCLAW_PLUGIN_MANIFEST_CACHE_MS=300000

then restart the gateway.

After restart, verify with:

slender warren
#

is that allowlist supposed to replace the plugins setup at the end of openclaw.json?

drifting arrowBOT
#

Not the whole thing, just merge it into your existing plugins block.

So if you already have something like:

{
  plugins: {
    load: {
      paths: [
        "/path/to/bt-remote",
        "/path/to/ir-remote",
        "/path/to/note-taker"
      ]
    },
    entries: {
      // existing per-plugin config
#
    }
  }
}

you’d turn it into:

{
  plugins: {
    allow: [
      "telegram",
      "microsoft",
      "openrouter",
      "groq",
#
      "bt-remote",
      "ir-remote",
      "note-taker"
    ],
    slots: {
      memory: "none"
    },
    load: {
      paths: [
        "/path/to/bt-remote",
        "/path/to/ir-remote",
        "/path/to/note-taker"
      ]
    },
    entries: {
#
      // keep existing per-plugin config here
    }
  }
}

So:

  • keep plugins.load.paths if that is how your custom plugins are discovered
  • keep plugins.entries if you have per-plugin settings
  • add plugins.allow
  • add plugins.slots.memory: "none" if you want memory off

Important, don’t create a second top-level plugins object. Edit the existing one.

slender warren
#

I've got something like

"plugins": {
"entries": {
"telegram": {
"enabled": true
},
"whatsapp": {
"enabled": false
},
"openrouter": {
"enabled": true
},
"amazon-bedrock-mantle": {
"enabled": false
},
"amazon-bedrock": {
"enabled": false
}
}
}
}

drifting arrowBOT
#

Yep, in your case I’d change it to something like this:

"plugins": {
  "allow": [
    "telegram",
    "microsoft",
    "openrouter",
    "groq",
    "bt-remote",
    "ir-remote",
    "note-taker"
  ],
  "slots": {
    "memory": "none"
  },
#
  "entries": {
    "telegram": { "enabled": true },
    "microsoft": { "enabled": true },
    "openrouter": { "enabled": true },
    "groq": { "enabled": true },

    "whatsapp": { "enabled": false },
    "amazon-bedrock-mantle": { "enabled": false },
    "amazon-bedrock": { "enabled": false }
  }
}

A couple notes:

  • add allow next to entries, not inside it
#
  • microsoft = Edge TTS
  • groq = your Groq transcription plugin
  • once allow is there, most of those enabled: false lines become kind of redundant, but keeping them is fine
  • if your custom plugins are loaded via plugins.load.paths, keep that too

So yes, your current block is the right place, you’re just adding allow and optionally slots.memory.

If you want, I can help you trim that to the absolute minimum final block.

slender warren
#

So after this it's not going to look through extensions at all?

drifting arrowBOT
#

No, not fully, and I don’t want to oversell it.

What that config does:

  • yes: restricts which plugins are allowed/activated
  • no: it does not currently stop OpenClaw from doing bundled plugin discovery/manifest reads altogether

So it will likely still touch the extensions/ tree.

The thing that should reduce the repeated filesystem churn is the cache TTL bump:

OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS=300000
OPENCLAW_PLUGIN_MANIFEST_CACHE_MS=300000

That means, roughly, “stop re-scanning every second”.

#

So the honest answer is:

  • allowlist = smaller active set
  • cache TTL = fewer repeated scans
  • zero bundled extension probing = not a supported config switch right now, as far as I can tell

If you want true “don’t even look there”, that’s probably an upstream perf fix/feature request rather than a config tweak.

slender warren
#

alright so that suggestion is just completely useless, isn't it?

drifting arrowBOT
#

Honestly, for your exact complaint, mostly yes.

If the goal is:

“stop OpenClaw from hammering bundled extension files every turn”

then the allowlist is not the real fix. It narrows activation, but it does not stop the discovery/manifest walk you traced.

So I think your frustration is fair.

The only part of that suggestion that might still help is the cache TTL tweak, and only if this is a long-lived gateway process where repeated turns can reuse the cache. If you still see the same openat() storm after that, then yeah, the allowlist advice is basically noise for this bottleneck.

At that point I’d call it what it is: a real perf bug / missing feature.

If you want, I can help turn your trace into a very sharp GitHub issue with:

  • the openat() numbers
#
  • the per-extension breakdown
  • your version (2026.4.15)
  • the exact ask: “respect plugins.allow before bundled discovery, or add a true disable-bundled-scan mode”

That would be the useful next step.

slender warren
#

sure you can do that...

drifting arrowBOT
#

Yep. I can’t file it for you, but here’s a ready-to-paste issue for https://github.com/openclaw/openclaw/issues

Title

Bundled plugin discovery ignores restrictive plugin config and adds 5–12s per turn via repeated extension file reads

Body

## Version

OpenClaw 2026.4.15 (`041266a`)

## Problem

Bundled extension/plugin discovery is adding a large fixed latency to every call, even when the actual LLM step is very fast.
#

In my case, the LLM step can be ~0.5s, but total call overhead increases by roughly **5 to 12 seconds** because OpenClaw keeps reading/scanning bundled plugin files.

## Profiling summary

From tracing the process:

- **37,635 `openat()` calls** on plugin files
- **29,957 successful reads**
- **7,666 `ENOENT`s** (looks like Node probing alternate paths)
- Per extension dir:
  - ~**315 opens each** for ~21 messaging plugins (`bluebubbles`, `discord`, `feishu`, `line`, `matrix`, `slack`, `teams`, `signal`, etc.)
  - ~**270 opens each** for model/provider plugins (`deepseek`, `fireworks`, `groq`, `huggingface`, `minimax`, `stepfun`, etc.)
  - ~**7,404 opens** in OpenClaw core
#
## Why this is surprising

I only actually need a very small subset of plugins:

### Bundled plugins I need
- `telegram`
- `microsoft` (Edge TTS)
- `openrouter`
- `groq`

### Custom plugins I need
- `bt-remote`
- `ir-remote`
- `note-taker`
#
I was expecting restrictive plugin config / allowlisting to prevent OpenClaw from walking/reading the full bundled extensions tree every turn.

## Actual behavior

Even with a small intended plugin set, OpenClaw still appears to scan/read bundled plugin manifests/files broadly across many unused bundled extensions.

`plugins.allow` seems to affect **activation**, but not the expensive bundled **discovery/manifest scan** path.

## Expected behavior

One of these should happen:

1. `plugins.allow` should be respected **before** bundled plugin discovery/manifest loading for excluded bundled plugins, or
2. There should be a real config/env switch to **disable bundled plugin scanning entirely** except for explicitly allowed plugins, or
3. There should be a persistent manifest/index cache so this does not hit the filesystem on every turn.
#

## Requested fix

Please add one or more of:

- early filtering of bundled plugins based on `plugins.allow`
- a true “disable bundled plugin scan” mode
- a longer-lived manifest/discovery cache that survives normal turn spacing
- fewer filesystem probes / less alternate-path probing for bundled plugin resolution

## Notes

The current short cache mitigation does not solve the root issue for this case. The main problem is that unused bundled extensions are still being touched at all, and the cumulative file IO is dominating end-to-end latency.

If you want, I can also tighten that into a shorter maintainer-friendly version.

slender warren
#

Can't I just delete all the extensions?

drifting arrowBOT
#

I wouldn’t do that on a normal install.

Short version:

  • packaged install: no, I don’t recommend deleting bundled extensions in place
  • source checkout / your own fork: maybe, but that becomes a local patch, not a supported config fix

Why I’m hesitant:

  • OpenClaw expects bundled plugin paths/metadata to exist
  • updates or doctor flows may restore or rely on them
  • deleting them by hand can turn this into a weird broken-install problem instead of a perf problem

So if you want the blunt-force route, the less bad version is:

  • run from a source checkout
  • make a local branch/fork
#
  • remove/prune the unused bundled extensions there
  • rebuild from source

That’s a real workaround, but it’s basically “maintain a custom build”.

So, can you do it? Technically yes, in your own source build.
Would I recommend deleting the installed bundled extensions out of a normal install? No.

slender warren
#

what is the difference between extensions and skills

drifting arrowBOT
#

Let me check the docs wording so I don’t blur the two.

#

Roughly:

  • extensions / plugins = code
  • skills = instructions

More concretely:

Extensions / plugins

These add real runtime capabilities, for example:

  • a channel like telegram
  • a model/provider like openrouter
  • speech/transcription like microsoft or groq
  • tools, web providers, browser runtime, etc.

They are executable code and get loaded by OpenClaw.