Openclaw Plugin System Blueprint
Plugin registration, lifecycle management, and capability-based permissions system for extending OpenClaw functionality
| Feature | openclaw-plugin-system |
| Category | Integration |
| Version | 1.0.0 |
| Tags | plugins, extensibility, capabilities, configuration, modular |
| YAML Source | View on GitHub |
| JSON API | openclaw-plugin-system.json |
Actors
| ID | Name | Type | Description |
|---|---|---|---|
plugin_developer | Plugin Developer | external | |
plugin_registry | Plugin Registry | system | |
gateway | OpenClaw Gateway | system | |
plugin_instance | Plugin Instance | system |
Fields
| Name | Type | Required | Label | Description |
|---|---|---|---|---|
plugin_id | text | Yes | Plugin ID | |
plugin_name | text | Yes | Plugin Name | |
plugin_version | text | Yes | Plugin Version | |
enabled | boolean | Yes | Enabled | |
config | json | No | Configuration | |
declared_capabilities | json | Yes | Declared Capabilities | |
initialized | boolean | No | Initialized | |
manifest_hash | text | No | Manifest Hash | |
plugin_scope | select | No | Execution Scope | |
hooks_enabled | json | No | Hooks Configuration |
States
State field: undefined
Rules
- plugin_loading:
-
discovery_paths: Plugins loaded from: 1. Bundled plugins (node_modules/openclaw*/index.ts) 2. Configured load paths (plugins.load.paths[]) 3. Node modules with @openclaw namespace Plugin must export: definePluginEntry() or defineChannelPluginEntry().
-
lazy_loading: Plugins loaded on-demand (not at startup by default). Trigger: First use or explicit /plugin load command. Exceptions: Critical plugins pre-loaded (auth, memory, context-engine). Benefit: Faster startup, reduced memory footprint.
-
manifest_validation: Every plugin provides manifest: { id, name, description, version, authors, capabilities } Validation: required fields + format checks. Error: plugin rejected if manifest invalid.
-
- plugin_lifecycle:
-
initialization_sequence: 1. Load module (require/import) 2. Validate manifest (id, version, capabilities) 3. Merge with config (from plugins.entries) 4. Initialize config schema (Zod/JSON Schema) 5. Call onEnable() hook (if defined) 6. Register capabilities with gateway 7. Mark initialized=true Failure at any step: plugin disabled, error logged.
-
enable_disable: Enable: Set enabled=true, call onEnable(), expose capabilities. Disable: Set enabled=false, call onDisable(), hide capabilities. Required plugin disabled: warning logged, may prevent execution. Dynamic enable/disable available via CLI.
-
reload_strategy: On config change: 1. Compare manifest_hash 2. If unchanged: skip reload 3. If changed: unload, reinitialize, reload Preserve auth profiles across reload.
-
- plugin_configuration:
-
config_schema_validation: Plugin defines configSchema (Zod or JSON Schema). config object validated against schema on load. Errors: detailed path reporting (e.g., “config.deeplink.port”). Invalid config: plugin disabled, error shown.
-
ui_hints: Config schema includes UI hints: { field, type, sensitive, description, ui_type } Respected by: CLI wizard, web config UI, mobile app.
-
nested_configuration: Plugins can have deeply nested config with recursive validation. Path-based access: config.integrations.discord.token.
-
environment_variable_substitution: Config values can reference env vars: “apiKey”: “${MY_API_KEY}” or “${API_URL:-https://default.com}” Substitution: performed during load. Secrets detection: _KEY, _TOKEN, _PASSWORD, _SECRET redacted in logs.
-
- capability_model:
-
capability_declaration: Plugins declare capabilities: [“chat.send”, “context.read”, “tool.custom”, “event.listen”] Capabilities are strings (provider/type/name format).
-
capability_gating: Tools/features check plugin.capabilities before invocation. Missing capability: tool call rejected with permission error. Prevents plugins from exceeding declared scope.
-
capability_categories: System: memory, context-engine, rag, tool.index Chat: chat.send, chat.receive, chat.edit Tools: tool.* (custom namespaces) Context: context.read, context.inject Events: event.listen, event.emit
-
- slot_based_plugins:
-
memory_slot: plugins.slots.memory: single plugin controls conversation memory. Only one memory plugin enabled at a time. Alternatives: default (file-based), vector DB, custom. Switching: update config, restart gateway.
-
context_engine_slot: plugins.slots.contextEngine: single plugin provides context building. Builds prompt context from conversation history. Alternatives: default (transcript), RAG, custom.
-
- plugin_allowlist_denylist:
-
allowlist_behavior: plugins.allow: string[] of allowed plugin IDs. If set: ONLY these plugins can load (whitelist mode). Others: rejected during load.
-
denylist_behavior: plugins.deny: string[] of blocked plugin IDs. If set: these plugins cannot load. Deny takes precedence over allow (safer default).
-
SLA
| Scope | Max Duration | Escalation |
|---|---|---|
| plugin_load_time | 1s | |
| capability_check | 1ms |
Outcomes
Plugin_loaded (Priority: 1)
Given:
- plugin_id provided
plugin_id(system) exists- plugin module found in search paths
Then:
- set_field target:
initializedvalue:false - set_field target:
manifest_hashvalue:hash(manifest) - transition_state field:
plugin_statefrom:unloadedto:loading
Result: Plugin module loaded, manifest validated
Plugin_initialized (Priority: 2)
Given:
plugin_state(db) eqloading- configSchema validated against config
- onEnable() hook completed without error
Then:
- set_field target:
initializedvalue:true - set_field target:
enabledvalue:true - emit_event event:
plugin.enabled - transition_state field:
plugin_statefrom:loadingto:enabled
Result: Plugin enabled, capabilities exposed to gateway
Capability_check (Priority: 3)
Given:
- plugin attempting tool use
required_capability(input) indeclared_capabilities
Then:
- set_field target:
capability_allowedvalue:true
Result: Capability check passed, tool use allowed
Capability_denied (Priority: 3) — Error: CAPABILITY_DENIED
Given:
required_capability(input) not_indeclared_capabilities
Then:
- set_field target:
capability_allowedvalue:false
Result: Capability check failed, tool use denied
Plugin_disabled (Priority: 4)
Given:
enabled(system) eqfalse
Then:
- call_service target:
external_service - transition_state field:
plugin_statefrom:enabledto:disabled - emit_event event:
plugin.disabled
Result: Plugin disabled, no longer accessible
Errors
| Code | Status | Message | Retry |
|---|---|---|---|
PLUGIN_NOT_FOUND | 404 | Plugin not found | No |
PLUGIN_INITIALIZATION_FAILED | 500 | Plugin failed to initialize | No |
INVALID_PLUGIN_CONFIG | 400 | Plugin configuration invalid | No |
CAPABILITY_DENIED | 403 | Plugin capability not declared | No |
AUTH_PROFILE_NOT_FOUND | 404 | Auth profile not found | No |
PLUGIN_CONFLICT | 409 | Plugin conflict | No |
Events
| Event | Description | Payload |
|---|---|---|
plugin.loaded | plugin_id, plugin_version | |
plugin.enabled | plugin_id, declared_capabilities | |
plugin.disabled | plugin_id | |
plugin.config_changed | plugin_id, config_hash | |
plugin.error | plugin_id, error_code, error_message |
Related Blueprints
| Feature | Relationship | Reason |
|---|---|---|
| openclaw-gateway-authentication | optional | Some plugins manage authentication |
| openclaw-llm-provider | optional | Plugins can provide LLM models |
AGI Readiness
Goals
Reliable Openclaw Plugin System
Plugin registration, lifecycle management, and capability-based permissions system for extending OpenClaw functionality
Success Metrics:
| Metric | Target | Measurement |
|---|---|---|
| success_rate | >= 99.5% | Successful operations divided by total attempts |
| error_recovery_rate | >= 95% | Errors that auto-recover without manual intervention |
Constraints:
- availability (non-negotiable): Must degrade gracefully when dependencies are unavailable
Autonomy
Level: supervised
Escalation Triggers:
error_rate > 5
Tradeoffs
| Prefer | Over | Reason |
|---|---|---|
| reliability | throughput | integration failures can cascade across systems |
Safety
| Action | Permission | Cooldown | Max Auto |
|---|---|---|---|
| plugin_loaded | autonomous | - | - |
| plugin_initialized | autonomous | - | - |
| capability_check | autonomous | - | - |
| capability_denied | autonomous | - | - |
| plugin_disabled | human_required | - | - |