Pipeline di caricamento
All’avvio, OpenClaw esegue approssimativamente queste operazioni:- individua le radici dei plugin candidati
- legge i manifest dei bundle nativi o compatibili e i metadati dei pacchetti
- rifiuta i candidati non sicuri
- normalizza la configurazione dei plugin (
plugins.enabled,allow,deny,entries,slots,load.paths) - determina l’abilitazione di ciascun candidato
- carica i moduli nativi abilitati: i moduli inclusi compilati usano un caricatore nativo; il codice sorgente TypeScript locale di terze parti usa Jiti come soluzione di emergenza
- chiama gli hook nativi
register(api)e raccoglie le registrazioni nel registro dei plugin - espone il registro ai comandi e alle superfici di runtime
activate è un alias legacy di register: il caricatore risolve quello presente (def.register ?? def.activate) e lo chiama nello stesso punto. Tutti i plugin inclusi usano register; preferisci register per i nuovi plugin.- il relativo punto di ingresso risolto esce dalla radice del plugin
- il relativo percorso (o la directory radice) è scrivibile da tutti
- per i plugin non inclusi, il proprietario del percorso non corrisponde all’uid corrente (o a root)
chmod sul posto (le installazioni npm/globali possono distribuire directory dei pacchetti con permessi 0777), quindi il controllo viene rieseguito; i controlli di proprietà vengono completamente ignorati per l’origine inclusa.
I candidati bloccati mantengono comunque l’id del plugin nella diagnostica emessa quando è noto (inclusi gli id risolti da un manifest all’interno di una directory altrimenti rifiutata), quindi una configurazione che fa riferimento a tale id vede un plugin bloccato associato a un avviso sulla sicurezza del percorso, anziché un errore non correlato di “plugin sconosciuto”.
Comportamento basato anzitutto sul manifest
Il manifest è la fonte autorevole del piano di controllo. OpenClaw lo usa per:- identificare il plugin
- individuare canali/Skills/schema di configurazione o funzionalità del bundle dichiarati
- convalidare
plugins.entries.<id>.config - arricchire etichette e segnaposto dell’interfaccia di controllo
- mostrare i metadati di installazione/catalogo
- conservare descrittori di attivazione e configurazione economici senza caricare il runtime del plugin
activation e setup del manifest rimangono sul piano di controllo. Sono descrittori costituiti esclusivamente da metadati per la pianificazione dell’attivazione e il rilevamento della configurazione; non sostituiscono la registrazione di runtime, register(...) o setupEntry. I consumer dell’attivazione in tempo reale usano i suggerimenti del manifest relativi a comandi, canali e provider per restringere il caricamento dei plugin prima della materializzazione più ampia del registro:
- il caricamento della CLI viene ristretto ai plugin proprietari del comando primario richiesto
- la configurazione del canale/risoluzione del plugin viene ristretta ai plugin proprietari dell’id del canale richiesto
- la configurazione/risoluzione di runtime esplicita del provider viene ristretta ai plugin proprietari dell’id del provider richiesto
- la pianificazione dell’avvio del Gateway usa
activation.onStartupper le importazioni esplicite all’avvio; i plugin senza metadati di avvio vengono caricati solo tramite trigger di attivazione più specifici
activation.* dal ripiego sulla proprietà del manifest:
Questa separazione dei motivi costituisce il confine di compatibilità: i metadati esistenti dei plugin continuano a funzionare, mentre il nuovo codice può rilevare suggerimenti generici o comportamenti di ripiego senza modificare la semantica di caricamento del runtime.
I precaricamenti del runtime eseguiti al momento della richiesta che richiedono l’ambito generale
all derivano comunque un insieme esplicito di id plugin effettivi dalla configurazione, dalla pianificazione dell’avvio, dai canali configurati, dagli slot e dalle regole di abilitazione automatica (resolveEffectivePluginIds in src/plugins/effective-plugin-ids.ts). Se l’insieme derivato è vuoto, OpenClaw mantiene vuoto l’ambito anziché ampliarlo a ogni plugin individuabile.
Il rilevamento della configurazione preferisce id di proprietà dei descrittori, come setup.providers e setup.cliBackends, per restringere i plugin candidati prima di ricorrere a setup-api per i plugin che richiedono ancora hook di runtime durante la configurazione. Gli elenchi di configurazione dei provider usano providerAuthChoices del manifest, le opzioni di configurazione derivate dai descrittori e i metadati del catalogo di installazione senza caricare il runtime del provider. Un valore esplicito setup.requiresRuntime: false interrompe il processo limitandolo ai descrittori; se requiresRuntime viene omesso, viene mantenuto il ripiego legacy su setup-api per compatibilità. Se più plugin rilevati rivendicano lo stesso id normalizzato di provider di configurazione o backend CLI, la ricerca della configurazione rifiuta il proprietario ambiguo anziché affidarsi all’ordine di rilevamento. Quando il runtime di configurazione viene effettivamente eseguito, la diagnostica del registro segnala le divergenze tra setup.providers / setup.cliBackends e i provider o backend CLI effettivamente registrati da setup-api, senza bloccare i plugin legacy.
Confine della cache dei plugin
OpenClaw non memorizza nella cache i risultati del rilevamento dei plugin o i dati diretti del registro dei manifest dietro finestre temporali. Le installazioni, le modifiche ai manifest e le variazioni dei percorsi di caricamento devono diventare visibili alla successiva lettura esplicita dei metadati o ricostruzione dell’istantanea. Il parser dei file manifest mantiene una cache limitata delle firme dei file, indicizzata tramite il percorso del manifest aperto insieme a dispositivo/inode, dimensione e mtime/ctime; tale cache evita soltanto di analizzare nuovamente byte invariati e non deve memorizzare nella cache risposte relative a rilevamento, registro, proprietario o criteri. Il percorso rapido sicuro per i metadati è la proprietà esplicita degli oggetti, non una cache nascosta. I percorsi critici di avvio del Gateway devono passare lungo la catena di chiamate ilPluginMetadataSnapshot corrente, la PluginLookUpTable derivata o un registro esplicito dei manifest. La convalida della configurazione, l’abilitazione automatica all’avvio, il bootstrap dei plugin e la selezione dei provider possono riutilizzare tali oggetti finché rappresentano la configurazione e l’inventario dei plugin correnti. La ricerca della configurazione ricostruisce comunque i metadati del manifest su richiesta, a meno che lo specifico percorso di configurazione non riceva un registro esplicito dei manifest; mantieni questo comportamento come ripiego per i percorsi non critici anziché aggiungere cache di ricerca nascoste. Quando l’input cambia, ricostruisci e sostituisci l’istantanea anziché modificarla o conservarne copie storiche. Le viste sul registro dei plugin attivi e gli helper di bootstrap dei canali inclusi devono essere ricalcolati dal registro/dalla radice correnti. Le mappe di breve durata sono accettabili all’interno di una singola chiamata per deduplicare il lavoro o impedire il rientro; non devono trasformarsi in cache dei metadati di processo.
Per il caricamento dei plugin, il livello di cache persistente è il caricamento del runtime. Può riutilizzare lo stato del caricatore quando il codice o gli artefatti installati vengono effettivamente caricati, ad esempio:
PluginLoaderCacheStatee registri di runtime attivi compatibili- cache jiti/dei moduli e cache dei caricatori delle superfici pubbliche usate per evitare di importare ripetutamente la stessa superficie di runtime
- cache del file system per gli artefatti dei plugin installati
- mappe di breve durata per chiamata destinate alla normalizzazione dei percorsi o alla risoluzione dei duplicati
- risultati del rilevamento
- registri diretti dei manifest
- registri dei manifest ricostruiti dall’indice dei plugin installati
- ricerca del proprietario del provider, soppressione dei modelli, criteri dei provider o metadati degli artefatti pubblici
- qualsiasi altra risposta derivata dal manifest per la quale una modifica al manifest, all’indice installato o al percorso di caricamento debba essere visibile alla successiva lettura dei metadati
Modello del registro
I plugin caricati non modificano direttamente variabili globali arbitrarie del core. Si registrano in un registro centrale dei plugin (PluginRegistry in src/plugins/registry-types.ts), che tiene traccia dei record dei plugin (identità, sorgente, origine, stato, diagnostica) e degli array per ogni funzionalità: strumenti, hook legacy e hook tipizzati, canali, provider, gestori RPC del Gateway, route HTTP, registratori CLI, servizi in background, comandi di proprietà dei plugin e decine di altre famiglie tipizzate di provider (sintesi vocale, incorporamenti, generazione di immagini/video/musica, recupero/ricerca sul web, infrastrutture degli agenti, azioni di sessione e così via).
Le funzionalità del core leggono quindi da tale registro anziché comunicare direttamente con i moduli dei plugin. Ciò mantiene il caricamento unidirezionale:
- modulo del plugin -> registrazione nel registro
- runtime del core -> utilizzo del registro
Callback di associazione delle conversazioni
I plugin che associano una conversazione possono reagire quando viene risolta un’approvazione. Usaapi.onConversationBindingResolved(...) per ricevere un callback dopo l’approvazione o il rifiuto di una richiesta di associazione:
status:"approved"o"denied"decision:"allow-once","allow-always"o"deny"binding: l’associazione risolta per le richieste approvaterequest: il riepilogo della richiesta originale, il suggerimento di scollegamento, l’id del mittente e i metadati della conversazione
Hook di runtime dei provider
I plugin dei provider presentano tre livelli:- Metadati del manifest per ricerche economiche prima del runtime:
setup.providers[].envVars, la compatibilità deprecataproviderAuthEnvVars,providerAuthAliases,providerAuthChoicesechannelEnvVars. - Hook in fase di configurazione:
catalog(discoverylegacy) insieme adapplyConfigDefaults. - Hook di runtime: oltre 40 hook facoltativi relativi ad autenticazione, risoluzione dei modelli, wrapping dei flussi, livelli di ragionamento, criteri di riproduzione ed endpoint di utilizzo. Consulta Ordine e utilizzo degli hook.
setup.providers[].envVars quando il provider dispone di
credenziali basate su variabili d’ambiente che i percorsi generici di
autenticazione/stato/selezione del modello devono poter rilevare senza caricare
il runtime del plugin. Il deprecato providerAuthEnvVars viene ancora letto
dall’adattatore di compatibilità durante il periodo di deprecazione e i plugin
non inclusi nel bundle che lo usano ricevono una diagnostica del manifest. Usa
il manifest providerAuthAliases quando un ID provider deve riutilizzare le
variabili d’ambiente, i profili di autenticazione, l’autenticazione basata sulla
configurazione e la scelta di onboarding per la chiave API di un altro ID
provider. Usa il manifest providerAuthChoices quando le interfacce CLI per
l’onboarding e la scelta dell’autenticazione devono conoscere l’ID della scelta
del provider, le etichette dei gruppi e il semplice collegamento
dell’autenticazione tramite un singolo flag, senza caricare il runtime del
provider. Mantieni le envVars del runtime del provider per i suggerimenti
destinati agli operatori, come le etichette di onboarding o le variabili di
configurazione dell’ID client e del segreto client OAuth.
Usa il manifest channelEnvVars quando un canale dispone di autenticazione o
configurazione basata su variabili d’ambiente che il fallback generico
dell’ambiente della shell, i controlli di configurazione/stato o le richieste di
configurazione devono poter rilevare senza caricare il runtime del canale.
Ordine e utilizzo degli hook
Per i plugin di modelli/provider, OpenClaw chiama gli hook approssimativamente in quest’ordine. La colonna “Quando usarlo” è una guida rapida per la decisione. I campi del provider destinati esclusivamente alla compatibilità che OpenClaw non chiama più, comeProviderPlugin.capabilities e suppressBuiltInModel,
sono intenzionalmente esclusi da questo elenco.
normalizeModelId, normalizeTransport e normalizeConfig verificano prima il
Plugin del provider corrispondente, quindi proseguono con gli altri Plugin del
provider dotati di hook finché uno non modifica effettivamente l’ID del modello
o il trasporto/la configurazione. In questo modo gli shim di
alias/compatibilità dei provider continuano a funzionare senza che il chiamante
debba sapere quale Plugin incluso gestisce la riscrittura. Se nessun hook del
provider riscrive una voce di configurazione supportata della famiglia Google,
il normalizzatore incluso della configurazione Google applica comunque la
relativa pulizia di compatibilità.
Se il provider richiede un protocollo sul filo completamente personalizzato o
un esecutore di richieste personalizzato, si tratta di una classe di estensione
diversa. Questi hook sono destinati al comportamento dei provider che continua
a essere eseguito nel normale ciclo di inferenza di OpenClaw.
resolveUsageAuth decide se OpenClaw deve chiamare fetchUsageSnapshot o
ricorrere alla risoluzione generica delle credenziali per le superfici di
utilizzo/stato. Restituisce
{ token, accountId?, subscriptionType?, rateLimitTier? } quando il provider
dispone di una credenziale per l’utilizzo (i metadati facoltativi del piano
vengono passati a fetchUsageSnapshot), restituisce
{ handled: true } quando l’autenticazione per l’utilizzo gestita dal provider
ha elaborato la richiesta e deve impedire il ripiego generico su chiave API/OAuth,
e restituisce null o undefined quando il provider non ha gestito
l’autenticazione per l’utilizzo.
Dichiarare le credenziali dell’organizzazione o di fatturazione in
providerUsageAuthEnvVars del manifest. Ciò consente alle superfici generiche
di rilevamento e rimozione dei segreti di riconoscerle senza renderle candidate
per l’autenticazione dell’inferenza.
Esempio di provider
Esempi integrati
I Plugin dei provider inclusi combinano gli hook descritti sopra per adattarsi alle esigenze di catalogo, autenticazione, ragionamento, riproduzione e utilizzo di ciascun fornitore. L’insieme autorevole degli hook risiede con ciascun Plugin inextensions/; questa pagina ne illustra le strutture anziché replicarne
l’elenco.
Provider di cataloghi pass-through
Provider di cataloghi pass-through
OpenRouter, Kilocode, Z.AI e xAI registrano
catalog insieme a
resolveDynamicModel / prepareDynamicModel, così possono esporre gli ID
dei modelli upstream prima del catalogo statico di OpenClaw.Provider di endpoint OAuth e di utilizzo
Provider di endpoint OAuth e di utilizzo
GitHub Copilot, Gemini CLI, ChatGPT Codex, MiniMax, Xiaomi e z.ai abbinano
prepareRuntimeAuth o formatApiKey a resolveUsageAuth +
fetchUsageSnapshot per gestire direttamente lo scambio dei token e
l’integrazione con /usage.Famiglie per la riproduzione e la pulizia delle trascrizioni
Famiglie per la riproduzione e la pulizia delle trascrizioni
Le famiglie condivise con nome (
google-gemini, passthrough-gemini,
anthropic-by-model, hybrid-anthropic-openai) consentono ai provider di
adottare i criteri delle trascrizioni tramite buildReplayPolicy, invece
di fare in modo che ciascun Plugin reimplementi la pulizia.Provider solo catalogo
Provider solo catalogo
byteplus, cloudflare-ai-gateway, huggingface, kimi-coding, nvidia,
qianfan, synthetic, together, venice, vercel-ai-gateway e
volcengine registrano soltanto catalog e usano il ciclo di inferenza
condiviso.Helper di flusso specifici per Anthropic
Helper di flusso specifici per Anthropic
Le intestazioni beta,
/fast / serviceTier e context1m risiedono
nell’interfaccia pubblica api.ts / contract-api.ts del Plugin Anthropic
(wrapAnthropicProviderStream, resolveAnthropicBetas,
resolveAnthropicFastMode, resolveAnthropicServiceTier) anziché
nell’SDK generico.Helper di runtime
I Plugin possono accedere a determinati helper del core tramiteapi.runtime.
Per la sintesi vocale:
textToSpeechrestituisce il normale payload di output TTS del core per le superfici di file/note vocali.- Utilizza la configurazione
messages.ttse la selezione del provider del core. - Restituisce un buffer audio PCM e la frequenza di campionamento. I Plugin devono ricampionare/codificare per i provider.
listVoicesè facoltativo per ciascun provider. Utilizzarlo per i selettori vocali o i flussi di configurazione gestiti dal fornitore.- Il core passa una scadenza risolta della richiesta agli hook
listVoicesdel provider; le impostazioni di timeout specifiche del provider possono sostituirla. - Gli elenchi delle voci possono includere metadati più dettagliati, come impostazioni locali, genere e tag di personalità, per selettori consapevoli del provider.
- OpenAI ed ElevenLabs supportano attualmente la telefonia. Microsoft no.
api.registerSpeechProvider(...).
- Mantenere nel core i criteri TTS, il ripiego e la consegna delle risposte.
- Utilizzare i provider vocali per il comportamento di sintesi gestito dal fornitore.
- L’input Microsoft legacy
edgeviene normalizzato nell’ID providermicrosoft. - Il modello di titolarità preferito è orientato all’azienda: un singolo Plugin del fornitore può gestire provider di testo, voce, immagini e contenuti multimediali futuri man mano che OpenClaw aggiunge i relativi contratti di funzionalità.
- Mantenere nel core l’orchestrazione, il ripiego, la configurazione e il collegamento ai canali.
- Mantenere il comportamento del fornitore nel Plugin del provider.
- L’espansione additiva deve rimanere tipizzata: nuovi metodi facoltativi, nuovi campi di risultato facoltativi, nuove funzionalità facoltative.
- La generazione video segue già lo stesso schema:
- il core gestisce il contratto di funzionalità e l’helper di runtime
- i Plugin dei fornitori registrano
api.registerVideoGenerationProvider(...) - i Plugin di funzionalità/canale utilizzano
api.runtime.videoGeneration.*
api.runtime.mediaUnderstanding.*è la superficie condivisa preferita per la comprensione di immagini/audio/video.extractStructuredWithModel(...)è l’interfaccia rivolta ai Plugin per un’estrazione delimitata, gestita dal provider e basata principalmente sulle immagini. Includere almeno un input immagine; gli input testuali forniscono contesto supplementare. I Plugin di prodotto gestiscono le proprie route e i propri schemi, mentre OpenClaw gestisce il confine provider/runtime.- Utilizza la configurazione audio della comprensione multimediale del core (
tools.media.audio) e l’ordine di ripiego dei provider. - Restituisce
{ text: undefined }quando non viene prodotto alcun risultato di trascrizione, ad esempio per un input ignorato/non supportato. api.runtime.stt.transcribeAudioFile(...)rimane disponibile come alias di compatibilità.
api.runtime.subagent:
provideremodelsono sostituzioni facoltative per singola esecuzione, non modifiche persistenti della sessione.- OpenClaw rispetta questi campi di sostituzione solo per i chiamanti attendibili.
- Per le esecuzioni di ripiego gestite dai Plugin, gli operatori devono fornire il consenso tramite
plugins.entries.<id>.subagent.allowModelOverride: true. - Utilizzare
plugins.entries.<id>.subagent.allowedModelsper limitare i Plugin attendibili a destinazioni canonicheprovider/modelspecifiche, oppure"*"per consentire esplicitamente qualsiasi destinazione. - Le esecuzioni dei sottoagenti di Plugin non attendibili continuano a funzionare, ma le richieste di sostituzione vengono rifiutate anziché ricorrere silenziosamente al ripiego.
- Le sessioni dei sottoagenti create dai Plugin vengono contrassegnate con l’ID del Plugin che le ha create. Il ripiego
api.runtime.subagent.deleteSession(...)può eliminare soltanto tali sessioni di proprietà; l’eliminazione arbitraria delle sessioni richiede comunque una richiesta Gateway con ambito amministrativo.
api.registerWebSearchProvider(...).
Note:
- Mantenere nel core la selezione del provider, la risoluzione delle credenziali e la semantica condivisa delle richieste.
- Utilizzare i provider di ricerca web per i trasporti di ricerca specifici del fornitore.
api.runtime.webSearch.*è la superficie condivisa preferita per i Plugin di funzionalità/canale che richiedono il comportamento di ricerca senza dipendere dal wrapper degli strumenti dell’agente.
api.runtime.imageGeneration
generate(...): genera un’immagine utilizzando la catena configurata di provider per la generazione di immagini.listProviders(...): elenca i provider disponibili per la generazione di immagini e le relative funzionalità.
Route HTTP del Gateway
I Plugin possono esporre endpoint HTTP tramiteapi.registerHttpRoute(...).
path: percorso della route nel server HTTP del Gateway.auth: obbligatorio,"gateway"o"plugin". Usa"gateway"per richiedere la normale autenticazione del Gateway oppure"plugin"per l’autenticazione o la verifica dei Webhook gestita dal Plugin.match: facoltativo."exact"(valore predefinito) o"prefix".handleUpgrade: gestore facoltativo per le richieste di upgrade WebSocket sulla stessa route.replaceExisting: facoltativo. Consente allo stesso Plugin di sostituire la registrazione della propria route esistente.handler: restituiscetruequando la route ha gestito la richiesta.
api.registerHttpHandler(...)è stato rimosso e causerà un errore di caricamento del Plugin. Usa inveceapi.registerHttpRoute(...).- Le route dei Plugin devono dichiarare esplicitamente
auth. - I conflitti esatti tra
path + matchvengono rifiutati, a meno che non sia impostatoreplaceExisting: true, e un Plugin non può sostituire la route di un altro Plugin. - Le route sovrapposte con livelli
authdiversi vengono rifiutate. Mantieni le catene di ripiegoexact/prefixesclusivamente sullo stesso livello di autenticazione. - Le route con
auth: "plugin"non ricevono automaticamente gli ambiti di runtime dell’operatore. Sono destinate ai Webhook e alla verifica delle firme gestiti dal Plugin, non alle chiamate privilegiate agli helper del Gateway. - Le route con
auth: "gateway"vengono eseguite all’interno dell’ambito di runtime di una richiesta del Gateway. La superficie predefinita (gatewayRuntimeScopeSurface: "write-default") è intenzionalmente prudente:- l’autenticazione bearer con segreto condiviso (
gateway.auth.mode = "token"/"password") e qualsiasi metodo di autenticazione diverso da proxy attendibile ricevono un unico ambitooperator.write, anche se il chiamante inviax-openclaw-scopes - anche i chiamanti
trusted-proxysenza un headerx-openclaw-scopesesplicito mantengono la superficie precedente limitata aoperator.write - i chiamanti
trusted-proxyche invianox-openclaw-scopesricevono invece gli ambiti dichiarati - una route può scegliere
gatewayRuntimeScopeSurface: "trusted-operator"per rispettare semprex-openclaw-scopesnelle modalità di autenticazione associate a un’identità, usando come ripiego l’insieme completo degli ambiti predefiniti della CLI quando l’header è assente
- l’autenticazione bearer con segreto condiviso (
- Regola pratica: non presumere che una route di Plugin autenticata tramite Gateway sia implicitamente una superficie amministrativa. Se la route richiede un comportamento riservato agli amministratori, scegli la superficie degli ambiti
trusted-operator, richiedi una modalità di autenticazione associata a un’identità e documenta il contratto esplicito dell’headerx-openclaw-scopes. - Dopo la corrispondenza della route e l’autenticazione, i normali gestori partecipano all’ammissione del lavoro radice del Gateway. Un Gateway in fase di preparazione o riavvio restituisce
503prima di invocare il gestore. La limitata eccezione è una route conauth: "gateway", autorizzata dal manifesto, che sceglie anche la superficietrusted-operatorspecifica della route; questa rimane raggiungibile per evitare che l’invio dei controlli di sospensione resti bloccato, mentre le normali route affini dello stesso Plugin rimangono dietro il limite di ammissione. La proprietà WebSocket dihandleUpgradeusa lo stesso limite di ammissione atomico; dopo che il gestore accetta un socket, il successivo ciclo di vita del socket appartiene al Plugin e non viene monitorato da questo limite.
Percorsi di importazione dell’SDK dei Plugin
Quando crei nuovi Plugin, usa i sottopercorsi specifici dell’SDK invece del barrel radice monoliticoopenclaw/plugin-sdk. Sottopercorsi principali:
I Plugin dei canali scelgono da una famiglia di interfacce specifiche:
channel-setup,
setup-runtime, setup-tools, channel-pairing,
channel-contract, channel-feedback, channel-inbound, channel-outbound,
command-auth, secret-input, webhook-ingress,
channel-targets e channel-actions. Il comportamento di approvazione dovrebbe essere consolidato
in un unico contratto approvalCapability, anziché essere distribuito tra campi
del Plugin non correlati. Consulta Plugin dei canali.
Gli helper di runtime e configurazione si trovano nei corrispondenti sottopercorsi specifici *-runtime
(approval-runtime, agent-runtime, lazy-runtime, directory-runtime,
text-runtime, runtime-store, system-event-runtime, heartbeat-runtime,
channel-activity-runtime e così via). Preferisci config-contracts,
plugin-config-runtime, runtime-config-snapshot e config-mutation
al barrel di compatibilità generico config-runtime.
openclaw/plugin-sdk/channel-runtime, openclaw/plugin-sdk/channel-lifecycle,
le piccole facciate degli helper dei canali, openclaw/plugin-sdk/outbound-runtime,
openclaw/plugin-sdk/outbound-send-deps, openclaw/plugin-sdk/config-runtime
e openclaw/plugin-sdk/infra-runtime sono shim di compatibilità deprecati per
i Plugin meno recenti. Il nuovo codice dovrebbe invece importare primitive generiche più specifiche.index.js— punto di ingresso del Plugin integratoapi.js— barrel di helper e tipiruntime-api.js— barrel riservato al runtimesetup-entry.js— punto di ingresso del Plugin di configurazione
openclaw/plugin-sdk/*. Non
importare mai src/* del pacchetto di un altro Plugin dal core o da un altro Plugin.
I punti di ingresso caricati tramite facciata preferiscono l’istantanea attiva della configurazione
di runtime, quando esiste, altrimenti usano come ripiego il file di configurazione risolto su disco.
I sottopercorsi specifici per funzionalità, come image-generation, media-understanding
e speech, esistono perché attualmente vengono utilizzati dai Plugin integrati. Non
costituiscono automaticamente contratti esterni stabili a lungo termine: consulta la pagina
di riferimento pertinente dell’SDK prima di farvi affidamento.
Schemi dello strumento per i messaggi
I Plugin devono gestire i contributi specifici del canale allo schemadescribeMessageTool(...) per primitive diverse dai messaggi, come reazioni, letture e sondaggi.
La presentazione condivisa per l’invio deve usare il contratto generico MessagePresentation
invece dei campi nativi del fornitore per pulsanti, componenti, blocchi o schede.
Consulta Presentazione dei messaggi per il contratto,
le regole di ripiego, la mappatura dei fornitori e l’elenco di controllo per gli autori di Plugin.
I Plugin in grado di inviare dichiarano ciò che possono rappresentare tramite le funzionalità dei messaggi:
presentationper i blocchi di presentazione semantici (text,context,divider,chart,table,buttons,select)delivery-pinper le richieste di consegna con elemento fissato
Risoluzione delle destinazioni dei canali
I Plugin dei canali devono gestire la semantica delle destinazioni specifica del canale. Mantieni generico l’host condiviso per i messaggi in uscita e usa la superficie dell’adattatore di messaggistica per le regole del fornitore:messaging.inferTargetChatType({ to })decide se una destinazione normalizzata deve essere trattata comedirect,groupochannelprima della ricerca nella directory.messaging.targetResolver.looksLikeId(raw, normalized)indica al core se un input deve passare direttamente alla risoluzione simile a un identificatore invece che alla ricerca nella directory.messaging.targetResolver.reservedLiteralselenca le parole isolate che costituiscono riferimenti a canali o sessioni per quel fornitore. La risoluzione preserva le voci configurate della directory prima di rifiutare i valori letterali riservati, quindi termina in modo sicuro in caso di mancata corrispondenza nella directory.messaging.targetResolver.resolveTarget(...)è il ripiego del Plugin quando il core necessita di una risoluzione finale gestita dal fornitore dopo la normalizzazione o dopo una mancata corrispondenza nella directory.messaging.resolveOutboundSessionRoute(...)gestisce la costruzione della route di sessione specifica del fornitore dopo la risoluzione di una destinazione.
- Usa
inferTargetChatTypeper le decisioni di categoria che devono avvenire prima della ricerca tra contatti o gruppi. - Usa
looksLikeIdper i controlli del tipo “tratta questo valore come identificatore esplicito o nativo della destinazione”. - Usa
resolveTargetper il ripiego della normalizzazione specifica del fornitore, non per una ricerca estesa nella directory. - Mantieni gli identificatori nativi del fornitore, come identificatori di chat, identificatori di thread, JID, handle e identificatori
di stanza, nei valori
targeto nei parametri specifici del fornitore, non nei campi generici dell’SDK.
Directory basate sulla configurazione
I Plugin che derivano le voci della directory dalla configurazione devono mantenere questa logica nel Plugin e riutilizzare gli helper condivisi diopenclaw/plugin-sdk/directory-runtime.
Usali quando un canale necessita di contatti o gruppi basati sulla configurazione, ad esempio:
- contatti per messaggi diretti determinati da una lista consentita
- mappe configurate di canali o gruppi
- ripieghi statici della directory limitati all’account
directory-runtime gestiscono esclusivamente operazioni generiche:
- filtraggio delle query
- applicazione dei limiti
- helper di deduplicazione e normalizzazione
- creazione di
ChannelDirectoryEntry[]
Cataloghi dei fornitori
I Plugin dei fornitori possono definire cataloghi di modelli per l’inferenza conregisterProvider({ catalog: { run(...) { ... } } }).
catalog.run(...) restituisce la stessa struttura che OpenClaw scrive in
models.providers:
{ provider }per una singola voce del fornitore{ providers }per più voci di fornitori
catalog quando il Plugin gestisce identificatori di modelli specifici del fornitore, valori
predefiniti dell’URL di base o metadati dei modelli subordinati all’autenticazione.
catalog.order controlla quando il catalogo di un Plugin viene unito rispetto ai fornitori
impliciti integrati di OpenClaw:
simple: fornitori basati su una semplice chiave API o su variabili d’ambienteprofile: fornitori che compaiono quando esistono profili di autenticazionepaired: fornitori che sintetizzano più voci correlatelate: ultimo passaggio, dopo gli altri fornitori impliciti
api.registerModelCatalogProvider({ provider, kinds, staticCatalog, liveCatalog }). Questo è il percorso futuro per le superfici di elenco, guida e selezione e supporta
righe text, voice, image_generation, video_generation e music_generation.
I Plugin dei fornitori continuano a gestire le chiamate agli endpoint in tempo reale, lo scambio dei token e
la mappatura delle risposte del produttore; il core gestisce la struttura comune delle righe, le etichette delle fonti e
la formattazione della guida degli strumenti multimediali. Le registrazioni dei fornitori per la generazione multimediale sintetizzano
automaticamente righe statiche del catalogo da defaultModel, models e
capabilities.
Compatibilità:
discoverycontinua a funzionare come alias precedente, ma emette un avviso di deprecazione- se vengono registrati sia
catalogsiadiscovery, OpenClaw usacataloged emette un avviso augmentModelCatalogè deprecato; i fornitori integrati devono pubblicare righe supplementari tramiteregisterModelCatalogProvider
Ispezione dei canali in sola lettura
Se il Plugin registra un canale, è preferibile implementareplugin.config.inspectAccount(cfg, accountId) insieme a resolveAccount(...).
Motivazione:
resolveAccount(...)è il percorso di runtime. Può presumere che le credenziali siano completamente materializzate e può terminare immediatamente con un errore quando mancano i segreti richiesti.- I percorsi dei comandi in sola lettura, come
openclaw status,openclaw status --all,openclaw channels status,openclaw channels resolvee i flussi di riparazione di doctor o della configurazione, non devono materializzare le credenziali di runtime soltanto per descrivere la configurazione.
inspectAccount(...):
- Restituisce solo lo stato descrittivo dell’account.
- Mantiene
enabledeconfigured. - Include i campi relativi all’origine e allo stato delle credenziali quando pertinenti, ad esempio:
tokenSource,tokenStatusbotTokenSource,botTokenStatusappTokenSource,appTokenStatussigningSecretSource,signingSecretStatus
- Non è necessario restituire i valori grezzi dei token solo per segnalare la disponibilità in sola lettura. Restituire
tokenStatus: "available"(e il campo di origine corrispondente) è sufficiente per i comandi di stato. - Usa
configured_unavailablequando una credenziale è configurata tramite SecretRef ma non è disponibile nel percorso del comando corrente.
Pacchetti di Plugin
Una directory di Plugin può includere unpackage.json con openclaw.extensions:
<manifestOrPackageName>/<fileBase> (l’id del manifest ha la precedenza quando è presente; altrimenti viene usato il nome senza ambito di package.json).
Se il Plugin importa dipendenze npm, installale in tale directory affinché node_modules sia disponibile (npm install / pnpm install).
Misura di sicurezza: ogni voce di openclaw.extensions deve rimanere all’interno della directory del Plugin dopo la risoluzione dei collegamenti simbolici. Le voci che escono dalla directory del pacchetto vengono rifiutate.
Nota sulla sicurezza: openclaw plugins install installa le dipendenze del Plugin con un comando npm install --omit=dev --ignore-scripts locale al progetto (senza script del ciclo di vita e senza dipendenze di sviluppo in fase di esecuzione), ignorando le impostazioni globali di installazione npm ereditate. Mantieni gli alberi delle dipendenze dei Plugin “JS/TS puri” ed evita i pacchetti che richiedono compilazioni postinstall.
Facoltativo: openclaw.setupEntry può puntare a un modulo leggero destinato esclusivamente alla configurazione. Quando OpenClaw necessita delle superfici di configurazione per un Plugin di canale disabilitato oppure quando un Plugin di canale è abilitato ma non ancora configurato, carica setupEntry anziché la voce completa del Plugin. Ciò rende più leggeri l’avvio e la configurazione quando la voce principale del Plugin collega anche strumenti, hook o altro codice destinato esclusivamente alla fase di esecuzione.
Facoltativo: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen può far sì che un Plugin di canale utilizzi lo stesso percorso setupEntry durante la fase di avvio precedente all’ascolto del Gateway, anche quando il canale è già configurato.
Usa questa opzione solo quando setupEntry copre completamente la superficie di avvio che deve esistere prima che il Gateway inizi l’ascolto. In pratica, ciò significa che la voce di configurazione deve registrare ogni funzionalità di proprietà del canale da cui dipende l’avvio, ad esempio:
- la registrazione del canale stesso
- tutti i percorsi HTTP che devono essere disponibili prima che il Gateway inizi l’ascolto
- tutti i metodi, gli strumenti o i servizi del Gateway che devono esistere durante la stessa finestra temporale
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
channels.<id>.accounts.* senza caricare la voce completa del Plugin. Matrix è l’attuale esempio incluso: quando esistono già account denominati, sposta in un account denominato promosso solo le chiavi di autenticazione/bootstrap e può mantenere una chiave configurata non canonica per l’account predefinito, anziché creare sempre accounts.default.
Questi adattatori di patch della configurazione mantengono differita l’individuazione della superficie contrattuale inclusa. Il tempo di importazione rimane ridotto; la superficie di promozione viene caricata solo al primo utilizzo, anziché riattivare l’avvio del canale incluso durante l’importazione del modulo.
Quando queste superfici di avvio includono metodi RPC del Gateway, mantienili sotto un prefisso specifico del Plugin. Gli spazi dei nomi amministrativi del nucleo (config.*, exec.approvals.*, wizard.*, update.*) rimangono riservati e vengono sempre risolti in operator.admin, anche se un Plugin richiede un ambito più ristretto.
Esempio:
Metadati del catalogo dei canali
I Plugin di canale possono pubblicizzare i metadati di configurazione/individuazione tramiteopenclaw.channel e i suggerimenti di installazione tramite openclaw.install. Ciò evita di inserire dati del catalogo nel nucleo.
Esempio:
openclaw.channel oltre all’esempio minimo:
detailLabel: etichetta secondaria per superfici di catalogo/stato più dettagliatedocsLabel: sostituisce il testo del collegamento alla documentazionepreferOver: id di Plugin/canali con priorità inferiore che questa voce di catalogo deve superareselectionDocsPrefix,selectionDocsOmitLabel,selectionExtras: controlli del testo della superficie di selezionemarkdownCapable: contrassegna il canale come compatibile con Markdown per le decisioni sulla formattazione in uscitaexposure.configured: nasconde il canale dalle superfici che elencano i canali configurati quando è impostato sufalseexposure.setup: nasconde il canale dai selettori interattivi di configurazione quando è impostato sufalseexposure.docs: contrassegna il canale come interno/privato per le superfici di navigazione della documentazioneshowConfigured/showInSetup: alias legacy ancora accettati per compatibilità; preferisciexposurequickstartAllowFrom: include il canale nel flusso rapido standardallowFromforceAccountBinding: richiede un’associazione esplicita dell’account anche quando esiste un solo accountpreferSessionLookupForAnnounceTarget: preferisce la ricerca della sessione durante la risoluzione delle destinazioni degli annunci
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
OPENCLAW_PLUGIN_CATALOG_PATHS (o OPENCLAW_MPM_CATALOG_PATHS) su uno o più file JSON (delimitati da virgole, punti e virgola o PATH). Ogni file deve contenere { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }. Il parser accetta inoltre "packages" o "plugins" come alias legacy della chiave "entries".
Le voci generate del catalogo dei canali e quelle del catalogo di installazione dei provider espongono informazioni normalizzate sull’origine dell’installazione accanto al blocco grezzo openclaw.install. Le informazioni normalizzate indicano se la specifica npm è una versione esatta o un selettore mobile, se sono presenti i metadati di integrità previsti e se è disponibile anche un percorso di origine locale. Quando l’identità del catalogo/pacchetto è nota, le informazioni normalizzate avvisano se il nome del pacchetto npm analizzato diverge da tale identità. Avvisano inoltre quando defaultChoice non è valido o punta a un’origine non disponibile e quando sono presenti metadati di integrità npm senza un’origine npm valida. I consumatori devono trattare installSource come un campo facoltativo aggiuntivo, affinché le voci create manualmente e gli shim del catalogo non debbano sintetizzarlo.
Ciò consente all’onboarding e alla diagnostica di spiegare lo stato del piano delle origini senza importare il runtime del Plugin.
Le voci npm esterne ufficiali devono preferire un npmSpec esatto insieme a expectedIntegrity. I semplici nomi di pacchetto e i dist-tag continuano a funzionare per compatibilità, ma mostrano avvisi relativi al piano delle origini, affinché il catalogo possa evolvere verso installazioni con versione bloccata e integrità verificata senza interrompere i Plugin esistenti. Quando l’onboarding esegue l’installazione da un percorso di catalogo locale, registra una voce gestita nell’indice dei Plugin con source: "path" e, quando possibile, un sourcePath relativo allo spazio di lavoro. Il percorso operativo assoluto di caricamento rimane in plugins.load.paths; il record di installazione evita di duplicare i percorsi della postazione locale nella configurazione persistente. Ciò rende le installazioni di sviluppo locali visibili alla diagnostica del piano delle origini senza aggiungere una seconda superficie che esponga percorsi grezzi del file system. La tabella SQLite persistente installed_plugin_index è la fonte autorevole per l’origine dell’installazione e può essere aggiornata senza caricare i moduli runtime del Plugin. La relativa mappa installRecords persiste anche quando il manifest di un Plugin è mancante o non valido; il relativo payload plugins è una vista ricostruibile del manifest.
Plugin del motore di contesto
I Plugin del motore di contesto gestiscono l’orchestrazione del contesto della sessione per l’acquisizione, l’assemblaggio e la Compaction. Registrali dal Plugin conapi.registerContextEngine(id, factory), quindi seleziona il motore attivo con plugins.slots.contextEngine.
Usa questa funzionalità quando il Plugin deve sostituire o estendere la pipeline di contesto predefinita, anziché limitarsi ad aggiungere la ricerca in memoria o degli hook.
ctx espone i valori facoltativi config, agentDir e workspaceDir per l’inizializzazione al momento della creazione.
assemble() può restituire contextProjection quando l’harness attivo dispone di un thread persistente nel backend. Omettilo per la proiezione legacy a ogni turno. Restituisci { mode: "thread_bootstrap", epoch } quando il contesto assemblato deve essere inserito una sola volta in un thread del backend e riutilizzato finché l’epoca non cambia. Modifica l’epoca dopo una variazione del contesto semantico del motore, ad esempio dopo un passaggio di Compaction gestito dal motore. Gli host possono mantenere i metadati delle chiamate agli strumenti, la forma dell’input e i risultati oscurati degli strumenti in una proiezione di bootstrap del thread, affinché i nuovi thread del backend conservino la continuità degli strumenti senza copiare payload grezzi contenenti segreti.
Se il motore non gestisce l’algoritmo di Compaction, mantieni implementato compact() e delegalo esplicitamente:
Aggiunta di una nuova funzionalità
Quando un plugin necessita di un comportamento non previsto dall’API attuale, non aggirare il sistema dei plugin accedendo direttamente a elementi privati. Aggiungi la funzionalità mancante. Sequenza consigliata:- Definisci il contratto del core. Stabilisci quale comportamento condiviso deve essere gestito dal core: criteri, fallback, unione della configurazione, ciclo di vita, semantica rivolta ai canali e struttura degli helper di runtime.
- Aggiungi superfici tipizzate per la registrazione e il runtime dei plugin. Estendi
OpenClawPluginApie/oapi.runtimecon la più piccola superficie tipizzata utile per la funzionalità. - Collega il core e i componenti consumer dei canali/delle funzionalità. I canali e i plugin di funzionalità devono utilizzare la nuova funzionalità tramite il core, senza importare direttamente un’implementazione specifica di un fornitore.
- Registra le implementazioni dei fornitori. I plugin dei fornitori registrano quindi i propri backend per la funzionalità.
- Aggiungi la copertura del contratto. Aggiungi test affinché la titolarità e la struttura della registrazione rimangano esplicite nel tempo.
Elenco di controllo della funzionalità
Quando aggiungi una nuova funzionalità, l’implementazione dovrebbe solitamente interessare insieme queste superfici:- tipi del contratto del core in
src/<capability>/types.ts - esecutore del core/helper di runtime in
src/<capability>/runtime.ts - superficie di registrazione dell’API dei plugin in
src/plugins/types.ts - collegamento del registro dei plugin in
src/plugins/registry.ts - esposizione del runtime dei plugin in
src/plugins/runtime/*quando i plugin di funzionalità/canale devono utilizzarla - helper di acquisizione/test in
src/test-utils/plugin-registration.ts - asserzioni sulla titolarità/sul contratto in
src/plugins/contracts/registry.ts - documentazione per operatori/plugin in
docs/
Modello di funzionalità
Schema minimo:src/plugins/contracts/registry.ts espone ricerche della titolarità
come providerContractPluginIds; i test verificano che l’elenco
contracts.videoGenerationProviders di un plugin corrisponda a ciò che registra effettivamente):
- il core gestisce il contratto della funzionalità e l’orchestrazione
- i plugin dei fornitori gestiscono le implementazioni specifiche dei fornitori
- i plugin di funzionalità/canale utilizzano gli helper di runtime
- i test del contratto mantengono esplicita la titolarità
Argomenti correlati
- Architettura dei plugin — modello pubblico e strutture delle funzionalità
- Sottopercorsi dell’SDK dei plugin
- Configurazione dell’SDK dei plugin
- Creazione di plugin