Plugins (Extensions)
Schnellstart (neu bei Plugins?)
Ein Plugin ist einfach ein kleines Code-Modul, das OpenClaw um zusätzliche Features erweitert (Commands, Tools und Gateway RPC).
Meistens nutzt du Plugins, wenn du ein Feature brauchst, das noch nicht in OpenClaw eingebaut ist (oder wenn du optional Features aus deiner Hauptinstallation raushalten willst).
Schnelleinstieg:
- Schau dir an, was bereits geladen ist:
openclaw plugins list
- Installiere ein offizielles Plugin (Beispiel: Voice Call):
openclaw plugins install @openclaw/voice-call
- Starte den Gateway neu und konfiguriere dann unter
plugins.entries.<id>.config.
Siehe Voice Call für ein konkretes Plugin-Beispiel.
Verfügbare Plugins (offiziell)
- Microsoft Teams ist seit 2026.1.15 nur als Plugin verfügbar; installiere
@openclaw/msteams, wenn du Teams nutzt. - Memory (Core) — mitgeliefertes Memory-Search-Plugin (standardmäßig aktiviert über
plugins.slots.memory) - Memory (LanceDB) — mitgeliefertes Langzeit-Memory-Plugin (Auto-Recall/Capture; setze
plugins.slots.memory = "memory-lancedb") - Voice Call —
@openclaw/voice-call - Zalo Personal —
@openclaw/zalouser - Matrix —
@openclaw/matrix - Nostr —
@openclaw/nostr - Zalo —
@openclaw/zalo - Microsoft Teams —
@openclaw/msteams - Google Antigravity OAuth (Provider Auth) — mitgeliefert als
google-antigravity-auth(standardmäßig deaktiviert) - Gemini CLI OAuth (Provider Auth) — mitgeliefert als
google-gemini-cli-auth(standardmäßig deaktiviert) - Qwen OAuth (Provider Auth) — mitgeliefert als
qwen-portal-auth(standardmäßig deaktiviert) - Copilot Proxy (Provider Auth) — lokale VS Code Copilot Proxy Bridge; unterscheidet sich vom eingebauten
github-copilotDevice Login (mitgeliefert, standardmäßig deaktiviert)
OpenClaw Plugins sind TypeScript-Module, die zur Laufzeit über jiti geladen werden. Config-Validierung führt keinen Plugin-Code aus; sie nutzt stattdessen das Plugin-Manifest und JSON Schema. Siehe Plugin-Manifest.
Plugins können registrieren:
- Gateway RPC Methods
- Gateway HTTP Handler
- Agent Tools
- CLI Commands
- Background Services
- Optionale Config-Validierung
- Skills (durch Auflistung von
skills-Verzeichnissen im Plugin-Manifest) - Auto-Reply Commands (werden ohne AI Agent ausgeführt)
Plugins laufen im selben Prozess wie der Gateway, behandle sie also als vertrauenswürdigen Code. Tool-Authoring-Guide: Plugin Agent Tools.
Runtime Helpers
Plugins können über api.runtime auf ausgewählte Core-Helpers zugreifen. Für Telefonie-TTS:
const result = await api.runtime.tts.textToSpeechTelephony({
text: "Hello from OpenClaw",
cfg: api.config,
});
Hinweise:
- Nutzt die Core-Konfiguration
messages.tts(OpenAI oder ElevenLabs). - Gibt PCM-Audio-Buffer + Sample-Rate zurück. Plugins müssen für Provider selbst resampling/encoding machen.
- Edge TTS wird für Telefonie nicht unterstützt.
Entdeckung & Priorität
OpenClaw scannt in dieser Reihenfolge:
- Config-Pfade
plugins.load.paths(Datei oder Verzeichnis)
- Workspace Extensions
<workspace>/.openclaw/extensions/*.ts<workspace>/.openclaw/extensions/*/index.ts
- Globale Extensions
~/.openclaw/extensions/*.ts~/.openclaw/extensions/*/index.ts
- Mitgelieferte Extensions (mit OpenClaw ausgeliefert, standardmäßig deaktiviert)
<openclaw>/extensions/*
Mitgelieferte Plugins müssen explizit über plugins.entries.<id>.enabled oder openclaw plugins enable <id> aktiviert werden. Installierte Plugins sind standardmäßig aktiviert, können aber auf die gleiche Weise deaktiviert werden.
Jedes Plugin muss eine openclaw.plugin.json-Datei in seinem Root-Verzeichnis enthalten. Wenn ein Pfad auf eine Datei zeigt, ist das Plugin-Root das Verzeichnis der Datei und muss das Manifest enthalten.
Wenn mehrere Plugins zur gleichen ID auflösen, gewinnt der erste Treffer in der obigen Reihenfolge und Kopien mit niedrigerer Priorität werden ignoriert.
Package Packs
Ein Plugin-Verzeichnis kann eine package.json mit openclaw.extensions enthalten:
{
"name": "my-pack",
"openclaw": {
"extensions": ["./src/safety.ts", "./src/tools.ts"]
}
}
Jeder Eintrag wird zu einem Plugin. Wenn das Pack mehrere Extensions auflistet, wird die Plugin-ID zu name/<fileBase>.
Wenn dein Plugin npm-Abhängigkeiten importiert, installiere sie in diesem Verzeichnis, damit node_modules verfügbar ist (npm install / pnpm install).
Channel Catalog Metadata
Channel-Plugins können Onboarding-Metadaten über openclaw.channel und Installations-Hinweise über openclaw.install bereitstellen. So bleibt der Core-Katalog datenfrei.
Beispiel:
{
"name": "@openclaw/nextcloud-talk",
"openclaw": {
"extensions": ["./index.ts"],
"channel": {
"id": "nextcloud-talk",
"label": "Nextcloud Talk",
"selectionLabel": "Nextcloud Talk (self-hosted)",
"docsPath": "/channels/nextcloud-talk",
"docsLabel": "nextcloud-talk",
"blurb": "Self-hosted Chat via Nextcloud Talk Webhook Bots.",
"order": 65,
"aliases": ["nc-talk", "nc"]
},
"install": {
"npmSpec": "@openclaw/nextcloud-talk",
"localPath": "extensions/nextcloud-talk",
"defaultChoice": "npm"
}
}
}
OpenClaw kann auch externe Channel-Kataloge zusammenführen (z. B. einen MPM-Registry-Export). Lege eine JSON-Datei an einem dieser Orte ab:
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
Oder zeige mit OPENCLAW_PLUGIN_CATALOG_PATHS (oder OPENCLAW_MPM_CATALOG_PATHS) auf eine oder mehrere JSON-Dateien (Komma/Semikolon/PATH-getrennt). Jede Datei sollte { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] } enthalten.
Plugin-IDs
Standard-Plugin-IDs:
- Package Packs:
package.jsonname - Standalone-Datei: Datei-Basisname (
~/.../voice-call.ts→voice-call)
Wenn ein Plugin id exportiert, nutzt OpenClaw diese, warnt aber, wenn sie nicht mit der konfigurierten ID übereinstimmt.
Konfiguration
{
plugins: {
enabled: true,
allow: ["voice-call"],
deny: ["untrusted-plugin"],
load: { paths: ["~/Projects/oss/voice-call-extension"] },
entries: {
"voice-call": { enabled: true, config: { provider: "twilio" } },
},
},
}
Felder:
enabled: Master-Toggle (Standard: true)allow: Allowlist (optional)deny: Denylist (optional; deny gewinnt)load.paths: zusätzliche Plugin-Dateien/-Verzeichnisseentries.<id>: Plugin-spezifische Toggles + Config
Config-Änderungen erfordern einen Gateway-Neustart.
Validierungsregeln (strikt):
- Unbekannte Plugin-IDs in
entries,allow,denyoderslotssind Fehler. - Unbekannte
channels.<id>-Keys sind Fehler, außer ein Plugin-Manifest deklariert die Channel-ID. - Plugin-Config wird mit dem JSON Schema validiert, das in
openclaw.plugin.json(configSchema) eingebettet ist. - Wenn ein Plugin deaktiviert ist, wird seine Config beibehalten und eine Warnung ausgegeben.
Plugin Slots (exklusive Kategorien)
Manche Plugin-Kategorien sind exklusiv (nur eines aktiv zur gleichen Zeit). Nutze plugins.slots, um auszuwählen, welches Plugin den Slot besitzt:
{
plugins: {
slots: {
memory: "memory-core", // oder "none" um Memory-Plugins zu deaktivieren
},
},
}
Wenn mehrere Plugins kind: "memory" deklarieren, wird nur das ausgewählte geladen. Andere werden mit Diagnostics deaktiviert.
Control UI (Schema + Labels)
Die Control UI nutzt config.schema (JSON Schema + uiHints), um bessere Formulare zu rendern.
OpenClaw erweitert uiHints zur Laufzeit basierend auf entdeckten Plugins:
- Fügt Plugin-spezifische Labels für
plugins.entries.<id>/.enabled/.confighinzu - Führt optionale Plugin-bereitgestellte Config-Field-Hints zusammen unter:
plugins.entries.<id>.config.<field>
Wenn du möchtest, dass deine Plugin-Config-Felder gute Labels/Platzhalter zeigen (und Secrets als sensibel markieren), stelle uiHints neben deinem JSON Schema im Plugin-Manifest bereit.
Beispiel:
{
"id": "my-plugin",
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"apiKey": { "type": "string" },
"region": { "type": "string" }
}
},
"uiHints": {
"apiKey": { "label": "API Key", "sensitive": true },
"region": { "label": "Region", "placeholder": "us-east-1" }
}
}
CLI
openclaw plugins list
openclaw plugins info <id>
openclaw plugins install <path> # kopiert eine lokale Datei/Verzeichnis nach ~/.openclaw/extensions/<id>
openclaw plugins install ./extensions/voice-call # relativer Pfad ok
openclaw plugins install ./plugin.tgz # installiert aus lokalem Tarball
openclaw plugins install ./plugin.zip # installiert aus lokalem Zip
openclaw plugins install -l ./extensions/voice-call # Link (keine Kopie) für Dev
openclaw plugins install @openclaw/voice-call # installiert von npm
openclaw plugins update <id>
openclaw plugins update --all
openclaw plugins enable <id>
openclaw plugins disable <id>
openclaw plugins doctor
plugins update funktioniert nur für npm-Installationen, die unter plugins.installs getrackt werden.
Plugins können auch eigene Top-Level-Commands registrieren (Beispiel: openclaw voicecall).
Plugin API (Überblick)
Plugins exportieren entweder:
- Eine Funktion:
(api) => { ... } - Ein Objekt:
{ id, name, configSchema, register(api) { ... } }
Plugin Hooks
Plugins können Hooks mitliefern und zur Laufzeit registrieren. So kann ein Plugin event-gesteuerte Automatisierung bündeln, ohne eine separate Hook-Pack-Installation.
Beispiel
import { registerPluginHooksFromDir } from "openclaw/plugin-sdk";
export default function register(api) {
registerPluginHooksFromDir(api, "./hooks");
}
Hinweise:
- Hook-Verzeichnisse folgen der normalen Hook-Struktur (
HOOK.md+handler.ts). - Hook-Eligibility-Regeln gelten weiterhin (OS/Bins/Env/Config-Anforderungen).
- Plugin-verwaltete Hooks erscheinen in
openclaw hooks listmitplugin:<id>. - Du kannst Plugin-verwaltete Hooks nicht über
openclaw hooksaktivieren/deaktivieren; aktiviere/deaktiviere stattdessen das Plugin.
Provider Plugins (Model Auth)
Plugins können Model Provider Auth-Flows registrieren, damit Nutzer OAuth oder API-Key-Setup innerhalb von OpenClaw ausführen können (keine externen Skripte nötig).
Registriere einen Provider über api.registerProvider(...). Jeder Provider stellt eine oder mehrere Auth-Methoden bereit (OAuth, API Key, Device Code, etc.). Diese Methoden ermöglichen:
openclaw models auth login --provider <id> [--method <id>]
Beispiel:
api.registerProvider({
id: "acme",
label: "AcmeAI",
auth: [
{
id: "oauth",
label: "OAuth",
kind: "oauth",
run: async (ctx) => {
// Führe OAuth-Flow aus und gib Auth-Profile zurück.
return {
profiles: [
{
profileId: "acme:default",
credential: {
type: "oauth",
provider: "acme",
access: "...",
refresh: "...",
expires: Date.now() + 3600 * 1000,
},
},
],
defaultModel: "acme/opus-1",
};
},
},
],
});
Hinweise:
runerhält einenProviderAuthContextmitprompter,runtime,openUrlundoauth.createVpsAwareHandlers-Helpers.- Gib
configPatchzurück, wenn du Standard-Models oder Provider-Config hinzufügen musst. - Gib
defaultModelzurück, damit--set-defaultAgent-Defaults aktualisieren kann.
Messaging Channel registrieren
Plugins können Channel-Plugins registrieren, die sich wie eingebaute Channels verhalten (WhatsApp, Telegram, etc.). Channel-Config liegt unter channels.<id> und wird von deinem Channel-Plugin-Code validiert.
const myChannel = {
id: "acmechat",
meta: {
id: "acmechat",
label: "AcmeChat",
selectionLabel: "AcmeChat (API)",
docsPath: "/channels/acmechat",
blurb: "Demo Channel Plugin.",
aliases: ["acme"],
},
capabilities: { chatTypes: ["direct"] },
config: {
listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
resolveAccount: (cfg, accountId) =>
cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? {
accountId,
},
},
outbound: {
deliveryMode: "direct",
sendText: async () => ({ ok: true }),
},
};
export default function (api) {
api.registerChannel({ plugin: myChannel });
}
Hinweise:
- Lege Config unter
channels.<id>ab (nichtplugins.entries). meta.labelwird für Labels in CLI/UI-Listen genutzt.meta.aliasesfügt alternative IDs für Normalisierung und CLI-Eingaben hinzu.meta.preferOverlistet Channel-IDs auf, die beim Auto-Enable übersprungen werden, wenn beide konfiguriert sind.meta.detailLabelundmeta.systemImageermöglichen UIs, reichhaltigere Channel-Labels/Icons anzuzeigen.
Neuen Messaging Channel schreiben (Schritt für Schritt)
Nutze dies, wenn du eine neue Chat-Oberfläche (einen “Messaging Channel”) willst, keinen Model Provider.
Model-Provider-Docs liegen unter /providers/*.
- Wähle eine ID + Config-Form
- Alle Channel-Config liegt unter
channels.<id>. - Bevorzuge
channels.<id>.accounts.<accountId>für Multi-Account-Setups.
- Definiere die Channel-Metadaten
meta.label,meta.selectionLabel,meta.docsPath,meta.blurbsteuern CLI/UI-Listen.meta.docsPathsollte auf eine Docs-Seite wie/channels/<id>zeigen.meta.preferOverlässt ein Plugin einen anderen Channel ersetzen (Auto-Enable bevorzugt es).meta.detailLabelundmeta.systemImagewerden von UIs für Detail-Text/Icons genutzt.
- Implementiere die erforderlichen Adapter
config.listAccountIds+config.resolveAccountcapabilities(Chat-Typen, Media, Threads, etc.)outbound.deliveryMode+outbound.sendText(für einfaches Senden)
- Füge optionale Adapter nach Bedarf hinzu
setup(Wizard),security(DM-Policy),status(Health/Diagnostics)gateway(Start/Stop/Login),mentions,threading,streamingactions(Message Actions),commands(Native Command Behavior)
- Registriere den Channel in deinem Plugin
api.registerChannel({ plugin })
Minimales Config-Beispiel:
{
channels: {
acmechat: {
accounts: {
default: { token: "ACME_TOKEN", enabled: true },
},
},
},
}
Minimales Channel-Plugin (nur Outbound):
const plugin = {
id: "acmechat",
meta: {
id: "acmechat",
label: "AcmeChat",
selectionLabel: "AcmeChat (API)",
docsPath: "/channels/acmechat",
blurb: "AcmeChat Messaging Channel.",
aliases: ["acme"],
},
capabilities: { chatTypes: ["direct"] },
config: {
listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
resolveAccount: (cfg, accountId) =>
cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? {
accountId,
},
},
outbound: {
deliveryMode: "direct",
sendText: async ({ text }) => {
// liefere `text` an deinen Channel hier
return { ok: true };
},
},
};
export default function (api) {
api.registerChannel({ plugin });
}
Lade das Plugin (Extensions-Verzeichnis oder plugins.load.paths), starte den Gateway neu und konfiguriere dann channels.<id> in deiner Config.
Agent Tools
Siehe den dedizierten Guide: Plugin Agent Tools.
Gateway RPC Method registrieren
export default function (api) {
api.registerGatewayMethod("myplugin.status", ({ respond }) => {
respond(true, { ok: true });
});
}
CLI Commands registrieren
export default function (api) {
api.registerCli(
({ program }) => {
program.command("mycmd").action(() => {
console.log("Hello");
});
},
{ commands: ["mycmd"] },
);
}
Auto-Reply Commands registrieren
Plugins können eigene Slash-Commands registrieren, die ohne AI Agent ausgeführt werden. Das ist nützlich für Toggle-Commands, Status-Checks oder schnelle Aktionen, die keine LLM-Verarbeitung brauchen.
export default function (api) {
api.registerCommand({
name: "mystatus",
description: "Show plugin status",
handler: (ctx) => ({
text: `Plugin is running! Channel: ${ctx.channel}`,
}),
});
}
Command-Handler-Context:
senderId: Die ID des Senders (falls verfügbar)channel: Der Channel, in dem der Command gesendet wurdeisAuthorizedSender: Ob der Sender ein autorisierter Nutzer istargs: Argumente, die nach dem Command übergeben wurden (wennacceptsArgs: true)commandBody: Der vollständige Command-Textconfig: Die aktuelle OpenClaw-Config
Command-Optionen:
name: Command-Name (ohne führendes/)description: Hilfetext, der in Command-Listen angezeigt wirdacceptsArgs: Ob der Command Argumente akzeptiert (Standard: false). Wenn false und Argumente übergeben werden, matcht der Command nicht und die Nachricht fällt durch zu anderen HandlernrequireAuth: Ob autorisierter Sender erforderlich ist (Standard: true)handler: Funktion, die{ text: string }zurückgibt (kann async sein)
Beispiel mit Autorisierung und Argumenten:
api.registerCommand({
name: "setmode",
description: "Set plugin mode",
acceptsArgs: true,
requireAuth: true,
handler: async (ctx) => {
const mode = ctx.args?.trim() || "default";
await saveMode(mode);
return { text: `Mode set to: ${mode}` };
},
});
Hinweise:
- Plugin-Commands werden vor eingebauten Commands und dem AI Agent verarbeitet
- Commands sind global registriert und funktionieren über alle Channels
- Command-Namen sind case-insensitive (
/MyStatusmatcht/mystatus) - Command-Namen müssen mit einem Buchstaben beginnen und dürfen nur Buchstaben, Zahlen, Bindestriche und Unterstriche enthalten
- Reservierte Command-Namen (wie
help,status,reset, etc.) können nicht von Plugins überschrieben werden - Doppelte Command-Registrierung über Plugins schlägt mit einem Diagnostic-Fehler fehl
Background Services registrieren
export default function (api) {
api.registerService({
id: "my-service",
start: () => api.logger.info("ready"),
stop: () => api.logger.info("bye"),
});
}
Namenskonventionen
- Gateway Methods:
pluginId.action(Beispiel:voicecall.status) - Tools:
snake_case(Beispiel:voice_call) - CLI Commands: kebab oder camel, aber vermeide Konflikte mit Core-Commands
Skills
Plugins können einen Skill im Repo mitliefern (skills/<name>/SKILL.md).
Aktiviere ihn mit plugins.entries.<id>.enabled (oder anderen Config-Gates) und stelle sicher, dass er in deinen Workspace/Managed-Skills-Locations vorhanden ist.
Distribution (npm)
Empfohlenes Packaging:
- Haupt-Package:
openclaw(dieses Repo) - Plugins: separate npm-Packages unter
@openclaw/*(Beispiel:@openclaw/voice-call)
Publishing-Vertrag:
- Plugin-
package.jsonmussopenclaw.extensionsmit einer oder mehreren Entry-Dateien enthalten. - Entry-Dateien können
.jsoder.tssein (jiti lädt TS zur Laufzeit). openclaw plugins install <npm-spec>nutztnpm pack, extrahiert nach~/.openclaw/extensions/<id>/und aktiviert es in der Config.- Config-Key-Stabilität: Scoped Packages werden zur unscoped ID für
plugins.entries.*normalisiert.
Beispiel-Plugin: Voice Call
Dieses Repo enthält ein Voice-Call-Plugin (Twilio oder Log-Fallback):
- Source:
extensions/voice-call - Skill:
skills/voice-call - CLI:
openclaw voicecall start|status - Tool:
voice_call - RPC:
voicecall.start,voicecall.status - Config (Twilio):
provider: "twilio"+twilio.accountSid/authToken/from(optionalstatusCallbackUrl,twimlUrl) - Config (Dev):
provider: "log"(kein Netzwerk)
Siehe Voice Call und extensions/voice-call/README.md für Setup und Nutzung.
Sicherheitshinweise
Plugins laufen im selben Prozess wie der Gateway. Behandle sie als vertrauenswürdigen Code:
- Installiere nur Plugins, denen du vertraust.
- Bevorzuge
plugins.allow-Allowlists. - Starte den Gateway nach Änderungen neu.
Plugins testen
Plugins können (und sollten) Tests mitliefern:
- In-Repo-Plugins können Vitest-Tests unter
src/**ablegen (Beispiel:src/plugins/voice-call.plugin.test.ts). - Separat veröffentlichte Plugins sollten ihre eigene CI ausführen (Lint/Build/Test) und validieren, dass
openclaw.extensionsauf den gebauten Entrypoint zeigt (dist/index.js).