Files
openclaw-skill/openclaw-knowhow-skill/output/openclaw-docs_data/pages/Plugins_Extensions_92ae13e4fe.json
Selig 4c966a3ad2 Initial commit: OpenClaw Skill Collection
6 custom skills (assign-task, dispatch-webhook, daily-briefing,
task-capture, qmd-brain, tts-voice) with technical documentation.
Compatible with Claude Code, OpenClaw, Codex CLI, and OpenCode.
2026-03-13 10:58:30 +08:00

222 lines
29 KiB
JSON
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"title": "Plugins (Extensions)",
"content": "## Quick start (new to plugins?)\n\nA plugin is just a **small code module** that extends OpenClaw with extra\nfeatures (commands, tools, and Gateway RPC).\n\nMost of the time, youll use plugins when you want a feature thats not built\ninto core OpenClaw yet (or you want to keep optional features out of your main\ninstall).\n\n1. See whats already loaded:\n\n2. Install an official plugin (example: Voice Call):\n\n3. Restart the Gateway, then configure under `plugins.entries.<id>.config`.\n\nSee [Voice Call](/plugins/voice-call) for a concrete example plugin.\n\n## Available plugins (official)\n\n* Microsoft Teams is plugin-only as of 2026.1.15; install `@openclaw/msteams` if you use Teams.\n* Memory (Core) — bundled memory search plugin (enabled by default via `plugins.slots.memory`)\n* Memory (LanceDB) — bundled long-term memory plugin (auto-recall/capture; set `plugins.slots.memory = \"memory-lancedb\"`)\n* [Voice Call](/plugins/voice-call) — `@openclaw/voice-call`\n* [Zalo Personal](/plugins/zalouser) — `@openclaw/zalouser`\n* [Matrix](/channels/matrix) — `@openclaw/matrix`\n* [Nostr](/channels/nostr) — `@openclaw/nostr`\n* [Zalo](/channels/zalo) — `@openclaw/zalo`\n* [Microsoft Teams](/channels/msteams) — `@openclaw/msteams`\n* Google Antigravity OAuth (provider auth) — bundled as `google-antigravity-auth` (disabled by default)\n* Gemini CLI OAuth (provider auth) — bundled as `google-gemini-cli-auth` (disabled by default)\n* Qwen OAuth (provider auth) — bundled as `qwen-portal-auth` (disabled by default)\n* Copilot Proxy (provider auth) — local VS Code Copilot Proxy bridge; distinct from built-in `github-copilot` device login (bundled, disabled by default)\n\nOpenClaw plugins are **TypeScript modules** loaded at runtime via jiti. **Config\nvalidation does not execute plugin code**; it uses the plugin manifest and JSON\nSchema instead. See [Plugin manifest](/plugins/manifest).\n\nPlugins can register:\n\n* Gateway RPC methods\n* Gateway HTTP handlers\n* Agent tools\n* CLI commands\n* Background services\n* Optional config validation\n* **Skills** (by listing `skills` directories in the plugin manifest)\n* **Auto-reply commands** (execute without invoking the AI agent)\n\nPlugins run **inprocess** with the Gateway, so treat them as trusted code.\nTool authoring guide: [Plugin agent tools](/plugins/agent-tools).\n\nPlugins can access selected core helpers via `api.runtime`. For telephony TTS:\n\n* Uses core `messages.tts` configuration (OpenAI or ElevenLabs).\n* Returns PCM audio buffer + sample rate. Plugins must resample/encode for providers.\n* Edge TTS is not supported for telephony.\n\n## Discovery & precedence\n\nOpenClaw scans, in order:\n\n* `plugins.load.paths` (file or directory)\n\n2. Workspace extensions\n\n* `<workspace>/.openclaw/extensions/*.ts`\n* `<workspace>/.openclaw/extensions/*/index.ts`\n\n* `~/.openclaw/extensions/*.ts`\n* `~/.openclaw/extensions/*/index.ts`\n\n4. Bundled extensions (shipped with OpenClaw, **disabled by default**)\n\n* `<openclaw>/extensions/*`\n\nBundled plugins must be enabled explicitly via `plugins.entries.<id>.enabled`\nor `openclaw plugins enable <id>`. Installed plugins are enabled by default,\nbut can be disabled the same way.\n\nEach plugin must include a `openclaw.plugin.json` file in its root. If a path\npoints at a file, the plugin root is the file's directory and must contain the\nmanifest.\n\nIf multiple plugins resolve to the same id, the first match in the order above\nwins and lower-precedence copies are ignored.\n\nA plugin directory may include a `package.json` with `openclaw.extensions`:\n\nEach entry becomes a plugin. If the pack lists multiple extensions, the plugin id\nbecomes `name/<fileBase>`.\n\nIf your plugin imports npm deps, install them in that directory so\n`node_modules` is available (`npm install` / `pnpm install`).\n\n### Channel catalog metadata\n\nChannel plugins can advertise onboarding metadata via `openclaw.channel` and\ninstall hints via `openclaw.install`. This keeps the core catalog data-free.\n\nOpenClaw can also merge **external channel catalogs** (for example, an MPM\nregistry export). Drop a JSON file at one of:\n\n* `~/.openclaw/mpm/plugins.json`\n* `~/.openclaw/mpm/catalog.json`\n* `~/.openclaw/plugins/catalog.json`\n\nOr point `OPENCLAW_PLUGIN_CATALOG_PATHS` (or `OPENCLAW_MPM_CATALOG_PATHS`) at\none or more JSON files (comma/semicolon/`PATH`-delimited). Each file should\ncontain `{ \"entries\": [ { \"name\": \"@scope/pkg\", \"openclaw\": { \"channel\": {...}, \"install\": {...} } } ] }`.\n\n* Package packs: `package.json` `name`\n* Standalone file: file base name (`~/.../voice-call.ts` → `voice-call`)\n\nIf a plugin exports `id`, OpenClaw uses it but warns when it doesnt match the\nconfigured id.\n\n* `enabled`: master toggle (default: true)\n* `allow`: allowlist (optional)\n* `deny`: denylist (optional; deny wins)\n* `load.paths`: extra plugin files/dirs\n* `entries.<id>`: perplugin toggles + config\n\nConfig changes **require a gateway restart**.\n\nValidation rules (strict):\n\n* Unknown plugin ids in `entries`, `allow`, `deny`, or `slots` are **errors**.\n* Unknown `channels.<id>` keys are **errors** unless a plugin manifest declares\n the channel id.\n* Plugin config is validated using the JSON Schema embedded in\n `openclaw.plugin.json` (`configSchema`).\n* If a plugin is disabled, its config is preserved and a **warning** is emitted.\n\n## Plugin slots (exclusive categories)\n\nSome plugin categories are **exclusive** (only one active at a time). Use\n`plugins.slots` to select which plugin owns the slot:\n\nIf multiple plugins declare `kind: \"memory\"`, only the selected one loads. Others\nare disabled with diagnostics.\n\n## Control UI (schema + labels)\n\nThe Control UI uses `config.schema` (JSON Schema + `uiHints`) to render better forms.\n\nOpenClaw augments `uiHints` at runtime based on discovered plugins:\n\n* Adds per-plugin labels for `plugins.entries.<id>` / `.enabled` / `.config`\n* Merges optional plugin-provided config field hints under:\n `plugins.entries.<id>.config.<field>`\n\nIf you want your plugin config fields to show good labels/placeholders (and mark secrets as sensitive),\nprovide `uiHints` alongside your JSON Schema in the plugin manifest.\n\n`plugins update` only works for npm installs tracked under `plugins.installs`.\n\nPlugins may also register their own toplevel commands (example: `openclaw voicecall`).\n\n## Plugin API (overview)\n\nPlugins export either:\n\n* A function: `(api) => { ... }`\n* An object: `{ id, name, configSchema, register(api) { ... } }`\n\nPlugins can ship hooks and register them at runtime. This lets a plugin bundle\nevent-driven automation without a separate hook pack install.\n\n* Hook directories follow the normal hook structure (`HOOK.md` + `handler.ts`).\n* Hook eligibility rules still apply (OS/bins/env/config requirements).\n* Plugin-managed hooks show up in `openclaw hooks list` with `plugin:<id>`.\n* You cannot enable/disable plugin-managed hooks via `openclaw hooks`; enable/disable the plugin instead.\n\n## Provider plugins (model auth)\n\nPlugins can register **model provider auth** flows so users can run OAuth or\nAPI-key setup inside OpenClaw (no external scripts needed).\n\nRegister a provider via `api.registerProvider(...)`. Each provider exposes one\nor more auth methods (OAuth, API key, device code, etc.). These methods power:\n\n* `openclaw models auth login --provider <id> [--method <id>]`\n\n* `run` receives a `ProviderAuthContext` with `prompter`, `runtime`,\n `openUrl`, and `oauth.createVpsAwareHandlers` helpers.\n* Return `configPatch` when you need to add default models or provider config.\n* Return `defaultModel` so `--set-default` can update agent defaults.\n\n### Register a messaging channel\n\nPlugins can register **channel plugins** that behave like builtin channels\n(WhatsApp, Telegram, etc.). Channel config lives under `channels.<id>` and is\nvalidated by your channel plugin code.\n\n* Put config under `channels.<id>` (not `plugins.entries`).\n* `meta.label` is used for labels in CLI/UI lists.\n* `meta.aliases` adds alternate ids for normalization and CLI inputs.\n* `meta.preferOver` lists channel ids to skip auto-enable when both are configured.\n* `meta.detailLabel` and `meta.systemImage` let UIs show richer channel labels/icons.\n\n### Write a new messaging channel (stepbystep)\n\nUse this when you want a **new chat surface** (a “messaging channel”), not a model provider.\nModel provider docs live under `/providers/*`.\n\n1. Pick an id + config shape\n\n* All channel config lives under `channels.<id>`.\n* Prefer `channels.<id>.accounts.<accountId>` for multiaccount setups.\n\n2. Define the channel metadata\n\n* `meta.label`, `meta.selectionLabel`, `meta.docsPath`, `meta.blurb` control CLI/UI lists.\n* `meta.docsPath` should point at a docs page like `/channels/<id>`.\n* `meta.preferOver` lets a plugin replace another channel (auto-enable prefers it).\n* `meta.detailLabel` and `meta.systemImage` are used by UIs for detail text/icons.\n\n3. Implement the required adapters\n\n* `config.listAccountIds` + `config.resolveAccount`\n* `capabilities` (chat types, media, threads, etc.)\n* `outbound.deliveryMode` + `outbound.sendText` (for basic send)\n\n4. Add optional adapters as needed\n\n* `setup` (wizard), `security` (DM policy), `status` (health/diagnostics)\n* `gateway` (start/stop/login), `mentions`, `threading`, `streaming`\n* `actions` (message actions), `commands` (native command behavior)\n\n5. Register the channel in your plugin\n\n* `api.registerChannel({ plugin })`\n\nMinimal config example:\n\nMinimal channel plugin (outboundonly):\n\nLoad the plugin (extensions dir or `plugins.load.paths`), restart the gateway,\nthen configure `channels.<id>` in your config.\n\nSee the dedicated guide: [Plugin agent tools](/plugins/agent-tools).\n\n### Register a gateway RPC method\n\n### Register CLI commands\n\n### Register auto-reply commands\n\nPlugins can register custom slash commands that execute **without invoking the\nAI agent**. This is useful for toggle commands, status checks, or quick actions\nthat don't need LLM processing.\n\nCommand handler context:\n\n* `senderId`: The sender's ID (if available)\n* `channel`: The channel where the command was sent\n* `isAuthorizedSender`: Whether the sender is an authorized user\n* `args`: Arguments passed after the command (if `acceptsArgs: true`)\n* `commandBody`: The full command text\n* `config`: The current OpenClaw config\n\n* `name`: Command name (without the leading `/`)\n* `description`: Help text shown in command lists\n* `acceptsArgs`: Whether the command accepts arguments (default: false). If false and arguments are provided, the command won't match and the message falls through to other handlers\n* `requireAuth`: Whether to require authorized sender (default: true)\n* `handler`: Function that returns `{ text: string }` (can be async)\n\nExample with authorization and arguments:\n\n* Plugin commands are processed **before** built-in commands and the AI agent\n* Commands are registered globally and work across all channels\n* Command names are case-insensitive (`/MyStatus` matches `/mystatus`)\n* Command names must start with a letter and contain only letters, numbers, hyphens, and underscores\n* Reserved command names (like `help`, `status`, `reset`, etc.) cannot be overridden by plugins\n* Duplicate command registration across plugins will fail with a diagnostic error\n\n### Register background services\n\n## Naming conventions\n\n* Gateway methods: `pluginId.action` (example: `voicecall.status`)\n* Tools: `snake_case` (example: `voice_call`)\n* CLI commands: kebab or camel, but avoid clashing with core commands\n\nPlugins can ship a skill in the repo (`skills/<name>/SKILL.md`).\nEnable it with `plugins.entries.<id>.enabled` (or other config gates) and ensure\nits present in your workspace/managed skills locations.\n\n## Distribution (npm)\n\nRecommended packaging:\n\n* Main package: `openclaw` (this repo)\n* Plugins: separate npm packages under `@openclaw/*` (example: `@openclaw/voice-call`)\n\n* Plugin `package.json` must include `openclaw.extensions` with one or more entry files.\n* Entry files can be `.js` or `.ts` (jiti loads TS at runtime).\n* `openclaw plugins install <npm-spec>` uses `npm pack`, extracts into `~/.openclaw/extensions/<id>/`, and enables it in config.\n* Config key stability: scoped packages are normalized to the **unscoped** id for `plugins.entries.*`.\n\n## Example plugin: Voice Call\n\nThis repo includes a voicecall plugin (Twilio or log fallback):\n\n* Source: `extensions/voice-call`\n* Skill: `skills/voice-call`\n* CLI: `openclaw voicecall start|status`\n* Tool: `voice_call`\n* RPC: `voicecall.start`, `voicecall.status`\n* Config (twilio): `provider: \"twilio\"` + `twilio.accountSid/authToken/from` (optional `statusCallbackUrl`, `twimlUrl`)\n* Config (dev): `provider: \"log\"` (no network)\n\nSee [Voice Call](/plugins/voice-call) and `extensions/voice-call/README.md` for setup and usage.\n\nPlugins run in-process with the Gateway. Treat them as trusted code:\n\n* Only install plugins you trust.\n* Prefer `plugins.allow` allowlists.\n* Restart the Gateway after changes.\n\nPlugins can (and should) ship tests:\n\n* In-repo plugins can keep Vitest tests under `src/**` (example: `src/plugins/voice-call.plugin.test.ts`).\n* Separately published plugins should run their own CI (lint/build/test) and validate `openclaw.extensions` points at the built entrypoint (`dist/index.js`).",
"code_samples": [
{
"code": "2. Install an official plugin (example: Voice Call):",
"language": "unknown"
},
{
"code": "3. Restart the Gateway, then configure under `plugins.entries.<id>.config`.\n\nSee [Voice Call](/plugins/voice-call) for a concrete example plugin.\n\n## Available plugins (official)\n\n* Microsoft Teams is plugin-only as of 2026.1.15; install `@openclaw/msteams` if you use Teams.\n* Memory (Core) — bundled memory search plugin (enabled by default via `plugins.slots.memory`)\n* Memory (LanceDB) — bundled long-term memory plugin (auto-recall/capture; set `plugins.slots.memory = \"memory-lancedb\"`)\n* [Voice Call](/plugins/voice-call) — `@openclaw/voice-call`\n* [Zalo Personal](/plugins/zalouser) — `@openclaw/zalouser`\n* [Matrix](/channels/matrix) — `@openclaw/matrix`\n* [Nostr](/channels/nostr) — `@openclaw/nostr`\n* [Zalo](/channels/zalo) — `@openclaw/zalo`\n* [Microsoft Teams](/channels/msteams) — `@openclaw/msteams`\n* Google Antigravity OAuth (provider auth) — bundled as `google-antigravity-auth` (disabled by default)\n* Gemini CLI OAuth (provider auth) — bundled as `google-gemini-cli-auth` (disabled by default)\n* Qwen OAuth (provider auth) — bundled as `qwen-portal-auth` (disabled by default)\n* Copilot Proxy (provider auth) — local VS Code Copilot Proxy bridge; distinct from built-in `github-copilot` device login (bundled, disabled by default)\n\nOpenClaw plugins are **TypeScript modules** loaded at runtime via jiti. **Config\nvalidation does not execute plugin code**; it uses the plugin manifest and JSON\nSchema instead. See [Plugin manifest](/plugins/manifest).\n\nPlugins can register:\n\n* Gateway RPC methods\n* Gateway HTTP handlers\n* Agent tools\n* CLI commands\n* Background services\n* Optional config validation\n* **Skills** (by listing `skills` directories in the plugin manifest)\n* **Auto-reply commands** (execute without invoking the AI agent)\n\nPlugins run **inprocess** with the Gateway, so treat them as trusted code.\nTool authoring guide: [Plugin agent tools](/plugins/agent-tools).\n\n## Runtime helpers\n\nPlugins can access selected core helpers via `api.runtime`. For telephony TTS:",
"language": "unknown"
},
{
"code": "Notes:\n\n* Uses core `messages.tts` configuration (OpenAI or ElevenLabs).\n* Returns PCM audio buffer + sample rate. Plugins must resample/encode for providers.\n* Edge TTS is not supported for telephony.\n\n## Discovery & precedence\n\nOpenClaw scans, in order:\n\n1. Config paths\n\n* `plugins.load.paths` (file or directory)\n\n2. Workspace extensions\n\n* `<workspace>/.openclaw/extensions/*.ts`\n* `<workspace>/.openclaw/extensions/*/index.ts`\n\n3. Global extensions\n\n* `~/.openclaw/extensions/*.ts`\n* `~/.openclaw/extensions/*/index.ts`\n\n4. Bundled extensions (shipped with OpenClaw, **disabled by default**)\n\n* `<openclaw>/extensions/*`\n\nBundled plugins must be enabled explicitly via `plugins.entries.<id>.enabled`\nor `openclaw plugins enable <id>`. Installed plugins are enabled by default,\nbut can be disabled the same way.\n\nEach plugin must include a `openclaw.plugin.json` file in its root. If a path\npoints at a file, the plugin root is the file's directory and must contain the\nmanifest.\n\nIf multiple plugins resolve to the same id, the first match in the order above\nwins and lower-precedence copies are ignored.\n\n### Package packs\n\nA plugin directory may include a `package.json` with `openclaw.extensions`:",
"language": "unknown"
},
{
"code": "Each entry becomes a plugin. If the pack lists multiple extensions, the plugin id\nbecomes `name/<fileBase>`.\n\nIf your plugin imports npm deps, install them in that directory so\n`node_modules` is available (`npm install` / `pnpm install`).\n\n### Channel catalog metadata\n\nChannel plugins can advertise onboarding metadata via `openclaw.channel` and\ninstall hints via `openclaw.install`. This keeps the core catalog data-free.\n\nExample:",
"language": "unknown"
},
{
"code": "OpenClaw can also merge **external channel catalogs** (for example, an MPM\nregistry export). Drop a JSON file at one of:\n\n* `~/.openclaw/mpm/plugins.json`\n* `~/.openclaw/mpm/catalog.json`\n* `~/.openclaw/plugins/catalog.json`\n\nOr point `OPENCLAW_PLUGIN_CATALOG_PATHS` (or `OPENCLAW_MPM_CATALOG_PATHS`) at\none or more JSON files (comma/semicolon/`PATH`-delimited). Each file should\ncontain `{ \"entries\": [ { \"name\": \"@scope/pkg\", \"openclaw\": { \"channel\": {...}, \"install\": {...} } } ] }`.\n\n## Plugin IDs\n\nDefault plugin ids:\n\n* Package packs: `package.json` `name`\n* Standalone file: file base name (`~/.../voice-call.ts` → `voice-call`)\n\nIf a plugin exports `id`, OpenClaw uses it but warns when it doesnt match the\nconfigured id.\n\n## Config",
"language": "unknown"
},
{
"code": "Fields:\n\n* `enabled`: master toggle (default: true)\n* `allow`: allowlist (optional)\n* `deny`: denylist (optional; deny wins)\n* `load.paths`: extra plugin files/dirs\n* `entries.<id>`: perplugin toggles + config\n\nConfig changes **require a gateway restart**.\n\nValidation rules (strict):\n\n* Unknown plugin ids in `entries`, `allow`, `deny`, or `slots` are **errors**.\n* Unknown `channels.<id>` keys are **errors** unless a plugin manifest declares\n the channel id.\n* Plugin config is validated using the JSON Schema embedded in\n `openclaw.plugin.json` (`configSchema`).\n* If a plugin is disabled, its config is preserved and a **warning** is emitted.\n\n## Plugin slots (exclusive categories)\n\nSome plugin categories are **exclusive** (only one active at a time). Use\n`plugins.slots` to select which plugin owns the slot:",
"language": "unknown"
},
{
"code": "If multiple plugins declare `kind: \"memory\"`, only the selected one loads. Others\nare disabled with diagnostics.\n\n## Control UI (schema + labels)\n\nThe Control UI uses `config.schema` (JSON Schema + `uiHints`) to render better forms.\n\nOpenClaw augments `uiHints` at runtime based on discovered plugins:\n\n* Adds per-plugin labels for `plugins.entries.<id>` / `.enabled` / `.config`\n* Merges optional plugin-provided config field hints under:\n `plugins.entries.<id>.config.<field>`\n\nIf you want your plugin config fields to show good labels/placeholders (and mark secrets as sensitive),\nprovide `uiHints` alongside your JSON Schema in the plugin manifest.\n\nExample:",
"language": "unknown"
},
{
"code": "## CLI",
"language": "unknown"
},
{
"code": "`plugins update` only works for npm installs tracked under `plugins.installs`.\n\nPlugins may also register their own toplevel commands (example: `openclaw voicecall`).\n\n## Plugin API (overview)\n\nPlugins export either:\n\n* A function: `(api) => { ... }`\n* An object: `{ id, name, configSchema, register(api) { ... } }`\n\n## Plugin hooks\n\nPlugins can ship hooks and register them at runtime. This lets a plugin bundle\nevent-driven automation without a separate hook pack install.\n\n### Example",
"language": "unknown"
},
{
"code": "Notes:\n\n* Hook directories follow the normal hook structure (`HOOK.md` + `handler.ts`).\n* Hook eligibility rules still apply (OS/bins/env/config requirements).\n* Plugin-managed hooks show up in `openclaw hooks list` with `plugin:<id>`.\n* You cannot enable/disable plugin-managed hooks via `openclaw hooks`; enable/disable the plugin instead.\n\n## Provider plugins (model auth)\n\nPlugins can register **model provider auth** flows so users can run OAuth or\nAPI-key setup inside OpenClaw (no external scripts needed).\n\nRegister a provider via `api.registerProvider(...)`. Each provider exposes one\nor more auth methods (OAuth, API key, device code, etc.). These methods power:\n\n* `openclaw models auth login --provider <id> [--method <id>]`\n\nExample:",
"language": "unknown"
},
{
"code": "Notes:\n\n* `run` receives a `ProviderAuthContext` with `prompter`, `runtime`,\n `openUrl`, and `oauth.createVpsAwareHandlers` helpers.\n* Return `configPatch` when you need to add default models or provider config.\n* Return `defaultModel` so `--set-default` can update agent defaults.\n\n### Register a messaging channel\n\nPlugins can register **channel plugins** that behave like builtin channels\n(WhatsApp, Telegram, etc.). Channel config lives under `channels.<id>` and is\nvalidated by your channel plugin code.",
"language": "unknown"
},
{
"code": "Notes:\n\n* Put config under `channels.<id>` (not `plugins.entries`).\n* `meta.label` is used for labels in CLI/UI lists.\n* `meta.aliases` adds alternate ids for normalization and CLI inputs.\n* `meta.preferOver` lists channel ids to skip auto-enable when both are configured.\n* `meta.detailLabel` and `meta.systemImage` let UIs show richer channel labels/icons.\n\n### Write a new messaging channel (stepbystep)\n\nUse this when you want a **new chat surface** (a “messaging channel”), not a model provider.\nModel provider docs live under `/providers/*`.\n\n1. Pick an id + config shape\n\n* All channel config lives under `channels.<id>`.\n* Prefer `channels.<id>.accounts.<accountId>` for multiaccount setups.\n\n2. Define the channel metadata\n\n* `meta.label`, `meta.selectionLabel`, `meta.docsPath`, `meta.blurb` control CLI/UI lists.\n* `meta.docsPath` should point at a docs page like `/channels/<id>`.\n* `meta.preferOver` lets a plugin replace another channel (auto-enable prefers it).\n* `meta.detailLabel` and `meta.systemImage` are used by UIs for detail text/icons.\n\n3. Implement the required adapters\n\n* `config.listAccountIds` + `config.resolveAccount`\n* `capabilities` (chat types, media, threads, etc.)\n* `outbound.deliveryMode` + `outbound.sendText` (for basic send)\n\n4. Add optional adapters as needed\n\n* `setup` (wizard), `security` (DM policy), `status` (health/diagnostics)\n* `gateway` (start/stop/login), `mentions`, `threading`, `streaming`\n* `actions` (message actions), `commands` (native command behavior)\n\n5. Register the channel in your plugin\n\n* `api.registerChannel({ plugin })`\n\nMinimal config example:",
"language": "unknown"
},
{
"code": "Minimal channel plugin (outboundonly):",
"language": "unknown"
},
{
"code": "Load the plugin (extensions dir or `plugins.load.paths`), restart the gateway,\nthen configure `channels.<id>` in your config.\n\n### Agent tools\n\nSee the dedicated guide: [Plugin agent tools](/plugins/agent-tools).\n\n### Register a gateway RPC method",
"language": "unknown"
},
{
"code": "### Register CLI commands",
"language": "unknown"
},
{
"code": "### Register auto-reply commands\n\nPlugins can register custom slash commands that execute **without invoking the\nAI agent**. This is useful for toggle commands, status checks, or quick actions\nthat don't need LLM processing.",
"language": "unknown"
},
{
"code": "Command handler context:\n\n* `senderId`: The sender's ID (if available)\n* `channel`: The channel where the command was sent\n* `isAuthorizedSender`: Whether the sender is an authorized user\n* `args`: Arguments passed after the command (if `acceptsArgs: true`)\n* `commandBody`: The full command text\n* `config`: The current OpenClaw config\n\nCommand options:\n\n* `name`: Command name (without the leading `/`)\n* `description`: Help text shown in command lists\n* `acceptsArgs`: Whether the command accepts arguments (default: false). If false and arguments are provided, the command won't match and the message falls through to other handlers\n* `requireAuth`: Whether to require authorized sender (default: true)\n* `handler`: Function that returns `{ text: string }` (can be async)\n\nExample with authorization and arguments:",
"language": "unknown"
},
{
"code": "Notes:\n\n* Plugin commands are processed **before** built-in commands and the AI agent\n* Commands are registered globally and work across all channels\n* Command names are case-insensitive (`/MyStatus` matches `/mystatus`)\n* Command names must start with a letter and contain only letters, numbers, hyphens, and underscores\n* Reserved command names (like `help`, `status`, `reset`, etc.) cannot be overridden by plugins\n* Duplicate command registration across plugins will fail with a diagnostic error\n\n### Register background services",
"language": "unknown"
}
],
"headings": [
{
"level": "h2",
"text": "Quick start (new to plugins?)",
"id": "quick-start-(new-to-plugins?)"
},
{
"level": "h2",
"text": "Available plugins (official)",
"id": "available-plugins-(official)"
},
{
"level": "h2",
"text": "Runtime helpers",
"id": "runtime-helpers"
},
{
"level": "h2",
"text": "Discovery & precedence",
"id": "discovery-&-precedence"
},
{
"level": "h3",
"text": "Package packs",
"id": "package-packs"
},
{
"level": "h3",
"text": "Channel catalog metadata",
"id": "channel-catalog-metadata"
},
{
"level": "h2",
"text": "Plugin IDs",
"id": "plugin-ids"
},
{
"level": "h2",
"text": "Config",
"id": "config"
},
{
"level": "h2",
"text": "Plugin slots (exclusive categories)",
"id": "plugin-slots-(exclusive-categories)"
},
{
"level": "h2",
"text": "Control UI (schema + labels)",
"id": "control-ui-(schema-+-labels)"
},
{
"level": "h2",
"text": "CLI",
"id": "cli"
},
{
"level": "h2",
"text": "Plugin API (overview)",
"id": "plugin-api-(overview)"
},
{
"level": "h2",
"text": "Plugin hooks",
"id": "plugin-hooks"
},
{
"level": "h3",
"text": "Example",
"id": "example"
},
{
"level": "h2",
"text": "Provider plugins (model auth)",
"id": "provider-plugins-(model-auth)"
},
{
"level": "h3",
"text": "Register a messaging channel",
"id": "register-a-messaging-channel"
},
{
"level": "h3",
"text": "Write a new messaging channel (stepbystep)",
"id": "write-a-new-messaging-channel-(stepbystep)"
},
{
"level": "h3",
"text": "Agent tools",
"id": "agent-tools"
},
{
"level": "h3",
"text": "Register a gateway RPC method",
"id": "register-a-gateway-rpc-method"
},
{
"level": "h3",
"text": "Register CLI commands",
"id": "register-cli-commands"
},
{
"level": "h3",
"text": "Register auto-reply commands",
"id": "register-auto-reply-commands"
},
{
"level": "h3",
"text": "Register background services",
"id": "register-background-services"
},
{
"level": "h2",
"text": "Naming conventions",
"id": "naming-conventions"
},
{
"level": "h2",
"text": "Skills",
"id": "skills"
},
{
"level": "h2",
"text": "Distribution (npm)",
"id": "distribution-(npm)"
},
{
"level": "h2",
"text": "Example plugin: Voice Call",
"id": "example-plugin:-voice-call"
},
{
"level": "h2",
"text": "Safety notes",
"id": "safety-notes"
},
{
"level": "h2",
"text": "Testing plugins",
"id": "testing-plugins"
}
],
"url": "llms-txt#plugins-(extensions)",
"links": []
}