Protocole Gateway (WebSocket)
Le protocole WS de Gateway est le plan de contrôle unique + transport de nœud pour OpenClaw. Tous les clients (CLI, interface web, application macOS, nœuds iOS/Android, nœuds sans interface) se connectent via WebSocket et déclarent leur rôle + portée au moment de la poignée de main.Transport
- WebSocket, trames texte avec charges utiles JSON.
- La première trame doit être une requête
connect.
Poignée de main (connect)
Gateway → Client (défi de pré-connexion) :server, features, snapshot et policy sont tous requis par le schéma
(src/gateway/protocol/schema/frames.ts). canvasHostUrl est facultatif. auth
rapporte le rôle/les scopes négociés lorsqu’ils sont disponibles, et inclut deviceToken
lorsque la gateway en émet un.
Lorsqu’aucun jeton d’appareil n’est émis, hello-ok.auth peut quand même rapporter les
autorisations négociées :
hello-ok inclut aussi :
hello-ok.auth peut aussi inclure des
entrées de rôle supplémentaires bornées dans deviceTokens :
scopes: [] et tout jeton opérateur transmis reste borné à la liste d’autorisation
de l’opérateur d’amorçage (operator.approvals, operator.read,
operator.talk.secrets, operator.write). Les vérifications de scope d’amorçage restent
préfixées par rôle : les entrées opérateur ne satisfont que les requêtes opérateur, et les rôles
non opérateur ont toujours besoin de scopes sous leur propre préfixe de rôle.
Exemple de nœud
Tramage
- Requête :
{type:"req", id, method, params} - Réponse :
{type:"res", id, ok, payload|error} - Événement :
{type:"event", event, payload, seq?, stateVersion?}
Rôles + scopes
Rôles
operator= client du plan de contrôle (CLI/UI/automatisation).node= hôte de capacités (camera/screen/canvas/system.run).
Scopes (operator)
Scopes courants :operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairingoperator.talk.secrets
talk.config avec includeSecrets: true requiert operator.talk.secrets
(ou operator.admin).
Les méthodes RPC Gateway enregistrées par des Plugin peuvent demander leur propre scope operator, mais
les préfixes d’administration réservés du cœur (config.*, exec.approvals.*, wizard.*,
update.*) se résolvent toujours en operator.admin.
Le scope de méthode n’est que le premier contrôle. Certaines commandes slash atteintes via
chat.send appliquent en plus des vérifications plus strictes au niveau de la commande. Par exemple, les écritures
persistantes /config set et /config unset requièrent operator.admin.
node.pair.approve a aussi une vérification de scope supplémentaire au moment de l’approbation, au-dessus du
scope de méthode de base :
- requêtes sans commande :
operator.pairing - requêtes avec commandes de nœud hors exec :
operator.pairing+operator.write - requêtes qui incluent
system.run,system.run.prepareousystem.which:operator.pairing+operator.admin
Caps/commands/permissions (node)
Les nœuds déclarent des revendications de capacité au moment de la connexion :caps: catégories de capacités de haut niveau.commands: liste d’autorisation de commandes pour l’invocation.permissions: bascules granulaires (par exemplescreen.record,camera.capture).
Présence
system-presencerenvoie des entrées indexées par identité d’appareil.- Les entrées de présence incluent
deviceId,rolesetscopesafin que les UI puissent afficher une seule ligne par appareil même lorsqu’il se connecte à la fois comme operator et comme node.
Portée des événements de diffusion
Les événements de diffusion WebSocket poussés par le serveur sont contrôlés par scope afin que les sessions limitées à l’appairage ou réservées aux nœuds ne reçoivent pas passivement le contenu des sessions.- Les trames de chat, d’agent et de résultat d’outil (y compris les événements
agentdiffusés en flux et les résultats d’appel d’outil) requièrent au minimumoperator.read. Les sessions sansoperator.readignorent entièrement ces trames. - Les diffusions
plugin.*définies par les Plugin sont contrôlées paroperator.writeouoperator.admin, selon la façon dont le Plugin les a enregistrées. - Les événements d’état et de transport (
heartbeat,presence,tick, cycle de vie de connexion/déconnexion, etc.) restent non restreints afin que la santé du transport reste observable pour chaque session authentifiée. - Les familles d’événements de diffusion inconnues sont contrôlées par scope par défaut (échec fermé), sauf si un gestionnaire enregistré les assouplit explicitement.
Familles de méthodes RPC courantes
Cette page n’est pas une exportation générée complète, mais la surface WS publique est plus large que les exemples de poignée de main/authentification ci-dessus. Voici les principales familles de méthodes que la Gateway expose aujourd’hui.hello-ok.features.methods est une liste de découverte conservative construite à partir de
src/gateway/server-methods-list.ts plus les exportations de méthodes Plugin/canal chargées.
Traitez-la comme une découverte de fonctionnalités, et non comme une exportation générée de chaque assistant appelable
implémenté dans src/gateway/server-methods/*.ts.
Système et identité
healthrenvoie l’instantané de santé de la gateway, mis en cache ou fraîchement sondé.statusrenvoie le résumé de type/statusde la gateway ; les champs sensibles sont inclus uniquement pour les clients operator à scope admin.gateway.identity.getrenvoie l’identité d’appareil de la gateway utilisée par les flux de relais et d’appairage.system-presencerenvoie l’instantané de présence actuel pour les appareils operator/node connectés.system-eventajoute un événement système et peut mettre à jour/diffuser le contexte de présence.last-heartbeatrenvoie le dernier événement Heartbeat persisté.set-heartbeatsactive ou désactive le traitement Heartbeat sur la gateway.
Modèles et utilisation
models.listrenvoie le catalogue de modèles autorisés à l’exécution.usage.statusrenvoie les fenêtres d’utilisation fournisseur / résumés de quota restant.usage.costrenvoie des résumés agrégés de coût d’utilisation pour une plage de dates.doctor.memory.statusrenvoie l’état de préparation de la mémoire vectorielle / des embeddings pour l’espace de travail de l’agent par défaut actif.sessions.usagerenvoie des résumés d’utilisation par session.sessions.usage.timeseriesrenvoie une série temporelle d’utilisation pour une session.sessions.usage.logsrenvoie les entrées de journal d’utilisation pour une session.
Canaux et assistants de connexion
channels.statusrenvoie les résumés d’état des canaux/Plugin intégrés + fournis.channels.logoutdéconnecte un canal/compte spécifique lorsque le canal prend en charge la déconnexion.web.login.startdémarre un flux de connexion QR/web pour le fournisseur de canal web actuel compatible QR.web.login.waitattend que ce flux de connexion QR/web se termine et démarre le canal en cas de réussite.push.testenvoie une notification push APNs de test à un nœud iOS enregistré.voicewake.getrenvoie les déclencheurs de mot d’activation enregistrés.voicewake.setmet à jour les déclencheurs de mot d’activation et diffuse la modification.
Messagerie et journaux
sendest la RPC de livraison sortante directe pour les envois ciblés par canal/compte/fil en dehors du moteur de chat.logs.tailrenvoie la fin configurée du journal de fichiers de la gateway avec curseur/limite et contrôles du nombre maximal d’octets.
Talk et TTS
talk.configrenvoie la charge utile de configuration Talk effective ;includeSecretsrequiertoperator.talk.secrets(ouoperator.admin).talk.modedéfinit/diffuse l’état actuel du mode Talk pour les clients WebChat/Control UI.talk.speaksynthétise la parole via le fournisseur de parole Talk actif.tts.statusrenvoie l’état d’activation TTS, le fournisseur actif, les fournisseurs de repli, et l’état de configuration du fournisseur.tts.providersrenvoie l’inventaire visible des fournisseurs TTS.tts.enableettts.disableactivent ou désactivent l’état des préférences TTS.tts.setProvidermet à jour le fournisseur TTS préféré.tts.convertexécute une conversion texte-parole ponctuelle.
Secrets, config, mise à jour et assistant
secrets.reloadre-résout les SecretRef actifs et échange l’état des secrets à l’exécution uniquement en cas de succès complet.secrets.resolverésout les affectations de secrets ciblées par commande pour un ensemble spécifique commande/cible.config.getrenvoie l’instantané de configuration actuel et son hash.config.setécrit une charge utile de configuration validée.config.patchfusionne une mise à jour partielle de configuration.config.applyvalide puis remplace la charge utile de configuration complète.config.schemarenvoie la charge utile du schéma de configuration en direct utilisée par Control UI et l’outillage CLI : schéma,uiHints, version et métadonnées de génération, y compris les métadonnées de schéma Plugin + canal lorsque l’exécution peut les charger. Le schéma inclut les métadonnées de champtitle/descriptiondérivées des mêmes libellés et textes d’aide utilisés par l’UI, y compris pour les objets imbriqués, jokers, éléments de tableau et branches de compositionanyOf/oneOf/allOflorsque la documentation de champ correspondante existe.config.schema.lookuprenvoie une charge utile de recherche limitée à un chemin pour un chemin de config : chemin normalisé, nœud de schéma superficiel, indice correspondant +hintPath, et résumés des enfants immédiats pour l’exploration UI/CLI.- Les nœuds de schéma de recherche conservent la documentation orientée utilisateur et les champs de validation courants :
title,description,type,enum,const,format,pattern, bornes numériques/chaînes/tableaux/objets, et indicateurs booléens tels queadditionalProperties,deprecated,readOnly,writeOnly. - Les résumés d’enfants exposent
key, lepathnormalisé,type,required,hasChildren, ainsi que lehint/hintPathcorrespondant.
- Les nœuds de schéma de recherche conservent la documentation orientée utilisateur et les champs de validation courants :
update.runexécute le flux de mise à jour de la gateway et planifie un redémarrage uniquement lorsque la mise à jour elle-même a réussi.wizard.start,wizard.next,wizard.statusetwizard.cancelexposent l’assistant d’intégration via WS RPC.
Familles majeures existantes
Assistants d’agent et d’espace de travail
agents.listrenvoie les entrées d’agent configurées.agents.create,agents.updateetagents.deletegèrent les enregistrements d’agent et le raccordement de l’espace de travail.agents.files.list,agents.files.getetagents.files.setgèrent les fichiers d’espace de travail d’amorçage exposés pour un agent.agent.identity.getrenvoie l’identité effective de l’assistant pour un agent ou une session.agent.waitattend qu’une exécution se termine et renvoie l’instantané terminal lorsque disponible.
Contrôle de session
sessions.listrenvoie l’index actuel des sessions.sessions.subscribeetsessions.unsubscribeactivent ou désactivent les abonnements aux événements de changement de session pour le client WS actuel.sessions.messages.subscribeetsessions.messages.unsubscribeactivent ou désactivent les abonnements aux événements de transcription/message pour une session.sessions.previewrenvoie des aperçus bornés de transcription pour des clés de session spécifiques.sessions.resolverésout ou canonise une cible de session.sessions.createcrée une nouvelle entrée de session.sessions.sendenvoie un message dans une session existante.sessions.steerest la variante d’interruption et de pilotage pour une session active.sessions.abortinterrompt le travail actif d’une session.sessions.patchmet à jour les métadonnées/remplacements d’une session.sessions.reset,sessions.deleteetsessions.compacteffectuent la maintenance de session.sessions.getrenvoie la ligne complète de session stockée.- L’exécution de chat utilise toujours
chat.history,chat.send,chat.abortetchat.inject. chat.historyest normalisé pour l’affichage pour les clients UI : les balises de directive inline sont supprimées du texte visible, les charges utiles XML d’appel d’outil en texte brut (y compris<tool_call>...</tool_call>,<function_call>...</function_call>,<tool_calls>...</tool_calls>,<function_calls>...</function_calls>, et les blocs d’appel d’outil tronqués) ainsi que les jetons de contrôle de modèle ASCII/pleine largeur divulgués sont supprimés, les lignes d’assistant constituées uniquement de jetons silencieux telles queNO_REPLY/no_replyexact sont omises, et les lignes surdimensionnées peuvent être remplacées par des espaces réservés.
Appairage d’appareil et jetons d’appareil
device.pair.listrenvoie les appareils appairés en attente et approuvés.device.pair.approve,device.pair.rejectetdevice.pair.removegèrent les enregistrements d’appairage d’appareil.device.token.rotatefait pivoter un jeton d’appareil appairé dans les limites de rôle et de scope approuvées.device.token.revokerévoque un jeton d’appareil appairé.
Appairage de nœud, invocation et travail en attente
node.pair.request,node.pair.list,node.pair.approve,node.pair.rejectetnode.pair.verifycouvrent l’appairage de nœud et la vérification d’amorçage.node.listetnode.describerenvoient l’état des nœuds connus/connectés.node.renamemet à jour le libellé d’un nœud appairé.node.invoketransmet une commande à un nœud connecté.node.invoke.resultrenvoie le résultat d’une requête d’invocation.node.eventtransporte les événements d’origine nœud vers la gateway.node.canvas.capability.refreshactualise les jetons de capacité canvas à portée limitée.node.pending.pulletnode.pending.acksont les API de file d’attente pour nœud connecté.node.pending.enqueueetnode.pending.draingèrent le travail en attente durable pour les nœuds hors ligne/déconnectés.
Familles d’approbation
exec.approval.request,exec.approval.get,exec.approval.listetexec.approval.resolvecouvrent les requêtes ponctuelles d’approbation exec ainsi que la recherche/relecture des approbations en attente.exec.approval.waitDecisionattend une approbation exec en attente et renvoie la décision finale (ounullen cas d’expiration).exec.approvals.getetexec.approvals.setgèrent les instantanés de politique d’approbation exec de la gateway.exec.approvals.node.getetexec.approvals.node.setgèrent la politique locale exec d’un nœud via des commandes de relais de nœud.plugin.approval.request,plugin.approval.list,plugin.approval.waitDecisionetplugin.approval.resolvecouvrent les flux d’approbation définis par des Plugin.
Autres familles majeures
- automatisation :
wakeplanifie une injection immédiate ou au prochain Heartbeat d’un texte de réveilcron.list,cron.status,cron.add,cron.update,cron.remove,cron.run,cron.runs
- skills/outils :
commands.list,skills.*,tools.catalog,tools.effective
Familles d’événements courantes
chat: mises à jour de chat UI telles quechat.injectet autres événements de chat uniquement de transcription.session.messageetsession.tool: mises à jour de transcription/flux d’événements pour une session abonnée.sessions.changed: l’index de session ou les métadonnées ont changé.presence: mises à jour de l’instantané de présence système.tick: événement périodique de maintien en vie / vivacité.health: mise à jour de l’instantané de santé de la gateway.heartbeat: mise à jour du flux d’événements Heartbeat.cron: événement de changement d’exécution/de tâche Cron.shutdown: notification d’arrêt de la gateway.node.pair.requested/node.pair.resolved: cycle de vie d’appairage de nœud.node.invoke.request: diffusion de requête d’invocation de nœud.device.pair.requested/device.pair.resolved: cycle de vie d’appareil appairé.voicewake.changed: la configuration des déclencheurs de mot d’activation a changé.exec.approval.requested/exec.approval.resolved: cycle de vie d’approbation exec.plugin.approval.requested/plugin.approval.resolved: cycle de vie d’approbation de Plugin.
Méthodes d’assistance pour nœud
- Les nœuds peuvent appeler
skills.binspour récupérer la liste actuelle des exécutables de skill pour les vérifications d’autorisation automatique.
Méthodes d’assistance pour operator
- Les operators peuvent appeler
commands.list(operator.read) pour récupérer l’inventaire des commandes à l’exécution pour un agent.agentIdest facultatif ; omettez-le pour lire l’espace de travail de l’agent par défaut.scopecontrôle quelle surface la valeur primairenamecible :textrenvoie le jeton de commande texte principal sans le/initialnativeet le chemin par défautbothrenvoient des noms natifs dépendants du fournisseur lorsqu’ils sont disponibles
textAliasestransporte les alias slash exacts tels que/modelet/m.nativeNametransporte le nom de commande native dépendant du fournisseur lorsqu’il existe.providerest facultatif et n’affecte que le nommage natif ainsi que la disponibilité des commandes natives de Plugin.includeArgs=falseomet les métadonnées d’arguments sérialisées de la réponse.
- Les operators peuvent appeler
tools.catalog(operator.read) pour récupérer le catalogue d’outils à l’exécution pour un agent. La réponse inclut les outils groupés et les métadonnées de provenance :source:coreoupluginpluginId: propriétaire du Plugin lorsquesource="plugin"optional: indique si un outil de Plugin est facultatif
- Les operators peuvent appeler
tools.effective(operator.read) pour récupérer l’inventaire d’outils effectif à l’exécution pour une session.sessionKeyest requis.- La gateway dérive le contexte d’exécution approuvé depuis la session côté serveur au lieu d’accepter un contexte d’authentification ou de livraison fourni par l’appelant.
- La réponse est limitée à la session et reflète ce que la conversation active peut utiliser à l’instant, y compris les outils core, Plugin et canal.
- Les operators peuvent appeler
skills.status(operator.read) pour récupérer l’inventaire visible des skills pour un agent.agentIdest facultatif ; omettez-le pour lire l’espace de travail de l’agent par défaut.- La réponse inclut l’éligibilité, les exigences manquantes, les vérifications de configuration et des options d’installation assainies sans exposer les valeurs de secret brutes.
- Les operators peuvent appeler
skills.searchetskills.detail(operator.read) pour les métadonnées de découverte ClawHub. - Les operators peuvent appeler
skills.install(operator.admin) selon deux modes :- Mode ClawHub :
{ source: "clawhub", slug, version?, force? }installe un dossier de skill dans le répertoireskills/de l’espace de travail de l’agent par défaut. - Mode programme d’installation gateway :
{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }exécute une action déclaréemetadata.openclaw.installsur l’hôte gateway.
- Mode ClawHub :
- Les operators peuvent appeler
skills.update(operator.admin) selon deux modes :- Le mode ClawHub met à jour un slug suivi ou toutes les installations ClawHub suivies dans l’espace de travail de l’agent par défaut.
- Le mode config applique un correctif aux valeurs
skills.entries.<skillKey>telles queenabled,apiKeyetenv.
Approbations Exec
- Lorsqu’une requête exec nécessite une approbation, la gateway diffuse
exec.approval.requested. - Les clients operator résolvent cela en appelant
exec.approval.resolve(requiert le scopeoperator.approvals). - Pour
host=node,exec.approval.requestdoit incluresystemRunPlan(argv/cwd/rawCommand/métadonnées de session canoniques). Les requêtes sanssystemRunPlansont rejetées. - Après approbation, les appels transmis
node.invoke system.runréutilisent cesystemRunPlancanonique comme contexte faisant autorité pour la commande/le répertoire courant/la session. - Si un appelant modifie
command,rawCommand,cwd,agentIdousessionKeyentreprepareet le transfert final approuvésystem.run, la gateway rejette l’exécution au lieu de faire confiance à la charge utile modifiée.
Repli de livraison d’agent
- Les requêtes
agentpeuvent incluredeliver=truepour demander une livraison sortante. bestEffortDeliver=falseconserve un comportement strict : les cibles de livraison non résolues ou internes uniquement renvoientINVALID_REQUEST.bestEffortDeliver=truepermet un repli vers une exécution limitée à la session lorsqu’aucune route livrable externe ne peut être résolue (par exemple sessions internes/webchat ou configurations multi-canaux ambiguës).
Gestion des versions
PROTOCOL_VERSIONse trouve danssrc/gateway/protocol/schema/protocol-schemas.ts.- Les clients envoient
minProtocol+maxProtocol; le serveur rejette les incompatibilités. - Les schémas + modèles sont générés à partir des définitions TypeBox :
pnpm protocol:genpnpm protocol:gen:swiftpnpm protocol:check
Constantes client
Le client de référence danssrc/gateway/client.ts utilise ces valeurs par défaut. Les valeurs sont
stables sur le protocole v3 et constituent la base attendue pour les clients tiers.
| Constante | Valeur par défaut | Source |
|---|---|---|
PROTOCOL_VERSION | 3 | src/gateway/protocol/schema/protocol-schemas.ts |
| Délai d’expiration des requêtes (par RPC) | 30_000 ms | src/gateway/client.ts (requestTimeoutMs) |
| Délai d’expiration preauth / connect-challenge | 10_000 ms | src/gateway/handshake-timeouts.ts (plage 250–10_000) |
| Backoff initial de reconnexion | 1_000 ms | src/gateway/client.ts (backoffMs) |
| Backoff maximal de reconnexion | 30_000 ms | src/gateway/client.ts (scheduleReconnect) |
| Limite de nouvelle tentative rapide après fermeture par jeton d’appareil | 250 ms | src/gateway/client.ts |
Délai de grâce avant terminate() en arrêt forcé | 250 ms | FORCE_STOP_TERMINATE_GRACE_MS |
Délai d’expiration par défaut de stopAndWait() | 1_000 ms | STOP_AND_WAIT_TIMEOUT_MS |
Intervalle de tick par défaut (avant hello-ok) | 30_000 ms | src/gateway/client.ts |
| Fermeture sur expiration du tick | code 4000 lorsque le silence dépasse tickIntervalMs * 2 | src/gateway/client.ts |
MAX_PAYLOAD_BYTES | 25 * 1024 * 1024 (25 MB) | src/gateway/server-constants.ts |
policy.tickIntervalMs, policy.maxPayload
et policy.maxBufferedBytes dans hello-ok ; les clients doivent respecter ces valeurs
plutôt que les valeurs par défaut d’avant la poignée de main.
Auth
- L’authentification Gateway par secret partagé utilise
connect.params.auth.tokenouconnect.params.auth.password, selon le mode d’authentification configuré. - Les modes porteurs d’identité tels que Tailscale Serve
(
gateway.auth.allowTailscale: true) ou le mode non-loopbackgateway.auth.mode: "trusted-proxy"satisfont la vérification d’authentification de connexion à partir des en-têtes de requête au lieu deconnect.params.auth.*. - Le mode d’entrée privée
gateway.auth.mode: "none"ignore entièrement l’authentification de connexion par secret partagé ; n’exposez pas ce mode sur une entrée publique/non approuvée. - Après l’appairage, la Gateway émet un jeton d’appareil limité au rôle + aux scopes de la connexion.
Il est renvoyé dans
hello-ok.auth.deviceTokenet doit être persisté par le client pour les futures connexions. - Les clients doivent persister le
hello-ok.auth.deviceTokenprincipal après toute connexion réussie. - Une reconnexion avec ce jeton d’appareil stocké doit également réutiliser l’ensemble de scopes approuvés stocké pour ce jeton. Cela préserve l’accès lecture/sonde/état déjà accordé et évite de réduire silencieusement les reconnexions à un scope implicite plus étroit limité à l’administration.
- Assemblage de l’authentification de connexion côté client (
selectConnectAuthdanssrc/gateway/client.ts) :auth.passwordest orthogonal et est toujours transmis lorsqu’il est défini.auth.tokenest renseigné dans l’ordre de priorité suivant : d’abord le jeton partagé explicite, puis undeviceTokenexplicite, puis un jeton par appareil stocké (indexé pardeviceId+role).auth.bootstrapTokenn’est envoyé que si aucun des éléments ci-dessus n’a résolu unauth.token. Un jeton partagé ou tout jeton d’appareil résolu le supprime.- La promotion automatique d’un jeton d’appareil stocké lors de la nouvelle tentative ponctuelle
AUTH_TOKEN_MISMATCHest limitée aux points de terminaison approuvés uniquement — loopback, ouwss://avec untlsFingerprintépinglé. Unwss://public sans épinglage n’est pas admissible.
- Les entrées supplémentaires
hello-ok.auth.deviceTokenssont des jetons de transfert d’amorçage. Ne les persistez que lorsque la connexion a utilisé une authentification d’amorçage sur un transport approuvé tel quewss://ou loopback/appairage local. - Si un client fournit un
deviceTokenexplicite ou desscopesexplicites, cet ensemble de scopes demandé par l’appelant reste faisant autorité ; les scopes en cache ne sont réutilisés que lorsque le client réutilise le jeton par appareil stocké. - Les jetons d’appareil peuvent être pivotés/révoqués via
device.token.rotateetdevice.token.revoke(requiert le scopeoperator.pairing). - L’émission/la rotation de jeton reste bornée à l’ensemble de rôles approuvé enregistré dans l’entrée d’appairage de cet appareil ; faire pivoter un jeton ne peut pas étendre l’appareil à un rôle que l’approbation d’appairage n’a jamais accordé.
- Pour les sessions à jeton d’appareil appairé, la gestion d’appareil est limitée au périmètre de l’appareil lui-même sauf si l’appelant
possède aussi
operator.admin: les appelants non administrateurs ne peuvent supprimer/révoquer/faire pivoter que leur propre entrée d’appareil. device.token.rotatevérifie également l’ensemble de scopes operator demandé par rapport aux scopes actuels de la session de l’appelant. Les appelants non administrateurs ne peuvent pas faire pivoter un jeton vers un ensemble de scopes operator plus large que celui qu’ils détiennent déjà.- Les échecs d’authentification incluent
error.details.codeainsi que des indications de récupération :error.details.canRetryWithDeviceToken(booléen)error.details.recommendedNextStep(retry_with_device_token,update_auth_configuration,update_auth_credentials,wait_then_retry,review_auth_configuration)
- Comportement client pour
AUTH_TOKEN_MISMATCH:- Les clients approuvés peuvent tenter une nouvelle tentative limitée avec un jeton par appareil en cache.
- Si cette nouvelle tentative échoue, les clients doivent arrêter les boucles automatiques de reconnexion et afficher des instructions d’action à l’opérateur.
Identité d’appareil + appairage
- Les nœuds doivent inclure une identité d’appareil stable (
device.id) dérivée de l’empreinte d’une paire de clés. - Les gateways émettent des jetons par appareil + rôle.
- Des approbations d’appairage sont requises pour les nouveaux IDs d’appareil, sauf si l’approbation automatique locale est activée.
- L’approbation automatique d’appairage est centrée sur les connexions loopback locales directes.
- OpenClaw dispose également d’un chemin étroit d’auto-connexion locale backend/conteneur pour des flux d’assistance à secret partagé approuvés.
- Les connexions tailnet ou LAN sur le même hôte sont toujours traitées comme distantes pour l’appairage et nécessitent une approbation.
- Tous les clients WS doivent inclure l’identité
devicelors deconnect(operator + node). Control UI ne peut l’omettre que dans ces modes :gateway.controlUi.allowInsecureAuth=truepour la compatibilité HTTP non sécurisée sur localhost uniquement.- authentification operator réussie de Control UI avec
gateway.auth.mode: "trusted-proxy". gateway.controlUi.dangerouslyDisableDeviceAuth=true(mode d’urgence, dégradation grave de la sécurité).
- Toutes les connexions doivent signer le nonce
connect.challengefourni par le serveur.
Diagnostics de migration de l’authentification d’appareil
Pour les clients hérités qui utilisent encore le comportement de signature antérieur au challenge,connect renvoie désormais
des codes de détail DEVICE_AUTH_* sous error.details.code avec une valeur stable error.details.reason.
Échecs de migration courants :
| Message | details.code | details.reason | Signification |
|---|---|---|---|
device nonce required | DEVICE_AUTH_NONCE_REQUIRED | device-nonce-missing | Le client a omis device.nonce (ou l’a envoyé vide). |
device nonce mismatch | DEVICE_AUTH_NONCE_MISMATCH | device-nonce-mismatch | Le client a signé avec un nonce obsolète/incorrect. |
device signature invalid | DEVICE_AUTH_SIGNATURE_INVALID | device-signature | La charge utile de signature ne correspond pas à la charge utile v2. |
device signature expired | DEVICE_AUTH_SIGNATURE_EXPIRED | device-signature-stale | L’horodatage signé est en dehors de la dérive autorisée. |
device identity mismatch | DEVICE_AUTH_DEVICE_ID_MISMATCH | device-id-mismatch | device.id ne correspond pas à l’empreinte de la clé publique. |
device public key invalid | DEVICE_AUTH_PUBLIC_KEY_INVALID | device-public-key | Le format/la canonicalisation de la clé publique a échoué. |
- Attendez toujours
connect.challenge. - Signez la charge utile v2 qui inclut le nonce du serveur.
- Envoyez le même nonce dans
connect.params.device.nonce. - La charge utile de signature préférée est
v3, qui lieplatformetdeviceFamilyen plus des champs appareil/client/rôle/scopes/jeton/nonce. - Les signatures héritées
v2restent acceptées pour compatibilité, mais l’épinglage des métadonnées d’appareil appairé contrôle toujours la politique de commande à la reconnexion.
TLS + épinglage
- TLS est pris en charge pour les connexions WS.
- Les clients peuvent facultativement épingler l’empreinte du certificat de la gateway (voir la configuration
gateway.tlsainsi quegateway.remote.tlsFingerprintou l’option CLI--tls-fingerprint).
Portée
Ce protocole expose l’API gateway complète (état, canaux, modèles, chat, agent, sessions, nœuds, approbations, etc.). La surface exacte est définie par les schémas TypeBox danssrc/gateway/protocol/schema.ts.