Plugin Entry Points
Every plugin exports a default entry object. The SDK provides three helpers for creating them.definePluginEntry
Import: openclaw/plugin-sdk/plugin-entry
For provider plugins, tool plugins, hook plugins, and anything that is not
a messaging channel.
| Field | Type | Required | Default |
|---|---|---|---|
id | string | Yes | — |
name | string | Yes | — |
description | string | Yes | — |
kind | string | No | — |
configSchema | OpenClawPluginConfigSchema | () => OpenClawPluginConfigSchema | No | Empty object schema |
register | (api: OpenClawPluginApi) => void | Yes | — |
idmust match youropenclaw.plugin.jsonmanifest.kindis for exclusive slots:"memory"or"context-engine".configSchemacan be a function for lazy evaluation.- OpenClaw resolves and memoizes that schema on first access, so expensive schema builders only run once.
defineChannelPluginEntry
Import: openclaw/plugin-sdk/channel-core
Wraps definePluginEntry with channel-specific wiring. Automatically calls
api.registerChannel({ plugin }), exposes an optional root-help CLI metadata
seam, and gates registerFull on registration mode.
| Field | Type | Required | Default |
|---|---|---|---|
id | string | Yes | — |
name | string | Yes | — |
description | string | Yes | — |
plugin | ChannelPlugin | Yes | — |
configSchema | OpenClawPluginConfigSchema | () => OpenClawPluginConfigSchema | No | Empty object schema |
setRuntime | (runtime: PluginRuntime) => void | No | — |
registerCliMetadata | (api: OpenClawPluginApi) => void | No | — |
registerFull | (api: OpenClawPluginApi) => void | No | — |
setRuntimeis called during registration so you can store the runtime reference (typically viacreatePluginRuntimeStore). It is skipped during CLI metadata capture.registerCliMetadataruns during bothapi.registrationMode === "cli-metadata"andapi.registrationMode === "full". Use it as the canonical place for channel-owned CLI descriptors so root help stays non-activating while normal CLI command registration remains compatible with full plugin loads.registerFullonly runs whenapi.registrationMode === "full". It is skipped during setup-only loading.- Like
definePluginEntry,configSchemacan be a lazy factory and OpenClaw memoizes the resolved schema on first access. - For plugin-owned root CLI commands, prefer
api.registerCli(..., { descriptors: [...] })when you want the command to stay lazy-loaded without disappearing from the root CLI parse tree. For channel plugins, prefer registering those descriptors fromregisterCliMetadata(...)and keepregisterFull(...)focused on runtime-only work. - If
registerFull(...)also registers gateway RPC methods, keep them on a plugin-specific prefix. Reserved core admin namespaces (config.*,exec.approvals.*,wizard.*,update.*) are always coerced tooperator.admin.
defineSetupPluginEntry
Import: openclaw/plugin-sdk/channel-core
For the lightweight setup-entry.ts file. Returns just { plugin } with no
runtime or CLI wiring.
defineSetupPluginEntry(...) with the narrow setup helper
families:
openclaw/plugin-sdk/setup-runtimefor runtime-safe setup helpers such as import-safe setup patch adapters, lookup-note output,promptResolvedAllowFrom,splitSetupEntries, and delegated setup proxiesopenclaw/plugin-sdk/channel-setupfor optional-install setup surfacesopenclaw/plugin-sdk/setup-toolsfor setup/install CLI/archive/docs helpers
Registration mode
api.registrationMode tells your plugin how it was loaded:
| Mode | When | What to register |
|---|---|---|
"full" | Normal gateway startup | Everything |
"setup-only" | Disabled/unconfigured channel | Channel registration only |
"setup-runtime" | Setup flow with runtime available | Channel registration plus only the lightweight runtime needed before the full entry loads |
"cli-metadata" | Root help / CLI metadata capture | CLI descriptors only |
defineChannelPluginEntry handles this split automatically. If you use
definePluginEntry directly for a channel, check mode yourself:
"setup-runtime" as the window where setup-only startup surfaces must
exist without re-entering the full bundled channel runtime. Good fits are
channel registration, setup-safe HTTP routes, setup-safe gateway methods, and
delegated setup helpers. Heavy background services, CLI registrars, and
provider/client SDK bootstraps still belong in "full".
For CLI registrars specifically:
- use
descriptorswhen the registrar owns one or more root commands and you want OpenClaw to lazy-load the real CLI module on first invocation - make sure those descriptors cover every top-level command root exposed by the registrar
- use
commandsalone only for eager compatibility paths
Plugin shapes
OpenClaw classifies loaded plugins by their registration behavior:| Shape | Description |
|---|---|
| plain-capability | One capability type (e.g. provider-only) |
| hybrid-capability | Multiple capability types (e.g. provider + speech) |
| hook-only | Only hooks, no capabilities |
| non-capability | Tools/commands/services but no capabilities |
openclaw plugins inspect <id> to see a plugin’s shape.
Related
- SDK Overview — registration API and subpath reference
- Runtime Helpers —
api.runtimeandcreatePluginRuntimeStore - Setup and Config — manifest, setup entry, deferred loading
- Channel Plugins — building the
ChannelPluginobject - Provider Plugins — provider registration and hooks