Skip to content

Skill enable/disable toggle doesn't apply without gateway restart and never reaches open chats #82

Description

@yikkuro

Summary

Enabling/disabling a skill from the desktop Skills page does not take effect until the gateway is manually restarted, and it never propagates to conversations that are already open. This is confusing: users toggle a skill on, the agent still can't see it (or still sees a disabled one), with no feedback that a restart is required.

Root cause

Two independent gaps:

  1. The toggle bypasses the gateway. The IPC handlers skills:update-allowlist and skills:update-managed-entries (desktop/src/main.ts:2658-2678) write ~/.openclaw/openclaw.json directly via fs.writeFileSync. The long-running gateway loads its config into memory and is never notified, so it keeps serving the skill list it read at boot. There is no lightweight reload RPC — desktop/src/gateway-client.ts:207 explicitly notes gateway.reload does not exist; the only refresh path is a full restart() (config.patch → SIGUSR1).

  2. The toggle doesn't participate in openclaw's skill-version mechanism. openclaw already supports refreshing skills in a running conversation: each session stores a skillsSnapshot with a version, and on every turn ensureSkillSnapshot rebuilds it from the current config when a global "skills snapshot version" has bumped (shouldRefreshSnapshot = snapshotVersion > 0 && sessionSnapshotVersion < snapshotVersion). That version is bumped by bumpSkillsSnapshotVersion(...), which today only fires from the chokidar file-watcher on SKILL.md changes (ensureSkillsWatcher / resolveWatchTargets). Toggling a skill only edits openclaw.json (skills.allowBundled / skills.entries) — it touches no skill file, so the version never bumps and existing sessions never rebuild.

(Runtime enforcement itself is correct: openclaw's shouldIncludeSkill() does honor skills.allowBundled and skills.entries.<name>.enabled === false.)

Impact / observed behavior

  • Toggle a skill on/off → the change is written to disk but the agent's available-skills list is unchanged.
  • After a manual gateway restart, new chats reflect the change — but existing/open chats still do not.
  • Note: a plain restart alone does not refresh existing chats either, because the in-memory snapshot version resets to 0 on boot, so restored sessions never satisfy shouldRefreshSnapshot.
  • Contrast: adding/removing actual skill files does propagate to existing chats on their next message, because the file-watcher bumps the version. Only the enable/disable toggle is broken.

Steps to reproduce

  1. Open a chat with the agent; ask which skills it can see.
  2. In Settings → Skills, enable a currently-disabled skill (e.g. bluebubbles) and disable an enabled one (e.g. test-skill).
  3. In the same chat, ask again — the list is unchanged.
  4. Even opening a brand-new chat shows no change until the gateway is restarted.

Proposed fix

Make the toggle behave like a real skill add/remove:

  1. Persist skill config through the gateway (or otherwise update its in-memory config) instead of a raw fs.writeFileSync, so the gateway sees the change.
  2. Bump the skills snapshot version after a toggle (call bumpSkillsSnapshotVersion({ reason: "manual" }), or expose it via a gateway RPC/IPC) so already-open conversations rebuild their skill list from the updated config on their next message.
  3. Debounce rapid toggles and show a brief "applying…" / "changes apply on the next message" hint in the UI.

References

  • desktop/src/main.ts:2658-2678skills:update-allowlist, skills:update-managed-entries (direct file write)
  • desktop/src/gateway-client.ts:184-209restart(); gateway.reload does not exist
  • openclaw runtime: ensureSkillSnapshot / shouldRefreshSnapshot, bumpSkillsSnapshotVersion, ensureSkillsWatcher, shouldIncludeSkill

Metadata

Metadata

Assignees

Labels

P0bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions