Plugin SDK reference
Plugin-Einstiegspunkte
Jedes Plugin exportiert ein standardmäßiges Einstiegsobjekt. Das SDK stellt eine Hilfsfunktion für
jede Einstiegsform bereit: defineToolPlugin, definePluginEntry,
defineChannelPluginEntry, defineSetupPluginEntry.
Paketeinstiege
Installierte Plugins verweisen mit den Feldern package.json und openclaw sowohl auf Quell-
als auch auf Build-Einstiege:
{ "openclaw": { "extensions": ["./src/index.ts"], "runtimeExtensions": ["./dist/index.js"], "setupEntry": "./src/setup-entry.ts", "runtimeSetupEntry": "./dist/setup-entry.js" }}extensionsundsetupEntrysind Quelleinstiege, die für die Entwicklung in Workspaces und Git- Checkouts verwendet werden.runtimeExtensionsundruntimeSetupEntrywerden für installierte Pakete bevorzugt: Dadurch können npm-Pakete auf die TypeScript-Kompilierung zur Laufzeit verzichten.runtimeExtensionsmuss, falls vorhanden, hinsichtlich der Array-Länge mitextensionsübereinstimmen (die Einträge werden positionsweise zugeordnet).runtimeSetupEntryerfordertsetupEntry.- Wenn ein
runtimeExtensions-/runtimeSetupEntry-Artefakt deklariert ist, aber fehlt, schlägt die Installation/Erkennung mit einem Paketierungsfehler fehl; OpenClaw greift nicht stillschweigend auf den Quellcode zurück. Der Rückgriff auf den Quellcode (siehe unten) gilt nur, wenn überhaupt kein Laufzeiteinstieg deklariert ist. - Wenn ein installiertes Paket nur einen TypeScript-Quelleinstieg deklariert, sucht OpenClaw
nach einem passenden gebauten
dist/*.js-Peer (oder.mjs/.cjs) und verwendet diesen; andernfalls greift es auf den TypeScript-Quellcode zurück. - Alle Einstiegspfade müssen innerhalb des Plugin-Paketverzeichnisses bleiben. Laufzeit-
einstiege und abgeleitete gebaute JS-Peers machen einen ausbrechenden
extensions- odersetupEntry-Quellpfad nicht gültig.
defineToolPlugin
Import: openclaw/plugin-sdk/tool-plugin
Für Plugins, die ausschließlich Agent-Tools hinzufügen. Hält den Quellcode kompakt, leitet Konfigurations-
und Tool-Parametertypen aus TypeBox-Schemas ab, verpackt einfache Rückgabewerte im
OpenClaw-Tool-Ergebnisformat und stellt statische Metadaten bereit, die
openclaw plugins build in das Plugin-Manifest schreibt (contracts.tools,
configSchema).
export default defineToolPlugin({ id: "stock-quotes", name: "Stock Quotes", description: "Fetch stock quotes.", configSchema: Type.Object({ apiKey: Type.Optional(Type.String({ description: "API key." })), }), tools: (tool) => [ tool({ name: "quote", label: "Quote", description: "Fetch a quote.", parameters: Type.Object({ symbol: Type.String({ description: "Ticker symbol." }), }), outputSchema: Type.Object( { symbol: Type.String(), hasKey: Type.Boolean(), }, { additionalProperties: false }, ), execute: async ({ symbol }, config) => ({ symbol, hasKey: Boolean(config.apiKey) }), }), ],});configSchemaist optional; wird es weggelassen, kommt ein striktes Schema für ein leeres Objekt zum Einsatz (das generierte Manifest enthält weiterhinconfigSchema).executegibt eine einfache Zeichenfolge oder einen JSON-serialisierbaren Wert zurück; die Hilfsfunktion verpackt diesen als Text-Tool-Ergebnis, wobeidetailsauf den ursprünglichen (nicht in eine Zeichenfolge umgewandelten) Rückgabewert gesetzt wird.outputSchemabeschreibt optional diesen ursprünglichendetails-Wert für Code Mode und Tool Search. Katalogaufrufe weisen ein ungültiges Schema vor der Ausführung zurück und validieren den endgültigen Wert, bevor sie ihn zurückgeben.- Für benutzerdefinierte Tool-Ergebnisse exportiert
openclaw/plugin-sdk/tool-resultstextResultundjsonResult. - Tool-Namen sind statisch, daher leitet
openclaw plugins buildcontracts.toolsaus den deklarierten Tools ab, ohne Namen manuell zu duplizieren. - Das Laden zur Laufzeit bleibt strikt: Installierte Plugins benötigen weiterhin
openclaw.plugin.jsonundpackage.jsonopenclaw.extensions. OpenClaw führt niemals Plugin-Code aus, um fehlende Manifestdaten abzuleiten.
definePluginEntry
Import: openclaw/plugin-sdk/plugin-entry
Für Provider-Plugins, fortgeschrittene Tool-Plugins, Hook-Plugins und alles, was kein Messaging-Kanal ist.
export default definePluginEntry({ id: "my-plugin", name: "My Plugin", description: "Short summary", register(api) { api.registerProvider({/* ... */}); api.registerTool({/* ... */}); },});| Feld | Typ | Erforderlich | Standardwert |
|---|---|---|---|
id |
string |
Ja | - |
name |
string |
Ja | - |
description |
string |
Ja | - |
kind |
string (veraltet, siehe unten) |
Nein | - |
configSchema |
OpenClawPluginConfigSchema | () => OpenClawPluginConfigSchema |
Nein | Schema für leeres Objekt |
reload |
OpenClawPluginReloadRegistration |
Nein | - |
nodeHostCommands |
OpenClawPluginNodeHostCommand[] |
Nein | - |
securityAuditCollectors |
OpenClawPluginSecurityAuditCollector[] |
Nein | - |
register |
(api: OpenClawPluginApi) => void |
Ja | - |
idmuss mit Ihremopenclaw.plugin.json-Manifest übereinstimmen.- Externe Sitzungskataloge verwenden
openclaw/plugin-sdk/session-catalogundapi.registerSessionCatalog({ id, label, list, read, continueSession?, archive? }). Der Core ist für diesessions.catalog.*-Gateway-Methoden zuständig; Provider geben Host-, Sitzungs- und normalisierte Transkriptprojektionen zurück, ohne RPCs zu registrieren. Ein Listen-Provider sollte den optionalenonHost(host)-Callback aufrufen, sobald jeder Host abgeschlossen ist; das zurückgegebene Host-Array bleibt als endgültiger Kompatibilitäts- Snapshot erforderlich. kindist veraltet: Deklarieren Sie stattdessen einen exklusiven Slot ("memory"oder"context-engine") im Feldkinddesopenclaw.plugin.json-Manifests. Der Laufzeiteinstiegkindbleibt lediglich als Kompatibilitätsrückfall für ältere Plugins erhalten.configSchemakann zur verzögerten Auswertung eine Funktion sein. OpenClaw löst das Schema beim ersten Zugriff auf und speichert es zwischen, sodass aufwendige Schema-Builder nur einmal ausgeführt werden.- Ein
nodeHostCommands-Deskriptor kannisAvailable({ config, env })definieren. Die Rückgabe vonfalselässt diesen Befehl und seine Fähigkeit aus der Gateway- Deklaration des Headless-Nodes weg. OpenClaw wertet ihn anhand der Node-lokalen Startkonfiguration aus; Befehlshandler sollten die Verfügbarkeit beim Aufruf dennoch validieren.
defineChannelPluginEntry
Import: openclaw/plugin-sdk/channel-core
Umschließt definePluginEntry mit kanalspezifischer Verdrahtung: Die Funktion ruft automatisch
api.registerChannel({ plugin }) auf, stellt eine optionale CLI-
Metadatenschnittstelle für die Root-Hilfe bereit und beschränkt registerFull auf den Registrierungsmodus.
export default defineChannelPluginEntry({ id: "my-channel", name: "My Channel", description: "Short summary", plugin: myChannelPlugin, setRuntime: setMyRuntime, registerCliMetadata(api) { api.registerCli(/* ... */); }, registerFull(api) { api.registerGatewayMethod(/* ... */); },});| Feld | Typ | Erforderlich | Standardwert |
|---|---|---|---|
id |
string |
Ja | - |
name |
string |
Ja | - |
description |
string |
Ja | - |
plugin |
ChannelPlugin |
Ja | - |
configSchema |
OpenClawPluginConfigSchema | () => OpenClawPluginConfigSchema |
Nein | Schema für leeres Objekt |
setRuntime |
(runtime: PluginRuntime) => void |
Nein | - |
registerCliMetadata |
(api: OpenClawPluginApi) => void |
Nein | - |
registerFull |
(api: OpenClawPluginApi) => void |
Nein | - |
Callbacks werden je Registrierungsmodus ausgeführt (vollständige Tabelle unter Registrierungsmodus):
setRuntimewird in jedem Modus außer"cli-metadata"und"tool-discovery"ausgeführt. Speichern Sie hier die Laufzeitreferenz, üblicherweise übercreatePluginRuntimeStore.registerCliMetadatawird für"cli-metadata","discovery"und"full"ausgeführt. Verwenden Sie dies als kanonische Stelle für kanaleigene CLI-Deskriptoren, damit die Root-Hilfe nicht aktivierend bleibt, Erkennungs-Snapshots statische Befehlsmetadaten enthalten und die normale CLI-Registrierung mit vollständigen Plugin-Ladevorgängen kompatibel bleibt.registerFullwird nur für"full"und"tool-discovery"ausgeführt. Für"tool-discovery"wird es anstelle der Kanalregistrierung ausgeführt: OpenClaw überspringtregisterChannel/setRuntimevollständig und ruft nurregisterFullauf. Daher muss jede Provider-/Tool-Registrierung, die Ihr Kanal für die eigenständige Tool-Erkennung oder -Ausführung benötigt, dort erfolgen und darf nicht hinter der normalen Kanaleinrichtung liegen.- Die Erkennungsregistrierung ist nicht aktivierend, aber nicht importfrei: OpenClaw kann
den vertrauenswürdigen Plugin-Einstieg und das Kanal-Plugin-Modul auswerten, um den
Snapshot zu erstellen. Halten Sie Importe auf oberster Ebene frei von Seiteneffekten und platzieren Sie Sockets,
Clients, Worker und Dienste ausschließlich hinter
"full"-Pfaden. - Wie
definePluginEntrykannconfigSchemaeine verzögerte Factory sein; OpenClaw speichert das aufgelöste Schema beim ersten Zugriff zwischen.
CLI-Registrierung:
- Verwenden Sie
api.registerCli(..., { descriptors: [...] })für Plugin-eigene Stamm- CLI-Befehle, die verzögert geladen werden sollen, ohne aus dem Parse-Baum der Stamm-CLI zu verschwinden. Deskriptornamen dürfen nur Buchstaben, Zahlen, Bindestriche und Unterstriche enthalten und müssen mit einem Buchstaben oder einer Zahl beginnen; OpenClaw lehnt andere Formen ab und entfernt Terminal-Steuersequenzen aus Beschreibungen, bevor die Hilfe dargestellt wird. Decken Sie jeden vom Registrar bereitgestellten Stamm eines Befehls der obersten Ebene ab.commandsallein verbleibt im früh geladenen Kompatibilitätspfad. - Verwenden Sie
api.registerNodeCliFeature(...)für Feature-Befehle gekoppelter Nodes, damit sie unteropenclaw nodeseingeordnet werden (entsprichtregisterCli(registrar, { parentPath: ["nodes"], ... })). - Fügen Sie für andere verschachtelte Plugin-Befehle
parentPathhinzu und registrieren Sie Befehle auf demprogram-Objekt, das an den Registrar übergeben wird; OpenClaw löst es zum übergeordneten Befehl auf, bevor das Plugin aufgerufen wird. - Registrieren Sie bei Channel-Plugins CLI-Deskriptoren aus
registerCliMetadataund beschränken SieregisterFullauf reine Laufzeitarbeit. - Wenn
registerFullauch Gateway-RPC-Methoden registriert, verwenden Sie dafür ein Plugin-spezifisches Präfix. Reservierte administrative Core-Namensräume (config.*,exec.approvals.*,wizard.*,update.*) werden immer zuoperator.adminumgewandelt.
defineSetupPluginEntry
Import: openclaw/plugin-sdk/channel-core
Für die schlanke Datei setup-entry.ts. Gibt nur { plugin } zurück, ohne
Laufzeit- oder CLI-Verdrahtung.
export default defineSetupPluginEntry(myChannelPlugin);OpenClaw lädt diese Datei anstelle des vollständigen Einstiegspunkts, wenn ein Channel deaktiviert oder nicht konfiguriert ist oder wenn verzögertes Laden aktiviert ist. Unter Einrichtung und Konfiguration erfahren Sie, wann dies relevant ist.
Kombinieren Sie defineSetupPluginEntry(...) mit den schmalen Familien von Einrichtungshilfen:
| Import | Verwendung |
|---|---|
openclaw/plugin-sdk/setup-runtime |
Laufzeitsichere Einrichtungshilfen: createSetupTranslator, importsichere Adapter für Einrichtungspatches, Ausgabe von Nachschlagehinweisen, promptResolvedAllowFrom, splitSetupEntries, delegierte Einrichtungs-Proxys |
openclaw/plugin-sdk/channel-setup |
Einrichtungsoberflächen für optionale Installationen |
openclaw/plugin-sdk/setup-tools |
CLI-, Archiv- und Dokumentationshilfen für Einrichtung und Installation |
Belassen Sie umfangreiche SDKs, die CLI-Registrierung und langlebige Laufzeitdienste im vollständigen Einstiegspunkt.
Gebündelte Workspace-Channels, die Einrichtungs- und Laufzeitoberflächen trennen, können
stattdessen defineBundledChannelSetupEntry(...) aus
openclaw/plugin-sdk/channel-entry-contract verwenden. Damit kann der Einrichtungs-
Einstiegspunkt einrichtungssichere Plugin-/Secrets-Exporte beibehalten und zugleich einen
Laufzeit-Setter bereitstellen:
export default defineBundledChannelSetupEntry({ importMetaUrl: import.meta.url, plugin: { specifier: "./channel-plugin-api.js", exportName: "myChannelPlugin", }, runtime: { specifier: "./runtime-api.js", exportName: "setMyChannelRuntime", }, registerSetupRuntime(api) { api.registerHttpRoute({ path: "/my-channel/events", auth: "plugin", handler: async (req, res) => { /* einrichtungssichere Route */ }, }); },});Verwenden Sie dies nur, wenn ein Einrichtungsablauf tatsächlich einen schlanken Laufzeit-Setter oder
eine einrichtungssichere Gateway-Oberfläche benötigt, bevor der vollständige Channel-Einstiegspunkt geladen wird.
registerSetupRuntime wird nur bei "setup-runtime"-Ladevorgängen ausgeführt; beschränken Sie ihn
auf reine Konfigurationsrouten oder -methoden, die vor der verzögerten
vollständigen Aktivierung vorhanden sein müssen.
Registrierungsmodus
api.registrationMode gibt Ihrem Plugin an, wie es geladen wurde:
| Modus | Zeitpunkt | Zu registrierende Elemente |
|---|---|---|
"full" |
Normaler Gateway-Start | Alles |
"discovery" |
Schreibgeschützte Funktionsermittlung | Channel-Registrierung sowie statische CLI-Deskriptoren; Einstiegscode darf geladen werden, aber überspringen Sie Sockets, Worker, Clients und Dienste |
"tool-discovery" |
Begrenztes Laden zum Auflisten oder Ausführen der Tools bestimmter Plugins | Nur Funktions-/Tool-Registrierung; keine Channel-Aktivierung |
"setup-only" |
Deaktivierter/nicht konfigurierter Channel | Nur Channel-Registrierung |
"setup-runtime" |
Einrichtungsablauf mit verfügbarer Laufzeit | Channel-Registrierung sowie nur die schlanke Laufzeit, die vor dem Laden des vollständigen Einstiegspunkts benötigt wird |
"cli-metadata" |
Stammsystemhilfe/Erfassung von CLI-Metadaten | Nur CLI-Deskriptoren |
defineChannelPluginEntry verarbeitet diese Aufteilung automatisch. Wenn Sie
definePluginEntry direkt für einen Channel verwenden, prüfen Sie den Modus selbst und beachten Sie,
dass "tool-discovery" die Channel-Registrierung überspringt:
register(api) { if ( api.registrationMode === "cli-metadata" || api.registrationMode === "discovery" || api.registrationMode === "full" ) { api.registerCli(/* ... */); if (api.registrationMode === "cli-metadata") return; } if (api.registrationMode === "tool-discovery") { // Nur funktionsbezogene Oberflächen (Provider/Tools) registrieren, keinen Channel. return; } api.registerChannel({ plugin: myPlugin }); if (api.registrationMode !== "full") return; // Umfangreiche reine Laufzeitregistrierungen api.registerService(/* ... */);}Langlebige Dienste können über ihren Dienstkontext kleine Invalidierungs- oder Lebenszyklusereignisse ausgeben:
api.registerService({ id: "index-events", start(ctx) { ctx.gatewayEvents?.emit("changed", { revision: 1 }, { scope: "operator.read" }); },});OpenClaw versieht dies mit dem Namensraum plugin.<plugin-id>.changed. Ereignisnamen bestehen aus einem
Kleinbuchstabensegment, Nutzdaten müssen begrenztes JSON sein und der Geltungsbereich muss
operator.read, operator.write oder operator.admin sein. Der Emitter existiert nur
während der Lebensdauer des Dienstes und wird nach dem Stoppen oder einem fehlgeschlagenen Start widerrufen. Bevorzugen Sie
Versions- oder Invalidierungsnutzdaten gegenüber vollständigen Datensätzen, damit autorisierte Clients den
kanonischen Zustand über die bereichsgebundenen Gateway-Methoden des Plugins erneut lesen.
Der Ermittlungsmodus erstellt einen nicht aktivierenden Registry-Snapshot. Er kann dennoch den Plugin-Einstiegspunkt und das Channel-Plugin-Objekt auswerten, damit OpenClaw Channel-Funktionen und statische CLI-Deskriptoren registrieren kann. Behandeln Sie die Modulauswertung bei der Ermittlung als vertrauenswürdig, aber schlank: keine Netzwerkclients, Unterprozesse, Listener, Datenbankverbindungen, Hintergrund-Worker, Zugangsdatenzugriffe oder andere aktive Laufzeitnebeneffekte auf oberster Ebene.
Behandeln Sie "setup-runtime" als das Zeitfenster, in dem reine Einrichtungsoberflächen für den Start
vorhanden sein müssen, ohne erneut in die vollständige gebündelte Channel-Laufzeit einzutreten. Gut geeignet sind
Channel-Registrierung, einrichtungssichere HTTP-Routen, einrichtungssichere Gateway-Methoden
und delegierte Einrichtungshilfen. Umfangreiche Hintergrunddienste, CLI-Registrare und
Initialisierungen von Provider-/Client-SDKs gehören weiterhin in "full".
Plugin-Formen
OpenClaw klassifiziert geladene Plugins anhand ihres Registrierungsverhaltens:
| Form | Beschreibung |
|---|---|
| plain-capability | Ein Funktionstyp (z. B. nur Provider) |
| hybrid-capability | Mehrere Funktionstypen (z. B. Provider + Sprachausgabe) |
| hook-only | Nur Hooks, keine Funktionen |
| non-capability | Tools/Befehle/Dienste, aber keine Funktionen |
Verwenden Sie openclaw plugins inspect <id>, um die Form eines Plugins anzuzeigen.
Verwandte Themen
- SDK-Übersicht - Registrierungs-API und Unterpfadreferenz
- Laufzeithilfen -
api.runtimeundcreatePluginRuntimeStore - Einrichtung und Konfiguration - Manifest, Einrichtungseinstiegspunkt, verzögertes Laden
- Channel-Plugins - Erstellen des
ChannelPlugin-Objekts - Provider-Plugins - Provider-Registrierung und Hooks