Building plugins
Plugins erstellen
Plugins erweitern OpenClaw um neue Funktionen: Kanäle, Modell-Provider, Sprache, Echtzeit-Transkription, Echtzeit-Stimme, Medienverständnis, Bildgenerierung, Videogenerierung, Web-Abruf, Websuche, Agent-Tools oder beliebige Kombinationen davon.
Sie müssen Ihr Plugin nicht zum OpenClaw-Repository hinzufügen. Veröffentlichen Sie es auf
ClawHub, und Benutzer installieren es mit
openclaw plugins install clawhub:<package-name>. Reine Package-Spezifikationen installieren
während der Launch-Umstellung weiterhin von npm.
Voraussetzungen
- Node >= 22 und ein Package-Manager (npm oder pnpm)
- Vertrautheit mit TypeScript (ESM)
- Für Plugins im Repository: Repository geklont und
pnpm installausgeführt. Die Plugin-Entwicklung aus einem Source-Checkout ist nur mit pnpm möglich, weil OpenClaw gebündelte Plugins aus den Workspace-Packagesextensions/*lädt.
Welche Art von Plugin?
OpenClaw mit einer Messaging-Plattform verbinden (Discord, IRC usw.)
Einen Modell-Provider hinzufügen (LLM, Proxy oder benutzerdefinierter Endpunkt)
Eine lokale KI-CLI auf OpenClaws Text-Fallback-Runner abbilden
Agent-Tools, Event-Hooks oder Dienste registrieren - fahren Sie unten fort
Für ein Kanal-Plugin, bei dem nicht garantiert ist, dass es installiert ist, wenn Onboarding/Setup
ausgeführt wird, verwenden Sie createOptionalChannelSetupSurface(...) aus
openclaw/plugin-sdk/channel-setup. Es erzeugt ein Setup-Adapter- und Wizard-Paar,
das die Installationsanforderung kommuniziert und echte Konfigurationsschreibvorgänge
geschlossen fehlschlagen lässt, bis das Plugin installiert ist.
Schnellstart: Tool-Plugin
Diese Anleitung erstellt ein minimales Plugin, das ein Agent-Tool registriert. Für Kanal- und Provider-Plugins gibt es oben verlinkte eigene Anleitungen.
Create the package and manifest
{"name": "@myorg/openclaw-my-plugin","version": "1.0.0","type": "module","openclaw": { "extensions": ["./index.ts"], "compat": { "pluginApi": ">=2026.3.24-beta.2", "minGatewayVersion": "2026.3.24-beta.2" }, "build": { "openclawVersion": "2026.3.24-beta.2", "pluginSdkVersion": "2026.3.24-beta.2" }}}{"id": "my-plugin","name": "My Plugin","description": "Adds a custom tool to OpenClaw","contracts": { "tools": ["my_tool"]},"activation": { "onStartup": true},"configSchema": { "type": "object", "additionalProperties": false}}Jedes Plugin benötigt ein Manifest, auch ohne Konfiguration. Zur Laufzeit registrierte Tools
müssen in contracts.tools aufgeführt sein, damit OpenClaw das besitzende
Plugin finden kann, ohne jede Plugin-Laufzeitumgebung zu laden. Plugins sollten außerdem
activation.onStartup bewusst deklarieren. Dieses Beispiel setzt es auf true. Siehe
Manifest für das vollständige Schema. Die kanonischen ClawHub-
Veröffentlichungssnippets befinden sich in docs/snippets/plugin-publish/.
Write the entry point
// index.tsimport { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";import { Type } from "@sinclair/typebox"; export 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 ist für Plugins, die keine Kanäle sind. Für Kanäle verwenden Sie
defineChannelPluginEntry - siehe Kanal-Plugins.
Vollständige Entry-Point-Optionen finden Sie unter Entry Points.
Test and publish
Externe Plugins: Mit ClawHub validieren und veröffentlichen, dann installieren:
clawhub package publish your-org/your-plugin --dry-runclawhub package publish your-org/your-pluginopenclaw plugins install clawhub:@myorg/openclaw-my-pluginReine Package-Spezifikationen wie @myorg/openclaw-my-plugin installieren während
der Launch-Umstellung von npm. Verwenden Sie clawhub:, wenn Sie ClawHub-Auflösung wünschen.
Plugins im Repository: Unter dem gebündelten Plugin-Workspace-Baum ablegen - wird automatisch erkannt.
pnpm test -- <bundled-plugin-root>/my-plugin/Plugin-Funktionen
Ein einzelnes Plugin kann über das api-Objekt beliebig viele Funktionen registrieren:
| Funktion | Registrierungsmethode | Detaillierte Anleitung |
|---|---|---|
| Text-Inferenz (LLM) | api.registerProvider(...) |
Provider-Plugins |
| CLI-Inferenz-Backend | api.registerCliBackend(...) |
CLI-Backend-Plugins |
| Kanal / Messaging | api.registerChannel(...) |
Kanal-Plugins |
| Sprache (TTS/STT) | api.registerSpeechProvider(...) |
Provider-Plugins |
| Echtzeit-Transkription | api.registerRealtimeTranscriptionProvider(...) |
Provider-Plugins |
| Echtzeit-Stimme | api.registerRealtimeVoiceProvider(...) |
Provider-Plugins |
| Medienverständnis | api.registerMediaUnderstandingProvider(...) |
Provider-Plugins |
| Bildgenerierung | api.registerImageGenerationProvider(...) |
Provider-Plugins |
| Musikgenerierung | api.registerMusicGenerationProvider(...) |
Provider-Plugins |
| Videogenerierung | api.registerVideoGenerationProvider(...) |
Provider-Plugins |
| Web-Abruf | api.registerWebFetchProvider(...) |
Provider-Plugins |
| Websuche | api.registerWebSearchProvider(...) |
Provider-Plugins |
| Tool-Ergebnis-Middleware | api.registerAgentToolResultMiddleware(...) |
SDK-Überblick |
| Agent-Tools | api.registerTool(...) |
Unten |
| Benutzerdefinierte Befehle | api.registerCommand(...) |
Entry Points |
| Plugin-Hooks | api.on(...) |
Plugin-Hooks |
| Interne Event-Hooks | api.registerHook(...) |
Entry Points |
| HTTP-Routen | api.registerHttpRoute(...) |
Interna |
| CLI-Unterbefehle | api.registerCli(...) |
Entry Points |
Die vollständige Registrierungs-API finden Sie unter SDK-Überblick.
Gebündelte Plugins können api.registerAgentToolResultMiddleware(...) verwenden, wenn sie
asynchrones Umschreiben von Tool-Ergebnissen benötigen, bevor das Modell die Ausgabe sieht. Deklarieren Sie die
Ziel-Laufzeiten in contracts.agentToolResultMiddleware, zum Beispiel
["pi", "codex"]. Dies ist eine vertrauenswürdige Schnittstelle für gebündelte Plugins; externe
Plugins sollten reguläre OpenClaw-Plugin-Hooks bevorzugen, solange OpenClaw keine
explizite Vertrauensrichtlinie für diese Funktion erhält.
Wenn Ihr Plugin benutzerdefinierte Gateway-RPC-Methoden registriert, belassen Sie diese unter einem
Plugin-spezifischen Präfix. Core-Admin-Namespaces (config.*,
exec.approvals.*, wizard.*, update.*) bleiben reserviert und werden immer zu
operator.admin aufgelöst, selbst wenn ein Plugin einen engeren Scope anfordert.
Hook-Guard-Semantik, die Sie beachten sollten:
before_tool_call:{ block: true }ist terminal und stoppt Handler mit niedrigerer Priorität.before_tool_call:{ block: false }wird als keine Entscheidung behandelt.before_tool_call:{ requireApproval: true }pausiert die Agent-Ausführung und fordert den Benutzer über das Exec-Genehmigungs-Overlay, Telegram-Schaltflächen, Discord-Interaktionen oder den Befehl/approveauf einem beliebigen Kanal zur Genehmigung auf.before_install:{ block: true }ist terminal und stoppt Handler mit niedrigerer Priorität.before_install:{ block: false }wird als keine Entscheidung behandelt.message_sending:{ cancel: true }ist terminal und stoppt Handler mit niedrigerer Priorität.message_sending:{ cancel: false }wird als keine Entscheidung behandelt.message_received: Bevorzugen Sie das typisierte FeldthreadId, wenn Sie eingehendes Thread-/Topic-Routing benötigen. Behalten Siemetadatafür kanalspezifische Extras bei.message_sending: Bevorzugen Sie die typisierten Routing-FelderreplyToId/threadIdgegenüber kanalspezifischen Metadaten-Schlüsseln.
Der Befehl /approve behandelt sowohl Exec- als auch Plugin-Genehmigungen mit begrenztem Fallback: Wenn eine Exec-Genehmigungs-ID nicht gefunden wird, versucht OpenClaw dieselbe ID erneut über Plugin-Genehmigungen. Die Weiterleitung von Plugin-Genehmigungen kann unabhängig über approvals.plugin in der Konfiguration konfiguriert werden.
Wenn benutzerdefinierte Genehmigungslogik denselben begrenzten Fallback-Fall erkennen muss,
bevorzugen Sie isApprovalNotFoundError aus openclaw/plugin-sdk/error-runtime,
anstatt Genehmigungsablauf-Strings manuell abzugleichen.
Beispiele und die Hook-Referenz finden Sie unter Plugin-Hooks.
Agent-Tools registrieren
Tools sind typisierte Funktionen, die das LLM aufrufen kann. Sie können erforderlich (immer verfügbar) oder optional (Opt-in durch den Benutzer) sein:
register(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 }, );}Tool-Factories erhalten ein vom Runtime bereitgestelltes Kontextobjekt. Verwenden Sie
ctx.activeModel, wenn ein Tool das aktive Modell für den aktuellen Turn protokollieren,
anzeigen oder sich daran anpassen muss. Das Objekt kann provider, modelId und
modelRef enthalten. Behandeln Sie es als informative Runtime-Metadaten, nicht als
Sicherheitsgrenze gegenüber dem lokalen Operator, installiertem Plugin-Code oder einer
modifizierten OpenClaw-Runtime. Für sensible lokale Tools sollten Sie ein explizites
Opt-in durch Plugin oder Operator beibehalten und geschlossen fehlschlagen, wenn die
Metadaten des aktiven Modells fehlen oder ungeeignet sind.
Jedes mit api.registerTool(...) registrierte Tool muss auch im Plugin-Manifest
deklariert werden:
{ "contracts": { "tools": ["my_tool", "workflow_tool"] }, "toolMetadata": { "workflow_tool": { "optional": true } }}OpenClaw erfasst und cached den validierten Deskriptor aus dem registrierten Tool,
sodass Plugins description- oder Schemadaten im Manifest nicht duplizieren müssen. Der
Manifest-Vertrag deklariert nur Ownership und Discovery; die Ausführung ruft weiterhin
die live registrierte Tool-Implementierung auf.
Setzen Sie toolMetadata.<tool>.optional: true für Tools, die mit
api.registerTool(..., { optional: true }) registriert wurden, damit OpenClaw das
Laden dieser Plugin-Runtime vermeiden kann, bis das Tool ausdrücklich allowlisted wird.
Benutzer aktivieren optionale Tools in der Konfiguration:
{ tools: { allow: ["workflow_tool"] },}- Tool-Namen dürfen nicht mit Core-Tools kollidieren (Konflikte werden übersprungen)
- Tools mit fehlerhaften Registrierungsobjekten, einschließlich fehlender
parameters, werden übersprungen und in den Plugin-Diagnosen gemeldet, statt Agent-Läufe zu unterbrechen - Verwenden Sie
optional: truefür Tools mit Seiteneffekten oder zusätzlichen Binäranforderungen - Benutzer können alle Tools aus einem Plugin aktivieren, indem sie die Plugin-ID zu
tools.allowhinzufügen
CLI-Befehle registrieren
Plugins können Root-openclaw-Befehlsgruppen mit api.registerCli hinzufügen. Stellen Sie
descriptors für jeden Top-Level-Befehlsroot bereit, damit OpenClaw den Befehl anzeigen
und routen kann, ohne jede Plugin-Runtime vorab zu laden.
register(api) { api.registerCli( ({ program }) => { const demo = program .command("demo-plugin") .description("Run demo plugin commands"); demo .command("ping") .description("Check that the plugin CLI is executable") .action(() => { console.log("demo-plugin:pong"); }); }, { descriptors: [ { name: "demo-plugin", description: "Run demo plugin commands", hasSubcommands: true, }, ], }, );}Prüfen Sie nach der Installation die Runtime-Registrierung und führen Sie den Befehl aus:
openclaw plugins inspect demo-plugin --runtime --jsonopenclaw demo-plugin pingImport-Konventionen
Importieren Sie immer aus fokussierten openclaw/plugin-sdk/<subpath>-Pfaden:
// Wrong: monolithic root (deprecated, will be removed) Die vollständige Subpath-Referenz finden Sie in der SDK-Übersicht.
Verwenden Sie innerhalb Ihres Plugins lokale Barrel-Dateien (api.ts, runtime-api.ts) für
interne Importe - importieren Sie Ihr eigenes Plugin niemals über seinen SDK-Pfad.
Für Provider-Plugins sollten Provider-spezifische Helper in diesen Package-Root-Barrels bleiben, sofern die Schnittstelle nicht wirklich generisch ist. Aktuelle gebündelte Beispiele:
- Anthropic: Claude-Stream-Wrapper und
service_tier-/Beta-Helper - OpenAI: Provider-Builder, Default-Model-Helper, Realtime-Provider
- OpenRouter: Provider-Builder plus Onboarding-/Konfigurations-Helper
Wenn ein Helper nur innerhalb eines gebündelten Provider-Pakets nützlich ist, belassen Sie ihn
an dieser Package-Root-Schnittstelle, statt ihn nach openclaw/plugin-sdk/* zu befördern.
Einige generierte openclaw/plugin-sdk/<bundled-id>-Helper-Schnittstellen existieren weiterhin
für die Wartung gebündelter Plugins, wenn sie nachverfolgte Owner-Nutzung haben. Behandeln Sie diese
als reservierte Oberflächen, nicht als Standardmuster für neue Drittanbieter-Plugins.
Checkliste vor der Einreichung
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s
package.json enthält korrekte openclaw-Metadaten
OPENCLAW_DOCS_MARKER:calloutClose:
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s openclaw.plugin.json-Manifest ist vorhanden und gültig OPENCLAW_DOCS_MARKER:calloutClose:
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s
Entry Point verwendet defineChannelPluginEntry oder definePluginEntry
OPENCLAW_DOCS_MARKER:calloutClose:
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s
Alle Importe verwenden fokussierte plugin-sdk/<subpath>-Pfade
OPENCLAW_DOCS_MARKER:calloutClose: