Plugin maintainer reference
Interna der Plugin-Architektur
Informationen zum öffentlichen Funktionsmodell, zu Plugin-Strukturen und zu den Verträgen für Zuständigkeit und Ausführung finden Sie unter Plugin-Architektur. Diese Seite behandelt die internen Mechanismen: Ladepipeline, Registry, Runtime-Hooks, Gateway-HTTP-Routen, Importpfade und Schematabellen.
Ladepipeline
Beim Start führt OpenClaw ungefähr folgende Schritte aus:
- mögliche Plugin-Stammverzeichnisse ermitteln
- native oder kompatible Bundle-Manifeste und Paketmetadaten lesen
- unsichere Kandidaten ablehnen
- Plugin-Konfiguration normalisieren (
plugins.enabled,allow,deny,entries,slots,load.paths) - Aktivierung für jeden Kandidaten bestimmen
- aktivierte native Module laden: erstellte gebündelte Module verwenden einen nativen Loader; lokaler TypeScript-Quellcode von Drittanbietern verwendet als Notlösung den Jiti-Fallback
- native
register(api)-Hooks aufrufen und Registrierungen in der Plugin-Registry sammeln - die Registry für Befehle und Runtime-Oberflächen bereitstellen
Sicherheitsprüfungen werden vor der Runtime-Ausführung durchgeführt. Die Ermittlung blockiert einen Kandidaten, wenn:
- sein aufgelöster Einstiegspunkt außerhalb des Plugin-Stammverzeichnisses liegt
- sein Pfad (oder sein Stammverzeichnis) für alle Benutzer beschreibbar ist
- bei nicht gebündelten Plugins der Pfadeigentümer nicht mit der aktuellen UID (oder root) übereinstimmt
Bei für alle Benutzer beschreibbaren gebündelten Verzeichnissen wird zunächst versucht, die Berechtigungen direkt mit chmod zu reparieren (npm-/globale Installationen können Paketverzeichnisse mit 0777 ausliefern), bevor die Prüfung erneut ausgeführt wird; Eigentümerprüfungen werden für gebündelte Ursprünge vollständig übersprungen.
Blockierte Kandidaten enthalten in der ausgegebenen Diagnose weiterhin ihre Plugin-ID, sofern diese bekannt ist (einschließlich IDs, die aus einem Manifest in einem ansonsten abgelehnten Verzeichnis aufgelöst wurden). Dadurch wird eine Konfiguration, die auf diese ID verweist, einem blockierten Plugin mit einer Warnung zur Pfadsicherheit zugeordnet, statt einen nicht zusammenhängenden Fehler „unbekanntes Plugin“ zu erhalten.
Manifest-zuerst-Verhalten
Das Manifest ist die maßgebliche Quelle der Steuerungsebene. OpenClaw verwendet es, um:
- das Plugin zu identifizieren
- deklarierte Kanäle, Skills, Konfigurationsschemas oder Bundle-Funktionen zu ermitteln
plugins.entries.<id>.configzu validieren- Beschriftungen und Platzhalter der Control UI zu ergänzen
- Installations- und Katalogmetadaten anzuzeigen
- kostengünstige Aktivierungs- und Einrichtungsdeskriptoren beizubehalten, ohne die Plugin-Runtime zu laden
Bei nativen Plugins ist das Runtime-Modul der Teil der Datenebene. Es registriert das tatsächliche Verhalten, etwa Hooks, Tools, Befehle oder Provider-Abläufe.
Optionale Manifest-Blöcke activation und setup verbleiben auf der Steuerungsebene. Sie sind reine Metadatendeskriptoren für die Aktivierungsplanung und Einrichtungsermittlung; sie ersetzen weder die Runtime-Registrierung noch register(...) oder setupEntry.
Aktive Aktivierungsverbraucher verwenden Hinweise zu Befehlen, Kanälen und Providern aus dem Manifest, um das Laden von Plugins vor einer umfassenderen Materialisierung der Registry einzugrenzen:
- Beim Laden der CLI wird auf Plugins eingegrenzt, denen der angeforderte primäre Befehl gehört
- Bei der Kanaleinrichtung und Plugin-Auflösung wird auf Plugins eingegrenzt, denen die angeforderte Kanal-ID gehört
- Bei der expliziten Provider-Einrichtung und Runtime-Auflösung wird auf Plugins eingegrenzt, denen die angeforderte Provider-ID gehört
- Die Startplanung des Gateway verwendet
activation.onStartupfür explizite Startimporte; Plugins ohne Startmetadaten werden nur über spezifischere Aktivierungsauslöser geladen
Der Aktivierungsplaner stellt sowohl eine reine ID-API für bestehende Aufrufer als auch eine Plan-API für Diagnosen bereit. Planeinträge geben an, warum ein Plugin ausgewählt wurde, und unterscheiden dabei explizite activation.*-Hinweise vom Fallback auf die Manifest-Zuständigkeit:
Grund (aus activation.*-Hinweisen) |
Grund (aus der Manifest-Zuständigkeit) |
|---|---|
activation-agent-harness-hint |
— |
activation-capability-hint |
— |
activation-channel-hint |
manifest-channel-owner (channels) |
activation-command-hint |
manifest-command-alias (commandAliases) |
activation-provider-hint |
manifest-provider-owner (providers), manifest-setup-provider-owner (setup.providers) |
activation-route-hint |
— |
| — (Hook-Auslöser hat keine Hinweisvariante) | manifest-hook-owner (hooks), manifest-tool-contract (contracts.tools) |
Diese Trennung der Gründe bildet die Kompatibilitätsgrenze: Bestehende Plugin-Metadaten funktionieren weiterhin, während neuer Code umfassende Hinweise oder Fallback-Verhalten erkennen kann, ohne die Semantik des Runtime-Ladens zu ändern.
Runtime-Vorabladevorgänge während einer Anfrage, die den umfassenden Bereich all anfordern, leiten weiterhin aus der Konfiguration, der Startplanung, den konfigurierten Kanälen, Slots und Regeln zur automatischen Aktivierung eine explizite effektive Menge von Plugin-IDs ab (resolveEffectivePluginIds in src/plugins/effective-plugin-ids.ts). Ist diese abgeleitete Menge leer, lässt OpenClaw den Bereich leer, statt ihn auf jedes ermittelbare Plugin zu erweitern.
Die Einrichtungsermittlung bevorzugt IDs aus Deskriptoren wie setup.providers und setup.cliBackends, um mögliche Plugins einzugrenzen, bevor für Plugins, die weiterhin Runtime-Hooks während der Einrichtung benötigen, auf setup-api zurückgegriffen wird. Listen zur Provider-Einrichtung verwenden providerAuthChoices aus dem Manifest, aus Deskriptoren abgeleitete Einrichtungsoptionen und Metadaten des Installationskatalogs, ohne die Provider-Runtime zu laden. Ein explizites setup.requiresRuntime: false begrenzt die Verarbeitung auf Deskriptoren; wenn requiresRuntime fehlt, bleibt aus Kompatibilitätsgründen der veraltete Fallback auf setup-api erhalten. Wenn mehrere ermittelte Plugins dieselbe normalisierte Provider-ID für die Einrichtung oder dieselbe CLI-Backend-ID beanspruchen, lehnt die Einrichtungssuche die mehrdeutige Zuständigkeit ab, statt sich auf die Ermittlungsreihenfolge zu verlassen. Wird die Einrichtungs-Runtime ausgeführt, melden Registry-Diagnosen Abweichungen zwischen setup.providers / setup.cliBackends und den Providern oder CLI-Backends, die tatsächlich durch setup-api registriert wurden, ohne veraltete Plugins zu blockieren.
Plugin-Cache-Grenze
OpenClaw speichert weder Ergebnisse der Plugin-Ermittlung noch direkte Daten der Manifest-Registry hinter zeitgesteuerten Cache-Fenstern. Installationen, Manifeständerungen und Änderungen an Ladepfaden müssen beim nächsten expliziten Lesen von Metadaten oder beim nächsten Neuaufbau eines Snapshots sichtbar werden. Der Parser für Manifestdateien verwendet einen begrenzten Cache für Dateisignaturen, dessen Schlüssel aus dem geöffneten Manifestpfad sowie Gerät/Inode, Größe und mtime/ctime besteht. Dieser Cache verhindert lediglich, dass unveränderte Bytes erneut geparst werden, und darf keine Antworten zu Ermittlung, Registry, Zuständigkeit oder Richtlinien zwischenspeichern.
Der sichere schnelle Metadatenpfad basiert auf expliziter Objektzuständigkeit, nicht auf einem verborgenen Cache.
Leistungskritische Pfade beim Start des Gateway sollten den aktuellen PluginMetadataSnapshot, die abgeleitete PluginLookUpTable oder eine explizite Manifest-Registry entlang der Aufrufkette weiterreichen. Konfigurationsvalidierung, automatische Aktivierung beim Start, Plugin-Bootstrap und Provider-Auswahl können diese Objekte wiederverwenden, solange sie die aktuelle Konfiguration und den aktuellen Plugin-Bestand repräsentieren. Die Einrichtungssuche rekonstruiert Manifest-Metadaten weiterhin bei Bedarf, sofern der jeweilige Einrichtungspfad keine explizite Manifest-Registry erhält; behalten Sie dies als Fallback für selten verwendete Pfade bei, statt verborgene Such-Caches hinzuzufügen. Wenn sich die Eingabe ändert, bauen Sie den Snapshot neu auf und ersetzen Sie ihn, statt ihn zu verändern oder historische Kopien aufzubewahren. Ansichten der aktiven Plugin-Registry und Bootstrap-Hilfsfunktionen für gebündelte Kanäle sollten aus der aktuellen Registry beziehungsweise dem aktuellen Stammverzeichnis neu berechnet werden. Kurzlebige Maps innerhalb eines einzelnen Aufrufs sind zulässig, um Arbeiten zu deduplizieren oder einen erneuten Eintritt zu verhindern; sie dürfen nicht zu Prozessmetadaten-Caches werden.
Beim Laden von Plugins ist das Runtime-Laden die persistente Cache-Schicht. Sie darf Loader-Zustand wiederverwenden, wenn Code oder installierte Artefakte tatsächlich geladen werden, beispielsweise:
PluginLoaderCacheStateund kompatible aktive Runtime-Registrys- Jiti-/Modul-Caches und Loader-Caches für öffentliche Oberflächen, die verhindern, dass dieselbe Runtime-Oberfläche wiederholt importiert wird
- Dateisystem-Caches für installierte Plugin-Artefakte
- kurzlebige Maps pro Aufruf für Pfadnormalisierung oder Duplikatauflösung
Diese Caches sind Implementierungsdetails der Datenebene. Sie dürfen keine Fragen der Steuerungsebene wie „Welchem Plugin gehört dieser Provider?“ beantworten, sofern der Aufrufer nicht ausdrücklich das Laden der Runtime angefordert hat.
Fügen Sie keine persistenten oder zeitgesteuerten Caches hinzu für:
- Ergebnisse der Ermittlung
- direkte Manifest-Registrys
- aus dem Index installierter Plugins rekonstruierte Manifest-Registrys
- Provider-Zuständigkeitssuche, Modellunterdrückung, Provider-Richtlinien oder Metadaten öffentlicher Artefakte
- andere aus dem Manifest abgeleitete Antworten, bei denen ein geändertes Manifest, ein geänderter Installationsindex oder ein geänderter Ladepfad beim nächsten Lesen der Metadaten sichtbar sein sollte
Aufrufer, die Manifest-Metadaten aus dem persistenten Index installierter Plugins neu aufbauen, rekonstruieren diese Registry bei Bedarf. Der Installationsindex ist ein dauerhafter Zustand der Quellebene; er ist kein verborgener prozessinterner Metadaten-Cache.
Registry-Modell
Geladene Plugins verändern nicht direkt beliebige globale Variablen des Kerns. Sie registrieren sich in einer zentralen Plugin-Registry (PluginRegistry in src/plugins/registry-types.ts), die Plugin-Datensätze (Identität, Quelle, Ursprung, Status und Diagnosen) sowie Arrays für jede Funktion verwaltet: Tools, veraltete und typisierte Hooks, Kanäle, Provider, Gateway-RPC-Handler, HTTP-Routen, CLI-Registrierungsfunktionen, Hintergrunddienste, Plugin-eigene Befehle und viele weitere typisierte Provider-Familien (Sprachausgabe, Einbettungen, Bild-/Video-/Musikgenerierung, Webabruf/-suche, Agent-Harnesses, Sitzungsaktionen und weitere).
Kernfunktionen lesen anschließend aus dieser Registry, statt direkt mit Plugin-Modulen zu kommunizieren. Dadurch bleibt das Laden unidirektional:
- Plugin-Modul -> Registrierung in der Registry
- Kern-Runtime -> Nutzung der Registry
Diese Trennung ist für die Wartbarkeit wichtig. Sie bedeutet, dass die meisten Kernoberflächen nur einen Integrationspunkt benötigen: „Registry lesen“, statt „jedes Plugin-Modul als Sonderfall behandeln“.
Callbacks für Konversationsbindungen
Plugins, die eine Konversation binden, können reagieren, wenn eine Genehmigung entschieden wurde.
Verwenden Sie api.onConversationBindingResolved(...), um einen Callback zu erhalten, nachdem eine Bindungsanfrage genehmigt oder abgelehnt wurde:
export default { id: "my-plugin", register(api) { api.onConversationBindingResolved(async (event) => { if (event.status === "approved") { // A binding now exists for this plugin + conversation. console.log(event.binding?.conversationId); return; } // The request was denied; clear any local pending state. console.log(event.request.conversation.conversationId); }); },};Felder der Callback-Nutzlast:
status:"approved"oder"denied"decision:"allow-once","allow-always"oder"deny"binding: die aufgelöste Bindung für genehmigte Anfragenrequest: die ursprüngliche Zusammenfassung der Anfrage, der Hinweis zur Trennung, die Absender-ID und die Konversationsmetadaten
Dieser Callback dient ausschließlich der Benachrichtigung. Er ändert nicht, wer eine Konversation binden darf, und wird ausgeführt, nachdem die Verarbeitung der Genehmigung im Kern abgeschlossen ist.
Provider-Runtime-Hooks
Provider-Plugins verfügen über drei Ebenen:
- Manifest-Metadaten für eine kostengünstige Suche vor dem Start der Runtime:
setup.providers[].envVars, das veraltete KompatibilitätsfeldproviderAuthEnvVars,providerAuthAliases,providerAuthChoicesundchannelEnvVars. - Hooks zur Konfigurationszeit:
catalog(veraltet:discovery) sowieapplyConfigDefaults. - Runtime-Hooks: mehr als 40 optionale Hooks für Authentifizierung, Modellauflösung, Stream-Kapselung, Denkstufen, Wiederholungsrichtlinien und Nutzungsendpunkte. Siehe Hook-Reihenfolge und Verwendung.
OpenClaw bleibt für die generische Agentenschleife, Failover, Transkriptverarbeitung und Tool-Richtlinien zuständig. Diese Hooks bilden die Erweiterungsoberfläche für Provider-spezifisches Verhalten, ohne dass dafür ein vollständig eigener Inferenztransport erforderlich ist.
Verwenden Sie im Manifest setup.providers[].envVars, wenn der Provider umgebungsvariablenbasierte Zugangsdaten besitzt, die generische Pfade für Authentifizierung, Status und Modellauswahl erkennen sollen, ohne die Plugin-Laufzeit zu laden. Das veraltete providerAuthEnvVars wird während des Übergangszeitraums weiterhin vom Kompatibilitätsadapter gelesen, und nicht gebündelte Plugins, die es verwenden, erhalten eine Manifestdiagnose. Verwenden Sie im Manifest providerAuthAliases, wenn eine Provider-ID die Umgebungsvariablen, Authentifizierungsprofile, konfigurationsbasierte Authentifizierung und die Onboarding-Auswahl für API-Schlüssel einer anderen Provider-ID wiederverwenden soll. Verwenden Sie im Manifest providerAuthChoices, wenn CLI-Oberflächen für Onboarding und Authentifizierungsauswahl die Auswahl-ID, Gruppenbeschriftungen und die einfache Authentifizierungskonfiguration des Providers über ein einzelnes Flag kennen sollen, ohne die Provider-Laufzeit zu laden. Behalten Sie envVars der Provider-Laufzeit für Hinweise an Betreiber bei, etwa Onboarding-Beschriftungen oder Einrichtungsvariablen für OAuth-Client-ID und -Client-Secret.
Verwenden Sie im Manifest channelEnvVars, wenn ein Kanal über umgebungsvariablengesteuerte Authentifizierung oder Einrichtung verfügt, die der generische Shell-Umgebungsfallback, Konfigurations-/Statusprüfungen oder Einrichtungsaufforderungen erkennen sollen, ohne die Kanallaufzeit zu laden.
Reihenfolge und Verwendung der Hooks
Für Modell-/Provider-Plugins ruft OpenClaw Hooks ungefähr in dieser Reihenfolge auf.
Die Spalte „Wann verwenden“ dient als schnelle Entscheidungshilfe.
Provider-Felder, die ausschließlich der Kompatibilität dienen und von OpenClaw nicht mehr aufgerufen werden, etwa ProviderPlugin.capabilities und suppressBuiltInModel, sind hier absichtlich nicht aufgeführt.
| Hook | Funktionsweise | Verwendung |
|---|---|---|
catalog |
Veröffentlicht die Provider-Konfiguration während der Generierung von models.json in models.providers |
Der Provider besitzt einen Katalog oder Standardwerte für die Basis-URL |
applyConfigDefaults |
Wendet bei der Konfigurationsmaterialisierung globale, Provider-eigene Konfigurationsstandardwerte an | Standardwerte hängen vom Authentifizierungsmodus, von der Umgebung oder von der Modellfamiliensemantik des Providers ab |
| (integrierte Modellsuche) | OpenClaw versucht zuerst den normalen Registry-/Katalogpfad | (kein Plugin-Hook) |
normalizeModelId |
Normalisiert veraltete oder Vorschau-Aliasse für Modell-IDs vor der Suche | Der Provider bereinigt Aliasse vor der kanonischen Modellauflösung |
normalizeTransport |
Normalisiert api / baseUrl der Provider-Familie vor der generischen Modellzusammenstellung |
Der Provider bereinigt den Transport für benutzerdefinierte Provider-IDs derselben Transportfamilie |
normalizeConfig |
Normalisiert models.providers.<id> vor der Laufzeit-/Provider-Auflösung |
Der Provider benötigt eine Konfigurationsbereinigung im Plugin; gebündelte Hilfsfunktionen der Google-Familie sichern zudem unterstützte Google-Konfigurationseinträge ab |
applyNativeStreamingUsageCompat |
Wendet Kompatibilitätsanpassungen für native Streaming-Nutzungsdaten auf konfigurierte Provider an | Der Provider benötigt Endpunkt-gesteuerte Korrekturen der Metadaten für native Streaming-Nutzungsdaten |
resolveConfigApiKey |
Löst die Authentifizierung über Umgebungsmarker für konfigurierte Provider vor dem Laden der Laufzeitauthentifizierung auf | Provider stellen eigene Hooks zur Auflösung von API-Schlüsseln über Umgebungsmarker bereit |
resolveSyntheticAuth |
Stellt lokale, selbst gehostete oder konfigurationsgestützte Authentifizierung bereit, ohne Klartext zu speichern | Der Provider kann mit einem synthetischen/lokalen Anmeldedatenmarker arbeiten |
resolveExternalAuthProfiles |
Überlagert Provider-eigene externe Authentifizierungsprofile; standardmäßig ist persistence für CLI-/App-eigene Anmeldedaten runtime-only |
Der Provider verwendet externe Anmeldedaten erneut, ohne kopierte Aktualisierungstoken zu speichern; deklarieren Sie contracts.externalAuthProviders im Manifest |
shouldDeferSyntheticProfileAuth |
Ordnet gespeicherte synthetische Profilplatzhalter hinter umgebungs-/konfigurationsgestützter Authentifizierung ein | Der Provider speichert synthetische Platzhalterprofile, die keinen Vorrang erhalten sollen |
resolveDynamicModel |
Synchroner Fallback für Provider-eigene Modell-IDs, die noch nicht in der lokalen Registry enthalten sind | Der Provider akzeptiert beliebige Modell-IDs des Upstream-Dienstes |
prepareDynamicModel |
Asynchrone Vorbereitung; anschließend wird resolveDynamicModel erneut ausgeführt |
Der Provider benötigt Netzwerkmetadaten, bevor unbekannte IDs aufgelöst werden |
normalizeResolvedModel |
Abschließende Anpassung, bevor der eingebettete Runner das aufgelöste Modell verwendet | Der Provider benötigt Transportanpassungen, verwendet aber weiterhin einen Core-Transport |
normalizeToolSchemas |
Normalisiert Tool-Schemas, bevor der eingebettete Runner sie verarbeitet | Der Provider benötigt eine Schema-Bereinigung für die Transportfamilie |
inspectToolSchemas |
Stellt nach der Normalisierung Provider-eigene Schemadiagnosen bereit | Der Provider möchte vor Schlüsselwörtern warnen, ohne dem Core Provider-spezifische Regeln hinzuzufügen |
resolveReasoningOutputMode |
Wählt den nativen oder Tag-basierten Vertrag für die Reasoning-Ausgabe | Der Provider benötigt Tag-basierte Reasoning-/Endausgaben anstelle nativer Felder |
prepareExtraParams |
Normalisiert Anfrageparameter vor den generischen Wrappern für Stream-Optionen | Der Provider benötigt standardmäßige Anfrageparameter oder eine Provider-spezifische Parameterbereinigung |
createStreamFn |
Ersetzt den normalen Stream-Pfad vollständig durch einen benutzerdefinierten Transport | Der Provider benötigt ein benutzerdefiniertes Übertragungsprotokoll und nicht nur einen Wrapper |
wrapStreamFn |
Stream-Wrapper, nachdem generische Wrapper angewendet wurden | Der Provider benötigt Kompatibilitäts-Wrapper für Anfrageheader, -text oder Modell, jedoch keinen benutzerdefinierten Transport |
resolveTransportTurnState |
Fügt native Transportheader oder Metadaten pro Interaktion hinzu | Der Provider möchte, dass generische Transporte eine Provider-native Interaktionsidentität senden |
resolveWebSocketSessionPolicy |
Fügt native WebSocket-Header oder eine Abklingrichtlinie für Sitzungen hinzu | Der Provider möchte bei generischen WS-Transporten Sitzungsheader oder die Fallback-Richtlinie anpassen |
formatApiKey |
Formatierer für Authentifizierungsprofile: Das gespeicherte Profil wird zur apiKey-Zeichenfolge der Laufzeit |
Der Provider speichert zusätzliche Authentifizierungsmetadaten und benötigt ein benutzerdefiniertes Format des Laufzeittokens |
refreshOAuth |
Überschreibt die OAuth-Aktualisierung für benutzerdefinierte Aktualisierungsendpunkte oder Fehlerrichtlinien | Der Provider passt nicht zu den gemeinsamen OpenClaw-Aktualisierungsmechanismen |
buildAuthDoctorHint |
Fügt bei fehlgeschlagener OAuth-Aktualisierung einen Reparaturhinweis an | Der Provider benötigt nach einem Aktualisierungsfehler eigene Anweisungen zur Reparatur der Authentifizierung |
matchesContextOverflowError |
Provider-eigene Erkennung einer Überschreitung des Kontextfensters | Der Provider liefert rohe Überlauffehler, die generische Heuristiken nicht erkennen würden |
classifyFailoverReason |
Provider-eigene Klassifizierung des Failover-Grunds | Der Provider kann rohe API-/Transportfehler auf Ratenbegrenzung, Überlastung usw. abbilden |
isCacheTtlEligible |
Richtlinie für den Prompt-Cache bei Proxy-/Backhaul-Providern | Der Provider benötigt Proxy-spezifische Zugangsregeln für die Cache-TTL |
buildMissingAuthMessage |
Ersetzt die generische Wiederherstellungsmeldung bei fehlender Authentifizierung | Der Provider benötigt einen Provider-spezifischen Wiederherstellungshinweis bei fehlender Authentifizierung |
augmentModelCatalog |
Fügt nach der Erkennung synthetische/endgültige Katalogzeilen hinzu (veraltet, siehe unten) | Der Provider benötigt synthetische Zeilen für Vorwärtskompatibilität in models list und Auswahlelementen |
resolveThinkingProfile |
Modellspezifische Auswahl, Anzeigebezeichnungen und Standardwert für die /think-Stufe |
Der Provider stellt für ausgewählte Modelle eine benutzerdefinierte Thinking-Abstufung oder binäre Bezeichnung bereit |
isBinaryThinking |
Kompatibilitäts-Hook zum Ein-/Ausschalten von Reasoning | Der Provider unterstützt nur binäres Ein-/Ausschalten von Thinking |
supportsXHighThinking |
Kompatibilitäts-Hook für die Reasoning-Unterstützung von xhigh |
Der Provider möchte xhigh nur für eine Teilmenge der Modelle aktivieren |
resolveDefaultThinkingLevel |
Kompatibilitäts-Hook für die standardmäßige /think-Stufe |
Der Provider definiert die standardmäßige /think-Richtlinie für eine Modellfamilie |
isModernModelRef |
Erkennung moderner Modelle für Live-Profilfilter und Smoke-Auswahl | Der Provider definiert die bevorzugte Modellzuordnung für Live-/Smoke-Tests |
prepareRuntimeAuth |
Tauscht konfigurierte Anmeldedaten unmittelbar vor der Inferenz gegen das tatsächliche Laufzeittoken bzw. den Laufzeitschlüssel aus | Der Provider benötigt einen Tokenaustausch oder kurzlebige Anmeldedaten für die Anfrage |
resolveUsageAuth |
Löst Anmeldedaten für Nutzung/Abrechnung für /usage und zugehörige Statusoberflächen auf |
Der Provider benötigt eine benutzerdefinierte Analyse des Nutzungs-/Kontingenttokens oder andere Anmeldedaten für die Nutzung |
fetchUsageSnapshot |
Ruft nach Auflösung der Authentifizierung Provider-spezifische Nutzungs-/Kontingentübersichten ab und normalisiert sie | Der Provider benötigt einen Provider-spezifischen Nutzungsendpunkt oder Parser für dessen Nutzdaten |
createEmbeddingProvider |
Einen Provider-eigenen Embedding-Adapter für Speicher/Suche erstellen | Das Verhalten von Speicher-Embeddings gehört in das Provider-Plugin |
buildReplayPolicy |
Eine Replay-Richtlinie zurückgeben, die die Verarbeitung des Transkripts für den Provider steuert | Der Provider benötigt eine benutzerdefinierte Transkriptrichtlinie (beispielsweise zum Entfernen von Denkblöcken) |
sanitizeReplayHistory |
Den Replay-Verlauf nach der allgemeinen Transkriptbereinigung umschreiben | Der Provider benötigt Provider-spezifische Replay-Anpassungen, die über die gemeinsamen Compaction-Hilfsfunktionen hinausgehen |
validateReplayTurns |
Abschließende Validierung oder Umformung der Replay-Turns vor dem eingebetteten Runner | Der Provider-Transport benötigt nach der allgemeinen Bereinigung eine strengere Validierung der Turns |
onModelSelected |
Provider-eigene Nebeneffekte nach der Auswahl ausführen | Der Provider benötigt Telemetrie oder Provider-eigenen Zustand, wenn ein Modell aktiv wird |
normalizeModelId, normalizeTransport und normalizeConfig prüfen zuerst das
passende Provider-Plugin und durchlaufen dann weitere Provider-Plugins mit
Hook-Unterstützung, bis eines davon die Modell-ID beziehungsweise den
Transport/die Konfiguration tatsächlich ändert. Dadurch funktionieren
Alias-/Kompatibilitäts-Provider-Shims weiterhin, ohne dass der Aufrufer wissen
muss, welches gebündelte Plugin für die Umschreibung zuständig ist. Wenn kein
Provider-Hook einen unterstützten Konfigurationseintrag der Google-Familie
umschreibt, führt der gebündelte Google-Konfigurationsnormalisierer weiterhin
diese Kompatibilitätsbereinigung durch.
Wenn der Provider ein vollständig benutzerdefiniertes Wire-Protokoll oder einen benutzerdefinierten Request-Executor benötigt, handelt es sich um eine andere Erweiterungsklasse. Diese Hooks sind für Provider-Verhalten vorgesehen, das weiterhin in der normalen Inferenzschleife von OpenClaw ausgeführt wird.
resolveUsageAuth entscheidet, ob OpenClaw fetchUsageSnapshot aufrufen oder
für Nutzungs-/Statusoberflächen auf die generische Auflösung von
Anmeldedaten zurückgreifen soll. Geben Sie
{ token, accountId?, subscriptionType?, rateLimitTier? } zurück, wenn der
Provider über Anmeldedaten für die Nutzungsabfrage verfügt (die optionalen
Tarifmetadaten werden an fetchUsageSnapshot weitergegeben), geben Sie
{ handled: true } zurück, wenn die Provider-eigene Authentifizierung für die
Nutzungsabfrage die Anfrage verarbeitet hat und den generischen Fallback auf
API-Schlüssel/OAuth unterdrücken muss, und geben Sie null oder undefined
zurück, wenn der Provider die Authentifizierung für die Nutzungsabfrage nicht
verarbeitet hat.
Deklarieren Sie Organisations- oder Abrechnungsanmeldedaten im Manifest unter
providerUsageAuthEnvVars. Dadurch können generische Erkennungs- und
Secret-Bereinigungsoberflächen sie erkennen, ohne sie zu Kandidaten für die
Inferenzauthentifizierung zu machen.
Provider-Beispiel
api.registerProvider({ id: "example-proxy", label: "Example Proxy", auth: [], catalog: { order: "simple", run: async (ctx) => { const apiKey = ctx.resolveProviderApiKey("example-proxy").apiKey; if (!apiKey) { return null; } return { provider: { baseUrl: "https://proxy.example.com/v1", apiKey, api: "openai-completions", models: [{ id: "auto", name: "Auto" }], }, }; }, }, resolveDynamicModel: (ctx) => ({ id: ctx.modelId, name: ctx.modelId, provider: "example-proxy", api: "openai-completions", baseUrl: "https://proxy.example.com/v1", reasoning: false, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128000, maxTokens: 8192, }), prepareRuntimeAuth: async (ctx) => { const exchanged = await exchangeToken(ctx.apiKey); return { apiKey: exchanged.token, baseUrl: exchanged.baseUrl, expiresAt: exchanged.expiresAt, }; }, resolveUsageAuth: async (ctx) => { const auth = await ctx.resolveOAuthToken(); return auth ? { token: auth.token } : null; }, fetchUsageSnapshot: async (ctx) => { return await fetchExampleProxyUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn); },});Integrierte Beispiele
Gebündelte Provider-Plugins kombinieren die oben genannten Hooks entsprechend
den Anforderungen des jeweiligen Anbieters an Katalog, Authentifizierung,
Denkprozesse, Replay und Nutzung. Der maßgebliche Hook-Satz befindet sich bei
jedem Plugin unter extensions/; diese Seite veranschaulicht die Strukturen,
anstatt die Liste zu spiegeln.
Provider mit durchgereichtem Katalog
OpenRouter, Kilocode, Z.AI und xAI registrieren catalog zusammen mit
resolveDynamicModel / prepareDynamicModel, damit sie vorgeschaltete
Modell-IDs vor dem statischen Katalog von OpenClaw bereitstellen können.
Provider mit OAuth- und Nutzungsendpunkten
GitHub Copilot, Gemini CLI, ChatGPT Codex, MiniMax, Xiaomi und z.ai
kombinieren prepareRuntimeAuth oder formatApiKey mit
resolveUsageAuth + fetchUsageSnapshot, um den Token-Austausch und die
/usage-Integration zu übernehmen.
Familien für Replay- und Transkriptbereinigung
Gemeinsam benannte Familien (google-gemini, passthrough-gemini,
anthropic-by-model, hybrid-anthropic-openai) ermöglichen Providern,
sich über buildReplayPolicy für Transkriptrichtlinien zu entscheiden,
anstatt die Bereinigung in jedem Plugin neu zu implementieren.
Provider ausschließlich mit Katalog
byteplus, cloudflare-ai-gateway, huggingface, kimi-coding, nvidia,
qianfan, synthetic, together, venice, vercel-ai-gateway und
volcengine registrieren nur catalog und verwenden die gemeinsame
Inferenzschleife.
Anthropic-spezifische Stream-Hilfsfunktionen
Beta-Header, /fast / serviceTier und context1m befinden sich innerhalb
der öffentlichen api.ts- / contract-api.ts-Schnittstelle des
Anthropic-Plugins (wrapAnthropicProviderStream, resolveAnthropicBetas,
resolveAnthropicFastMode, resolveAnthropicServiceTier) und nicht im
generischen SDK.
Laufzeit-Hilfsfunktionen
Plugins können über api.runtime auf ausgewählte Kern-Hilfsfunktionen zugreifen.
Für TTS:
const clip = await api.runtime.tts.textToSpeech({ text: "Hello from OpenClaw", cfg: api.config,}); const result = await api.runtime.tts.textToSpeechTelephony({ text: "Hello from OpenClaw", cfg: api.config,}); const voices = await api.runtime.tts.listVoices({ provider: "elevenlabs", cfg: api.config,});Hinweise:
textToSpeechgibt die normale TTS-Ausgabenutzlast des Kerns für Datei-/Sprachnotizoberflächen zurück.- Verwendet die Kernkonfiguration
messages.ttsund die Provider-Auswahl. - Gibt einen PCM-Audiopuffer und die Abtastrate zurück. Plugins müssen für die Provider neu abtasten/kodieren.
listVoicesist je Provider optional. Verwenden Sie es für anbietereigene Stimmenauswahlen oder Einrichtungsabläufe.- Der Kern übergibt den Provider-Hooks für
listVoiceseine aufgelöste Request-Deadline; Provider-spezifische Zeitüberschreitungseinstellungen können sie überschreiben. - Stimmenlisten können umfangreichere Metadaten wie Gebietsschema, Geschlecht und Persönlichkeitstags für Provider-bewusste Auswahloberflächen enthalten.
- OpenAI und ElevenLabs unterstützen derzeit Telefonie. Microsoft nicht.
Plugins können über api.registerSpeechProvider(...) auch Sprachausgabe-Provider registrieren.
api.registerSpeechProvider({ id: "acme-speech", label: "Acme Speech", isConfigured: ({ config }) => Boolean(config.messages?.tts), synthesize: async (req) => { return { audioBuffer: Buffer.from([]), outputFormat: "mp3", fileExtension: ".mp3", voiceCompatible: false, }; },});Hinweise:
- Belassen Sie TTS-Richtlinien, Fallback und Antwortzustellung im Kern.
- Verwenden Sie Sprachausgabe-Provider für anbietereigenes Syntheseverhalten.
- Die veraltete Microsoft-Eingabe
edgewird auf die Provider-IDmicrosoftnormalisiert. - Das bevorzugte Zuständigkeitsmodell ist unternehmensorientiert: Ein Anbieter-Plugin kann Text-, Sprach-, Bild- und zukünftige Medien-Provider verwalten, wenn OpenClaw diese Funktionsverträge hinzufügt.
Für das Verständnis von Bildern, Audio und Videos registrieren Plugins einen typisierten Provider für Medienverständnis anstelle eines generischen Schlüssel-Wert-Containers:
api.registerMediaUnderstandingProvider({ id: "google", capabilities: ["image", "audio", "video"], describeImage: async (req) => ({ text: "..." }), transcribeAudio: async (req) => ({ text: "..." }), describeVideo: async (req) => ({ text: "..." }),});Hinweise:
- Belassen Sie Orchestrierung, Fallback, Konfiguration und Channel-Verkabelung im Kern.
- Belassen Sie das Anbieterverhalten im Provider-Plugin.
- Additive Erweiterungen sollten typisiert bleiben: neue optionale Methoden, neue optionale Ergebnisfelder und neue optionale Funktionen.
- Die Videogenerierung folgt bereits demselben Muster:
- Der Kern verwaltet den Funktionsvertrag und die Laufzeit-Hilfsfunktion.
- Anbieter-Plugins registrieren
api.registerVideoGenerationProvider(...). - Funktions-/Channel-Plugins verwenden
api.runtime.videoGeneration.*.
Für Laufzeit-Hilfsfunktionen zum Medienverständnis können Plugins Folgendes aufrufen:
const image = await api.runtime.mediaUnderstanding.describeImageFile({ filePath: "/tmp/inbound-photo.jpg", cfg: api.config, agentDir: "/tmp/agent",}); const video = await api.runtime.mediaUnderstanding.describeVideoFile({ filePath: "/tmp/inbound-video.mp4", cfg: api.config,}); const extraction = await api.runtime.mediaUnderstanding.extractStructuredWithModel({ provider: "codex", model: "gpt-5.6-sol", input: [ { type: "image", buffer: receiptImageBuffer, fileName: "receipt.png", mime: "image/png", }, { type: "text", text: "Use the printed fields as the source of truth." }, ], instructions: "Return entities and searchable tags.", schemaName: "example.evidence", jsonSchema: { type: "object", properties: { entities: { type: "array", items: { type: "string" } }, tags: { type: "array", items: { type: "string" } }, }, }, cfg: api.config,});Für die Audiotranskription können Plugins entweder die Laufzeit für Medienverständnis oder den älteren STT-Alias verwenden:
const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ filePath: "/tmp/inbound-audio.ogg", cfg: api.config, // Optional when MIME cannot be inferred reliably: mime: "audio/ogg",});Hinweise:
api.runtime.mediaUnderstanding.*ist die bevorzugte gemeinsame Oberfläche für das Verständnis von Bildern, Audio und Videos.extractStructuredWithModel(...)ist die Plugin-seitige Schnittstelle für begrenzte, Provider-eigene, bildorientierte Extraktion. Fügen Sie mindestens eine Bildeingabe ein; Texteingaben dienen als ergänzender Kontext. Produkt-Plugins verwalten ihre Routen und Schemas, während OpenClaw die Provider-/Laufzeitgrenze verwaltet.- Verwendet die Audiokonfiguration des Kern-Medienverständnisses (
tools.media.audio) und die Fallback-Reihenfolge der Provider. - Gibt
{ text: undefined }zurück, wenn keine Transkriptionsausgabe erzeugt wird (beispielsweise bei übersprungenen/nicht unterstützten Eingaben). api.runtime.stt.transcribeAudioFile(...)bleibt als Kompatibilitätsalias bestehen.
Plugins können über api.runtime.subagent auch Subagent-Läufe im Hintergrund starten:
const result = await api.runtime.subagent.run({ sessionKey: "agent:main:subagent:search-helper", message: "Expand this query into focused follow-up searches.", provider: "openai", model: "gpt-4.1-mini", deliver: false,});Hinweise:
providerundmodelsind optionale Überschreibungen je Lauf, keine dauerhaften Sitzungsänderungen.- OpenClaw berücksichtigt diese Überschreibungsfelder nur bei vertrauenswürdigen Aufrufern.
- Für Plugin-eigene Fallback-Läufe müssen Betreiber dies mit
plugins.entries.<id>.subagent.allowModelOverride: trueaktivieren. - Verwenden Sie
plugins.entries.<id>.subagent.allowedModels, um vertrauenswürdige Plugins auf bestimmte kanonischeprovider/model-Ziele zu beschränken, oder"*", um ausdrücklich jedes Ziel zuzulassen. - Subagent-Läufe nicht vertrauenswürdiger Plugins funktionieren weiterhin, Überschreibungsanfragen werden jedoch abgelehnt, anstatt stillschweigend auf einen Fallback zurückzugreifen.
- Von Plugins erstellte Subagent-Sitzungen werden mit der ID des erstellenden Plugins gekennzeichnet. Der Fallback
api.runtime.subagent.deleteSession(...)darf nur diese eigenen Sitzungen löschen; das Löschen beliebiger Sitzungen erfordert weiterhin eine Gateway-Anfrage mit Administratorberechtigung.
Für die Websuche können Plugins die gemeinsame Laufzeit-Hilfsfunktion verwenden, anstatt auf die Verkabelung der Agent-Werkzeuge zuzugreifen:
const providers = api.runtime.webSearch.listProviders({ config: api.config,}); const result = await api.runtime.webSearch.search({ config: api.config, args: { query: "OpenClaw plugin runtime helpers", count: 5, },});Plugins können über api.registerWebSearchProvider(...) auch Websuch-Provider
registrieren.
Hinweise:
- Belassen Sie Provider-Auswahl, Auflösung von Anmeldedaten und gemeinsame Request-Semantik im Kern.
- Verwenden Sie Websuch-Provider für anbieterspezifische Suchtransporte.
api.runtime.webSearch.*ist die bevorzugte gemeinsame Oberfläche für Funktions-/Channel-Plugins, die Suchverhalten benötigen, ohne vom Wrapper des Agent-Werkzeugs abhängig zu sein.
api.runtime.imageGeneration
const result = await api.runtime.imageGeneration.generate({ config: api.config, args: { prompt: "A friendly lobster mascot", size: "1024x1024" },}); const providers = api.runtime.imageGeneration.listProviders({ config: api.config,});generate(...): Erzeugt ein Bild über die konfigurierte Kette von Bildgenerierungs-Providern.listProviders(...): Listet verfügbare Bildgenerierungs-Provider und ihre Funktionen auf.
Gateway-HTTP-Routen
Plugins können mit api.registerHttpRoute(...) HTTP-Endpunkte bereitstellen.
api.registerHttpRoute({ path: "/acme/webhook", auth: "plugin", match: "exact", handler: async (_req, res) => { res.statusCode = 200; res.end("ok"); return true; },});Routenfelder:
path: Routenpfad unter dem HTTP-Server des Gateways.auth: erforderlich,"gateway"oder"plugin". Verwenden Sie"gateway", um die normale Gateway-Authentifizierung zu verlangen, oder"plugin"für eine vom Plugin verwaltete Authentifizierung/Webhook-Verifizierung.match: optional."exact"(Standard) oder"prefix".handleUpgrade: optionaler Handler für WebSocket-Upgrade-Anfragen auf derselben Route.replaceExisting: optional. Erlaubt demselben Plugin, seine eigene vorhandene Routenregistrierung zu ersetzen.handler: Gibttruezurück, wenn die Route die Anfrage verarbeitet hat.
Hinweise:
api.registerHttpHandler(...)wurde entfernt und verursacht einen Fehler beim Laden des Plugins. Verwenden Sie stattdessenapi.registerHttpRoute(...).- Plugin-Routen müssen
authexplizit deklarieren. - Exakte Konflikte bei
path + matchwerden abgelehnt, sofern nichtreplaceExisting: truegesetzt ist, und ein Plugin kann die Route eines anderen Plugins nicht ersetzen. - Sich überschneidende Routen mit unterschiedlichen
auth-Stufen werden abgelehnt. Behalten Sieexact/prefix-Weiterleitungsketten ausschließlich auf derselben Authentifizierungsstufe. - Routen mit
auth: "plugin"erhalten nicht automatisch Operator-Laufzeitbereiche. Sie sind für vom Plugin verwaltete Webhooks/Signaturverifizierung vorgesehen, nicht für privilegierte Gateway-Hilfsaufrufe. - Routen mit
auth: "gateway"werden innerhalb eines Gateway-Anfragelaufzeitbereichs ausgeführt. Die Standardoberfläche (gatewayRuntimeScopeSurface: "write-default") ist bewusst konservativ:- Die Bearer-Authentifizierung mit gemeinsamem Geheimnis (
gateway.auth.mode = "token"/"password") sowie jede Authentifizierungsmethode ohne vertrauenswürdigen Proxy erhalten einen einzelnen Bereichoperator.write, selbst wenn der Aufruferx-openclaw-scopessendet. trusted-proxy-Aufrufer ohne explizitenx-openclaw-scopes-Header behalten ebenfalls die bisherige Oberfläche, die ausschließlichoperator.writeumfasst.trusted-proxy-Aufrufer, diex-openclaw-scopessenden, erhalten stattdessen die deklarierten Bereiche.- Eine Route kann
gatewayRuntimeScopeSurface: "trusted-operator"aktivieren, damitx-openclaw-scopesbei identitätstragenden Authentifizierungsmodi immer berücksichtigt wird (wenn der Header fehlt, wird auf den vollständigen Standardsatz von CLI-Bereichen zurückgegriffen).
- Die Bearer-Authentifizierung mit gemeinsamem Geheimnis (
- Praktische Regel: Gehen Sie nicht davon aus, dass eine Gateway-authentifizierte Plugin-Route implizit eine Administratoroberfläche ist. Wenn Ihre Route ausschließlich Administratoren vorbehaltenes Verhalten benötigt, aktivieren Sie die Bereichsoberfläche
trusted-operator, verlangen Sie einen identitätstragenden Authentifizierungsmodus und dokumentieren Sie den expliziten Header-Vertrag fürx-openclaw-scopes. - Nach Routenabgleich und Authentifizierung unterliegen gewöhnliche Handler der Zugangssteuerung für Gateway-Hauptaufgaben. Ein vorbereitetes oder neu startendes Gateway gibt
503zurück, bevor der Handler aufgerufen wird. Die eng begrenzte Ausnahme ist eine durch das Manifest berechtigte Route mitauth: "gateway", die außerdem die routenspezifische Oberflächetrusted-operatoraktiviert; sie bleibt erreichbar, damit die Weiterleitung der Steuerung zur Aussetzung nicht blockiert wird, während gewöhnliche benachbarte Routen desselben Plugins weiterhin hinter der Zugangsgrenze liegen. Die Zuständigkeit von WebSocket-handleUpgradeverwendet dieselbe atomare Zugangsgrenze; sobald der Handler einen Socket akzeptiert, liegt dessen weitere Lebensdauer in der Verantwortung des Plugins und wird von dieser Grenze nicht nachverfolgt.
Importpfade des Plugin SDK
Verwenden Sie beim Erstellen neuer Plugins schmale SDK-Unterpfade anstelle des monolithischen Root-Barrels openclaw/plugin-sdk. Kern-Unterpfade:
| Unterpfad | Zweck |
|---|---|
openclaw/plugin-sdk/plugin-entry |
Primitive zur Plugin-Registrierung |
openclaw/plugin-sdk/channel-core |
Hilfsfunktionen für Kanaleinstieg und -erstellung |
openclaw/plugin-sdk/core |
Generische gemeinsame Hilfsfunktionen und übergreifender Vertrag |
openclaw/plugin-sdk/config-schema |
Zod-Schema der Root-openclaw.json (OpenClawSchema) |
Kanal-Plugins wählen aus einer Familie schmaler Schnittstellen aus: channel-setup,
setup-runtime, setup-tools, channel-pairing,
channel-contract, channel-feedback, channel-inbound, channel-outbound,
command-auth, secret-input, webhook-ingress,
channel-targets und channel-actions. Das Genehmigungsverhalten sollte in
einem einzigen approvalCapability-Vertrag gebündelt werden, statt über
nicht zusammengehörige Plugin-Felder verteilt zu sein. Siehe Kanal-Plugins.
Laufzeit- und Konfigurationshilfen befinden sich unter passenden, fokussierten
*-runtime-Unterpfaden (approval-runtime, agent-runtime, lazy-runtime,
directory-runtime, text-runtime, runtime-store, system-event-runtime,
heartbeat-runtime, channel-activity-runtime usw.). Bevorzugen Sie
config-contracts, plugin-config-runtime, runtime-config-snapshot und
config-mutation gegenüber dem breiten Kompatibilitäts-Barrel config-runtime.
Repo-interne Einstiegspunkte (je Root des gebündelten Plugin-Pakets):
index.js— Einstiegspunkt des gebündelten Pluginsapi.js— Barrel für Hilfsfunktionen/Typenruntime-api.js— ausschließlich für die Laufzeit bestimmtes Barrelsetup-entry.js— Einstiegspunkt des Einrichtungs-Plugins
Externe Plugins sollten ausschließlich Unterpfade von openclaw/plugin-sdk/*
importieren. Importieren Sie niemals src/* eines anderen Plugin-Pakets aus
dem Kern oder einem anderen Plugin. Über eine Fassade geladene Einstiegspunkte
bevorzugen den aktiven Snapshot der Laufzeitkonfiguration, sofern vorhanden,
und greifen andernfalls auf die aufgelöste Konfigurationsdatei auf dem
Datenträger zurück.
Fähigkeitsspezifische Unterpfade wie image-generation, media-understanding
und speech existieren, weil gebündelte Plugins sie derzeit verwenden. Sie
sind nicht automatisch langfristig unveränderliche externe Verträge. Prüfen
Sie die entsprechende SDK-Referenzseite, wenn Sie sich auf sie verlassen.
Schemas für Nachrichtenwerkzeuge
Plugins sollten kanalspezifische Schemabeiträge für describeMessageTool(...)
für Primitive übernehmen, die keine Nachrichten sind, beispielsweise
Reaktionen, Lesebestätigungen und Umfragen. Die gemeinsame Sendedarstellung
sollte den generischen Vertrag MessagePresentation anstelle von
Provider-nativen Schaltflächen-, Komponenten-, Block- oder Kartenfeldern
verwenden. Informationen zum Vertrag, zu Fallback-Regeln, zur Provider-Zuordnung
und zur Prüfliste für Plugin-Autoren finden Sie unter
Nachrichtendarstellung.
Sendefähige Plugins deklarieren über Nachrichtenfähigkeiten, was sie darstellen können:
presentationfür semantische Darstellungsblöcke (text,context,divider,chart,table,buttons,select)delivery-pinfür Anforderungen zur angehefteten Zustellung
Der Kern entscheidet, ob die Darstellung nativ gerendert oder auf Text reduziert wird. Stellen Sie über das generische Nachrichtenwerkzeug keine Provider-nativen UI-Ausweichmöglichkeiten bereit. Veraltete SDK-Hilfsfunktionen für bisherige native Schemas bleiben für bestehende Drittanbieter-Plugins exportiert, neue Plugins sollten sie jedoch nicht verwenden.
Auflösung von Kanalzielen
Kanal-Plugins sollten die kanalspezifische Zielsemantik übernehmen. Halten Sie den gemeinsamen ausgehenden Host generisch und verwenden Sie die Oberfläche des Nachrichtenadapters für Provider-Regeln:
messaging.inferTargetChatType({ to })entscheidet vor der Verzeichnissuche, ob ein normalisiertes Ziel alsdirect,groupoderchannelbehandelt werden soll.messaging.targetResolver.looksLikeId(raw, normalized)teilt dem Kern mit, ob eine Eingabe direkt mit einer ID-ähnlichen Auflösung verarbeitet werden soll, anstatt das Verzeichnis zu durchsuchen.messaging.targetResolver.reservedLiteralslistet einzelne Wörter auf, die für diesen Provider Kanal-/Sitzungsreferenzen darstellen. Bei der Auflösung werden konfigurierte Verzeichniseinträge berücksichtigt, bevor reservierte Literale abgelehnt werden; bei einem Fehlschlag der Verzeichnissuche wird anschließend sicher abgebrochen.messaging.targetResolver.resolveTarget(...)ist der Plugin-Fallback, wenn der Kern nach der Normalisierung oder nach einem Fehlschlag der Verzeichnissuche eine abschließende, vom Provider verwaltete Auflösung benötigt.messaging.resolveOutboundSessionRoute(...)übernimmt die Provider-spezifische Erstellung der Sitzungsroute, sobald ein Ziel aufgelöst wurde.
Empfohlene Aufteilung:
- Verwenden Sie
inferTargetChatTypefür Kategorieentscheidungen, die vor der Suche nach Kontakten/Gruppen erfolgen sollen. - Verwenden Sie
looksLikeIdfür Prüfungen nach dem Muster „dies als explizite/native Ziel-ID behandeln“. - Verwenden Sie
resolveTargetals Fallback für die Provider-spezifische Normalisierung, nicht für eine umfassende Verzeichnissuche. - Behalten Sie Provider-native IDs wie Chat-IDs, Thread-IDs, JIDs, Handles und
Raum-IDs innerhalb von
target-Werten oder Provider-spezifischen Parametern, nicht in generischen SDK-Feldern.
Konfigurationsgestützte Verzeichnisse
Plugins, die Verzeichniseinträge aus der Konfiguration ableiten, sollten diese
Logik im Plugin belassen und die gemeinsamen Hilfsfunktionen aus
openclaw/plugin-sdk/directory-runtime wiederverwenden.
Verwenden Sie dies, wenn ein Kanal konfigurationsgestützte Kontakte/Gruppen benötigt, beispielsweise:
- durch Zulassungslisten gesteuerte Direktnachrichtenkontakte
- konfigurierte Kanal-/Gruppenzuordnungen
- kontobezogene statische Verzeichnis-Fallbacks
Die gemeinsamen Hilfsfunktionen in directory-runtime übernehmen nur
generische Operationen:
- Abfragefilterung
- Anwendung von Begrenzungen
- Hilfsfunktionen zur Deduplizierung/Normalisierung
- Erstellung von
ChannelDirectoryEntry[]
Kanalspezifische Kontoprüfungen und ID-Normalisierungen sollten in der Plugin-Implementierung verbleiben.
Provider-Kataloge
Provider-Plugins können Modellkataloge für Inferenz mit
registerProvider({ catalog: { run(...) { ... } } }) definieren.
catalog.run(...) gibt dieselbe Struktur zurück, die OpenClaw in
models.providers schreibt:
{ provider }für einen Provider-Eintrag{ providers }für mehrere Provider-Einträge
Verwenden Sie catalog, wenn das Plugin Provider-spezifische Modell-IDs,
Standard-Basis-URLs oder authentifizierungsabhängige Modellmetadaten verwaltet.
catalog.order steuert, wann der Katalog eines Plugins relativ zu den
integrierten impliziten Providern von OpenClaw zusammengeführt wird:
simple: einfache, durch API-Schlüssel oder Umgebungsvariablen gesteuerte Providerprofile: Provider, die bei vorhandenen Authentifizierungsprofilen erscheinenpaired: Provider, die mehrere zusammengehörige Provider-Einträge erzeugenlate: letzter Durchlauf nach anderen impliziten Providern
Spätere Provider gewinnen bei Schlüsselkollisionen, sodass Plugins einen integrierten Provider-Eintrag mit derselben Provider-ID gezielt überschreiben können.
Plugins können außerdem schreibgeschützte Modellzeilen über
api.registerModelCatalogProvider({ provider, kinds, staticCatalog, liveCatalog }) veröffentlichen. Dies ist der zukünftige Weg für Listen-, Hilfe- und
Auswahloberflächen und unterstützt Zeilen für text, voice,
image_generation, video_generation und music_generation. Provider-Plugins
bleiben für Live-Endpunktaufrufe, Token-Austausch und die Zuordnung von
Herstellerantworten zuständig; der Kern übernimmt die gemeinsame Zeilenstruktur,
Quellenbezeichnungen und die Formatierung der Hilfe für Medienwerkzeuge.
Registrierungen von Providern zur Mediengenerierung erzeugen automatisch
statische Katalogzeilen aus defaultModel, models und capabilities.
Kompatibilität:
discoveryfunktioniert weiterhin als veralteter Alias, gibt jedoch eine Veraltungswarnung aus.- Wenn sowohl
catalogals auchdiscoveryregistriert sind, verwendet OpenClawcatalogund gibt eine Warnung aus. augmentModelCatalogist veraltet; gebündelte Provider sollten ergänzende Zeilen überregisterModelCatalogProviderveröffentlichen.
Schreibgeschützte Kanalprüfung
Wenn Ihr Plugin einen Kanal registriert, sollten Sie vorzugsweise
plugin.config.inspectAccount(cfg, accountId) zusammen mit
resolveAccount(...) implementieren.
Gründe:
resolveAccount(...)ist der Laufzeitpfad. Er darf davon ausgehen, dass Zugangsdaten vollständig materialisiert sind, und kann sofort fehlschlagen, wenn erforderliche Geheimnisse fehlen.- Schreibgeschützte Befehlspfade wie
openclaw status,openclaw status --all,openclaw channels status,openclaw channels resolvesowie Reparaturabläufe für Doctor/Konfiguration sollten keine Laufzeit-Zugangsdaten materialisieren müssen, nur um die Konfiguration zu beschreiben.
Empfohlenes Verhalten von inspectAccount(...):
- Geben Sie nur einen beschreibenden Kontostatus zurück.
- Behalten Sie
enabledundconfiguredbei. - Geben Sie bei Bedarf Felder für Quelle und Status der Zugangsdaten an, beispielsweise:
tokenSource,tokenStatusbotTokenSource,botTokenStatusappTokenSource,appTokenStatussigningSecretSource,signingSecretStatus
- Sie müssen keine unverschlüsselten Tokenwerte zurückgeben, nur um die schreibgeschützte
Verfügbarkeit zu melden. Die Rückgabe von
tokenStatus: "available"(zusammen mit dem entsprechenden Quellfeld) reicht für Statusbefehle aus. - Verwenden Sie
configured_unavailable, wenn Zugangsdaten über SecretRef konfiguriert, aber im aktuellen Befehlspfad nicht verfügbar sind.
Dadurch können schreibgeschützte Befehle „konfiguriert, aber in diesem Befehlspfad nicht verfügbar“ melden, anstatt abzustürzen oder das Konto fälschlicherweise als nicht konfiguriert auszuweisen.
Paketbündel
Ein Plugin-Verzeichnis kann eine package.json mit openclaw.extensions enthalten:
{ "name": "my-pack", "openclaw": { "extensions": ["./src/safety.ts", "./src/tools.ts"], "setupEntry": "./src/setup-entry.ts" }}Jeder Eintrag wird zu einem Plugin. Wenn das Bündel mehrere Erweiterungen auflistet,
wird die Plugin-ID zu <manifestOrPackageName>/<fileBase> (die Manifest-ID hat
Vorrang, sofern vorhanden; andernfalls wird der Name aus package.json ohne
Namensraum verwendet).
Wenn Ihr Plugin npm-Abhängigkeiten importiert, installieren Sie diese in diesem
Verzeichnis, sodass node_modules verfügbar ist (npm install / pnpm install).
Sicherheitsvorkehrung: Jeder Eintrag in openclaw.extensions muss nach der
Auflösung symbolischer Verknüpfungen innerhalb des Plugin-Verzeichnisses verbleiben.
Einträge, die aus dem Paketverzeichnis herausführen, werden abgelehnt.
Sicherheitshinweis: openclaw plugins install installiert Plugin-Abhängigkeiten
mit einem projektlokalen npm install --omit=dev --ignore-scripts (keine
Lebenszyklusskripte und zur Laufzeit keine Entwicklungsabhängigkeiten), wobei
übernommene globale npm-Installationseinstellungen ignoriert werden.
Halten Sie die Abhängigkeitsbäume von Plugins „reines JS/TS“ und vermeiden Sie
Pakete, die postinstall-Builds erfordern.
Optional: openclaw.setupEntry kann auf ein schlankes Modul verweisen, das nur
für die Einrichtung bestimmt ist. Wenn OpenClaw Einrichtungsoberflächen für ein
deaktiviertes Kanal-Plugin benötigt oder wenn ein Kanal-Plugin aktiviert, aber
noch nicht konfiguriert ist, lädt es setupEntry anstelle des vollständigen
Plugin-Einstiegspunkts. Dadurch bleiben Start und Einrichtung schlanker, wenn
Ihr Haupt-Plugin-Einstiegspunkt zusätzlich Werkzeuge, Hooks oder anderen
ausschließlich zur Laufzeit benötigten Code einbindet.
Optional: Mit openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
kann ein Kanal-Plugin während der Vorbereitungsphase vor dem Lauschen des Gateways
denselben setupEntry-Pfad verwenden, selbst wenn der Kanal bereits konfiguriert ist.
Verwenden Sie dies nur, wenn setupEntry die vor dem Beginn des Lauschens durch
den Gateway erforderliche Startoberfläche vollständig abdeckt. In der Praxis
bedeutet dies, dass der Einrichtungseinstiegspunkt jede kanaleigene Fähigkeit
registrieren muss, von der der Start abhängt, beispielsweise:
- die Kanalregistrierung selbst
- sämtliche HTTP-Routen, die verfügbar sein müssen, bevor der Gateway mit dem Lauschen beginnt
- sämtliche Gateway-Methoden, Werkzeuge oder Dienste, die im selben Zeitraum vorhanden sein müssen
Wenn Ihr vollständiger Einstiegspunkt weiterhin eine erforderliche Startfähigkeit bereitstellt, aktivieren Sie dieses Flag nicht. Behalten Sie für das Plugin das Standardverhalten bei und lassen Sie OpenClaw während des Starts den vollständigen Einstiegspunkt laden.
Gebündelte Kanäle können außerdem Hilfsfunktionen für die reine Einrichtungs- Vertragsoberfläche veröffentlichen, die der Kern abfragen kann, bevor die vollständige Kanallaufzeit geladen wird. Die aktuelle Einrichtungsoberfläche für die Überführung ist:
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
Der Kern verwendet diese Oberfläche, wenn er eine veraltete Einzelkonto-
Kanalkonfiguration nach channels.<id>.accounts.* überführen muss, ohne den
vollständigen Plugin-Einstiegspunkt zu laden. Matrix ist das aktuelle gebündelte
Beispiel: Wenn bereits benannte Konten vorhanden sind, verschiebt es nur
Authentifizierungs-/Bootstrap-Schlüssel in ein benanntes überführtes Konto und
kann einen konfigurierten, nicht kanonischen Schlüssel für das Standardkonto
beibehalten, anstatt immer accounts.default zu erstellen.
Diese Einrichtungs-Patchadapter halten die Ermittlung gebündelter Vertragsoberflächen träge. Die Importzeit bleibt kurz; die Überführungsoberfläche wird erst bei der ersten Verwendung geladen, anstatt beim Modulimport den Start gebündelter Kanäle erneut auszuführen.
Wenn diese Startoberflächen Gateway-RPC-Methoden umfassen, behalten Sie dafür
ein Plugin-spezifisches Präfix bei. Die administrativen Kern-Namensräume
(config.*, exec.approvals.*, wizard.*, update.*) bleiben reserviert und
werden stets in operator.admin aufgelöst, selbst wenn ein Plugin einen engeren
Geltungsbereich anfordert.
Beispiel:
{ "name": "@scope/my-channel", "openclaw": { "extensions": ["./index.ts"], "setupEntry": "./setup-entry.ts", "startup": { "deferConfiguredChannelFullLoadUntilAfterListen": true } }}Metadaten des Kanalkatalogs
Kanal-Plugins können über openclaw.channel Metadaten für Einrichtung und
Ermittlung sowie über openclaw.install Installationshinweise bereitstellen.
Dadurch bleibt der Kernkatalog frei von Daten.
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": "<bundled-plugin-local-path>", "defaultChoice": "npm" } }}Nützliche Felder von openclaw.channel, die über das Minimalbeispiel hinausgehen:
detailLabel: sekundäre Bezeichnung für ausführlichere Katalog-/StatusoberflächendocsLabel: überschreibt den Linktext für den DokumentationslinkpreferOver: Plugin-/Kanal-IDs mit niedrigerer Priorität, die dieser Katalogeintrag übertreffen sollselectionDocsPrefix,selectionDocsOmitLabel,selectionExtras: Steuerung des Textes auf der AuswahloberflächemarkdownCapable: kennzeichnet den Kanal für Entscheidungen zur ausgehenden Formatierung als Markdown-fähigexposure.configured: blendet den Kanal in Auflistungsoberflächen für konfigurierte Kanäle aus, wenn auffalsegesetztexposure.setup: blendet den Kanal in interaktiven Auswahlmenüs für Einrichtung/Konfiguration aus, wenn auffalsegesetztexposure.docs: kennzeichnet den Kanal für Dokumentations-Navigationsoberflächen als intern/privatshowConfigured/showInSetup: veraltete Aliasse, die aus Kompatibilitätsgründen weiterhin akzeptiert werden; bevorzugen SieexposurequickstartAllowFrom: nimmt den Kanal in den standardmäßigenallowFrom-Ablauf für den Schnellstart aufforceAccountBinding: erfordert eine explizite Kontobindung, selbst wenn nur ein Konto vorhanden istpreferSessionLookupForAnnounceTarget: bevorzugt die Sitzungssuche beim Auflösen von Bekanntgabezielen
OpenClaw kann außerdem externe Kanalkataloge zusammenführen (beispielsweise einen Export aus einer MPM-Registry). Legen Sie eine JSON-Datei an einem der folgenden Orte ab:
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
Alternativ können Sie OPENCLAW_PLUGIN_CATALOG_PATHS (oder
OPENCLAW_MPM_CATALOG_PATHS) auf eine oder mehrere JSON-Dateien verweisen lassen
(durch Kommas, Semikolons oder PATH getrennt). Jede Datei sollte
{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }
enthalten. Der Parser akzeptiert außerdem "packages" oder "plugins" als
veraltete Aliasse für den Schlüssel "entries".
Generierte Einträge des Kanalkatalogs und Einträge des Provider-Installationskatalogs
stellen neben dem unverarbeiteten Block openclaw.install normalisierte Angaben
zur Installationsquelle bereit. Die normalisierten Angaben zeigen, ob die
npm-Spezifikation eine exakte Version oder ein variabler Selektor ist, ob die
erwarteten Integritätsmetadaten vorhanden sind und ob außerdem ein lokaler
Quellpfad verfügbar ist. Wenn die Katalog-/Paketidentität bekannt ist, warnen die
normalisierten Angaben, falls der ausgelesene npm-Paketname von dieser Identität
abweicht. Sie warnen außerdem, wenn defaultChoice ungültig ist oder auf eine
nicht verfügbare Quelle verweist und wenn npm-Integritätsmetadaten ohne eine
gültige npm-Quelle vorhanden sind. Verbraucher sollten installSource als
additives optionales Feld behandeln, damit manuell erstellte Einträge und
Katalog-Kompatibilitätsschichten es nicht erzeugen müssen.
Dadurch können Onboarding und Diagnose den Zustand der Quellebene erläutern,
ohne die Plugin-Laufzeit zu importieren.
Offizielle externe npm-Einträge sollten eine exakte npmSpec zusammen mit
expectedIntegrity bevorzugen. Reine Paketnamen und Dist-Tags funktionieren
aus Kompatibilitätsgründen weiterhin, zeigen jedoch Warnungen zur Quellebene an,
damit der Katalog schrittweise zu festgeschriebenen, integritätsgeprüften
Installationen übergehen kann, ohne bestehende Plugins zu beeinträchtigen.
Wenn das Onboarding aus einem lokalen Katalogpfad installiert, zeichnet es einen
verwalteten Plugin-Indexeintrag mit source: "path" und nach Möglichkeit einem
arbeitsbereichsrelativen sourcePath auf. Der absolute operative Ladepfad
verbleibt in plugins.load.paths; der Installationseintrag vermeidet es, lokale
Arbeitsstationspfade in die langlebige Konfiguration zu duplizieren. Dadurch
bleiben lokale Entwicklungsinstallationen für die Diagnose der Quellebene
sichtbar, ohne eine zweite Offenlegungsoberfläche für unverarbeitete
Dateisystempfade hinzuzufügen. Die persistierte SQLite-Tabelle
installed_plugin_index ist die maßgebliche Quelle für Installationen und kann
aktualisiert werden, ohne Plugin-Laufzeitmodule zu laden. Ihre installRecords-
Zuordnung bleibt dauerhaft erhalten, selbst wenn ein Plugin-Manifest fehlt oder
ungültig ist; ihre plugins-Nutzlast ist eine wiederherstellbare Manifestansicht.
Plugins für Kontext-Engines
Plugins für Kontext-Engines übernehmen die Orchestrierung des Sitzungskontexts
für Aufnahme, Zusammenstellung und Compaction. Registrieren Sie sie aus Ihrem
Plugin mit api.registerContextEngine(id, factory) und wählen Sie anschließend
die aktive Engine mit plugins.slots.contextEngine aus.
Verwenden Sie dies, wenn Ihr Plugin die standardmäßige Kontextpipeline ersetzen oder erweitern muss, anstatt lediglich Speichersuche oder Hooks hinzuzufügen.
export default function (api) { api.registerContextEngine("lossless-claw", (ctx) => ({ info: { id: "lossless-claw", name: "Lossless Claw", ownsCompaction: true }, async ingest() { return { ingested: true }; }, async assemble({ messages, sessionKey, availableTools, citationsMode }) { return { messages, estimatedTokens: 0, systemPromptAddition: buildMemorySystemPromptAddition({ availableTools: availableTools ?? new Set(), citationsMode, agentId: resolveSessionAgentId({ config: ctx.config, sessionKey }), agentSessionKey: sessionKey, }), }; }, async compact() { return { ok: true, compacted: false }; }, }));}Der Factory-Kontext ctx stellt optionale Werte für config, agentDir und
workspaceDir zur Initialisierung während der Erstellung bereit.
assemble() kann contextProjection zurückgeben, wenn das aktive Testgerüst
über einen persistenten Backend-Thread verfügt. Lassen Sie es für die veraltete
Projektion pro Durchlauf weg. Geben Sie { mode: "thread_bootstrap", epoch }
zurück, wenn der zusammengestellte Kontext einmalig in einen Backend-Thread
eingefügt und bis zur Änderung der Epoche wiederverwendet werden soll. Ändern Sie
die Epoche nach semantischen Änderungen am Kontext der Engine, beispielsweise
nach einem von der Engine gesteuerten Compaction-Durchlauf. Hosts können
Metadaten von Werkzeugaufrufen, die Eingabeform und bereinigte Werkzeugergebnisse
in einer Thread-Bootstrap-Projektion beibehalten, damit neue Backend-Threads die
Werkzeugkontinuität bewahren, ohne unverarbeitete, geheimnishaltige Nutzlasten
zu kopieren.
Wenn Ihre Engine den Compaction-Algorithmus nicht besitzt, lassen Sie
compact() implementiert und delegieren Sie ihn ausdrücklich:
buildMemorySystemPromptAddition, delegateCompactionToRuntime,} from "openclaw/plugin-sdk/core"; export default function (api) { api.registerContextEngine("my-memory-engine", (ctx) => ({ info: { id: "my-memory-engine", name: "My Memory Engine", ownsCompaction: false, }, async ingest() { return { ingested: true }; }, async assemble({ messages, sessionKey, availableTools, citationsMode }) { return { messages, estimatedTokens: 0, systemPromptAddition: buildMemorySystemPromptAddition({ availableTools: availableTools ?? new Set(), citationsMode, agentId: resolveSessionAgentId({ config: ctx.config, sessionKey }), agentSessionKey: sessionKey, }), }; }, async compact(params) { return await delegateCompactionToRuntime(params); }, }));}Hinzufügen einer neuen Fähigkeit
Wenn ein Plugin ein Verhalten benötigt, das nicht zur aktuellen API passt, umgehen Sie das Plugin-System nicht durch einen privaten internen Zugriff. Fügen Sie die fehlende Fähigkeit hinzu.
Empfohlene Reihenfolge:
- Definieren Sie den Kernvertrag. Legen Sie fest, welches gemeinsame Verhalten der Kern übernehmen soll: Richtlinien, Fallback, Zusammenführung der Konfiguration, Lebenszyklus, kanalbezogene Semantik und Form der Runtime-Hilfsfunktion.
- Fügen Sie typisierte Oberflächen für Plugin-Registrierung und Runtime hinzu. Erweitern Sie
OpenClawPluginApiund/oderapi.runtimeum die kleinste zweckmäßige typisierte Fähigkeitsoberfläche. - Binden Sie Kern und Kanal-/Funktionsnutzer an. Kanäle und Funktions-Plugins sollten die neue Fähigkeit über den Kern nutzen, statt eine herstellerspezifische Implementierung direkt zu importieren.
- Registrieren Sie herstellerspezifische Implementierungen. Hersteller-Plugins registrieren anschließend ihre Backends für die Fähigkeit.
- Fügen Sie Vertragsabdeckung hinzu. Fügen Sie Tests hinzu, damit Eigentümerschaft und Registrierungsform dauerhaft explizit bleiben.
Auf diese Weise behält OpenClaw klare Vorgaben bei, ohne fest auf die Weltsicht eines einzelnen Providers zugeschnitten zu werden. Eine konkrete Datei-Checkliste und ein ausgearbeitetes Beispiel finden Sie im Kochbuch für Fähigkeiten.
Checkliste für Fähigkeiten
Wenn Sie eine neue Fähigkeit hinzufügen, sollte die Implementierung normalerweise die folgenden Oberflächen gemeinsam betreffen:
- Kernvertragstypen in
src/<capability>/types.ts - Kern-Runner bzw. Runtime-Hilfsfunktion in
src/<capability>/runtime.ts - Registrierungsoberfläche der Plugin-API in
src/plugins/types.ts - Verdrahtung der Plugin-Registry in
src/plugins/registry.ts - Bereitstellung über die Plugin-Runtime in
src/plugins/runtime/*, wenn Funktions-/Kanal-Plugins darauf zugreifen müssen - Erfassungs-/Testhilfen in
src/test-utils/plugin-registration.ts - Prüfungen der Eigentümerschaft und Verträge in
src/plugins/contracts/registry.ts - Dokumentation für Betreiber und Plugins in
docs/
Wenn eine dieser Oberflächen fehlt, deutet das normalerweise darauf hin, dass die Fähigkeit noch nicht vollständig integriert ist.
Vorlage für Fähigkeiten
Minimales Muster:
// core contractexport type VideoGenerationProviderPlugin = { id: string; label: string; generateVideo: (req: VideoGenerationRequest) => Promise<VideoGenerationResult>;}; // plugin APIapi.registerVideoGenerationProvider({ id: "openai", label: "OpenAI", async generateVideo(req) { return await generateOpenAiVideo(req); },}); // shared runtime helper for feature/channel pluginsconst clip = await api.runtime.videoGeneration.generate({ prompt: "Show the robot walking through the lab.", cfg,});Muster für Vertragstests (src/plugins/contracts/registry.ts stellt Abfragen der Eigentümerschaft wie providerContractPluginIds bereit; Tests prüfen, ob die Liste contracts.videoGenerationProviders eines Plugins mit den tatsächlich registrierten Einträgen übereinstimmt):
expect(pluginManifest.contracts?.videoGenerationProviders).toEqual(["openai"]);Dadurch bleibt die Regel einfach:
- Der Kern übernimmt den Fähigkeitsvertrag und die Orchestrierung.
- Hersteller-Plugins übernehmen herstellerspezifische Implementierungen.
- Funktions-/Kanal-Plugins nutzen Runtime-Hilfsfunktionen.
- Vertragstests halten die Eigentümerschaft explizit.
Verwandte Themen
- Plugin-Architektur — öffentliches Fähigkeitsmodell und zugehörige Formen
- Unterpfade des Plugin-SDK
- Einrichtung des Plugin-SDK
- Plugins erstellen