Caricamento in corso...
Caricamento in corso...
Last synced: Today, 22:00
Technical reference for the OpenClaw framework. Real-time synchronization with the official documentation engine.
Use this file to discover all available pages before exploring further.
Plugins extend OpenClaw with new capabilities: channels, model providers, speech, realtime transcription, realtime voice, media understanding, image generation, video generation, web fetch, web search, agent tools, or any combination.
You do not need to add your plugin to the OpenClaw repository. Publish to ClawHub and users install with
openclaw plugins install <package-name>pnpm installConnect OpenClaw to a messaging platform (Discord, IRC, etc.)
Add a model provider (LLM, proxy, or custom endpoint)
Register agent tools, event hooks, or services — continue below
For a channel plugin that isn't guaranteed to be installed when onboarding/setup runs, use
createOptionalChannelSetupSurface(...)openclaw/plugin-sdk/channel-setupThis walkthrough creates a minimal plugin that registers an agent tool. Channel and provider plugins have dedicated guides linked above.
text```json openclaw.plugin.json theme={"theme":{"light":"min-light","dark":"min-dark"}} { "id": "my-plugin", "name": "My Plugin", "description": "Adds a custom tool to OpenClaw", "activation": { "onStartup": true }, "configSchema": { "type": "object", "additionalProperties": false } } ``` </CodeGroup> Every plugin needs a manifest, even with no config, and every plugin should declare `activation.onStartup` intentionally. Runtime-registered tools need startup import, so this example sets it to `true`. See [Manifest](/plugins/manifest) for the full schema. The canonical ClawHub publish snippets live in `docs/snippets/plugin-publish/`.
textexport default definePluginEntry({ id: "my-plugin", name: "My Plugin", description: "Adds a custom tool to OpenClaw", register(api) { api.registerTool({ name: "my_tool", description: "Do a thing", parameters: Type.Object({ input: Type.String() }), async execute(_id, params) { return { content: [{ type: "text", text: `Got: ${params.input}` }] }; }, }); }, }); ``` `definePluginEntry` is for non-channel plugins. For channels, use `defineChannelPluginEntry` — see [Channel Plugins](/plugins/sdk-channel-plugins). For full entry point options, see [Entry Points](/plugins/sdk-entrypoints).
text```bash} clawhub package publish your-org/your-plugin --dry-run clawhub package publish your-org/your-plugin openclaw plugins install clawhub:@myorg/openclaw-my-plugin ``` OpenClaw also checks ClawHub before npm for bare package specs like `@myorg/openclaw-my-plugin`; npm remains a fallback for packages that have not migrated to ClawHub yet. **In-repo plugins:** place under the bundled plugin workspace tree — automatically discovered. ```bash} pnpm test -- <bundled-plugin-root>/my-plugin/ ```
A single plugin can register any number of capabilities via the
api| Capability | Registration method | Detailed guide |
|---|---|---|
| Text inference (LLM) | text api.registerProvider(...) | Provider Plugins |
| CLI inference backend | text api.registerCliBackend(...) | CLI Backends |
| Channel / messaging | text api.registerChannel(...) | Channel Plugins |
| Speech (TTS/STT) | text api.registerSpeechProvider(...) | Provider Plugins |
| Realtime transcription | text api.registerRealtimeTranscriptionProvider(...) | Provider Plugins |
| Realtime voice | text api.registerRealtimeVoiceProvider(...) | Provider Plugins |
| Media understanding | text api.registerMediaUnderstandingProvider(...) | Provider Plugins |
| Image generation | text api.registerImageGenerationProvider(...) | Provider Plugins |
| Music generation | text api.registerMusicGenerationProvider(...) | Provider Plugins |
| Video generation | text api.registerVideoGenerationProvider(...) | Provider Plugins |
| Web fetch | text api.registerWebFetchProvider(...) | Provider Plugins |
| Web search | text api.registerWebSearchProvider(...) | Provider Plugins |
| Tool-result middleware | text api.registerAgentToolResultMiddleware(...) | SDK Overview |
| Agent tools | text api.registerTool(...) | Below |
| Custom commands | text api.registerCommand(...) | Entry Points |
| Plugin hooks | text api.on(...) | Plugin hooks |
| Internal event hooks | text api.registerHook(...) | Entry Points |
| HTTP routes | text api.registerHttpRoute(...) | Internals |
| CLI subcommands | text api.registerCli(...) | Entry Points |
For the full registration API, see SDK Overview.
Bundled plugins can use
api.registerAgentToolResultMiddleware(...)contracts.agentToolResultMiddleware["pi", "codex"]If your plugin registers custom gateway RPC methods, keep them on a plugin-specific prefix. Core admin namespaces (
config.*exec.approvals.*wizard.*update.*operator.adminHook guard semantics to keep in mind:
before_tool_call{ block: true }before_tool_call{ block: false }before_tool_call{ requireApproval: true }/approvebefore_install{ block: true }before_install{ block: false }message_sending{ cancel: true }message_sending{ cancel: false }message_receivedthreadIdmetadatamessage_sendingreplyToIdthreadIdThe
/approveapprovals.pluginIf custom approval plumbing needs to detect that same bounded fallback case, prefer
isApprovalNotFoundErroropenclaw/plugin-sdk/error-runtimeSee Plugin hooks for examples and the hook reference.
Tools are typed functions the LLM can call. They can be required (always available) or optional (user opt-in):
typescriptregister(api) { // Required tool — always available api.registerTool({ name: "my_tool", description: "Do a thing", parameters: Type.Object({ input: Type.String() }), async execute(_id, params) { return { content: [{ type: "text", text: params.input }] }; }, }); // Optional tool — user must add to allowlist api.registerTool( { name: "workflow_tool", description: "Run a workflow", parameters: Type.Object({ pipeline: Type.String() }), async execute(_id, params) { return { content: [{ type: "text", text: params.pipeline }] }; }, }, { optional: true }, ); }
Users enable optional tools in config:
json5{ tools: { allow: ["workflow_tool"] }, }
parametersoptional: truetools.allowAlways import from focused
openclaw/plugin-sdk/<subpath>typescriptimport { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store"; // Wrong: monolithic root (deprecated, will be removed) import { ... } from "openclaw/plugin-sdk";
For the full subpath reference, see SDK Overview.
Within your plugin, use local barrel files (
api.tsruntime-api.tsFor provider plugins, keep provider-specific helpers in those package-root barrels unless the seam is truly generic. Current bundled examples:
service_tierIf a helper is only useful inside one bundled provider package, keep it on that package-root seam instead of promoting it into
openclaw/plugin-sdk/*Some generated
openclaw/plugin-sdk/<bundled-id>openclawdefineChannelPluginEntrydefinePluginEntryplugin-sdk/<subpath>pnpm test -- <bundled-plugin-root>/my-plugin/pnpm check
WatchReleasesv2026.3.N-beta.1plugin-forumall goodBeta blocker: <plugin-name> - <summary>beta-blockermainfix(<plugin-id>): beta blocker - <summary>Build a messaging channel plugin
Build a model provider plugin
Import map and registration API reference
TTS, search, subagent via api.runtime
Test utilities and patterns
Full manifest schema reference
© 2024 TaskFlow Mirror
Powered by TaskFlow Sync Engine