Lade-Pipeline
Beim Start führt OpenClaw grob Folgendes aus:- mögliche Plugin-Roots erkennen
- 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 festlegen
- aktivierte native Module laden: gebaute gebündelte Module verwenden einen nativen Loader; ungebaute native Plugins verwenden jiti
- native
register(api)-Hooks aufrufen und Registrierungen in der Plugin-Registry sammeln - die Registry für Befehle/Laufzeit-Oberflächen verfügbar machen
activate ist ein Legacy-Alias für register — der Loader löst jeweils auf, was vorhanden ist (def.register ?? def.activate), und ruft es an derselben Stelle auf. Alle gebündelten Plugins verwenden register; bevorzugen Sie register für neue Plugins.Manifest-first-Verhalten
Das Manifest ist die Control-Plane-Quelle der Wahrheit. OpenClaw verwendet es, um:- das Plugin zu identifizieren
- deklarierte Channels/Skills/Konfigurationsschema oder Bundle-Fähigkeiten zu erkennen
plugins.entries.<id>.configzu validieren- Labels/Platzhalter der Control UI anzureichern
- Installations-/Katalogmetadaten anzuzeigen
- günstige Aktivierungs- und Einrichtungsdeskriptoren zu bewahren, ohne die Plugin-Laufzeit zu laden
activation und setup bleiben auf der Control Plane.
Sie sind reine Metadaten-Deskriptoren für Aktivierungsplanung und Setup-Erkennung;
sie ersetzen keine Laufzeitregistrierung, register(...) oder setupEntry.
Die ersten Verbraucher der Live-Aktivierung nutzen jetzt Manifest-Hinweise für Befehle, Channels und Provider,
um das Laden von Plugins vor einer breiteren Materialisierung der Registry einzugrenzen:
- Das CLI-Laden wird auf Plugins eingegrenzt, denen der angeforderte primäre Befehl gehört
- Channel-Setup/Plugin-Auflösung wird auf Plugins eingegrenzt, denen die angeforderte Channel-ID gehört
- explizite Provider-Setup-/Laufzeit-Auflösung wird auf Plugins eingegrenzt, denen die angeforderte Provider-ID gehört
activation.*-Planungshinweise von Manifest-Eigentums-
Fallbacks wie providers, channels, commandAliases, setup.providers,
contracts.tools und Hooks. Diese Aufteilung der Gründe ist die Kompatibilitätsgrenze:
vorhandene Plugin-Metadaten funktionieren weiterhin, während neuer Code breite Hinweise
oder Fallback-Verhalten erkennen kann, ohne die Semantik des Laufzeitladens zu ändern.
Die Setup-Erkennung bevorzugt jetzt descriptor-eigene IDs wie setup.providers und
setup.cliBackends, um Kandidaten-Plugins einzugrenzen, bevor auf
setup-api für Plugins zurückgegriffen wird, die weiterhin Setup-Laufzeit-Hooks benötigen. Wenn mehr als
ein erkanntes Plugin dieselbe normalisierte Setup-Provider- oder CLI-Backend-
ID beansprucht, verweigert die Setup-Suche den mehrdeutigen Eigentümer, statt sich auf die Erkennungsreihenfolge zu verlassen.
Was der Loader zwischenspeichert
OpenClaw hält kurze In-Process-Caches für:- Erkennungsergebnisse
- Manifest-Registry-Daten
- geladene Plugin-Registries
- Setzen Sie
OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1oderOPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1, um diese Caches zu deaktivieren. - Passen Sie die Cache-Fenster mit
OPENCLAW_PLUGIN_DISCOVERY_CACHE_MSundOPENCLAW_PLUGIN_MANIFEST_CACHE_MSan.
Registry-Modell
Geladene Plugins verändern nicht direkt beliebige globale Core-Zustände. Sie registrieren sich in einer zentralen Plugin-Registry. Die Registry verfolgt:- Plugin-Datensätze (Identität, Quelle, Ursprung, Status, Diagnosen)
- Tools
- Legacy-Hooks und typisierte Hooks
- Channels
- Provider
- Gateway-RPC-Handler
- HTTP-Routen
- CLI-Registrare
- Hintergrunddienste
- Plugin-eigene Befehle
- Plugin-Modul -> Registry-Registrierung
- Core-Laufzeit -> Registry-Nutzung
Callbacks für Conversation-Bindings
Plugins, die eine Conversation binden, können reagieren, wenn eine Genehmigung aufgelöst wird. Verwenden Sieapi.onConversationBindingResolved(...), um einen Callback zu erhalten, nachdem eine Bind-
Anfrage genehmigt oder abgelehnt wurde:
status:"approved"oder"denied"decision:"allow-once","allow-always"oder"deny"binding: die aufgelöste Bindung für genehmigte Anfragenrequest: die ursprüngliche Anfragenzusammenfassung, Detach-Hinweis, Sender-ID und Conversation-Metadaten
Provider-Laufzeit-Hooks
Provider-Plugins haben drei Ebenen:- Manifest-Metadaten für günstige Lookup-Vorgänge vor der Laufzeit:
providerAuthEnvVars,providerAuthAliases,providerAuthChoicesundchannelEnvVars. - Hooks zur Konfigurationszeit:
catalog(Legacy-discovery) plusapplyConfigDefaults. - Laufzeit-Hooks: mehr als 40 optionale Hooks für Auth, Modellauflösung, Stream-Wrapping, Thinking-Levels, Replay-Richtlinie und Usage-Endpunkte. Siehe die vollständige Liste unter Reihenfolge und Verwendung der Hooks.
providerAuthEnvVars, wenn der Provider env-basierte Zugangsdaten hat,
die generische Auth-/Status-/Model-Picker-Pfade sehen sollen, ohne die Plugin-Laufzeit zu laden.
Verwenden Sie Manifest-providerAuthAliases, wenn eine Provider-ID die env-Variablen,
Auth-Profile, konfigurationsgestützte Auth und die API-Key-Onboarding-Auswahl einer anderen Provider-ID
wiederverwenden soll. Verwenden Sie Manifest-providerAuthChoices, wenn CLI-Oberflächen für Onboarding/Auth-Auswahl
die Choice-ID, Gruppen-Labels und einfache Auth-Verdrahtung mit nur einem Flag des Providers kennen sollen, ohne die Provider-Laufzeit zu laden.
Behalten Sie Laufzeit-envVars des Providers für operatorseitige Hinweise wie Onboarding-Labels oder
Setup-Variablen für OAuth-Client-ID/Client-Secret bei.
Verwenden Sie Manifest-channelEnvVars, wenn ein Channel env-gesteuerte Auth oder Einrichtung hat,
die generischer Shell-env-Fallback, Konfigurations-/Statusprüfungen oder Setup-Prompts sehen sollen,
ohne die Channel-Laufzeit zu laden.
Reihenfolge und Verwendung der Hooks
Für Modell-/Provider-Plugins ruft OpenClaw Hooks grob in dieser Reihenfolge auf. Die Spalte „Wann verwenden“ ist die schnelle Entscheidungshilfe.| # | Hook | Funktion | Wann verwenden |
|---|---|---|---|
| 1 | catalog | Provider-Konfiguration während der models.json-Generierung in models.providers veröffentlichen | Der Provider besitzt einen Katalog oder Standardwerte für base URL |
| 2 | applyConfigDefaults | Provider-eigene globale Konfigurationsstandardwerte während der Konfigurationsmaterialisierung anwenden | Standardwerte hängen von Auth-Modus, env oder der Semantik der Provider-Modellfamilie ab |
| — | (integrierte Modellauflösung) | OpenClaw versucht zuerst den normalen Registry-/Katalogpfad | (kein Plugin-Hook) |
| 3 | normalizeModelId | Legacy- oder Preview-Aliasse für Modell-IDs vor der Auflösung normalisieren | Der Provider besitzt Alias-Bereinigung vor der kanonischen Modellauflösung |
| 4 | normalizeTransport | api / baseUrl der Provider-Familie vor der generischen Modellassemblierung normalisieren | Der Provider besitzt Transport-Bereinigung für benutzerdefinierte Provider-IDs in derselben Transportfamilie |
| 5 | normalizeConfig | models.providers.<id> vor der Laufzeit-/Provider-Auflösung normalisieren | Der Provider benötigt Konfigurationsbereinigung, die beim Plugin liegen sollte; gebündelte Helper der Google-Familie sichern auch unterstützte Google-Konfigurationseinträge ab |
| 6 | applyNativeStreamingUsageCompat | Native Streaming-Usage-Kompatibilitätsumschreibungen auf Konfigurations-Provider anwenden | Der Provider benötigt endpunktgesteuerte Korrekturen für native Streaming-Usage-Metadaten |
| 7 | resolveConfigApiKey | Env-Marker-Auth für Konfigurations-Provider vor dem Laden der Laufzeit-Auth auflösen | Der Provider besitzt eine provider-eigene API-Key-Auflösung für env-Marker; amazon-bedrock hat hier ebenfalls einen integrierten AWS-env-Marker-Resolver |
| 8 | resolveSyntheticAuth | lokale/self-hosted oder konfigurationsgestützte Auth sichtbar machen, ohne Klartext zu persistieren | Der Provider kann mit einem synthetischen/lokalen Credential-Marker arbeiten |
| 9 | resolveExternalAuthProfiles | Provider-eigene externe Auth-Profile überlagern; Standard für persistence ist runtime-only für CLI-/App-eigene Zugangsdaten | Der Provider verwendet externe Auth-Zugangsdaten erneut, ohne kopierte Refresh-Tokens zu persistieren; deklarieren Sie contracts.externalAuthProviders im Manifest |
| 10 | shouldDeferSyntheticProfileAuth | gespeicherte synthetische Profil-Platzhalter hinter env-/konfigurationsgestützte Auth zurückstufen | Der Provider speichert synthetische Platzhalterprofile, die nicht die höchste Priorität haben sollen |
| 11 | resolveDynamicModel | synchrones Fallback für provider-eigene Modell-IDs, die noch nicht in der lokalen Registry sind | Der Provider akzeptiert beliebige Upstream-Modell-IDs |
| 12 | prepareDynamicModel | asynchrones Warm-up, danach läuft resolveDynamicModel erneut | Der Provider benötigt Netzwerkmetadaten, bevor unbekannte IDs aufgelöst werden können |
| 13 | normalizeResolvedModel | letzte Umschreibung, bevor der eingebettete Runner das aufgelöste Modell verwendet | Der Provider benötigt Transport-Umschreibungen, verwendet aber weiterhin einen Core-Transport |
| 14 | contributeResolvedModelCompat | Kompatibilitäts-Flags für Vendor-Modelle hinter einem anderen kompatiblen Transport beitragen | Der Provider erkennt seine eigenen Modelle auf Proxy-Transporten, ohne die Kontrolle über den Provider zu übernehmen |
| 15 | capabilities | provider-eigene Transcript-/Tooling-Metadaten, die von gemeinsam genutzter Core-Logik verwendet werden | Der Provider benötigt Besonderheiten für Transcript/Provider-Familie |
| 16 | normalizeToolSchemas | Tool-Schemas normalisieren, bevor der eingebettete Runner sie sieht | Der Provider benötigt Schema-Bereinigung für die Transportfamilie |
| 17 | inspectToolSchemas | provider-eigene Schema-Diagnosen nach der Normalisierung sichtbar machen | Der Provider möchte Keyword-Warnungen ausgeben, ohne dem Core provider-spezifische Regeln beizubringen |
| 18 | resolveReasoningOutputMode | Vertrag für nativen vs. getaggten Reasoning-Output auswählen | Der Provider benötigt getaggten Reasoning-/Final-Output statt nativer Felder |
| 19 | prepareExtraParams | Normalisierung von Request-Parametern vor generischen Stream-Options-Wrappern | Der Provider benötigt Standard-Request-Parameter oder provider-spezifische Parameter-Bereinigung |
| 20 | createStreamFn | den normalen Stream-Pfad vollständig durch einen benutzerdefinierten Transport ersetzen | Der Provider benötigt ein benutzerdefiniertes Wire-Protokoll, nicht nur einen Wrapper |
| 21 | wrapStreamFn | Stream-Wrapper, nachdem generische Wrapper angewendet wurden | Der Provider benötigt Wrapper für Request-Header/Body/Modell-Kompatibilität ohne benutzerdefinierten Transport |
| 22 | resolveTransportTurnState | native Transport-Header oder Metadaten pro Turn anhängen | Der Provider möchte, dass generische Transporte provider-native Turn-Identität senden |
| 23 | resolveWebSocketSessionPolicy | native WebSocket-Header oder Session-Cool-down-Richtlinie anhängen | Der Provider möchte, dass generische WS-Transporte Session-Header oder Fallback-Richtlinien abstimmen |
| 24 | formatApiKey | Formatter für Auth-Profile: gespeichertes Profil wird zum Laufzeit-String apiKey | Der Provider speichert zusätzliche Auth-Metadaten und benötigt eine benutzerdefinierte Laufzeit-Token-Form |
| 25 | refreshOAuth | OAuth-Refresh-Override für benutzerdefinierte Refresh-Endpunkte oder Richtlinie bei Refresh-Fehlern | Der Provider passt nicht zu den gemeinsam genutzten pi-ai-Refreshers |
| 26 | buildAuthDoctorHint | Reparaturhinweis, der angehängt wird, wenn OAuth-Refresh fehlschlägt | Der Provider benötigt provider-eigene Hinweise zur Auth-Reparatur nach einem Refresh-Fehler |
| 27 | matchesContextOverflowError | provider-eigener Matcher für Context-Window-Überläufe | Der Provider hat rohe Overflow-Fehler, die generische Heuristiken übersehen würden |
| 28 | classifyFailoverReason | provider-eigene Klassifizierung des Failover-Grunds | Der Provider kann rohe API-/Transportfehler auf Rate-Limit/Überlastung/usw. abbilden |
| 29 | isCacheTtlEligible | Prompt-Cache-Richtlinie für Proxy-/Backhaul-Provider | Der Provider benötigt proxy-spezifisches Cache-TTL-Gating |
| 30 | buildMissingAuthMessage | Ersatz für die generische Wiederherstellungsnachricht bei fehlender Auth | Der Provider benötigt einen provider-spezifischen Wiederherstellungshinweis bei fehlender Auth |
| 31 | suppressBuiltInModel | Unterdrückung veralteter Upstream-Modelle plus optionaler nutzerseitiger Fehlerhinweis | Der Provider muss veraltete Upstream-Zeilen ausblenden oder durch einen Vendor-Hinweis ersetzen |
| 32 | augmentModelCatalog | synthetische/finale Katalogzeilen, die nach der Erkennung angehängt werden | Der Provider benötigt synthetische Forward-Compat-Zeilen in models list und Auswahlfeldern |
| 33 | resolveThinkingProfile | modellspezifischer /think-Level-Satz, Anzeige-Labels und Standardwert | Der Provider stellt für ausgewählte Modelle eine benutzerdefinierte Thinking-Stufenleiter oder binäre Bezeichnung bereit |
| 34 | isBinaryThinking | Kompatibilitäts-Hook für Reasoning-Umschaltung an/aus | Der Provider bietet nur binäres Thinking an/aus an |
| 35 | supportsXHighThinking | Kompatibilitäts-Hook für xhigh-Reasoning-Unterstützung | Der Provider möchte xhigh nur für eine Teilmenge von Modellen aktivieren |
| 36 | resolveDefaultThinkingLevel | Kompatibilitäts-Hook für den Standardwert von /think | Der Provider besitzt die Standardrichtlinie für /think einer Modellfamilie |
| 37 | isModernModelRef | Matcher für moderne Modelle für Live-Profilfilter und Smoke-Auswahl | Der Provider besitzt das Matching bevorzugter Modelle für Live/Smoke |
| 38 | prepareRuntimeAuth | eine konfigurierte Zugangsinformation unmittelbar vor der Inferenz in das tatsächliche Laufzeit-Token/den Schlüssel umtauschen | Der Provider benötigt einen Token-Austausch oder kurzlebige Anfrage-Zugangsdaten |
| 39 | resolveUsageAuth | Usage-/Billing-Zugangsdaten für /usage und verwandte Statusoberflächen auflösen | Der Provider benötigt benutzerdefiniertes Parsing von Usage-/Quota-Token oder andere Usage-Zugangsdaten |
| 40 | fetchUsageSnapshot | provider-spezifische Usage-/Quota-Snapshots abrufen und normalisieren, nachdem Auth aufgelöst wurde | Der Provider benötigt einen provider-spezifischen Usage-Endpunkt oder Payload-Parser |
| 41 | createEmbeddingProvider | einen provider-eigenen Embedding-Adapter für Memory/Search erstellen | Das Verhalten von Memory-Embeddings gehört zum Provider-Plugin |
| 42 | buildReplayPolicy | eine Replay-Richtlinie zurückgeben, die die Transcript-Verarbeitung für den Provider steuert | Der Provider benötigt eine benutzerdefinierte Transcript-Richtlinie (zum Beispiel das Entfernen von Thinking-Blöcken) |
| 43 | sanitizeReplayHistory | Replay-Verlauf nach der generischen Transcript-Bereinigung umschreiben | Der Provider benötigt provider-spezifische Replay-Umschreibungen über gemeinsam genutzte Compaction-Helper hinaus |
| 44 | validateReplayTurns | endgültige Replay-Turn-Validierung oder Umformung vor dem eingebetteten Runner | Der Provider-Transport benötigt nach der generischen Bereinigung eine strengere Turn-Validierung |
| 45 | onModelSelected | provider-eigene Seiteneffekte nach der Modellauswahl ausführen | Der Provider benötigt Telemetrie oder provider-eigenen Status, wenn ein Modell aktiv wird |
normalizeModelId, normalizeTransport und normalizeConfig prüfen zuerst das
zugeordnete Provider-Plugin und fallen dann auf andere hook-fähige Provider-Plugins
zurück, bis eines die Modell-ID oder den Transport/die Konfiguration tatsächlich ändert. So bleiben
Alias-/Kompatibilitäts-Provider-Shims funktionsfähig, ohne dass der Aufrufer wissen muss, welches
gebündelte Plugin die Umschreibung besitzt. Wenn kein Provider-Hook einen unterstützten
Google-Familien-Konfigurationseintrag umschreibt, wendet der gebündelte Google-Konfigurations-Normalizer
diese Kompatibilitätsbereinigung weiterhin an.
Wenn der Provider ein vollständig benutzerdefiniertes Wire-Protokoll oder einen benutzerdefinierten Request-Executor benötigt,
ist das eine andere Klasse von Erweiterung. Diese Hooks sind für Provider-Verhalten gedacht,
das weiterhin auf der normalen Inferenzschleife von OpenClaw läuft.
Provider-Beispiel
Integrierte Beispiele
Gebündelte Provider-Plugins kombinieren die oben genannten Hooks, um den Katalog, die Auth, das Thinking, das Replay und die Usage-Anforderungen jedes Anbieters abzudecken. Der maßgebliche Hook-Satz lebt bei jedem Plugin unterextensions/; diese Seite veranschaulicht die Formen, statt
die Liste zu spiegeln.
Pass-through-Katalog-Provider
Pass-through-Katalog-Provider
OpenRouter, Kilocode, Z.AI, xAI registrieren
catalog plus
resolveDynamicModel / prepareDynamicModel, damit sie Upstream-
Modell-IDs vor dem statischen Katalog von OpenClaw sichtbar machen können.OAuth- und Usage-Endpunkt-Provider
OAuth- und Usage-Endpunkt-Provider
GitHub Copilot, Gemini CLI, ChatGPT Codex, MiniMax, Xiaomi, z.ai kombinieren
prepareRuntimeAuth oder formatApiKey mit resolveUsageAuth +
fetchUsageSnapshot, um Token-Austausch und /usage-Integration selbst zu steuern.Replay- und Transcript-Bereinigungsfamilien
Replay- und Transcript-Bereinigungsfamilien
Gemeinsam genutzte benannte Familien (
google-gemini, passthrough-gemini,
anthropic-by-model, hybrid-anthropic-openai) erlauben Providern, über
buildReplayPolicy in die Transcript-Richtlinie einzusteigen, statt dass jedes Plugin
die Bereinigung neu implementiert.Nur-Katalog-Provider
Nur-Katalog-Provider
byteplus, cloudflare-ai-gateway, huggingface, kimi-coding, nvidia,
qianfan, synthetic, together, venice, vercel-ai-gateway und
volcengine registrieren nur catalog und nutzen die gemeinsame Inferenzschleife.Anthropic-spezifische Stream-Helper
Anthropic-spezifische Stream-Helper
Beta-Header,
/fast / serviceTier und context1m liegen innerhalb der
öffentlichen api.ts- / contract-api.ts-Schnittstelle des Anthropic-Plugins
(wrapAnthropicProviderStream, resolveAnthropicBetas,
resolveAnthropicFastMode, resolveAnthropicServiceTier) statt im
generischen SDK.Laufzeit-Helper
Plugins können überapi.runtime auf ausgewählte Core-Helper zugreifen. Für TTS:
textToSpeechgibt die normale Core-TTS-Ausgabe-Payload für Datei-/Sprachnotiz-Oberflächen zurück.- Verwendet die Core-Konfiguration
messages.ttsund die Provider-Auswahl. - Gibt einen PCM-Audiopuffer + Sample-Rate zurück. Plugins müssen für Provider neu sampeln/kodieren.
listVoicesist je nach Provider optional. Verwenden Sie es für provider-eigene Voice-Picker oder Setup-Flows.- Voice-Listen können umfangreichere Metadaten wie Gebietsschema, Geschlecht und Personality-Tags für providerbewusste Picker enthalten.
- OpenAI und ElevenLabs unterstützen heute Telephony. Microsoft nicht.
api.registerSpeechProvider(...) registrieren.
- Behalten Sie TTS-Richtlinie, Fallback und Antwortzustellung im Core.
- Verwenden Sie Speech-Provider für anbieterbezogenes Syntheseverhalten.
- Legacy-Microsoft-
edge-Eingaben werden auf die Provider-IDmicrosoftnormalisiert. - Das bevorzugte Ownership-Modell ist unternehmensorientiert: Ein Vendor-Plugin kann Text-, Speech-, Bild- und künftige Medien-Provider besitzen, während OpenClaw diese Fähigkeitsverträge erweitert.
- Behalten Sie Orchestrierung, Fallback, Konfiguration und Channel-Verdrahtung im Core.
- Behalten Sie anbieterbezogenes Verhalten im Provider-Plugin.
- Additive Erweiterung sollte typisiert bleiben: neue optionale Methoden, neue optionale Ergebnisfelder, neue optionale Fähigkeiten.
- Die Videogenerierung folgt bereits demselben Muster:
- der Core besitzt den Fähigkeitsvertrag und den Laufzeit-Helper
- Vendor-Plugins registrieren
api.registerVideoGenerationProvider(...) - Feature-/Channel-Plugins nutzen
api.runtime.videoGeneration.*
api.runtime.mediaUnderstanding.*ist die bevorzugte gemeinsame Oberfläche für Bild-/Audio-/Videoverständnis.- Verwendet die Audio-Konfiguration des Core für Media-Understanding (
tools.media.audio) und die Fallback-Reihenfolge der Provider. - Gibt
{ text: undefined }zurück, wenn keine Transkriptionsausgabe erzeugt wird (zum Beispiel bei übersprungenen/nicht unterstützten Eingaben). api.runtime.stt.transcribeAudioFile(...)bleibt als Kompatibilitätsalias bestehen.
api.runtime.subagent starten:
providerundmodelsind optionale Overrides pro Lauf, keine persistenten Session-Änderungen.- OpenClaw berücksichtigt diese Override-Felder nur für vertrauenswürdige Aufrufer.
- Für Plugin-eigene Fallback-Läufe müssen Operatoren mit
plugins.entries.<id>.subagent.allowModelOverride: trueexplizit zustimmen. - Verwenden Sie
plugins.entries.<id>.subagent.allowedModels, um vertrauenswürdige Plugins auf bestimmte kanonische Zieleprovider/modelzu beschränken, oder"*", um jedes Ziel explizit zuzulassen. - Nicht vertrauenswürdige Plugin-Subagent-Läufe funktionieren weiterhin, aber Override-Anfragen werden abgelehnt, statt stillschweigend auf Fallback umzuschalten.
api.registerWebSearchProvider(...) registrieren.
Hinweise:
- Behalten Sie Provider-Auswahl, Auflösung der Zugangsdaten und gemeinsame Request-Semantik im Core.
- Verwenden Sie Websuche-Provider für anbieterspezifische Suchtransporte.
api.runtime.webSearch.*ist die bevorzugte gemeinsame Oberfläche für Feature-/Channel-Plugins, die Suchverhalten benötigen, ohne vom Agent-Tool-Wrapper abzuhängen.
api.runtime.imageGeneration
generate(...): Ein Bild mit der konfigurierten Provider-Kette für Bildgenerierung erzeugen.listProviders(...): Verfügbare Provider für Bildgenerierung und deren Fähigkeiten auflisten.
Gateway-HTTP-Routen
Plugins können HTTP-Endpunkte mitapi.registerHttpRoute(...) verfügbar machen.
path: Routenpfad unter dem Gateway-HTTP-Server.auth: erforderlich. Verwenden Sie"gateway", um normale Gateway-Auth zu verlangen, oder"plugin"für Plugin-verwaltete Auth/Webhook-Verifizierung.match: optional."exact"(Standard) oder"prefix".replaceExisting: optional. Erlaubt demselben Plugin, seine eigene vorhandene Routenregistrierung zu ersetzen.handler: gibttruezurück, wenn die Route die Anfrage verarbeitet hat.
api.registerHttpHandler(...)wurde entfernt und verursacht einen Plugin-Ladefehler. Verwenden Sie stattdessenapi.registerHttpRoute(...).- Plugin-Routen müssen
authexplizit deklarieren. - Exakte Konflikte bei
path + matchwerden abgelehnt, sofern nichtreplaceExisting: truegesetzt ist, und ein Plugin kann keine Route eines anderen Plugins ersetzen. - Überlappende Routen mit unterschiedlichen
auth-Stufen werden abgelehnt. Halten Sieexact-/prefix-Fallthrough-Ketten nur auf derselben Auth-Stufe. - Routen mit
auth: "plugin"erhalten nicht automatisch Runtime-Scopes für Operatoren. Sie sind für Plugin-verwaltete Webhooks/Signaturverifizierung gedacht, nicht für privilegierte Gateway-Helper-Aufrufe. - Routen mit
auth: "gateway"laufen innerhalb eines Gateway-Request-Runtime-Scopes, aber dieser Scope ist absichtlich konservativ:- Shared-Secret-Bearer-Auth (
gateway.auth.mode = "token"/"password") hält Runtime-Scopes für Plugin-Routen aufoperator.writefest, selbst wenn der Aufruferx-openclaw-scopessendet - vertrauenswürdige HTTP-Modi mit Identitätsträgern (zum Beispiel
trusted-proxyodergateway.auth.mode = "none"bei privatem Ingress) berücksichtigenx-openclaw-scopesnur, wenn der Header explizit vorhanden ist - wenn
x-openclaw-scopesbei solchen Plugin-Routenanfragen mit Identitätsträgern fehlt, fällt der Runtime-Scope aufoperator.writezurück
- Shared-Secret-Bearer-Auth (
- Praktische Regel: Gehen Sie nicht davon aus, dass eine per Gateway-auth geschützte Plugin-Route implizit eine Admin-Oberfläche ist. Wenn Ihre Route reines Admin-Verhalten benötigt, verlangen Sie einen HTTP-Modus mit Identitätsträgern und dokumentieren Sie den expliziten Header-Vertrag für
x-openclaw-scopes.
Plugin-SDK-Importpfade
Verwenden Sie schmale SDK-Unterpfade statt des monolithischen Root- Barrelsopenclaw/plugin-sdk, wenn Sie neue Plugins erstellen. Zentrale Unterpfade:
| Unterpfad | Zweck |
|---|---|
openclaw/plugin-sdk/plugin-entry | Primitive für die Plugin-Registrierung |
openclaw/plugin-sdk/channel-core | Helper für Channel-Entry/Build |
openclaw/plugin-sdk/core | Generische gemeinsame Helper und Umbrella-Vertrag |
openclaw/plugin-sdk/config-schema | Zod-Schema für Root-openclaw.json (OpenClawSchema) |
channel-setup,
setup-runtime, setup-adapter-runtime, setup-tools, channel-pairing,
channel-contract, channel-feedback, channel-inbound, channel-lifecycle,
channel-reply-pipeline, command-auth, secret-input, webhook-ingress,
channel-targets und channel-actions. Genehmigungsverhalten sollte auf einem
einzigen Vertrag approvalCapability konsolidiert werden, statt es über nicht zusammenhängende
Plugin-Felder zu vermischen. Siehe Channel plugins.
Laufzeit- und Konfigurations-Helper liegen unter passenden Unterpfaden mit *-runtime
(approval-runtime, config-runtime, infra-runtime, agent-runtime,
lazy-runtime, directory-runtime, text-runtime, runtime-store usw.).
openclaw/plugin-sdk/channel-runtime ist veraltet — ein Kompatibilitäts-Shim für
ältere Plugins. Neuer Code sollte stattdessen schmalere generische Primitive importieren.index.js— Einstiegspunkt für gebündelte Pluginsapi.js— Barrel für Helper/Typenruntime-api.js— reines Laufzeit-Barrelsetup-entry.js— Einstiegspunkt für Setup-Plugins
openclaw/plugin-sdk/*-Unterpfade importieren. Importieren Sie niemals
src/* eines anderen Plugin-Pakets aus dem Core oder aus einem anderen Plugin.
Über Fassade geladene Einstiegspunkte bevorzugen den aktiven Laufzeit-Konfigurations-Snapshot, wenn einer
vorhanden ist, und fallen sonst auf die auf der Festplatte aufgelöste Konfigurationsdatei zurück.
Fähigkeitsspezifische Unterpfade wie image-generation, media-understanding
und speech existieren, weil gebündelte Plugins sie heute verwenden. Sie sind nicht
automatisch langfristig eingefrorene externe Verträge — prüfen Sie die relevante SDK-
Referenzseite, wenn Sie sich darauf verlassen.
Message-Tool-Schemas
Plugins sollten channel-spezifische Schema-Beiträge fürdescribeMessageTool(...)
für Nicht-Nachrichten-Primitive wie Reaktionen, Lesebestätigungen und Umfragen besitzen.
Die gemeinsame Send-Darstellung sollte den generischen Vertrag MessagePresentation
anstelle von provider-nativen Feldern für Buttons, Components, Blocks oder Cards verwenden.
Siehe Message Presentation für den Vertrag,
Fallback-Regeln, Provider-Zuordnung und die Checkliste für Plugin-Autoren.
Plugins mit Sendefähigkeit deklarieren über Message-Fähigkeiten, was sie rendern können:
presentationfür semantische Darstellungsblöcke (text,context,divider,buttons,select)delivery-pinfür Anfragen zur angehefteten Zustellung
Auflösung von Channel-Zielen
Channel-Plugins sollten channel-spezifische Zielsemantik besitzen. Halten Sie den gemeinsamen Outbound-Host generisch und verwenden Sie die Oberfläche des Messaging-Adapters für Provider-Regeln:messaging.inferTargetChatType({ to })entscheidet, ob ein normalisiertes Ziel vor der Directory-Suche alsdirect,groupoderchannelbehandelt werden soll.messaging.targetResolver.looksLikeId(raw, normalized)teilt dem Core mit, ob eine Eingabe direkt zur id-artigen Auflösung springen soll statt zur Directory-Suche.messaging.targetResolver.resolveTarget(...)ist der Plugin-Fallback, wenn der Core nach der Normalisierung oder nach einem Directory-Fehlschlag eine abschließende provider-eigene Auflösung benötigt.messaging.resolveOutboundSessionRoute(...)besitzt den Aufbau der provider-spezifischen Session- Route, sobald ein Ziel aufgelöst wurde.
- Verwenden Sie
inferTargetChatTypefür Kategorieentscheidungen, die vor der Suche nach Peers/Gruppen erfolgen sollten. - Verwenden Sie
looksLikeIdfür Prüfungen im Stil „als explizite/native Ziel-ID behandeln“. - Verwenden Sie
resolveTargetals provider-spezifischen Normalisierungs-Fallback, nicht für breit angelegte Directory-Suche. - Behalten Sie provider-native IDs wie Chat-IDs, Thread-IDs, JIDs, Handles und Raum-
IDs in
target-Werten oder provider-spezifischen Parametern, nicht in generischen SDK- Feldern.
Konfigurationsgestützte Directories
Plugins, die Directory-Einträge aus der Konfiguration ableiten, sollten diese Logik im Plugin behalten und die gemeinsamen Helper ausopenclaw/plugin-sdk/directory-runtime wiederverwenden.
Verwenden Sie dies, wenn ein Channel konfigurationsgestützte Peers/Gruppen benötigt wie:
- durch Allowlist gesteuerte DM-Peers
- konfigurierte Channel-/Gruppenzuordnungen
- kontobezogene statische Directory-Fallbacks
directory-runtime behandeln nur generische Operationen:
- Query-Filterung
- Anwendung von Limits
- Deduping-/Normalisierungs-Helper
- Aufbau von
ChannelDirectoryEntry[]
Provider-Kataloge
Provider-Plugins können Modellkataloge für Inferenz definieren mitregisterProvider({ catalog: { run(...) { ... } } }).
catalog.run(...) gibt dieselbe Form zurück, die OpenClaw in
models.providers schreibt:
{ provider }für einen Provider-Eintrag{ providers }für mehrere Provider-Einträge
catalog, wenn das Plugin provider-spezifische Modell-IDs, Standardwerte für base URL
oder auth-gesteuerte Modellmetadaten besitzt.
catalog.order steuert, wann der Katalog eines Plugins relativ zu den
integrierten impliziten Providern von OpenClaw zusammengeführt wird:
simple: einfache API-Key- oder env-gesteuerte Providerprofile: Provider, die erscheinen, wenn Auth-Profile existierenpaired: Provider, die mehrere zusammengehörige Provider-Einträge synthetisierenlate: letzter Durchlauf, nach anderen impliziten Providern
discoveryfunktioniert weiterhin als Legacy-Alias- wenn sowohl
catalogals auchdiscoveryregistriert sind, verwendet OpenClawcatalog
Schreibgeschützte Channel-Inspektion
Wenn Ihr Plugin einen Channel registriert, implementieren Sie bevorzugtplugin.config.inspectAccount(cfg, accountId) zusammen mit resolveAccount(...).
Warum:
resolveAccount(...)ist der Laufzeitpfad. Er darf annehmen, dass Zugangsdaten vollständig materialisiert sind, und kann schnell fehlschlagen, wenn erforderliche Secrets fehlen.- Schreibgeschützte Befehlswege wie
openclaw status,openclaw status --all,openclaw channels status,openclaw channels resolveund Doctor-/Config- Repair-Flows sollten Laufzeit-Zugangsdaten nicht materialisieren müssen, nur um die Konfiguration zu beschreiben.
inspectAccount(...):
- Geben Sie nur beschreibenden Kontostatus zurück.
- Behalten Sie
enabledundconfiguredbei. - Schließen Sie relevante Felder für Quelle/Status von Zugangsdaten ein, zum Beispiel:
tokenSource,tokenStatusbotTokenSource,botTokenStatusappTokenSource,appTokenStatussigningSecretSource,signingSecretStatus
- Sie müssen keine rohen Token-Werte zurückgeben, nur um schreibgeschützte
Verfügbarkeit zu melden. Die Rückgabe von
tokenStatus: "available"(und dem passenden Quellfeld) reicht für Befehle im Stil von Status aus. - Verwenden Sie
configured_unavailable, wenn Zugangsdaten über SecretRef konfiguriert, aber im aktuellen Befehlsweg nicht verfügbar sind.
Paket-Packs
Ein Plugin-Verzeichnis kann einepackage.json mit openclaw.extensions enthalten:
name/<fileBase>.
Wenn Ihr Plugin npm-Abhängigkeiten importiert, installieren Sie sie in diesem Verzeichnis, damit
node_modules verfügbar ist (npm install / pnpm install).
Sicherheitsleitplanke: Jeder Eintrag in openclaw.extensions muss nach der Symlink-Auflösung innerhalb des Plugin-
Verzeichnisses bleiben. Einträge, die aus dem Paketverzeichnis ausbrechen, werden
abgelehnt.
Sicherheitshinweis: openclaw plugins install installiert Plugin-Abhängigkeiten mit
npm install --omit=dev --ignore-scripts (keine Lifecycle-Skripte, keine Entwicklungsabhängigkeiten zur Laufzeit). Halten Sie die Plugin-Abhängigkeits-
Bäume „reines JS/TS“ und vermeiden Sie Pakete, die postinstall-Builds erfordern.
Optional: openclaw.setupEntry kann auf ein leichtgewichtiges Modul nur für Setup zeigen.
Wenn OpenClaw Setup-Oberflächen für ein deaktiviertes Channel-Plugin benötigt oder
wenn ein Channel-Plugin aktiviert, aber noch nicht konfiguriert ist, lädt es setupEntry
anstelle des vollständigen Plugin-Einstiegspunkts. Dadurch bleiben Start und Setup leichter,
wenn Ihr Haupteinstiegspunkt auch Tools, Hooks oder anderen nur zur Laufzeit benötigten
Code verdrahtet.
Optional: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
kann ein Channel-Plugin für denselben setupEntry-Pfad während der
Pre-Listen-Startphase des Gateway aktivieren, selbst wenn der Channel bereits konfiguriert ist.
Verwenden Sie dies nur, wenn setupEntry die Startoberfläche vollständig abdeckt, die
vor dem Beginn des Listen des Gateway existieren muss. In der Praxis bedeutet das, dass der Setup-Einstiegspunkt
jede channel-eigene Fähigkeit registrieren muss, von der der Start abhängt, zum Beispiel:
- die Channel-Registrierung selbst
- alle HTTP-Routen, die verfügbar sein müssen, bevor das Gateway beginnt zuzuhören
- alle Gateway-Methoden, Tools oder Dienste, die in diesem selben Zeitraum vorhanden sein müssen
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
channels.<id>.accounts.* promoten muss, ohne den vollständigen Plugin-Einstiegspunkt zu laden.
Matrix ist das aktuelle gebündelte Beispiel: Es verschiebt nur Auth-/Bootstrap-Schlüssel in ein
benanntes promotetes Konto, wenn bereits benannte Konten existieren, und es kann einen
konfigurierten nicht-kanonischen Standard-Kontoschlüssel bewahren, statt immer
accounts.default zu erstellen.
Diese Setup-Patch-Adapter halten die Erkennung der gebündelten Vertragsoberfläche lazy. Die Importzeit
bleibt gering; die Promotionsoberfläche wird erst bei der ersten Verwendung geladen, statt den
Start des gebündelten Channels beim Modulimport erneut zu betreten.
Wenn diese Startoberflächen Gateway-RPC-Methoden enthalten, behalten Sie sie auf 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 schmaleren Scope anfordert.
Beispiel:
Channel-Katalogmetadaten
Channel-Plugins können Setup-/Erkennungsmetadaten überopenclaw.channel und
Installationshinweise über openclaw.install bereitstellen. Dadurch bleiben die Core-Katalogdaten frei von Daten.
Beispiel:
openclaw.channel-Felder über das Minimalbeispiel hinaus:
detailLabel: sekundäres Label für umfangreichere Katalog-/StatusoberflächendocsLabel: überschreibt den Linktext für den Docs-LinkpreferOver: Plugin-/Channel-IDs mit geringerer Priorität, die dieser Katalogeintrag übertreffen sollselectionDocsPrefix,selectionDocsOmitLabel,selectionExtras: Textsteuerungen für die AuswahloberflächemarkdownCapable: markiert den Channel als Markdown-fähig für Entscheidungen zur ausgehenden Formatierungexposure.configured: blendet den Channel aus Oberflächen zur Auflistung konfigurierter Channels aus, wenn auffalsegesetztexposure.setup: blendet den Channel aus interaktiven Setup-/Configure-Auswahlfeldern aus, wenn auffalsegesetztexposure.docs: markiert den Channel für Docs-Navigationsoberflächen als intern/privatshowConfigured/showInSetup: Legacy-Aliasse werden aus Kompatibilitätsgründen weiterhin akzeptiert; bevorzugen SieexposurequickstartAllowFrom: aktiviert für den Channel den standardmäßigen Quickstart-FlowallowFromforceAccountBinding: verlangt explizites Account-Binding, auch wenn nur ein Konto existiertpreferSessionLookupForAnnounceTarget: bevorzugt Session-Lookup beim Auflösen von Ankündigungszielen
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
OPENCLAW_PLUGIN_CATALOG_PATHS (oder OPENCLAW_MPM_CATALOG_PATHS) auf
eine oder mehrere JSON-Dateien (durch Komma/Semikolon/PATH getrennt). Jede Datei sollte
{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] } enthalten. Der Parser akzeptiert auch "packages" oder "plugins" als Legacy-Aliasse für den Schlüssel "entries".
Generierte Channel-Katalogeinträge und Provider-Installationskatalogeinträge legen
normalisierte Fakten zur Installationsquelle neben den rohen openclaw.install-Block. Die
normalisierten Fakten identifizieren, ob die npm-Spezifikation eine exakte Version oder ein schwebender
Selektor ist, ob erwartete Integritätsmetadaten vorhanden sind und ob auch ein lokaler
Quellpfad verfügbar ist. Verbraucher sollten installSource als additives optionales Feld behandeln, damit
ältere handgebaute Einträge und Kompatibilitäts-Shims es nicht synthetisieren
müssen. Dadurch können Onboarding und Diagnose
den Zustand der Quellseite erklären, ohne die Plugin-Laufzeit zu importieren.
Offizielle externe npm-Einträge sollten eine exakte npmSpec plus
expectedIntegrity bevorzugen. Reine Paketnamen und Dist-Tags funktionieren aus
Kompatibilitätsgründen weiterhin, erzeugen aber Warnungen auf der Quellseite, damit sich der Katalog
in Richtung gepinnter, integritätsgeprüfter Installationen bewegen kann, ohne bestehende Plugins zu beschädigen.
Wenn das Onboarding aus einem lokalen Katalogpfad installiert, zeichnet es einen
Eintrag in plugins.installs mit source: "path" und einem workspace-relativen
sourcePath auf, wenn möglich. Der absolute operative Ladepfad bleibt in
plugins.load.paths; der Installationsdatensatz vermeidet es, lokale Workstation-
Pfade in langlebige Konfiguration zu duplizieren. Dadurch bleiben lokale Entwicklungsinstallationen für
Diagnosen auf der Quellseite sichtbar, ohne eine zweite rohe Offenlegungsoberfläche
für Dateisystempfade hinzuzufügen.
Context-Engine-Plugins
Context-Engine-Plugins besitzen die Orchestrierung des Session-Kontexts für Ingest, Zusammenstellung und Compaction. Registrieren Sie sie aus Ihrem Plugin mitapi.registerContextEngine(id, factory) und wählen Sie dann die aktive Engine mit
plugins.slots.contextEngine.
Verwenden Sie dies, wenn Ihr Plugin die Standard-
Context-Pipeline ersetzen oder erweitern muss, statt nur Memory-Suche oder Hooks hinzuzufügen.
compact()
implementiert und delegieren Sie ihn explizit:
Hinzufügen einer neuen Fähigkeit
Wenn ein Plugin Verhalten benötigt, das nicht zur aktuellen API passt, umgehen Sie das Plugin-System nicht mit einem privaten Direkteingriff. Fügen Sie die fehlende Fähigkeit hinzu. Empfohlene Reihenfolge:- den Core-Vertrag definieren Entscheiden Sie, welches gemeinsame Verhalten der Core besitzen soll: Richtlinie, Fallback, Konfigurationszusammenführung, Lifecycle, channelseitige Semantik und Form des Laufzeit-Helpers.
- typisierte Plugin-Registrierungs-/Laufzeitoberflächen hinzufügen
Erweitern Sie
OpenClawPluginApiund/oderapi.runtimeum die kleinste nützliche typisierte Fähigkeitsoberfläche. - Core + Verbraucher in Channels/Features verdrahten Channels und Feature-Plugins sollten die neue Fähigkeit über den Core nutzen, nicht indem sie direkt eine Vendor-Implementierung importieren.
- Vendor-Implementierungen registrieren Vendor-Plugins registrieren dann ihre Backends für die Fähigkeit.
- Vertragsabdeckung hinzufügen Fügen Sie Tests hinzu, damit Eigentümerschaft und Registrierungsform im Lauf der Zeit explizit bleiben.
Checkliste für Fähigkeiten
Wenn Sie eine neue Fähigkeit hinzufügen, sollte die Implementierung diese Oberflächen normalerweise gemeinsam berühren:- Core-Vertragstypen in
src/<capability>/types.ts - Core-Runner/Laufzeit-Helper in
src/<capability>/runtime.ts - Plugin-API-Registrierungsoberfläche in
src/plugins/types.ts - Plugin-Registry-Verdrahtung in
src/plugins/registry.ts - Plugin-Laufzeit-Exponierung in
src/plugins/runtime/*, wenn Feature-/Channel- Plugins sie nutzen müssen - Capture-/Test-Helper in
src/test-utils/plugin-registration.ts - Assertions für Eigentümerschaft/Vertrag in
src/plugins/contracts/registry.ts - Operator-/Plugin-Dokumentation in
docs/
Vorlage für Fähigkeiten
Minimales Muster:- der Core besitzt den Fähigkeitsvertrag + die Orchestrierung
- Vendor-Plugins besitzen Vendor-Implementierungen
- Feature-/Channel-Plugins nutzen Laufzeit-Helper
- Vertragstests halten Eigentümerschaft explizit
Verwandt
- Plugin architecture — öffentliches Fähigkeitsmodell und Formen
- Plugin SDK subpaths
- Plugin SDK setup
- Building plugins