Protocollo Gateway (WebSocket)
Il protocollo WS del Gateway è l’unico control plane + trasporto dei nodi per OpenClaw. Tutti i client (CLI, UI web, app macOS, nodi iOS/Android, nodi headless) si connettono tramite WebSocket e dichiarano il proprio ruolo + ambito al momento dell’handshake.Trasporto
- WebSocket, frame di testo con payload JSON.
- Il primo frame deve essere una richiesta
connect.
Handshake (connect)
Gateway → Client (challenge pre-connessione):
hello-ok include anche:
hello-ok.auth può includere anche
voci di ruolo aggiuntive limitate in deviceTokens:
scopes: [] e qualsiasi token operatore trasferito resta limitato alla
allowlist bootstrap dell’operatore (operator.approvals, operator.read,
operator.talk.secrets, operator.write). I controlli di ambito bootstrap restano
con prefisso di ruolo: le voci operatore soddisfano solo richieste operatore, e i ruoli non operatore
continuano a richiedere ambiti sotto il proprio prefisso di ruolo.
Esempio di nodo
Framing
- Richiesta:
{type:"req", id, method, params} - Risposta:
{type:"res", id, ok, payload|error} - Evento:
{type:"event", event, payload, seq?, stateVersion?}
Ruoli + ambiti
Ruoli
operator= client del control plane (CLI/UI/automazione).node= host di capacità (camera/screen/canvas/system.run).
Ambiti (operator)
Ambiti comuni:operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairingoperator.talk.secrets
talk.config con includeSecrets: true richiede operator.talk.secrets
(o operator.admin).
I metodi RPC del gateway registrati dai plugin possono richiedere il proprio ambito operatore, ma
i prefissi admin core riservati (config.*, exec.approvals.*, wizard.*,
update.*) vengono sempre risolti come operator.admin.
L’ambito del metodo è solo il primo controllo. Alcuni slash command raggiunti tramite
chat.send applicano controlli più rigorosi a livello di comando. Ad esempio, le scritture persistenti
/config set e /config unset richiedono operator.admin.
node.pair.approve ha anche un controllo di ambito aggiuntivo al momento dell’approvazione oltre
all’ambito base del metodo:
- richieste senza comando:
operator.pairing - richieste con comandi del nodo diversi da exec:
operator.pairing+operator.write - richieste che includono
system.run,system.run.prepareosystem.which:operator.pairing+operator.admin
Caps/commands/permissions (node)
I nodi dichiarano le richieste di capacità al momento della connessione:caps: categorie di capacità di alto livello.commands: allowlist dei comandi per invoke.permissions: interruttori granulari (ad esempioscreen.record,camera.capture).
Presenza
system-presencerestituisce voci indicizzate per identità del dispositivo.- Le voci di presenza includono
deviceId,rolesescopescosì le UI possono mostrare una sola riga per dispositivo anche quando si connette sia come operator sia come node.
Famiglie di metodi RPC comuni
Questa pagina non è un dump completo generato, ma la superficie WS pubblica è più ampia rispetto agli esempi di handshake/auth sopra. Queste sono le principali famiglie di metodi che il Gateway espone oggi.hello-ok.features.methods è un elenco di rilevamento conservativo costruito da
src/gateway/server-methods-list.ts più le esportazioni dei metodi di plugin/canali caricati.
Trattalo come rilevamento di funzionalità, non come un dump generato di ogni helper richiamabile
implementato in src/gateway/server-methods/*.ts.
Sistema e identità
healthrestituisce lo snapshot di salute del gateway memorizzato nella cache o appena sondato.statusrestituisce il riepilogo del gateway in stile/status; i campi sensibili sono inclusi solo per client operator con ambito admin.gateway.identity.getrestituisce l’identità del dispositivo gateway usata dai flussi di relay e pairing.system-presencerestituisce lo snapshot di presenza corrente per i dispositivi operator/node connessi.system-eventaggiunge un evento di sistema e può aggiornare/trasmettere il contesto di presenza.last-heartbeatrestituisce l’ultimo evento heartbeat persistito.set-heartbeatsabilita/disabilita l’elaborazione heartbeat sul gateway.
Modelli e utilizzo
models.listrestituisce il catalogo dei modelli consentiti in runtime.usage.statusrestituisce riepiloghi delle finestre di utilizzo dei provider/quota residua.usage.costrestituisce riepiloghi aggregati dei costi per un intervallo di date.doctor.memory.statusrestituisce lo stato di prontezza di vector-memory / embedding per il workspace dell’agente predefinito attivo.sessions.usagerestituisce riepiloghi di utilizzo per sessione.sessions.usage.timeseriesrestituisce serie temporali di utilizzo per una sessione.sessions.usage.logsrestituisce le voci del log di utilizzo per una sessione.
Canali e helper di login
channels.statusrestituisce riepiloghi di stato di canali/plugin integrati + inclusi.channels.logoutesegue il logout di uno specifico canale/account dove il canale supporta il logout.web.login.startavvia un flusso di login QR/web per l’attuale provider di canale web con supporto QR.web.login.waitattende il completamento di quel flusso di login QR/web e avvia il canale in caso di successo.push.testinvia un push APNs di test a un nodo iOS registrato.voicewake.getrestituisce i trigger wake-word memorizzati.voicewake.setaggiorna i trigger wake-word e trasmette la modifica.
Messaggistica e log
sendè l’RPC diretto di consegna in uscita per invii mirati a canale/account/thread al di fuori del chat runner.logs.tailrestituisce la coda del file di log del gateway configurato con controlli di cursore/limite e byte massimi.
Talk e TTS
talk.configrestituisce il payload effettivo di configurazione Talk;includeSecretsrichiedeoperator.talk.secrets(ooperator.admin).talk.modeimposta/trasmette lo stato corrente della modalità Talk per i client WebChat/Control UI.talk.speaksintetizza voce tramite il provider speech Talk attivo.tts.statusrestituisce lo stato abilitato TTS, il provider attivo, i provider di fallback e lo stato della configurazione del provider.tts.providersrestituisce l’inventario visibile dei provider TTS.tts.enableetts.disableattivano/disattivano lo stato delle preferenze TTS.tts.setProvideraggiorna il provider TTS preferito.tts.convertesegue una conversione text-to-speech una tantum.
Secrets, config, update e wizard
secrets.reloadririsolve i SecretRef attivi e sostituisce lo stato dei segreti in runtime solo in caso di successo completo.secrets.resolverisolve le assegnazioni dei segreti destinati ai comandi per uno specifico insieme di comando/destinazione.config.getrestituisce lo snapshot e l’hash della configurazione corrente.config.setscrive un payload di configurazione convalidato.config.patchunisce un aggiornamento parziale della configurazione.config.applyconvalida + sostituisce l’intero payload della configurazione.config.schemarestituisce il payload dello schema di configurazione live usato da Control UI e dagli strumenti CLI: schema,uiHints, versione e metadati di generazione, inclusi i metadati di schema di plugin + canali quando il runtime può caricarli. Lo schema include metadati dei campititle/descriptionderivati dalle stesse etichette e dallo stesso testo di aiuto usati dalla UI, incluse ramificazioni di composizione per oggetti annidati, wildcard, elementi di array eanyOf/oneOf/allOfquando esiste documentazione dei campi corrispondente.config.schema.lookuprestituisce un payload di lookup con ambito di percorso per un percorso di configurazione: percorso normalizzato, un nodo di schema superficiale, hint corrispondente +hintPath, e riepiloghi dei figli immediati per il drill-down UI/CLI.- I nodi di schema di lookup mantengono la documentazione rivolta all’utente e i campi di validazione comuni:
title,description,type,enum,const,format,pattern, limiti numerici/stringa/array/oggetto e flag booleani comeadditionalProperties,deprecated,readOnly,writeOnly. - I riepiloghi figli espongono
key,pathnormalizzato,type,required,hasChildren, piùhint/hintPathcorrispondenti.
- I nodi di schema di lookup mantengono la documentazione rivolta all’utente e i campi di validazione comuni:
update.runesegue il flusso di aggiornamento del gateway e pianifica un riavvio solo quando l’aggiornamento stesso è riuscito.wizard.start,wizard.next,wizard.statusewizard.cancelespongono il wizard di onboarding tramite WS RPC.
Famiglie principali esistenti
Helper di agente e workspace
agents.listrestituisce le voci agente configurate.agents.create,agents.updateeagents.deletegestiscono i record degli agenti e il wiring del workspace.agents.files.list,agents.files.geteagents.files.setgestiscono i file bootstrap del workspace esposti per un agente.agent.identity.getrestituisce l’identità effettiva dell’assistente per un agente o una sessione.agent.waitattende il termine di un’esecuzione e restituisce lo snapshot terminale quando disponibile.
Controllo delle sessioni
sessions.listrestituisce l’indice corrente delle sessioni.sessions.subscribeesessions.unsubscribeattivano/disattivano le sottoscrizioni agli eventi di modifica delle sessioni per l’attuale client WS.sessions.messages.subscribeesessions.messages.unsubscribeattivano/disattivano le sottoscrizioni agli eventi di trascrizione/messaggi per una sessione.sessions.previewrestituisce anteprime limitate della trascrizione per specifiche chiavi di sessione.sessions.resolverisolve o canonizza una destinazione di sessione.sessions.createcrea una nuova voce di sessione.sessions.sendinvia un messaggio in una sessione esistente.sessions.steerè la variante interrupt-and-steer per una sessione attiva.sessions.abortinterrompe il lavoro attivo per una sessione.sessions.patchaggiorna metadati/override di sessione.sessions.reset,sessions.deleteesessions.compacteseguono manutenzione della sessione.sessions.getrestituisce l’intera riga di sessione memorizzata.- l’esecuzione chat continua a usare
chat.history,chat.send,chat.abortechat.inject. chat.historyè normalizzato per la visualizzazione per i client UI: i tag direttiva inline vengono rimossi dal testo visibile, i payload XML delle chiamate agli strumenti in testo semplice (inclusi<tool_call>...</tool_call>,<function_call>...</function_call>,<tool_calls>...</tool_calls>,<function_calls>...</function_calls>e blocchi di chiamata agli strumenti troncati) e i token di controllo del modello ASCII/a larghezza piena trapelati vengono rimossi, le righe assistant costituite solo da token silenziosi comeNO_REPLY/no_replyesatti vengono omesse e le righe sovradimensionate possono essere sostituite con segnaposto.
Pairing dei dispositivi e token dispositivo
device.pair.listrestituisce i dispositivi associati in attesa e approvati.device.pair.approve,device.pair.rejectedevice.pair.removegestiscono i record di associazione dei dispositivi.device.token.rotateruota un token dispositivo associato entro i limiti di ruolo e ambiti approvati.device.token.revokerevoca un token dispositivo associato.
Pairing dei nodi, invoke e lavoro in sospeso
node.pair.request,node.pair.list,node.pair.approve,node.pair.rejectenode.pair.verifycoprono pairing dei nodi e verifica bootstrap.node.listenode.describerestituiscono lo stato dei nodi noti/connessi.node.renameaggiorna un’etichetta di nodo associato.node.invokeinoltra un comando a un nodo connesso.node.invoke.resultrestituisce il risultato di una richiesta invoke.node.eventtrasporta gli eventi originati dal nodo nel gateway.node.canvas.capability.refreshaggiorna i token di capacità canvas con ambito definito.node.pending.pullenode.pending.acksono le API di coda del nodo connesso.node.pending.enqueueenode.pending.draingestiscono il lavoro in sospeso durevole per nodi offline/disconnessi.
Famiglie di approvazione
exec.approval.requesteexec.approval.resolvecoprono richieste di approvazione exec una tantum.exec.approval.waitDecisionattende una decisione su un’approvazione exec in sospeso e restituisce la decisione finale (onullin caso di timeout).exec.approvals.geteexec.approvals.setgestiscono gli snapshot della policy di approvazione exec del gateway.exec.approvals.node.geteexec.approvals.node.setgestiscono la policy locale exec del nodo tramite comandi relay del nodo.plugin.approval.request,plugin.approval.waitDecisioneplugin.approval.resolvecoprono i flussi di approvazione definiti dai plugin.
Altre famiglie principali
- automazione:
wakepianifica un’iniezione di testo wake immediata o al prossimo heartbeatcron.list,cron.status,cron.add,cron.update,cron.remove,cron.run,cron.runs
- skills/tools:
skills.*,tools.catalog,tools.effective
Famiglie di eventi comuni
chat: aggiornamenti chat UI comechat.injecte altri eventi chat solo trascrizione.session.messageesession.tool: aggiornamenti di trascrizione/stream di eventi per una sessione sottoscritta.sessions.changed: l’indice sessione o i metadati sono cambiati.presence: aggiornamenti dello snapshot di presenza del sistema.tick: evento periodico di keepalive / liveness.health: aggiornamento dello snapshot di salute del gateway.heartbeat: aggiornamento dello stream di eventi heartbeat.cron: evento di modifica di esecuzione/job cron.shutdown: notifica di arresto del gateway.node.pair.requested/node.pair.resolved: ciclo di vita del pairing del nodo.node.invoke.request: trasmissione di una richiesta invoke del nodo.device.pair.requested/device.pair.resolved: ciclo di vita del dispositivo associato.voicewake.changed: la configurazione dei trigger wake-word è cambiata.exec.approval.requested/exec.approval.resolved: ciclo di vita dell’approvazione exec.plugin.approval.requested/plugin.approval.resolved: ciclo di vita dell’approvazione del plugin.
Metodi helper del nodo
- I nodi possono chiamare
skills.binsper ottenere l’elenco corrente degli eseguibili delle skill per i controlli di auto-allow.
Metodi helper dell’operatore
- Gli operatori possono chiamare
tools.catalog(operator.read) per ottenere il catalogo degli strumenti in runtime per un agente. La risposta include strumenti raggruppati e metadati di provenienza:source:coreopluginpluginId: proprietario del plugin quandosource="plugin"optional: indica se uno strumento plugin è facoltativo
- Gli operatori possono chiamare
tools.effective(operator.read) per ottenere l’inventario effettivo degli strumenti in runtime per una sessione.sessionKeyè obbligatorio.- Il gateway ricava lato server il contesto runtime attendibile dalla sessione invece di accettare autenticazione o contesto di consegna forniti dal chiamante.
- La risposta ha ambito di sessione e riflette ciò che la conversazione attiva può usare in questo momento, inclusi strumenti core, plugin e canali.
- Gli operatori possono chiamare
skills.status(operator.read) per ottenere l’inventario visibile delle skill per un agente.agentIdè facoltativo; omettendolo si legge il workspace dell’agente predefinito.- La risposta include idoneità, requisiti mancanti, controlli di configurazione e opzioni di installazione sanificate senza esporre valori segreti grezzi.
- Gli operatori possono chiamare
skills.searcheskills.detail(operator.read) per i metadati di discovery di ClawHub. - Gli operatori possono chiamare
skills.install(operator.admin) in due modalità:- modalità ClawHub:
{ source: "clawhub", slug, version?, force? }installa una cartella skill nella directoryskills/del workspace dell’agente predefinito. - modalità installer del gateway:
{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }esegue un’azionemetadata.openclaw.installdichiarata sull’host del gateway.
- modalità ClawHub:
- Gli operatori possono chiamare
skills.update(operator.admin) in due modalità:- la modalità ClawHub aggiorna uno slug tracciato o tutte le installazioni ClawHub tracciate nel workspace dell’agente predefinito.
- la modalità config applica patch ai valori
skills.entries.<skillKey>comeenabled,apiKeyedenv.
Approvazioni exec
- Quando una richiesta exec richiede approvazione, il gateway trasmette
exec.approval.requested. - I client operator risolvono chiamando
exec.approval.resolve(richiede l’ambitooperator.approvals). - Per
host=node,exec.approval.requestdeve includeresystemRunPlan(argv/cwd/rawCommand/metadati sessione canonici). Le richieste senzasystemRunPlanvengono rifiutate. - Dopo l’approvazione, le chiamate inoltrate
node.invoke system.runriutilizzano quelsystemRunPlancanonico come contesto autorevole di comando/cwd/sessione. - Se un chiamante modifica
command,rawCommand,cwd,agentIdosessionKeytra prepare e l’inoltro finale approvatosystem.run, il gateway rifiuta l’esecuzione invece di fidarsi del payload modificato.
Fallback di consegna dell’agente
- Le richieste
agentpossono includeredeliver=trueper richiedere la consegna in uscita. bestEffortDeliver=falsemantiene il comportamento rigoroso: destinazioni di consegna irrisolte o solo interne restituisconoINVALID_REQUEST.bestEffortDeliver=trueconsente il fallback all’esecuzione solo sessione quando non è possibile risolvere alcuna route consegnabile esterna (ad esempio sessioni interne/webchat o configurazioni multicanale ambigue).
Versioning
PROTOCOL_VERSIONsi trova insrc/gateway/protocol/schema.ts.- I client inviano
minProtocol+maxProtocol; il server rifiuta le incompatibilità. - Schemi + modelli sono generati da definizioni TypeBox:
pnpm protocol:genpnpm protocol:gen:swiftpnpm protocol:check
Auth
- L’autenticazione gateway con segreto condiviso usa
connect.params.auth.tokenoppureconnect.params.auth.password, a seconda della modalità auth configurata. - Le modalità con identità come Tailscale Serve
(
gateway.auth.allowTailscale: true) ogateway.auth.mode: "trusted-proxy"non loopback soddisfano il controllo auth di connect dagli header della richiesta invece che daconnect.params.auth.*. - La modalità private-ingress
gateway.auth.mode: "none"salta completamente l’autenticazione connect con segreto condiviso; non esporre tale modalità su ingress pubblici/non attendibili. - Dopo il pairing, il Gateway emette un token dispositivo con ambito definito per ruolo + ambiti della connessione. Viene restituito in
hello-ok.auth.deviceTokene deve essere persistito dal client per le connessioni future. - I client devono persistere il
hello-ok.auth.deviceTokenprimario dopo qualsiasi connessione riuscita. - La riconnessione con quel token dispositivo memorizzato dovrebbe anche riutilizzare l’insieme di ambiti approvati memorizzato per quel token. Questo preserva l’accesso read/probe/status già concesso ed evita di restringere silenziosamente le riconnessioni a un ambito implicito più ristretto solo admin.
- La normale precedenza auth di connect è prima token/password condivisi espliciti, poi
deviceTokenesplicito, poi token per dispositivo memorizzato, poi token bootstrap. - Le voci aggiuntive
hello-ok.auth.deviceTokenssono token di handoff bootstrap. Persistile solo quando la connessione ha usato auth bootstrap su un trasporto attendibile comewss://o loopback/pairing locale. - Se un client fornisce un
deviceTokenesplicito oscopesespliciti, quell’insieme di ambiti richiesto dal chiamante rimane autorevole; gli ambiti memorizzati vengono riutilizzati solo quando il client riusa il token per dispositivo memorizzato. - I token dispositivo possono essere ruotati/revocati tramite
device.token.rotateedevice.token.revoke(richiede l’ambitooperator.pairing). - L’emissione/rotazione dei token resta limitata all’insieme di ruoli approvati registrato nella voce di pairing di quel dispositivo; la rotazione di un token non può espandere il dispositivo in un ruolo che l’approvazione del pairing non ha mai concesso.
- Per le sessioni di token dei dispositivi associati, la gestione del dispositivo ha ambito autonomo a meno che il
chiamante non abbia anche
operator.admin: i chiamanti non admin possono rimuovere/revocare/ruotare solo la propria voce del dispositivo. device.token.rotatecontrolla anche l’insieme di ambiti operatore richiesto rispetto agli ambiti della sessione corrente del chiamante. I chiamanti non admin non possono ruotare un token verso un insieme di ambiti operatore più ampio di quello che già possiedono.- Gli errori auth includono
error.details.codepiù suggerimenti di recupero:error.details.canRetryWithDeviceToken(boolean)error.details.recommendedNextStep(retry_with_device_token,update_auth_configuration,update_auth_credentials,wait_then_retry,review_auth_configuration)
- Comportamento del client per
AUTH_TOKEN_MISMATCH:- I client attendibili possono tentare un retry limitato con un token per dispositivo in cache.
- Se quel retry fallisce, i client devono interrompere i loop automatici di riconnessione e mostrare indicazioni di azione all’operatore.
Identità del dispositivo + pairing
- I nodi devono includere un’identità di dispositivo stabile (
device.id) derivata dall’impronta digitale di una coppia di chiavi. - I gateway emettono token per dispositivo + ruolo.
- Le approvazioni di pairing sono richieste per nuovi ID dispositivo, a meno che l’approvazione automatica locale non sia abilitata.
- L’approvazione automatica del pairing è centrata sulle connessioni dirette loopback locali.
- OpenClaw ha anche un percorso ristretto di auto-connessione backend/container-local per flussi helper con segreto condiviso attendibili.
- Le connessioni tailnet o LAN sullo stesso host sono comunque trattate come remote per il pairing e richiedono approvazione.
- Tutti i client WS devono includere l’identità
deviceduranteconnect(operator + node). La Control UI può ometterla solo in queste modalità:gateway.controlUi.allowInsecureAuth=trueper compatibilità con HTTP insicuro solo localhost.- autenticazione riuscita della Control UI operator con
gateway.auth.mode: "trusted-proxy". gateway.controlUi.dangerouslyDisableDeviceAuth=true(break-glass, grave downgrade della sicurezza).
- Tutte le connessioni devono firmare il nonce
connect.challengefornito dal server.
Diagnostica della migrazione auth del dispositivo
Per i client legacy che usano ancora il comportamento di firma pre-challenge,connect ora restituisce
codici di dettaglio DEVICE_AUTH_* sotto error.details.code con un error.details.reason stabile.
Errori di migrazione comuni:
| Messaggio | details.code | details.reason | Significato |
|---|---|---|---|
device nonce required | DEVICE_AUTH_NONCE_REQUIRED | device-nonce-missing | Il client ha omesso device.nonce (o lo ha inviato vuoto). |
device nonce mismatch | DEVICE_AUTH_NONCE_MISMATCH | device-nonce-mismatch | Il client ha firmato con un nonce obsoleto/errato. |
device signature invalid | DEVICE_AUTH_SIGNATURE_INVALID | device-signature | Il payload della firma non corrisponde al payload v2. |
device signature expired | DEVICE_AUTH_SIGNATURE_EXPIRED | device-signature-stale | Il timestamp firmato è fuori dallo skew consentito. |
device identity mismatch | DEVICE_AUTH_DEVICE_ID_MISMATCH | device-id-mismatch | device.id non corrisponde all’impronta del public key. |
device public key invalid | DEVICE_AUTH_PUBLIC_KEY_INVALID | device-public-key | Il formato/canonicalizzazione del public key non è riuscito. |
- Attendere sempre
connect.challenge. - Firmare il payload v2 che include il nonce del server.
- Inviare lo stesso nonce in
connect.params.device.nonce. - Il payload di firma preferito è
v3, che vincolaplatformedeviceFamilyoltre ai campi device/client/role/scopes/token/nonce. - Le firme legacy
v2restano accettate per compatibilità, ma il pinning dei metadati del dispositivo associato continua a controllare la policy dei comandi alla riconnessione.
TLS + pinning
- TLS è supportato per le connessioni WS.
- I client possono facoltativamente eseguire il pinning dell’impronta del certificato del gateway (vedi configurazione
gateway.tlspiùgateway.remote.tlsFingerprinto CLI--tls-fingerprint).
Ambito
Questo protocollo espone l’intera API gateway (status, canali, modelli, chat, agent, sessioni, nodi, approvazioni, ecc.). La superficie esatta è definita dagli schemi TypeBox insrc/gateway/protocol/schema.ts.