The plugin SDK is the typed contract between plugins and core. This page is the reference for what to import and what you can register.Documentation Index
Fetch the complete documentation index at: https://docs.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
This page is for plugin authors using
openclaw/plugin-sdk/* inside
OpenClaw. For external apps, scripts, dashboards, CI jobs, and IDE extensions
that want to run agents through the Gateway, use the
OpenClaw App SDK and the @openclaw/sdk package
instead.Import convention
Always import from a specific subpath:openclaw/plugin-sdk/channel-core; keep openclaw/plugin-sdk/core for
the broader umbrella surface and shared helpers such as
buildChannelConfigSchema.
For channel config, publish the channel-owned JSON Schema through
openclaw.plugin.json#channelConfigs. The plugin-sdk/channel-config-schema
subpath is for shared schema primitives and the generic builder. OpenClaw’s
bundled plugins use plugin-sdk/bundled-channel-config-schema for retained
bundled-channel schemas. Deprecated compatibility exports remain on
plugin-sdk/channel-config-schema-legacy; neither bundled schema subpath is a
pattern for new plugins.
Subpath reference
The plugin SDK is exposed as a set of narrow subpaths grouped by area (plugin entry, channel, provider, auth, runtime, capability, memory, and reserved bundled-plugin helpers). For the full catalog — grouped and linked — see Plugin SDK subpaths. The generated list of 200+ subpaths lives inscripts/lib/plugin-sdk-entrypoints.json.
Registration API
Theregister(api) callback receives an OpenClawPluginApi object with these
methods:
Capability registration
| Method | What it registers |
|---|---|
api.registerProvider(...) | Text inference (LLM) |
api.registerAgentHarness(...) | Experimental low-level agent executor |
api.registerCliBackend(...) | Local CLI inference backend |
api.registerChannel(...) | Messaging channel |
api.registerSpeechProvider(...) | Text-to-speech / STT synthesis |
api.registerRealtimeTranscriptionProvider(...) | Streaming realtime transcription |
api.registerRealtimeVoiceProvider(...) | Duplex realtime voice sessions |
api.registerMediaUnderstandingProvider(...) | Image/audio/video analysis |
api.registerImageGenerationProvider(...) | Image generation |
api.registerMusicGenerationProvider(...) | Music generation |
api.registerVideoGenerationProvider(...) | Video generation |
api.registerWebFetchProvider(...) | Web fetch / scrape provider |
api.registerWebSearchProvider(...) | Web search |
Tools and commands
| Method | What it registers |
|---|---|
api.registerTool(tool, opts?) | Agent tool (required or { optional: true }) |
api.registerCommand(def) | Custom command (bypasses the LLM) |
agentPromptGuidance when the agent needs a short,
command-owned routing hint. Keep that text about the command itself; do not add
provider- or plugin-specific policy to core prompt builders.
Infrastructure
| Method | What it registers |
|---|---|
api.registerHook(events, handler, opts?) | Event hook |
api.registerHttpRoute(params) | Gateway HTTP endpoint |
api.registerGatewayMethod(name, handler) | Gateway RPC method |
api.registerGatewayDiscoveryService(service) | Local Gateway discovery advertiser |
api.registerCli(registrar, opts?) | CLI subcommand |
api.registerService(service) | Background service |
api.registerInteractiveHandler(registration) | Interactive handler |
api.registerAgentToolResultMiddleware(...) | Runtime tool-result middleware |
api.registerMemoryPromptSupplement(builder) | Additive memory-adjacent prompt section |
api.registerMemoryCorpusSupplement(adapter) | Additive memory search/read corpus |
Host hooks for workflow plugins
Host hooks are the SDK seams for plugins that need to participate in the host lifecycle rather than only adding a provider, channel, or tool. They are generic contracts; Plan Mode can use them, but so can approval workflows, workspace policy gates, background monitors, setup wizards, and UI companion plugins.| Method | Contract it owns |
|---|---|
api.registerSessionExtension(...) | Plugin-owned, JSON-compatible session state projected through Gateway sessions |
api.enqueueNextTurnInjection(...) | Durable exactly-once context injected into the next agent turn for one session |
api.registerTrustedToolPolicy(...) | Bundled/trusted pre-plugin tool policy that can block or rewrite tool params |
api.registerToolMetadata(...) | Tool catalog display metadata without changing the tool implementation |
api.registerCommand(...) | Scoped plugin commands; command results can set continueAgent: true; Discord native commands support descriptionLocalizations |
api.registerControlUiDescriptor(...) | Control UI contribution descriptors for session, tool, run, or settings surfaces |
api.registerRuntimeLifecycle(...) | Cleanup callbacks for plugin-owned runtime resources on reset/delete/reload paths |
api.registerAgentEventSubscription(...) | Sanitized event subscriptions for workflow state and monitors |
api.setRunContext(...) / getRunContext(...) / clearRunContext(...) | Per-run plugin scratch state cleared on terminal run lifecycle |
api.registerSessionSchedulerJob(...) | Plugin-owned session scheduler job records with deterministic cleanup |
- External plugins can own session extensions, UI descriptors, commands, tool metadata, next-turn injections, and normal hooks.
- Trusted tool policies run before ordinary
before_tool_callhooks and are bundled-only because they participate in host safety policy. - Reserved command ownership is bundled-only. External plugins should use their own command names or aliases.
allowPromptInjection=falsedisables prompt-mutating hooks includingagent_turn_prepare,before_prompt_build,heartbeat_prompt_contribution, prompt fields from legacybefore_agent_start, andenqueueNextTurnInjection.
| Plugin archetype | Hooks used |
|---|---|
| Approval workflow | Session extension, command continuation, next-turn injection, UI descriptor |
| Budget/workspace policy gate | Trusted tool policy, tool metadata, session projection |
| Background lifecycle monitor | Runtime lifecycle cleanup, agent event subscription, session scheduler ownership/cleanup, heartbeat prompt contribution, UI descriptor |
| Setup or onboarding wizard | Session extension, scoped commands, Control UI descriptor |
Reserved core admin namespaces (
config.*, exec.approvals.*, wizard.*,
update.*) always stay operator.admin, even if a plugin tries to assign a
narrower gateway method scope. Prefer plugin-specific prefixes for
plugin-owned methods.When to use tool-result middleware
When to use tool-result middleware
Bundled plugins can use
api.registerAgentToolResultMiddleware(...) when
they need to rewrite a tool result after execution and before the runtime
feeds that result back into the model. This is the trusted runtime-neutral
seam for async output reducers such as tokenjuice.Bundled plugins must declare contracts.agentToolResultMiddleware for each
targeted runtime, for example ["pi", "codex"]. External plugins
cannot register this middleware; keep normal OpenClaw plugin hooks for work
that does not need pre-model tool-result timing. The old Pi-only embedded
extension factory registration path has been removed.Gateway discovery registration
api.registerGatewayDiscoveryService(...) lets a plugin advertise the active
Gateway on a local discovery transport such as mDNS/Bonjour. OpenClaw calls the
service during Gateway startup when local discovery is enabled, passes the
current Gateway ports and non-secret TXT hint data, and calls the returned
stop handler during Gateway shutdown.
CLI registration metadata
api.registerCli(registrar, opts?) accepts two kinds of top-level metadata:
commands: explicit command roots owned by the registrardescriptors: parse-time command descriptors used for root CLI help, routing, and lazy plugin CLI registration
descriptors that cover every top-level command root exposed by that
registrar.
commands by itself only when you do not need lazy root CLI registration.
That eager compatibility path remains supported, but it does not install
descriptor-backed placeholders for parse-time lazy loading.
CLI backend registration
api.registerCliBackend(...) lets a plugin own the default config for a local
AI CLI backend such as codex-cli.
- The backend
idbecomes the provider prefix in model refs likecodex-cli/gpt-5. - The backend
configuses the same shape asagents.defaults.cliBackends.<id>. - User config still wins. OpenClaw merges
agents.defaults.cliBackends.<id>over the plugin default before running the CLI. - Use
normalizeConfigwhen a backend needs compatibility rewrites after merge (for example normalizing old flag shapes). - Use
resolveExecutionArgsfor request-scoped argv rewrites that belong to the CLI dialect, such as mapping OpenClaw thinking levels to a native effort flag.
Exclusive slots
| Method | What it registers |
|---|---|
api.registerContextEngine(id, factory) | Context engine (one active at a time). The assemble() callback receives availableTools and citationsMode so the engine can tailor prompt additions. |
api.registerMemoryCapability(capability) | Unified memory capability |
api.registerMemoryPromptSection(builder) | Memory prompt section builder |
api.registerMemoryFlushPlan(resolver) | Memory flush plan resolver |
api.registerMemoryRuntime(runtime) | Memory runtime adapter |
Memory embedding adapters
| Method | What it registers |
|---|---|
api.registerMemoryEmbeddingProvider(adapter) | Memory embedding adapter for the active plugin |
registerMemoryCapabilityis the preferred exclusive memory-plugin API.registerMemoryCapabilitymay also exposepublicArtifacts.listArtifacts(...)so companion plugins can consume exported memory artifacts throughopenclaw/plugin-sdk/memory-host-coreinstead of reaching into a specific memory plugin’s private layout.registerMemoryPromptSection,registerMemoryFlushPlan, andregisterMemoryRuntimeare legacy-compatible exclusive memory-plugin APIs.MemoryFlushPlan.modelcan pin the flush turn to an exactprovider/modelreference, such asollama/qwen3:8b, without inheriting the active fallback chain.registerMemoryEmbeddingProviderlets the active memory plugin register one or more embedding adapter ids (for exampleopenai,gemini, or a custom plugin-defined id).- User config such as
agents.defaults.memorySearch.providerandagents.defaults.memorySearch.fallbackresolves against those registered adapter ids.
Events and lifecycle
| Method | What it does |
|---|---|
api.on(hookName, handler, opts?) | Typed lifecycle hook |
api.onConversationBindingResolved(handler) | Conversation binding callback |
Hook decision semantics
before_tool_call: returning{ block: true }is terminal. Once any handler sets it, lower-priority handlers are skipped.before_tool_call: returning{ block: false }is treated as no decision (same as omittingblock), not as an override.before_install: returning{ block: true }is terminal. Once any handler sets it, lower-priority handlers are skipped.before_install: returning{ block: false }is treated as no decision (same as omittingblock), not as an override.reply_dispatch: returning{ handled: true, ... }is terminal. Once any handler claims dispatch, lower-priority handlers and the default model dispatch path are skipped.message_sending: returning{ cancel: true }is terminal. Once any handler sets it, lower-priority handlers are skipped.message_sending: returning{ cancel: false }is treated as no decision (same as omittingcancel), not as an override.message_received: use the typedthreadIdfield when you need inbound thread/topic routing. Keepmetadatafor channel-specific extras.message_sending: use typedreplyToId/threadIdrouting fields before falling back to channel-specificmetadata.gateway_start: usectx.config,ctx.workspaceDir, andctx.getCron?.()for gateway-owned startup state instead of relying on internalgateway:startuphooks.cron_changed: observe gateway-owned cron lifecycle changes. Useevent.job?.state?.nextRunAtMsandctx.getCron?.()when syncing external wake schedulers, and keep OpenClaw as the source of truth for due checks and execution.
API object fields
| Field | Type | Description |
|---|---|---|
api.id | string | Plugin id |
api.name | string | Display name |
api.version | string? | Plugin version (optional) |
api.description | string? | Plugin description (optional) |
api.source | string | Plugin source path |
api.rootDir | string? | Plugin root directory (optional) |
api.config | OpenClawConfig | Current config snapshot (active in-memory runtime snapshot when available) |
api.pluginConfig | Record<string, unknown> | Plugin-specific config from plugins.entries.<id>.config |
api.runtime | PluginRuntime | Runtime helpers |
api.logger | PluginLogger | Scoped logger (debug, info, warn, error) |
api.registrationMode | PluginRegistrationMode | Current load mode; "setup-runtime" is the lightweight pre-full-entry startup/setup window |
api.resolvePath(input) | (string) => string | Resolve path relative to plugin root |
Internal module convention
Within your plugin, use local barrel files for internal imports:api.ts, runtime-api.ts,
index.ts, setup-entry.ts, and similar public entry files) prefer the
active runtime config snapshot when OpenClaw is already running. If no runtime
snapshot exists yet, they fall back to the resolved config file on disk.
Packaged bundled plugin facades should be loaded through OpenClaw’s plugin
facade loaders; direct imports from dist/extensions/... bypass the manifest
and runtime sidecar checks that packaged installs use for plugin-owned code.
Provider plugins can expose a narrow plugin-local contract barrel when a
helper is intentionally provider-specific and does not belong in a generic SDK
subpath yet. Bundled examples:
- Anthropic: public
api.ts/contract-api.tsseam for Claude beta-header andservice_tierstream helpers. @openclaw/openai-provider:api.tsexports provider builders, default-model helpers, and realtime provider builders.@openclaw/openrouter-provider:api.tsexports the provider builder plus onboarding/config helpers.
Related
Entry points
definePluginEntry and defineChannelPluginEntry options.Runtime helpers
Full
api.runtime namespace reference.Setup and config
Packaging, manifests, and config schemas.
Testing
Test utilities and lint rules.
SDK migration
Migrating from deprecated surfaces.
Plugin internals
Deep architecture and capability model.