Gateway
Protocole du Gateway
Le protocole WS du Gateway constitue l’unique plan de contrôle et le transport des nœuds pour OpenClaw. Les clients opérateurs et nœuds (CLI, interface Web, application macOS, nœuds iOS/Android, nœuds sans interface) se connectent via WebSocket et déclarent un rôle et une portée lors de la négociation initiale.
Transport et tramage
- WebSocket, trames texte, charges utiles JSON.
- La première trame doit être une requête
connect. - Les trames précédant la connexion sont limitées à 64 KiB (
MAX_PREAUTH_PAYLOAD_BYTES). Après la négociation initiale, respectezhello-ok.policy.maxPayloadethello-ok.policy.maxBufferedBytes. Lorsque les diagnostics sont activés, les trames entrantes surdimensionnées et les tampons sortants lents émettent des événementspayload.largeavant que le Gateway ferme la connexion ou abandonne la trame. Ces événements contiennentsurface, les tailles en octets, les limites et un code de motif sûr, mais jamais le corps des messages, le contenu des pièces jointes, les octets bruts des trames, les jetons, les cookies ou les secrets.
Formats des trames :
- Requête :
{type:"req", id, method, params} - Réponse :
{type:"res", id, ok, payload|error} - Événement :
{type:"event", event, payload, seq?, stateVersion?}
Les méthodes produisant des effets de bord nécessitent des clés d’idempotence (voir le schéma).
Négociation initiale
Le Gateway envoie un défi avant la connexion :
{ "type": "event", "event": "connect.challenge", "payload": { "nonce": "…", "ts": 1737264000000 }}Le client répond avec connect :
{ "type": "req", "id": "…", "method": "connect", "params": { "minProtocol": 4, "maxProtocol": 4, "client": { "id": "cli", "version": "1.2.3", "platform": "macos", "mode": "operator" }, "role": "operator", "scopes": ["operator.read", "operator.write"], "caps": [], "commands": [], "permissions": {}, "auth": { "token": "…" }, "locale": "en-US", "userAgent": "openclaw-cli/1.2.3", "device": { "id": "device_fingerprint", "publicKey": "…", "signature": "…", "signedAt": 1737264000000, "nonce": "…" } }}Le Gateway répond avec hello-ok :
{ "type": "res", "id": "…", "ok": true, "payload": { "type": "hello-ok", "protocol": 4, "server": { "version": "…", "connId": "…" }, "features": { "methods": ["…"], "events": ["…"] }, "snapshot": { "…": "…" }, "auth": { "role": "operator", "scopes": ["operator.read", "operator.write"] }, "policy": { "maxPayload": 26214400, "maxBufferedBytes": 52428800, "tickIntervalMs": 15000 } }}server, features, snapshot, policy et auth sont tous requis par
HelloOkSchema (packages/gateway-protocol/src/schema/frames.ts). auth
indique le rôle et les portées négociés même lorsqu’aucun jeton d’appareil n’est émis (format
ci-dessus). pluginSurfaceUrls est facultatif et associe les noms de surfaces de Plugin (par exemple
canvas) à des URL hébergées et limitées à leur portée ; ces URL pouvant expirer, les nœuds appellent
node.pluginSurface.refresh avec { "surface": "canvas" } pour obtenir une nouvelle entrée.
Le chemin obsolète canvasHostUrl / canvasCapability / node.canvas.capability.refresh
n’est pas pris en charge ; utilisez les surfaces de Plugin.
Pendant que le Gateway termine encore le démarrage des processus auxiliaires, connect peut renvoyer une
erreur UNAVAILABLE pouvant faire l’objet d’une nouvelle tentative, avec details.reason: "startup-sidecars" et
retryAfterMs. Réessayez dans la limite de votre délai de connexion au lieu de considérer cela comme
un échec définitif de la négociation initiale.
Lorsqu’un jeton d’appareil est émis, hello-ok.auth l’ajoute :
{ "auth": { "deviceToken": "…", "role": "operator", "scopes": ["operator.read", "operator.write"] }}L’amorçage intégré par code QR/code de configuration est un chemin de transfert mobile. Une connexion réussie avec un code de configuration de base renvoie un jeton de nœud principal ainsi qu’un jeton opérateur limité :
{ "auth": { "deviceToken": "…", "role": "node", "scopes": [], "deviceTokens": [ { "deviceToken": "…", "role": "operator", "scopes": ["operator.approvals", "operator.read", "operator.talk.secrets", "operator.write"] } ] }}Ce transfert à l’opérateur est volontairement limité : il suffit pour démarrer la boucle
de l’opérateur mobile et la configuration native, notamment operator.talk.secrets pour les lectures
de configuration de Talk, mais n’inclut aucune portée de modification de l’appairage ni operator.admin. Un accès
plus étendu à l’appairage ou à l’administration nécessite un flux distinct d’appairage approuvé ou de jeton. Ne conservez
hello-ok.auth.deviceTokens que lorsque l’authentification d’amorçage a été effectuée via un
transport fiable (wss:// ou un appairage en boucle locale/local).
Les clients backend fiables exécutés dans le même processus (client.id: "gateway-client",
client.mode: "backend") peuvent omettre device sur les connexions directes en boucle locale lorsqu’ils
s’authentifient avec le jeton ou le mot de passe partagé du Gateway. Ce chemin est réservé
aux RPC internes du plan de contrôle (par exemple, les mises à jour de session de sous-agent) et évite
que des références d’appairage CLI/appareil obsolètes bloquent les opérations locales du backend. Les clients distants,
issus d’un navigateur, de type nœud, ou utilisant explicitement un jeton d’appareil ou une identité d’appareil passent toujours
par les contrôles normaux d’appairage et d’élévation de portée.
Rôle de worker et protocole fermé
Les workers cloud utilisent un point d’entrée dédié en boucle locale via le tunnel SSH appartenant au Gateway,
avec clé d’hôte épinglée. Il accepte uniquement l’identité du worker et ne distribue jamais
l’authentification générale, les événements de nœuds, les RPC d’opérateur ou les méthodes de Plugin. Un connect
strict vérifie un identifiant de connexion de courte durée, stocké sous forme de hachage et lié à l’environnement, au hachage
du paquet, à l’époque du propriétaire, à la version de l’ensemble de RPC, à l’expiration et à une session nullable ; il
vérifie séparément la version et l’ensemble de fonctionnalités actuels. En cas de réussite, il renvoie un
worker-hello-ok minimal ; la négociation des fonctionnalités est indépendante de la version générale du protocole.
Les trames restent inférieures à 64 KiB. La liste d’autorisation fermée contient
worker.heartbeat, worker.transcript.commit et worker.live-event.
Les validations de transcription utilisent une clôture par époque du propriétaire, une liaison de session appartenant au Gateway, une opération
de comparaison-échange sur la feuille de base et une relecture durable des séquences ; le Gateway génère les identifiants
d’entrée et de parent de transcription au moyen du mécanisme normal d’écriture de session. La propriété et l’expiration sont
revérifiées à chaque RPC.
Capacités du client
Les clients opérateurs peuvent annoncer des capacités facultatives dans connect.params.caps :
tool-events: accepte les événements structurés du cycle de vie des outils.inline-widgets: peut afficher les résultats d’outils sous forme de widgets intégrés hébergés.
Les capacités du client décrivent le client connecté, et non l’autorisation. Les outils d’agent peuvent déclarer des capacités requises ; le Gateway omet ces outils sauf si chaque exigence figure dans les caps du client d’origine. Les exécutions provenant d’un canal ne disposent d’aucune capacité de client Gateway ; les outils soumis à des capacités sont donc indisponibles même lorsque la politique des outils les autorise explicitement.
Exemple de connexion d’un nœud
{ "type": "req", "id": "…", "method": "connect", "params": { "minProtocol": 4, "maxProtocol": 4, "client": { "id": "ios-node", "version": "1.2.3", "platform": "ios", "mode": "node" }, "role": "node", "scopes": [], "caps": ["camera", "canvas", "screen", "location", "voice"], "commands": ["camera.snap", "canvas.navigate", "screen.record", "location.get"], "permissions": { "camera.capture": true, "screen.record": false }, "auth": { "token": "…" }, "locale": "en-US", "userAgent": "openclaw-ios/1.2.3", "device": { "id": "device_fingerprint", "publicKey": "…", "signature": "…", "signedAt": 1737264000000, "nonce": "…" } }}Les nœuds déclarent leurs capacités revendiquées au moment de la connexion :
caps: catégories générales telles quecamera,canvas,screen,location,voice,talk.commands: liste d’autorisation des commandes pouvant être invoquées.permissions: paramètres granulaires (par exemplescreen.record,camera.capture).
Le Gateway les considère comme des déclarations et applique les listes d’autorisation côté serveur.
Rôles et portées
Pour consulter le modèle complet des portées d’opérateur, les contrôles effectués au moment de l’approbation et la sémantique des secrets partagés, voir Portées d’opérateur.
Rôles :
operator: client du plan de contrôle (CLI/interface utilisateur/automatisation).node: hôte de capacités (caméra/écran/canvas/system.run).worker: hôte d’exécution cloud sur le protocole dédié et fermé des workers.
Portées d’opérateur (src/gateway/operator-scopes.ts), ensemble fermé complet :
operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairingoperator.talk.secrets
talk.config avec includeSecrets: true nécessite operator.talk.secrets (ou
operator.admin). Lorsque les secrets sont inclus, lisez l’identifiant de connexion du fournisseur Talk actif
dans talk.resolved.config.apiKey ; talk.providers.<id>.apiKey
conserve le format de la source et peut être un objet SecretRef ou une chaîne expurgée.
Les méthodes RPC du Gateway enregistrées par un Plugin peuvent demander leur propre portée d’opérateur,
mais ces préfixes principaux réservés correspondent toujours à operator.admin
(src/shared/gateway-method-policy.ts) : config.*, exec.approvals.*,
wizard.*, update.*.
La portée de la méthode n’est que le premier contrôle. Certaines commandes à barre oblique accessibles via
chat.send appliquent des contrôles plus stricts au niveau de la commande : les écritures persistantes /config set et
/config unset nécessitent operator.admin, même pour les clients Gateway qui
disposent déjà d’une portée d’opérateur inférieure.
node.pair.approve comporte un contrôle supplémentaire de la portée au moment de l’approbation, en plus de la
portée de base de la méthode (operator.pairing), fondé sur les commands déclarées
dans la requête en attente (src/infra/node-pairing-authz.ts) :
| Commandes déclarées | Portées requises |
|---|---|
| aucune | operator.pairing |
| commandes sans exécution | operator.pairing + operator.write |
inclut system.run, system.run.prepare ou system.which |
operator.pairing + operator.admin |
Capacités/commandes/autorisations (nœud)
Les nœuds déclarent leurs capacités revendiquées au moment de la connexion :
caps: catégories générales de capacités telles quecamera,canvas,screen,location,voiceettalk.commands: liste d’autorisation des commandes pouvant être invoquées.permissions: paramètres granulaires (par exemplescreen.record,camera.capture).
Le Gateway les considère comme des déclarations et applique les listes d’autorisation côté serveur.
Les nœuds connectés peuvent publier des descripteurs facultatifs d’outils Plugin ou MCP visibles par l’agent
avec node.pluginTools.update après une connexion ou une reconnexion réussie.
Les hôtes de nœuds sans interface redémarrent pour appliquer les modifications déclaratives de l’inventaire MCP.
Cette méthode de mise à jour est l’unique chemin de publication ; les descripteurs d’outils de Plugin ne sont pas acceptés dans
les paramètres de connect. Chaque descripteur doit utiliser un name d’outil compatible avec le fournisseur et désigner
une command figurant dans la liste d’autorisation actuelle des commandes du nœud. Le Gateway fait confiance aux métadonnées
des descripteurs provenant du nœud appairé, filtre les descripteurs qui ne font pas partie de la surface de commandes approuvée,
les supprime lorsque le nœud se déconnecte et rejette les tentatives d’un opérateur
de modifier le catalogue d’un autre nœud. Définissez gateway.nodes.pluginTools.enabled: false
pour ignorer les descripteurs publiés par les nœuds.
Les hôtes de nœuds connectés publient leur catalogue complet de remplacement des compétences avec
node.skills.update. Cette méthode réservée au rôle de nœud constitue l’unique chemin de publication
des compétences du nœud ; les compétences ne sont pas acceptées dans les paramètres de connect. Chaque descripteur contient un
nom sûr, une description et un contenu SKILL.md de taille limitée. Le Gateway analyse ce
contenu avec le chargeur de compétences normal, l’inclut dans les instantanés de compétences de l’agent
tant que le nœud est connecté et le supprime lors de la déconnexion. Définissez
gateway.nodes.skills.enabled: false pour ignorer les compétences publiées par les nœuds.
Présence
system-presencerenvoie des entrées indexées par identité d’appareil, notammentdeviceId,rolesetscopes, afin que les interfaces utilisateur puissent afficher une ligne par appareil même lorsqu’il se connecte à la fois comme opérateur et comme nœud.node.listinclut les champs facultatifslastSeenAtMsetlastSeenReason. Les nœuds connectés indiquent l’heure de connexion actuelle avec le motifconnect; les nœuds appairés peuvent également signaler une présence durable en arrière-plan via un événement de nœud fiable.
Les nœuds macOS natifs peuvent également envoyer des événements node.presence.activity
authentifiés avec une durée d’inactivité d’entrée limitée. Le Gateway détermine les
horodatages d’activité selon sa propre horloge, expose le Mac connecté le plus récent via
node.list et node.describe, et diffuse les mises à jour node.presence aux clients
disposant d’une portée de lecture. Consultez Présence active de l’ordinateur
pour en savoir plus sur la sélection, la confidentialité, le contexte du modèle et le
comportement de routage des notifications.
Événement de maintien en vie du nœud en arrière-plan
Les nœuds appellent node.event avec event: "node.presence.alive" pour enregistrer qu’un
nœud appairé était actif lors d’un réveil en arrière-plan, sans le marquer comme connecté :
{ "event": "node.presence.alive", "payloadJSON": "{\"trigger\":\"silent_push\",\"sentAtMs\":1737264000000,\"displayName\":\"Peter's iPhone\",\"version\":\"2026.4.28\",\"platform\":\"iOS 18.4.0\",\"deviceFamily\":\"iPhone\",\"modelIdentifier\":\"iPhone17,1\",\"pushTransport\":\"relay\"}"}trigger est une énumération fermée : background, silent_push, bg_app_refresh,
significant_location, manual, connect. Les valeurs inconnues sont normalisées en
background (src/shared/node-presence.ts). L’événement n’est conservé que pour les
sessions authentifiées d’appareils nœuds ; les sessions sans appareil ou non appairées
renvoient handled: false.
Les Gateways qui réussissent renvoient un résultat structuré :
{ "ok": true, "event": "node.presence.alive", "handled": true, "reason": "persisted"}Les anciens Gateways peuvent uniquement renvoyer { "ok": true } pour node.event ;
considérez cela comme un RPC acquitté, et non comme une persistance durable de la présence.
Portée des événements diffusés
Les événements de diffusion envoyés par le serveur sont filtrés selon la portée afin que
les sessions limitées à l’appairage ou aux nœuds ne reçoivent pas passivement le contenu
des sessions (src/gateway/server-broadcast.ts) :
- Les trames de chat, d’agent et de résultats d’outils (événements
agentdiffusés en continu, événements de résultats d’outils) nécessitent au minimumoperator.read. Les sessions qui n’en disposent pas ignorent entièrement ces trames. - Les diffusions
plugin.*définies par les Plugins sont limitées par défaut àoperator.writeouoperator.admin; les entrées explicites telles queplugin.approval.requested/plugin.approval.resolvedutilisent plutôtoperator.approvals. - Les événements d’état et de transport (
heartbeat,presence,tick, cycle de vie de connexion/déconnexion) restent sans restriction afin que l’état du transport soit observable par chaque session authentifiée. - Les familles inconnues d’événements diffusés sont filtrées par portée par défaut (fermeture en cas d’échec), sauf si un gestionnaire enregistré les assouplit explicitement.
Chaque connexion cliente conserve son propre numéro de séquence par client, de sorte que les diffusions restent ordonnées de manière monotone sur ce socket, même lorsque différents clients voient des sous-ensembles distincts du flux d’événements, filtrés selon leur portée.
Familles de méthodes RPC
hello-ok.features.methods est une liste de découverte prudente construite à partir de
src/gateway/server-methods-list.ts et des exportations de méthodes des Plugins/canaux
chargés — il ne s’agit pas d’une extraction générée de toutes les méthodes, et certaines
méthodes (par exemple push.test, web.login.start, web.login.wait, sessions.usage)
sont intentionnellement exclues de la découverte, bien qu’elles soient réelles et
appelables. Considérez cette liste comme un mécanisme de découverte des fonctionnalités,
et non comme une énumération complète de src/gateway/server-methods/*.ts.
Système et identité
healthrenvoie l’instantané de l’état du Gateway mis en cache ou récemment vérifié.diagnostics.stabilityrenvoie l’enregistreur limité de stabilité des diagnostics récents : noms d’événements, nombres, tailles en octets, relevés de mémoire, état des files d’attente/sessions, noms de canaux/Plugins, identifiants de session. Aucun texte de chat, corps de Webhook, résultat d’outil, corps brut de requête/réponse, jeton, cookie ou secret. Nécessiteoperator.read.statusrenvoie le résumé du Gateway au format de/status; les champs sensibles sont réservés aux clients opérateurs disposant de la portée d’administration.gateway.identity.getrenvoie l’identité de l’appareil Gateway utilisée par les flux de relais et d’appairage.system-presencerenvoie l’instantané de présence actuel des appareils opérateurs/nœuds 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 conservé.set-heartbeatsactive ou désactive le traitement des Heartbeats sur le Gateway.gateway.suspend.preparecrée un court bail de suspension coopérative uniquement lorsque le travail suivi du Gateway est inactif.gateway.suspend.statusvérifie ce bail, etgateway.suspend.resumele libère après la reprise ou l’abandon d’une opération de l’hôte.
Modèles et utilisation
models.listrenvoie le catalogue des modèles autorisés à l’exécution. Consultez « Vues demodels.list» ci-dessous.usage.statusrenvoie les fenêtres d’utilisation du fournisseur et les résumés des quotas restants.usage.costrenvoie les résumés agrégés des coûts d’utilisation pour une plage de dates. TransmettezagentIdpour un agent, ouagentScope: "all"pour agréger les agents configurés.doctor.memory.statusrenvoie l’état de préparation de la mémoire vectorielle / des représentations vectorielles mises en cache pour l’espace de travail actif de l’agent par défaut. Transmettez{ "probe": true }ou{ "deep": true }uniquement pour effectuer un ping direct explicite du fournisseur de représentations vectorielles. Transmettez{ "agentId": "agent-id" }pour limiter les statistiques du magasin Dreaming à l’espace de travail d’un agent ; si ce paramètre est omis, les espaces de travail Dreaming configurés sont agrégés.doctor.memory.dreamDiary,doctor.memory.backfillDreamDiary,doctor.memory.resetDreamDiary,doctor.memory.resetGroundedShortTerm,doctor.memory.repairDreamingArtifactsetdoctor.memory.dedupeDreamDiaryacceptent le paramètre facultatif{ "agentId": "agent-id" }; s’il est omis, ils opèrent sur l’espace de travail configuré de l’agent par défaut.doctor.memory.remHarnessrenvoie un aperçu limité et en lecture seule du banc d’essai REM pour les clients distants du plan de contrôle, comprenant les chemins des espaces de travail, des extraits de mémoire, le Markdown ancré généré et les candidats à la promotion profonde. Nécessiteoperator.read.sessions.usagerenvoie des résumés d’utilisation par session. TransmettezagentIdpour un agent, ouagentScope: "all"pour répertorier ensemble les agents configurés. Les deux méthodes d’utilisation acceptentmode: "specific"avec untimeZoneIANA pour des limites et des périodes de jours calendaires tenant compte de l’heure d’été.utcOffsetreste pris en charge pour les anciens clients et comme solution de repli lorsque l’environnement d’exécution du Gateway ne reconnaît pas le fuseau demandé.sessions.usage.timeseriesrenvoie les séries chronologiques d’utilisation d’une session.sessions.usage.logsrenvoie les entrées du journal d’utilisation d’une session.
Canaux et assistants de connexion
channels.statusrenvoie les résumés d’état des canaux/Plugins intégrés et fournis.channels.logoutdéconnecte un canal/compte précis lorsque le canal le permet.web.login.startlance un flux de connexion QR/Web pour le fournisseur actuel de canal Web compatible avec les codes QR.web.login.waitattend la fin de ce flux 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 mots de réveil enregistrés.voicewake.setmet à jour les déclencheurs de mots de réveil et diffuse la modification.
Gestion des Plugins
plugins.list(operator.read) renvoie l’inventaire des Plugins installés ainsi qu’une sélection officielle organisée localement, les diagnostics et une indication précisant si le mode d’installation actuel autorise les modifications.plugins.search(operator.read) recherche les familles de Plugins de code et de lots installables dans ClawHub. Transmettez unequerynon vide et unelimitfacultative comprise entre 1 et 100.plugins.install(operator.admin) installe soit une entrée du catalogue officiel avec{ source: "official", pluginId }, soit un paquet ClawHub avec{ source: "clawhub", packageName, version?, acknowledgeClawHubRisk? }. Les installations ClawHub préservent les vérifications de confiance, d’intégrité et de politique d’installation du Gateway. Les installations réussies nécessitent le redémarrage du Gateway.plugins.setEnabled(operator.admin) modifie la politique d’activation d’un Plugin installé avec{ pluginId, enabled }. La réponse comprend l’entrée de catalogue mise à jour, les métadonnées de redémarrage et tous les avertissements relatifs à la sélection d’emplacement.plugins.uninstall(operator.admin) supprime un Plugin installé en externe avec{ pluginId }: les références de configuration, l’enregistrement d’installation et les fichiers gérés. Les Plugins fournis ne peuvent pas être désinstallés, seulement désactivés. La réponse répertorie les actions de suppression et nécessite toujours le redémarrage du Gateway.
Messagerie et journaux
sendest le RPC de livraison sortante directe destiné aux envois ciblant un canal, un compte et un fil de discussion en dehors de l’exécuteur de chat.logs.tailrenvoie la fin configurée du journal fichier du Gateway avec des contrôles de curseur/limite et de nombre maximal d’octets.
Terminal de l’opérateur
terminal.opendémarre un PTY hôte pour unagentIdexplicite ou l’agent par défaut, puis renvoie l’agent résolu, le répertoire de travail, l’interpréteur de commandes et l’état de confinement.terminal.input,terminal.resizeetterminal.closeopèrent uniquement sur les sessions appartenant à la connexion appelante.- Les événements
terminal.dataetterminal.exitne sont diffusés qu’à la connexion propriétaire de la session. - Les sessions dont la connexion est interrompue sont détachées, et non arrêtées : elles restent rattachables pendant
gateway.terminal.detachedSessionTimeoutSeconds(valeur par défaut : 300 ;0rétablit l’arrêt à la déconnexion), tandis que les sorties récentes s’accumulent dans une mémoire tampon limitée côté serveur. terminal.listrenvoie les sessions rattachables ;terminal.attachrattache une session active ou détachée à la connexion appelante et renvoie la mémoire tampon de relecture (prise de contrôle de type tmux — un précédent propriétaire actif reçoitterminal.exitavec la raisondetached) ;terminal.textlit la mémoire tampon sous forme de texte brut sans s’y rattacher.- Chaque méthode de terminal nécessite
operator.admin;gateway.terminal.enableddoit être explicitement défini sur true. Les agents entièrement isolés sont refusés, et toute modification de la politique d’un agent ferme les PTY existants et en cours d’ouverture, y compris ceux qui sont détachés.
Conversation et TTS
talk.catalogrenvoie le catalogue en lecture seule des fournisseurs Conversation pour la parole, la transcription en continu et la voix en temps réel : identifiants canoniques des fournisseurs, alias du registre, libellés, état de configuration, résultatreadyfacultatif au niveau du groupe, identifiants de modèles/voix exposés, modes canoniques, transports, stratégies de cerveau et indicateurs audio/de capacités en temps réel, sans renvoyer les secrets des fournisseurs ni modifier la configuration globale. Les Gateway actuels définissentreadyaprès avoir appliqué la sélection du fournisseur d'exécution ; considérez son absence comme non vérifiée sur les Gateway plus anciens.talk.configrenvoie la charge utile de configuration Conversation effective ;includeSecretsnécessiteoperator.talk.secrets(ouoperator.admin).talk.session.createcrée une session Conversation détenue par le Gateway pourrealtime/gateway-relay,transcription/gateway-relayoustt-tts/managed-room. Pourstt-tts/managed-room, les appelants disposant deoperator.writequi transmettentsessionKeydoivent également transmettrespawnedBypour une visibilité limitée de la clé de session ; la création d'unesessionKeysans portée etbrain: "direct-tools"nécessitentoperator.admin.talk.session.joinvalide un jeton de session de salle gérée, émetsession.readyousession.replacedselon les besoins, et renvoie les métadonnées de la salle/session ainsi que les événements Conversation récents, mais jamais le jeton en texte brut ni son condensat.talk.session.appendAudioajoute l'audio d'entrée PCM encodé en base64 aux sessions de relais en temps réel et de transcription détenues par le Gateway.talk.session.startTurn,talk.session.endTurnettalk.session.cancelTurnpilotent le cycle de vie des tours d'une salle gérée, avec rejet des tours obsolètes avant l'effacement de l'état.talk.session.cancelOutputarrête la sortie audio de l'assistant, principalement pour permettre l'interruption contrôlée par VAD dans les sessions de relais du Gateway.talk.session.submitToolResulttermine un appel d'outil du fournisseur émis par une session de relais en temps réel détenue par le Gateway. La requête attend tout signal de fin asynchrone exposé par le pont du fournisseur ; les soumissions ayant échoué maintiennent l'exécution liée active et n'émettent pas d'événement de résultat d'outil réussi. Transmettezoptions: { willContinue: true }pour une sortie d'outil intermédiaire ouoptions: { suppressResponse: true }lorsque le pont du fournisseur annonce la prise en charge de la suppression et que le résultat ne doit pas démarrer une autre réponse.talk.session.steerenvoie un contrôle vocal de l'exécution active à une session Conversation détenue par le Gateway et adossée à un agent :{ sessionId, text, mode? }, oùmodevautstatus,steer,canceloufollowup; si le mode est omis, il est déterminé à partir du texte prononcé.talk.session.closeferme une session de relais, de transcription ou de salle gérée détenue par le Gateway et émet les événements Conversation terminaux.talk.modedéfinit/diffuse l'état actuel du mode Conversation pour les clients WebChat/Control UI.talk.client.createcrée une session de fournisseur en temps réel détenue par le client utilisantwebrtcouprovider-websocket, tandis que le Gateway gère la configuration, les identifiants, les instructions et la politique des outils.talk.client.toolCallpermet aux transports en temps réel détenus par le client de transmettre les appels d'outils du fournisseur à la politique du Gateway. Le premier outil pris en charge estopenclaw_agent_consult; les clients obtiennent un identifiant d'exécution et attendent les événements normaux du cycle de vie de la conversation avant de soumettre le résultat d'outil propre au fournisseur.talk.client.steerenvoie un contrôle vocal de l'exécution active pour les transports en temps réel détenus par le client. Le Gateway résout l'exécution intégrée active à partir desessionKeyet renvoie un résultat structuré accepté/refusé au lieu d'ignorer silencieusement le pilotage.talk.eventest le canal d'événements Conversation unique pour les adaptateurs en temps réel, de transcription, STT/TTS, de salle gérée, de téléphonie et de réunion.talk.speaksynthétise la parole par l'intermédiaire du fournisseur de parole Conversation actif.tts.statusrenvoie l'état d'activation du TTS, le fournisseur actif, les fournisseurs de secours et l'état de configuration des fournisseurs.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.converteffectue une conversion ponctuelle de texte en parole.tts.speak(operator.write) restitue letextnon vide avec la chaîne de fournisseurs TTS généraux configurée et renvoie un clip complet en ligne sous la formeaudioBase64, ainsi que les métadonnéesprovideret, facultativement,outputFormat,mimeTypeetfileExtension. Contrairement àtts.convert, il ne renvoie pas de chemin local au Gateway ; contrairement àtalk.speak, il ne nécessite pas de fournisseur Conversation. Un texte dépassantmessages.tts.maxTextLengthrenvoieINVALID_REQUEST; les échecs de synthèse renvoientUNAVAILABLE.
Secrets, configuration, mise à jour et assistant
secrets.reloadrésout à nouveau les SecretRefs actives et ne remplace l'état des secrets d'exécution qu'en cas de réussite complète.secrets.resolverésout les affectations de secrets ciblées par commande pour un ensemble précis de commandes/cibles.config.getrenvoie l'instantané et le condensat actuels de la configuration.config.setécrit une charge utile de configuration validée.config.patchfusionne une mise à jour partielle de la configuration. Le remplacement destructif d'un tableau nécessite que le chemin concerné figure dansreplacePaths; les tableaux imbriqués sous des entrées de tableau utilisent des chemins[]tels queagents.list[].skills.config.applyvalide et remplace la charge utile de configuration complète.config.schemarenvoie la charge utile du schéma de configuration actif utilisée par les outils Control UI et CLI : schéma,uiHints, version, métadonnées de génération, ainsi que les métadonnées des schémas des plugins et canaux lorsqu'elles peuvent être chargées. Elle inclut les métadonnéestitle/descriptionissues des mêmes libellés/textes d'aide que l'interface utilisateur, y compris pour les objets imbriqués, les caractères génériques, les éléments de tableau et les branches de compositionanyOf/oneOf/allOflorsque la documentation des champs correspondants existe.config.schema.lookuprenvoie une charge utile de recherche limitée à un chemin pour un chemin de configuration : chemin normalisé, nœud de schéma superficiel, indication correspondante avechintPath,reloadKindfacultatif et résumés des enfants immédiats pour l'exploration descendante dans l'interface utilisateur/la CLI.reloadKindvautrestart,hotounone(src/config/schema.ts) et reflète le planificateur de rechargement de la configuration du Gateway pour le chemin demandé. Les nœuds du schéma de recherche conservent la documentation destinée à l'utilisateur et les champs de validation courants (title,description,type,enum,const,format,pattern, limites numériques/de chaînes/de tableaux/d'objets,additionalProperties,deprecated,readOnly,writeOnly). Les résumés des enfants exposentkey, lepathnormalisé,type,required,hasChildren, lereloadKindfacultatif, ainsi que leshint/hintPathcorrespondants.update.runexécute le flux de mise à jour du Gateway et planifie un redémarrage uniquement si la mise à jour a réussi ; les appelants disposant d'une session peuvent inclurecontinuationMessageafin que le démarrage reprenne un tour de suivi de l'agent par l'intermédiaire de la file d'attente de continuation après redémarrage. Les mises à jour du gestionnaire de paquets et les mises à jour supervisées d'une extraction Git depuis le plan de contrôle utilisent un transfert détaché vers un service géré au lieu de remplacer l'arborescence des paquets ou de modifier les sorties de l'extraction/de la compilation dans le Gateway actif. Un transfert démarré renvoieok: trueavecresult.reason: "managed-service-handoff-started"ethandoff.status: "started"; les transferts indisponibles ou ayant échoué renvoientok: falseavecmanaged-service-handoff-unavailableoumanaged-service-handoff-failed, ainsi quehandoff.commandlorsqu'une mise à jour manuelle depuis le shell est requise. « Indisponible » signifie qu'OpenClaw ne dispose pas d'une limite de supervision sûre ni d'une identité de service durable, telle queOPENCLAW_SYSTEMD_UNITpour systemd. Pendant un transfert démarré, la sentinelle de redémarrage peut brièvement signalerstats.reason: "restart-health-pending"; la continuation est retardée jusqu'à ce que la CLI vérifie le Gateway redémarré et écrive la sentinelleokfinale.update.statusactualise et renvoie la dernière sentinelle de redémarrage de mise à jour, y compris la version en cours d'exécution après redémarrage lorsqu'elle est disponible.wizard.start,wizard.next,wizard.statusetwizard.cancelexposent l'assistant d'intégration par RPC WS.
Assistants pour les agents et les espaces de travail
agents.listrenvoie les entrées d'agents configurées, y compris les métadonnées effectives du modèle et de l'environnement d'exécution.agents.create,agents.updateetagents.deletegèrent les enregistrements des agents et le raccordement des espaces de travail.agents.files.list,agents.files.getetagents.files.setgèrent les fichiers d'amorçage de l'espace de travail exposés pour un agent.audit.activity.listrenvoie le registre d'activité versionné contenant uniquement des métadonnées ;audit.listreste le RPC d'exécution/d'outil préservant la compatibilité.agents.workspace.listetagents.workspace.get(operator.read) exposent une navigation paginée en lecture seule dans le répertoire de l'espace de travail d'un agent pour les clients du domaine d'opérateur de confiance décrit dans Portées de l'opérateur. Les requêtes acceptent uniquement les chemins relatifs à l'espace de travail ; les lectures restent confinées à la racine de l'espace de travail résolue en chemin réel (les échappements par liens symboliques et liens physiques sont rejetés), leur taille est plafonnée et elles sont limitées au texte UTF-8 ainsi qu'aux types d'images courants (base64). Les réponses n'exposent pas le chemin de l'espace de travail sur l'hôte. Cet espace de noms ne propose aucune opération d'écriture.tasks.list,tasks.getettasks.cancelexposent le registre des tâches du Gateway aux clients SDK et opérateur. Consultez RPC du registre des tâches ci-dessous.artifacts.list,artifacts.getetartifacts.downloadexposent des résumés et téléchargements d'artefacts dérivés des transcriptions pour une portée explicitesessionKey,runIdoutaskId. Les requêtes d'exécution et de tâche résolvent la session propriétaire côté serveur et ne renvoient que les médias de transcription dont la provenance correspond ; les sources d'URL non sûres ou locales renvoient des téléchargements non pris en charge au lieu d'être récupérées côté serveur.environments.listetenvironments.statuspréservent la découverte des environnements locaux au Gateway et des environnements Node. Les workers cloud configurés et les enregistrements durables laissés par des profils antérieurs ajoutent des métadonnéesworkeravecproviderId, leleaseIdfacultatif,state,ageMs, leidleMsfacultatif etattachedSessionIds. Les états du cycle de vie d'un worker sontrequested,provisioning,bootstrapping,ready,attached,idle,draining,destroying,destroyed,failedetorphaned.environments.create({ profileId, idempotencyKey }) provisionne un worker à partir d'un profil de fournisseur de plugin configuré ; les nouvelles tentatives avec la même clé réutilisent l'opération durable.environments.destroy({ environmentId }) demande la suppression idempotente d'un environnement de worker durable. Les deux nécessitentoperator.admin, constituent des écritures du plan de contrôle et renvoient le même format de résumé d'environnement que celui utilisé par les réponses d'état.agent.identity.getrenvoie l'identité effective de l'assistant pour un agent ou une session.agent.waitattend la fin d'une exécution et renvoie l'instantané terminal lorsqu'il est disponible.
Contrôle des sessions
sessions.listrenvoie l’index actuel des sessions, y compris les métadonnéesagentRuntimede chaque ligne lorsqu’un backend d’exécution d’agent est configuré.sessions.subscribeetsessions.unsubscribeactivent ou désactivent les abonnements aux événements de modification des sessions pour le client WS actuel.sessions.messages.subscribeetsessions.messages.unsubscribeactivent ou désactivent les abonnements aux événements de transcription/message pour une session. TransmettezincludeApprovals: truepour recevoir également les événements de cycle de viesession.approvalassainis pour les approbations dont l’audience persistée comprend cette session exacte et dont la liaison au réviseur autorise le client abonné. La réponse d’abonnement comprend alors unapprovalReplayborné des approbations en attente ; il fait autorité lorsquetruncatedvaut false. L’activation est propre à chaque appel d’abonnement et n’est pas persistante : se réabonner à la même session sansincludeApprovals: truesupprime un abonnement existant aux approbations. Outre l’autorité normale de lecture de la session, cette activation exigeoperator.admin, ouoperator.approvalssur un appareil appairé.sessions.previewrenvoie des aperçus bornés des transcriptions pour des clés de session spécifiques.sessions.describerenvoie une ligne de session du Gateway pour une clé de session exacte.sessions.resolverésout ou canonicalise une cible de session.sessions.createcrée une nouvelle entrée de session.worktree: trueprovisionne un worktree géré ; les paramètres facultatifsworktreeBaseRef/worktreeNamesélectionnent la référence de base et le nom de la branche, etexecNode(operator.admin) lie l’exécution de la session à un hôte Node. Le worktree créé est repris dans le résultat et persisté dans la ligne de session (worktree: { id, branch, repoRoot }). Lorsque l’entrée est créée, mais que son appel initial imbriqué àchat.sendest rejeté, le résultat positif comprendrunStarted: falseetrunError; les clients peuvent conserver le prompt et réessayer avec la clé de session renvoyée.sessions.groups.list,sessions.groups.put,sessions.groups.renameetsessions.groups.deletegèrent le catalogue de groupes de sessions personnalisés appartenant au Gateway (noms + ordre d’affichage). L’appartenance reste définie dans le champcategoryde chaque session ; le renommage et la suppression mettent à jour les sessions membres côté serveur.sessions.sendenvoie un message dans une session existante.sessions.steerest la variante d’interruption et de réorientation pour une session active.sessions.abortinterrompt le travail actif d’une session. Transmettezkeyavec unrunIdfacultatif, ou uniquementrunIdpour les exécutions actives que le Gateway peut associer à une session.sessions.patchmet à jour les métadonnées/remplacements de la session et indique le modèle canonique résolu ainsi que l’agentRuntimeeffectif.sessions.reset,sessions.deleteetsessions.compactassurent la maintenance des sessions.sessions.getrenvoie la ligne complète de la session stockée.- L’exécution du chat utilise toujours
chat.history,chat.send,chat.abortetchat.inject.chat.historyest normalisé pour l’affichage destiné aux clients d’interface utilisateur : les balises de directives en ligne sont supprimées du texte visible, les charges utiles XML en texte brut des appels d’outils (<tool_call>...</tool_call>,<function_call>...</function_call>,<tool_calls>...</tool_calls>,<function_calls>...</function_calls>et les blocs d’appels d’outils tronqués) ainsi que les jetons de contrôle de modèle ASCII/pleine chasse divulgués sont supprimés, les lignes de l’assistant constituées uniquement de jetons silencieux (NO_REPLY/no_replyexacts) sont omises et les lignes surdimensionnées peuvent être remplacées par des espaces réservés. chat.message.getest le lecteur additif borné du message complet pour une seule entrée visible de la transcription. TransmettezsessionKey, éventuellementagentIdlorsque la sélection de session est limitée à l’agent, ainsi qu’unmessageIdde transcription précédemment exposé parchat.history; le Gateway renvoie la même projection normalisée pour l’affichage, sans la limite de troncature de l’historique allégé, lorsque l’entrée stockée est toujours disponible et n’est pas surdimensionnée.chat.toolTitlesrenvoie de courts titres décrivant l’objectif des appels d’outils affichés dans l’interface de contrôle (par lots, 24 éléments maximum avec des entrées bornées). Cette fonctionnalité doit être activée viagateway.controlUi.toolTitles(désactivée par défaut) ; les Gateway où elle est désactivée répondent{ titles: {}, disabled: true }sans appel au modèle afin que les clients cessent leurs requêtes. Lorsqu’elle est activée, les titres utilisent le routage standard du modèle utilitaire : soit unutilityModelexplicitement configuré (une décision de l’opérateur qui, comme pour toutes les tâches utilitaires, peut envoyer un contenu de tâche borné au fournisseur choisi), soit le petit modèle par défaut déclaré par le fournisseur de la session afin qu’aucune nouvelle destination de sortie n’apparaisse implicitement ; unutilityModelvide les désactive entièrement. Les titres ne se rabattent jamais sur le modèle principal. Les résultats sont mis en cache dans la base de données d’état propre à l’agent, avec pour clé le nom de l’outil + l’entrée, de sorte que les consultations répétées ne refacturent jamais les mêmes appels.chat.sendaccepte le paramètre ponctuelfastMode: "auto"afin d’utiliser le mode rapide pour les appels au modèle démarrés avant le seuil automatique, puis de lancer les appels ultérieurs de nouvelle tentative, de repli, de résultat d’outil ou de continuation sans mode rapide. Le seuil est fixé par défaut à 60 secondes (DEFAULT_FAST_MODE_AUTO_ON_SECONDS) et peut être configuré par modèle avecagents.defaults.models["<provider>/<model>"].params.fastAutoOnSeconds. Un appelant dechat.sendpeut transmettre le paramètre ponctuelfastAutoOnSecondspour remplacer le seuil de cette requête.
Appairage des appareils et jetons d’appareil
device.pair.listrenvoie les appareils appairés en attente et approuvés.device.pair.setupCodecrée un code de configuration mobile et, par défaut, une URL de données QR au format PNG. Il exigeoperator.adminet est volontairement omis de la découverte annoncée. Le résultat comprendsetupCode, le champ facultatifqrDataUrl,gatewayUrl, le libellé non secretautheturlSource.device.pair.approve,device.pair.rejectetdevice.pair.removegèrent les enregistrements d’appairage des appareils.device.pair.renameattribue un libellé d’opérateur ({ deviceId, label }) qui est privilégié par rapport au nom d’affichage indiqué par le client et persiste après la réparation ou la réapprobation de l’appareil.device.token.rotaterenouvelle le jeton d’un appareil appairé dans les limites de son rôle approuvé et de la portée de l’appelant.device.token.revokerévoque le jeton d’un appareil appairé dans les limites de son rôle approuvé et de la portée de l’appelant.
Le code de configuration intègre un identifiant d’amorçage à courte durée de vie. Les clients ne doivent ni le journaliser ni le conserver au-delà du processus d’appairage.
Appairage des Nodes, invocation et travail en attente
node.pair.list,node.pair.approve,node.pair.rejectetnode.pair.removecouvrent les approbations des capacités des Nodes.node.pair.requestetnode.pair.verifyont été supprimés dans la version 2026.7 avec le stockage autonome d’appairage des Nodes ; les demandes en attente sont créées par le Gateway lors des connexions des Nodes.node.listetnode.describerenvoient l’état connu/connecté des Nodes.node.renamemet à jour le libellé d’un Node appairé.node.invoketransmet une commande à un Node connecté.node.invoke.resultrenvoie le résultat d’une demande d’invocation.mcp.tools.call.v1est la commande sans interface graphique de l’hôte Node permettant d’appeler un outil MCP configuré localement sur le Node. Elle est transmise vianode.invoke, exige que le Node déclare la commande et reste soumise à l’approbation d’appairage ainsi qu’àgateway.nodes.denyCommands.node.eventtransmet au Gateway les événements provenant des Nodes.node.pluginTools.updateest le seul chemin de publication permettant de remplacer les descripteurs d’outils de Plugin/MCP visibles par l’agent du Node connecté ; les paramètres deconnectne les transportent pas.node.pending.pulletnode.pending.acksont les API de file d’attente du Node connecté.node.pending.enqueueetnode.pending.draingèrent le travail en attente durable pour les Nodes hors ligne/déconnectés.
Familles d’approbations
approval.getetapproval.resolvesont les méthodes d’approbation durable indépendantes du type (portéeoperator.approvals).approval.getrenvoie une projection assainie, en attente ou terminale conservée, avec unurlPathstable ;approval.resolveaccepte l’identifiant canonique de l’approbation, unkindexplicite et une décision, applique une résolution où la première réponse l’emporte et renvoie toujours le résultat canonique enregistré.exec.approval.request,exec.approval.get,exec.approval.listetexec.approval.resolvecouvrent les demandes ponctuelles d’approbation d’exécution ainsi que la recherche/relecture des approbations en attente. Ce sont des adaptateurs de frontière de protocole reposant sur le même registre durable des approbations.exec.approval.waitDecisionattend la décision d’une approbation d’exécution en attente et renvoie la décision finale (ounullen cas d’expiration du délai).exec.approvals.getetexec.approvals.setgèrent les instantanés de stratégie d’approbation des exécutions du Gateway.exec.approvals.node.getetexec.approvals.node.setgèrent la stratégie locale au Node d’approbation des exécutions via les commandes de relais du Node.plugin.approval.request,plugin.approval.list,plugin.approval.waitDecisionetplugin.approval.resolvecouvrent les flux d’approbation définis par les Plugins.
Automatisation, Skills et outils
- Automatisation :
wakeprogramme l’injection immédiate ou au prochain Heartbeat d’un texte de réveil ;cron.get,cron.list,cron.status,cron.add,cron.update,cron.remove,cron.run,cron.runsgèrent le travail planifié. cron.runreste un RPC de type mise en file d’attente pour les exécutions manuelles. Les clients nécessitant une sémantique d’achèvement doivent lire lerunIdrenvoyé et interroger périodiquementcron.runs.cron.runsaccepte un filtre facultatifrunIdnon vide afin que les clients puissent suivre une seule exécution manuelle en file d’attente sans entrer en concurrence avec d’autres entrées d’historique de la même tâche.- Skills et outils :
commands.list,skills.*,tools.catalog,tools.effective,tools.invoke. Consultez les méthodes d’assistance pour l’opérateur ci-dessous.
Familles d’événements courantes
chat: mises à jour du chat de l’interface utilisateur, telles quechat.inject, et autres événements de chat limités à la transcription. Dans le protocole v4, les charges utiles différentielles transportentdeltaText;messagereste l’instantané cumulatif de l’assistant. Les remplacements qui ne sont pas des préfixes définissentreplace=trueet utilisentdeltaTextcomme texte de remplacement.session.message,session.operation,session.tool: mises à jour de la transcription, de l’opération de session en cours et du flux d’événements pour une session abonnée.session.approval: état assaini, en attente et terminal, des approbations pour un abonné explicitement activé sur une session exacte. Les approbations enfants utilisent l’audience persistée de l’ancêtre ; les événements ne modifient jamais les transcriptions et ne réveillent pas les agents.sessions.changed: l’index ou les métadonnées des sessions ont changé.presence: mises à jour de l’instantané de présence du système.tick: événement périodique de maintien de connexion/vérification d’activité.health: mise à jour de l’instantané d’état du Gateway.heartbeat: mise à jour du flux d’événements Heartbeat.cron: événement de modification d’une exécution/tâche Cron.shutdown: notification d’arrêt du Gateway.node.pair.requested/node.pair.resolved: cycle de vie de l’appairage des Nodes.node.invoke.request: diffusion d’une demande d’invocation d’un Node.device.pair.requested/device.pair.resolved: cycle de vie des appareils appairés.voicewake.changed: la configuration du déclencheur par mot de réveil a changé.exec.approval.requested/exec.approval.resolved: cycle de vie des approbations d’exécution.plugin.approval.requested/plugin.approval.resolved: cycle de vie des approbations de Plugin.
Méthodes d’assistance pour les Nodes
Les Nodes peuvent appeler skills.bins pour récupérer la liste actuelle des exécutables des Skills
afin d’effectuer les vérifications d’autorisation automatique.
RPC du registre d’audit
audit.activity.list fournit aux clients opérateurs une vue stable, de la plus récente à la plus ancienne, des métadonnées du cycle de vie
des exécutions d’agents, des actions d’outils et des messages explicitement activés. Il exige
operator.read. Les requêtes excluent les enregistrements datant de plus de 30 jours, et le registre
SQLite partagé est limité à 100,000 enregistrements. Les lignes expirées sont supprimées au
démarrage du Gateway, lors de la maintenance horaire et des écritures ultérieures. Consultez
l’historique d’audit pour le modèle de données et la sémantique de confidentialité.
- Paramètres :
agentId,sessionKeyourunIdexact facultatif ;kindfacultatif ("agent_run","tool_action"ou"message") ;statusfacultatif ("started","succeeded","failed","cancelled","timed_out","blocked"ou"unknown") ;directiondu message facultative ("inbound"ou"outbound") etchannelexact ; bornes inclusivesafter/beforefacultatives en millisecondes Unix ;limitfacultatif de1à500; et chaînecursorfacultative provenant de la page précédente. - Résultat :
{ "events": AuditActivityEventV1[], "nextCursor"?: string }.
L’union de résultats V1 nommée comporte des schémas distincts pour les
exécutions d’agent, les actions d’outil, les messages entrants et les messages
sortants. Le discriminateur eventType vaut respectivement agent_run,
tool_action, inbound_message ou outbound_message ; kind et la
direction du message restent disponibles pour le filtrage et l’affichage.
Chaque événement possède un entier schemaVersion: 1. Les références
d’identité de message utilisent le format exact
hmac-sha256:v1:<32 hex key id>:<64 hex digest> ; l’identifiant d’un acteur
expéditeur de canal utilise le même format.
Toutes les variantes exigent eventType, schemaVersion, eventId, sequence,
sourceSequence, occurredAt, kind, action, status, actor et
redaction. Les champs des variantes sont les suivants :
eventType |
Champs obligatoires | Champs facultatifs |
|---|---|---|
agent_run |
agentId, runId ; kind: "agent_run" |
sessionKey, sessionId, errorCode |
tool_action |
agentId, runId ; kind: "tool_action" |
sessionKey, sessionId, toolCallId, toolName, errorCode |
inbound_message |
direction: "inbound", channel, conversationKind, outcome |
agentId, runId, durationMs, resultCount, références d’identité, reasonCode, errorCode |
outbound_message |
direction: "outbound", channel, conversationKind, outcome |
agentId, runId, durationMs, resultCount, références d’identité, reasonCode, deliveryKind, failureStage, errorCode |
Les énumérations fermées des messages sont les suivantes :
conversationKind:direct,group,channelouunknown.outcomeentrant :completed,skippedoufailed;reasonCodefacultatif :duplicate,reply_operation_active,reply_operation_aborted,fast_abort,plugin_bound_handled,plugin_bound_unavailable,plugin_bound_declined,plugin_bound_error,before_dispatch_handled,acp_dispatch_completed,acp_dispatch_failed,acp_dispatch_emptyouacp_dispatch_aborted.outcomesortant :sent,suppressed,failedouunknown;reasonCodefacultatif :cancelled_by_message_sending_hook,cancelled_by_reply_payload_sending_hook,empty_after_message_sending_hook,empty_after_reply_payload_sending_hookouno_visible_payload. Un adaptateur qui ne renvoie aucune identité de plateforme estunknown, car l’effet de bord externe ne peut pas être réfuté.deliveryKind:text,mediaouother;failureStage:platform_send,queueouunknown.
Les champs terminaux sont corrélés, et non facultatifs indépendamment :
| Variante | Correspondance terminale |
|---|---|
| Exécution d’agent | started n’a pas d’errorCode ; chaque état final autre qu’un succès exige son code run_* correspondant. |
| Action d’outil | started et les succès n’ont pas d’errorCode ; chaque autre état final exige son code tool_* correspondant. |
| Message entrant | succeeded = completed ; blocked = skipped ; failed = failed plus message_processing_failed. Lorsqu’il est présent, reasonCode doit appartenir à cette famille terminale. |
| Message sortant | succeeded = sent ; blocked = suppressed plus reasonCode ; failed = failed plus errorCode et failureStage ; unknown = unknown plus failureStage. |
Chaque événement d’activité comprend un identifiant d’événement stable, une
séquence de registre monotone, la séquence de l’événement source, un horodatage,
un acteur, une action, un état, un entier schemaVersion: 1 et
redaction: "metadata_only". Les enregistrements d’exécution et d’outil
exigent la provenance de l’agent et de l’exécution et peuvent inclure la
provenance de la session. Les enregistrements de message peuvent inclure les
identifiants de l’agent et de l’exécution, mais n’incluent délibérément jamais
sessionKey ni sessionId ; le filtre de requête sessionKey ne s’applique
donc qu’aux lignes d’exécution et d’outil. Les événements d’outil peuvent
inclure l’identifiant de l’appel d’outil et le nom de l’outil.
Les enregistrements de message utilisent message.inbound.processed ou
message.outbound.finished et ajoutent la direction, le canal, le type de
conversation, le résultat normalisé ainsi que, facultativement, le type de
livraison, l’étape de l’échec, la durée, le nombre de résultats, le code de
motif et des pseudonymes avec clé, locaux à l’installation, pour le compte, la
conversation, le message et la cible. Ces pseudonymes facilitent la corrélation,
mais ne constituent pas une anonymisation : la base de données d’état contient
leur clé, contrairement aux exportations RPC et CLI. Le registre ne stocke ni
les prompts, ni le contenu des messages, ni les arguments ou résultats des
outils, ni la sortie des commandes, ni le texte brut des erreurs. Les valeurs
sessionKey des exécutions et des outils restent des métadonnées de corrélation
brutes et peuvent intégrer des identifiants de compte de plateforme ou de pair ;
les enregistrements de message omettent les clés de session.
Pour les lignes entrantes, durationMs mesure la durée du traitement principal jusqu’à son état terminal et resultCount compte les charges utiles finalisées de type outil mis en file d’attente, bloc et réponse. Pour les lignes sortantes, durationMs couvre la prise en charge de la livraison jusqu’à l’accusé de réception, la lettre morte ou la réconciliation (temps d’attente en file compris), et resultCount compte les envois physiques identifiés vers la plateforme. deliveryKind, lorsqu’il est présent, décrit la charge utile effective après les hooks et le rendu ; les lignes supprimées ou ambiguës en raison d’un plantage l’omettent.
La couverture actuelle des messages inclut les messages entrants acceptés qui atteignent le traitement principal, y compris les résultats de doublon ou terminaux du cœur. La couverture sortante écrit une ligne terminale par charge utile de réponse logique d’origine qui atteint la livraison durable partagée ; le découpage et la distribution par les adaptateurs sont agrégés dans resultCount. Les envois pouvant être retentés ou ambigus mis en file d’attente ne sont enregistrés qu’après un accusé de réception, une lettre morte ou une réconciliation. Les chemins locaux aux Plugins et les chemins d’envoi direct qui contournent ces limites partagées ne sont pas encore couverts. La file d’attente bornée des workers fonctionne au mieux et peut perdre des enregistrements en cas de défaillance ou de saturation ; cette surface ne constitue donc pas une archive de conformité sans perte.
L’enregistrement est activé par défaut et contrôlé par
audit.enabled. L’enregistrement des messages est
contrôlé séparément par audit.messages et sa valeur par défaut est "off". Lorsque
l’enregistrement est désactivé, audit.activity.list continue de fournir les enregistrements écrits
précédemment jusqu’à leur expiration.
Les schémas livrés de requête et de résultat audit.list, ainsi que le schéma AuditEvent, restent
inchangés et renvoient uniquement les enregistrements d’exécution d’agent et d’action d’outil. Les nouveaux clients
opérateur doivent appeler audit.activity.list lorsque le Gateway l’annonce. Les anciens
Gateways peuvent signaler soit unknown method: audit.activity.list, soit, parce que
l’autorisation précédait la recherche de méthode dans les versions livrées, missing scope: operator.admin pour une requête limitée à la lecture. Considérez ce dernier cas comme une absence de méthode
uniquement lorsque la méthode n’a pas été annoncée. Un client peut alors réessayer audit.list
uniquement lorsque ses filtres ne nécessitent pas la prise en charge du type de message, de la direction ou du canal.
Utilisez openclaw audit pour les requêtes textuelles et les exportations JSON bornées.
RPC du registre des tâches
Les clients opérateur inspectent et annulent les enregistrements de tâches en arrière-plan du Gateway au moyen
des RPC du registre des tâches (packages/gateway-protocol/src/schema/tasks.ts). Ceux-ci
renvoient des résumés de tâches assainis, et non l’état brut de l’environnement d’exécution.
tasks.listnécessiteoperator.read.- Paramètres :
statusfacultatif ("queued","running","completed","failed","cancelled"ou"timed_out") ou un tableau de ces états,agentIdfacultatif,sessionKeyfacultatif,limitfacultatif de1à500, et chaînecursorfacultative. - Résultat :
{ "tasks": TaskSummary[], "nextCursor"?: string }.
- Paramètres :
tasks.getnécessiteoperator.read.- Paramètres :
{ "taskId": string }. - Résultat :
{ "task": TaskSummary }. - Les identifiants de tâche manquants renvoient le format d’erreur « introuvable » du Gateway.
- Paramètres :
tasks.cancelnécessiteoperator.write.- Paramètres :
{ "taskId": string, "reason"?: string }. - Résultat :
{ "found": boolean, "cancelled": boolean, "reason"?: string, "task"?: TaskSummary }. foundindique si le registre contenait une tâche correspondante.cancelledindique si l’environnement d’exécution a accepté ou enregistré l’annulation.
- Paramètres :
TaskSummary comprend id, status et des métadonnées facultatives : kind,
runtime, title, agentId, sessionKey, childSessionKey, ownerKey,
runId, taskId, flowId, parentTaskId, sourceId, les horodatages, la progression,
le résumé terminal et le texte d’erreur assaini. agentId identifie l’agent
qui exécute la tâche ; sessionKey et ownerKey préservent le contexte du demandeur et du contrôle.
Méthodes auxiliaires pour les opérateurs
commands.list(operator.read) récupère l’inventaire des commandes d’exécution pour un agent.agentIdest facultatif ; omettez-le pour lire l’espace de travail de l’agent par défaut.scopedétermine la surface ciblée par lenameprincipal :textrenvoie le jeton principal de la commande textuelle sans le/initial ;nativeet le cheminbothpar défaut renvoient les noms natifs adaptés au fournisseur lorsqu’ils sont disponibles.textAliasescontient les alias exacts avec barre oblique, tels que/modelet/m.nativeNamecontient le nom de commande natif adapté au fournisseur lorsqu’il existe.providerest facultatif et influe uniquement sur la dénomination native ainsi que sur la disponibilité des commandes natives du Plugin.includeArgs=falseomet de la réponse les métadonnées sérialisées des arguments.
tools.catalog(operator.read) récupère le catalogue des outils d’exécution pour un agent. La réponse comprend les outils regroupés et les métadonnées de provenance :source:coreoupluginpluginId: Plugin propriétaire lorsquesource="plugin"optional: indique si un outil de Plugin est facultatif
tools.effective(operator.read) récupère l’inventaire des outils effectivement disponibles à l’exécution pour une session.sessionKeyest requis.- Le Gateway déduit le contexte d’exécution fiable de la session côté serveur au lieu d’accepter un contexte d’authentification ou de livraison fourni par l’appelant.
- La réponse est une projection propre à la session, dérivée par le serveur, de l’inventaire actif, comprenant les outils du cœur, des Plugins, des canaux et des serveurs MCP déjà découverts.
tools.effectiveest en lecture seule pour MCP : il peut projeter le catalogue MCP d’une session active au travers de la stratégie finale des outils, mais ne crée pas d’environnements d’exécution MCP, ne connecte pas de transports et n’émet pastools/list. Si aucun catalogue actif correspondant n’existe, la réponse peut inclure un avis tel quemcp-not-yet-connected,mcp-not-yet-listedoumcp-stale-catalog.- Les entrées d’outils effectifs utilisent
source="core",source="plugin",source="channel"ousource="mcp".
tools.invoke(operator.write) appelle un outil disponible par le même chemin de stratégie du Gateway que/tools/invoke.nameest requis.args,sessionKey,agentId,confirmetidempotencyKeysont facultatifs.- Si
sessionKeyetagentIdsont tous deux présents, l’agent de la session résolue doit correspondre àagentId. - Les enveloppes du cœur réservées au propriétaire, telles que
cron,gatewayetnodes, nécessitent une identité de propriétaire/administrateur (operator.admin), même sitools.invokelui-même relève deoperator.write. - La réponse est une enveloppe destinée au SDK avec les champs
ok,toolName, un champoutputfacultatif et des champserrortypés. Les refus liés à l’approbation ou à la stratégie renvoientok:falsedans la charge utile au lieu de contourner le pipeline de stratégie des outils du Gateway.
skills.status(operator.read) récupère 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 comprend l’éligibilité, les exigences manquantes, les vérifications de configuration et les options d’installation assainies sans exposer les valeurs brutes des secrets.
skills.searchetskills.detail(operator.read) renvoient les métadonnées de découverte de ClawHub.skills.upload.begin,skills.upload.chunketskills.upload.commit(operator.admin) préparent une archive privée de Skill avant son installation. Il s’agit d’un chemin de téléversement administratif distinct destiné aux clients de confiance, et non du flux normal d’installation de Skills de ClawHub ; il est désactivé par défaut sauf siskills.install.allowUploadedArchivesest activé.skills.upload.begin({ kind: "skill-archive", slug, sizeBytes, sha256?, force?, idempotencyKey? })crée un téléversement lié à ce slug et à cette valeur de forçage.skills.upload.chunk({ uploadId, offset, dataBase64 })ajoute des octets à l’offset décodé exact.skills.upload.commit({ uploadId, sha256? })vérifie la taille finale et le SHA-256. La validation ne fait que finaliser le téléversement ; elle n’installe pas le Skill.- Les archives de Skills téléversées sont des archives zip contenant un fichier
SKILL.mdà la racine. Le nom du répertoire interne de l’archive ne sélectionne jamais la cible d’installation.
skills.install(operator.admin) comporte trois 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 téléversement :
{ source: "upload", uploadId, slug, force?, sha256?, timeoutMs? }installe un téléversement validé dans le répertoireskills/<slug>de l’espace de travail de l’agent par défaut. Le slug et la valeur de forçage doivent correspondre à la requêteskills.upload.begind’origine. Ce mode est refusé sauf siskills.install.allowUploadedArchivesest activé ; ce paramètre n’influe pas sur les installations ClawHub. - Mode programme d’installation du Gateway :
{ name, installId, timeoutMs? }exécute une actionmetadata.openclaw.installdéclarée sur l’hôte du Gateway. Les clients plus anciens peuvent encore envoyerdangerouslyForceUnsafeInstall; ce champ est obsolète, accepté uniquement pour assurer la compatibilité du protocole et ignoré. Utilisezsecurity.installPolicypour les décisions d’installation relevant de l’opérateur.
- Mode ClawHub :
skills.update(operator.admin) comporte 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 configuration modifie les valeurs de
skills.entries.<skillKey>, telles queenabled,apiKeyetenv.
Vues de models.list
models.list accepte un paramètre view facultatif
(src/agents/model-catalog-visibility.ts) :
- Omis ou
"default": siagents.defaults.modelsest configuré, la réponse correspond au catalogue autorisé, y compris les modèles découverts dynamiquement pour les entréesprovider/*. Sinon, la réponse correspond au catalogue complet du Gateway. "configured": comportement dimensionné pour un sélecteur. Siagents.defaults.modelsest configuré, il reste prioritaire, y compris pour la découverte limitée au fournisseur des entréesprovider/*. Sans liste d’autorisation, la réponse utilise les entrées explicitesmodels.providers.<provider>.modelset se rabat sur le catalogue complet uniquement lorsqu’aucune ligne de modèle configurée n’existe."provider-config": inventairemodels.providers.*.modelsdéfini par la source, indépendant des listes d’autorisation du sélecteur. Les lignes comprennent les capacités publiques des modèles et la disponibilité tenant compte des routes, mais omettent les points de terminaison des fournisseurs, les données d’authentification et la configuration des requêtes d’exécution."all": catalogue complet du Gateway, sans tenir compte deagents.defaults.models. À utiliser pour les interfaces de diagnostic ou de découverte, et non pour les sélecteurs de modèles habituels.
Approbations d’exécution
- Lorsqu’une requête d’exécution nécessite une approbation, le Gateway diffuse
exec.approval.requested. - Les clients opérateurs la traitent en appelant
exec.approval.resolve(nécessiteoperator.approvals). - Pour
host=node,exec.approval.requestdoit incluresystemRunPlan(argv/cwd/rawCommandcanoniques et métadonnées de session). Les requêtes sanssystemRunPlansont rejetées. - Après approbation, les appels
node.invoke system.runtransférés réutilisent cesystemRunPlancanonique comme contexte faisant autorité pour la commande, le répertoire de travail et la session. - Si un appelant modifie
command,rawCommand,cwd,agentIdousessionKeyentre la préparation et le transfert final approuvé desystem.run, le Gateway rejette l’exécution au lieu de faire confiance à la charge utile modifiée.
Repli de livraison de l’agent
- Les requêtes
agentpeuvent incluredeliver=truepour demander une livraison sortante. bestEffortDeliver=false(valeur par défaut) conserve un comportement strict : les cibles de livraison non résolues ou uniquement internes renvoientINVALID_REQUEST.bestEffortDeliver=trueautorise le repli vers une exécution limitée à la session lorsqu’aucune route de livraison externe ne peut être résolue (par exemple, les sessions internes/webchat ou les configurations multicanaux ambiguës).- Les résultats finaux d’
agentpeuvent inclureresult.deliveryStatuslorsqu’une livraison a été demandée, avec les mêmes étatssent,suppressed,partial_failedetfailedque ceux documentés pouropenclaw agent --json --deliver.
Gestion des versions
PROTOCOL_VERSION,MIN_CLIENT_PROTOCOL_VERSION,MIN_NODE_PROTOCOL_VERSIONetMIN_PROBE_PROTOCOL_VERSIONse trouvent danspackages/gateway-protocol/src/version.ts.- Les clients envoient
minProtocol+maxProtocol. Les clients opérateurs et d’interface utilisateur doivent inclure le protocole actuel dans cette plage ; les clients et serveurs actuels utilisent le protocole v4. - Les clients authentifiés ayant à la fois
role: "node"etclient.mode: "node"peuvent utiliser le protocole de Node N-1 (actuellement v3). Les sondes légères de redémarrage utilisent la même fenêtre N-1. L’authentification des appareils, l’association, les portées, la stratégie des commandes et les approbations d’exécution restent inchangées par cette fenêtre de compatibilité. Les capacités et commandes de Node appartenant aux Plugins sont masquées jusqu’à ce que le Node soit mis à niveau vers le protocole actuel, car leurs surfaces hébergées ne font pas partie du contrat N-1. - Les schémas et les modèles sont générés à partir des définitions TypeBox :
pnpm protocol:genpnpm protocol:gen:swiftpnpm protocol:check
Constantes des clients
L’implémentation cliente de référence se trouve dans packages/gateway-client/src/
(OpenClaw l’enveloppe au moyen de la façade légère src/gateway/client.ts). Ces
valeurs par défaut sont stables dans l’ensemble du protocole v4 et constituent la base attendue pour
les clients tiers.
| Constante | Valeur par défaut | Source |
|---|---|---|
PROTOCOL_VERSION |
4 |
packages/gateway-protocol/src/version.ts |
MIN_CLIENT_PROTOCOL_VERSION |
4 |
packages/gateway-protocol/src/version.ts |
MIN_NODE_PROTOCOL_VERSION |
3 |
packages/gateway-protocol/src/version.ts |
MIN_PROBE_PROTOCOL_VERSION |
3 |
packages/gateway-protocol/src/version.ts |
| Délai d’expiration des requêtes (par RPC) | 30_000 ms |
packages/gateway-client/src/client.ts (requestTimeoutMs) |
| Délai de préauthentification / défi de connexion | 15_000 ms |
packages/gateway-client/src/timeouts.ts (la variable d’environnement OPENCLAW_HANDSHAKE_TIMEOUT_MS peut augmenter le délai alloué conjointement au serveur et au client) |
| Délai initial avant reconnexion | 1_000 ms |
packages/gateway-client/src/client.ts (backoffMs) |
| Délai maximal avant reconnexion | 30_000 ms |
packages/gateway-client/src/client.ts (scheduleReconnect) |
| Limite de nouvelle tentative rapide après une fermeture liée au jeton d’appareil | 250 ms |
packages/gateway-client/src/client.ts |
Délai de grâce avant arrêt forcé par terminate() |
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 |
packages/gateway-client/src/client.ts |
| Fermeture après expiration du tick | code 4000 lorsque le silence dépasse tickIntervalMs * 2 |
packages/gateway-client/src/client.ts |
MAX_PAYLOAD_BYTES |
25 * 1024 * 1024 (25 MB) |
src/gateway/server-constants.ts |
Le serveur annonce les valeurs effectives de policy.tickIntervalMs,
policy.maxPayload et policy.maxBufferedBytes dans hello-ok ; les clients
doivent respecter ces valeurs plutôt que les valeurs par défaut antérieures à la négociation.
Le client de référence laisse les requêtes finies gérer leur délai configuré lorsque
chaque requête en attente en possède un. Une requête expectFinal sans
timeoutMs fini, toute requête avec timeoutMs: null, ou un mélange de requêtes
finies et sans limite maintient actif le mécanisme de surveillance des ticks. Si les événements entrants et
les réponses restent silencieux au-delà du seuil d’expiration des ticks, le client ferme le
socket avec le code 4000, rejette toutes les requêtes en attente et se reconnecte. Il ne
réexécute pas les requêtes rejetées après la reconnexion.
Authentification
- L’authentification du Gateway par secret partagé utilise
connect.params.auth.tokenouconnect.params.auth.password, selon le modegateway.auth.modeconfiguré ("none" | "token" | "password" | "trusted-proxy"). - Les modes porteurs d’identité tels que Tailscale Serve (
gateway.auth.allowTailscale: true) ougateway.auth.mode: "trusted-proxy"hors loopback satisfont le contrôle d’authentification de connexion à partir des en-têtes de requête plutôt que 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 fiable. - Après l’association, le Gateway émet un jeton d’appareil limité au rôle et aux
portées de la connexion, renvoyé dans
hello-ok.auth.deviceToken. Les clients doivent le conserver après toute connexion réussie. - Lors d’une reconnexion avec ce jeton d’appareil enregistré, l’ensemble des portées approuvé et enregistré pour ce jeton doit également être réutilisé. Cela préserve l’accès en lecture/sondage/état déjà accordé et évite que les reconnexions ne soient silencieusement réduites à une portée implicite réservée à l’administration.
- Assemblage de l’authentification de connexion côté client (
selectConnectAuthdanspackages/gateway-client/src/client.ts) :auth.passwordest indépendant et toujours transmis lorsqu’il est défini.auth.tokenest renseigné selon l’ordre de priorité suivant : d’abord le jeton partagé explicite, puis undeviceTokenexplicite, puis un jeton enregistré par appareil (indexé pardeviceId+role).auth.bootstrapTokenest envoyé uniquement lorsqu’aucune des valeurs précédentes n’a permis de déterminerauth.token. Un jeton partagé ou tout jeton d’appareil déterminé le désactive.- La promotion automatique d’un jeton d’appareil enregistré lors de la tentative unique
après
AUTH_TOKEN_MISMATCHest limitée aux points de terminaison fiables : loopback, ouwss://avec untlsFingerprintépinglé. Unwss://public sans épinglage n’est pas admissible.
- L’amorçage intégré par code de configuration renvoie le
hello-ok.auth.deviceTokendu Node principal ainsi qu’un jeton d’opérateur à durée limitée danshello-ok.auth.deviceTokenspour un transfert fiable vers un appareil mobile. Le jeton d’opérateur inclutoperator.talk.secretspour les lectures de configuration Talk natives, mais exclut les portées de modification d’association etoperator.admin. - Tant qu’un amorçage par code de configuration non standard attend une approbation,
les détails de
PAIRING_REQUIREDincluentrecommendedNextStep: "wait_then_retry",retryable: trueetpauseReconnect: false. Continuez à vous reconnecter avec le même jeton d’amorçage jusqu’à l’approbation de la requête ou jusqu’à ce que le jeton devienne invalide. - Ne conservez
hello-ok.auth.deviceTokensque lorsque la connexion a utilisé une authentification d’amorçage sur un transport fiable tel quewss://ou une association loopback/locale. - Si un client fournit un
deviceTokenexplicite ou desscopesexplicites, cet ensemble de portées demandé par l’appelant reste la référence ; les portées mises en cache ne sont réutilisées que lorsque le client réutilise le jeton enregistré par appareil. - Les jetons d’appareil peuvent être renouvelés/révoqués via
device.token.rotateetdevice.token.revoke(nécessiteoperator.pairing). Le renouvellement ou la révocation du jeton d’un Node ou d’un autre rôle non-opérateur nécessite égalementoperator.admin. device.token.rotaterenvoie les métadonnées de renouvellement. Il renvoie le nouveau jeton porteur uniquement pour les appels provenant du même appareil et déjà authentifiés avec ce jeton d’appareil, afin que les clients utilisant uniquement un jeton puissent conserver son remplacement avant de se reconnecter. Les renouvellements effectués avec un secret partagé ou par un administrateur ne renvoient pas le jeton porteur.- L’émission, le renouvellement et la révocation de jetons restent limités à l’ensemble de rôles approuvé et enregistré dans l’entrée d’association de cet appareil ; la modification d’un jeton ne peut pas étendre les droits ni cibler un rôle d’appareil que l’approbation de l’association n’a jamais accordé.
- Pour les sessions avec jeton d’appareil associé, la gestion des appareils est limitée à l’appareil lui-même, sauf si
l’appelant possède également
operator.admin: les appelants non administrateurs peuvent gérer uniquement le jeton d’opérateur de leur propre entrée d’appareil. La gestion des jetons de Node et des autres rôles non-opérateur est réservée aux administrateurs, même pour le propre appareil de l’appelant. device.token.rotateetdevice.token.revokevérifient également l’ensemble des portées du jeton d’opérateur ciblé par rapport aux portées de la session actuelle de l’appelant. Les appelants non administrateurs ne peuvent ni renouveler ni révoquer un jeton d’opérateur dont les portées sont plus larges que celles qu’ils possèdent 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: l’une des valeursretry_with_device_token,update_auth_configuration,update_auth_credentials,wait_then_retry,review_auth_configuration(packages/gateway-protocol/src/connect-error-details.ts).
- Comportement du client pour
AUTH_TOKEN_MISMATCH:- Les clients fiables peuvent effectuer une seule nouvelle tentative limitée avec un jeton par appareil mis en cache.
- Si cette tentative échoue, arrêtez les boucles de reconnexion automatique et affichez des instructions d’intervention à l’opérateur.
AUTH_SCOPE_MISMATCHsignifie que le jeton d’appareil a été reconnu, mais qu’il ne couvre pas le rôle ou les portées demandés. Ne le présentez pas comme un jeton incorrect ; invitez l’opérateur à effectuer une nouvelle association ou à approuver le contrat de portée plus restreint/plus large.
Identité et association des appareils
- Les Nodes 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 et par rôle.
- Les approbations d’association sont requises pour les nouveaux identifiants d’appareil, sauf si l’approbation automatique locale est activée.
- L’approbation automatique des associations est centrée sur les connexions loopback locales directes.
- OpenClaw dispose également d’un chemin étroit d’auto-connexion locale au backend/conteneur pour les flux d’assistance fiables utilisant un secret partagé.
- Les connexions tailnet ou LAN sur le même hôte sont toujours traitées comme distantes pour l’association et nécessitent une approbation.
- Les clients WS incluent normalement l’identité
devicependantconnect(opérateur + Node). Les seules exceptions permettant un opérateur sans appareil sont les chemins de confiance explicites :gateway.controlUi.allowInsecureAuth=truepour la compatibilité HTTP non sécurisée limitée à localhost.- une authentification réussie de l’opérateur dans l’interface de contrôle avec
gateway.auth.mode: "trusted-proxy". gateway.controlUi.dangerouslyDisableDeviceAuth=true(mesure d’urgence, dégradation sévère de la sécurité).- les RPC backend
gateway-clienten loopback direct sur le chemin interne réservé aux assistants.
- L’omission de l’identité de l’appareil a des conséquences sur les portées. Lorsqu’une
connexion d’opérateur sans appareil est autorisée via un chemin de confiance explicite, OpenClaw
efface tout de même les portées autodéclarées en les remplaçant par un ensemble vide, sauf si ce chemin possède une
exception nommée de conservation des portées. Les méthodes soumises à des portées échouent alors avec
missing scope. gateway.controlUi.dangerouslyDisableDeviceAuth=trueest un chemin de conservation des portées d’urgence de l’interface de contrôle. Il n’accorde pas de portées à des clients WebSocket backend personnalisés ou structurés comme la CLI.- Le chemin réservé de l’assistant backend
gateway-clienten loopback direct conserve les portées uniquement pour les RPC internes du plan de contrôle local ; les identifiants de backend personnalisés ne bénéficient pas de cette exception. - Toutes les connexions doivent signer le nonce
connect.challengefourni par le serveur.
Diagnostics de migration de l’authentification des appareils
Pour les anciens clients qui utilisent encore le comportement de signature antérieur au défi, connect
renvoie des codes de détail DEVICE_AUTH_* dans error.details.code avec une valeur
error.details.reason stable.
É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 ou 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é se trouve 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 ou la canonicalisation de la clé publique a échoué. |
Cible de migration :
- 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 privilégiée est
v3(buildDeviceAuthPayloadV3danspackages/gateway-client/src/device-auth.ts), qui lieplatformetdeviceFamilyen plus des champs d’appareil/client/rôle/portées/jeton/nonce. - Les signatures
v2héritées restent acceptées à des fins de compatibilité, mais l’épinglage des métadonnées des appareils appairés continue de contrôler la stratégie des commandes lors de la reconnexion.
TLS et épinglage
- TLS est pris en charge pour les connexions WS (configuration
gateway.tls). - Les clients peuvent éventuellement épingler l’empreinte du certificat du Gateway via
gateway.remote.tlsFingerprintou l’option CLI--tls-fingerprint.
Portée
Ce protocole expose l’intégralité de l’API du Gateway : état, canaux, modèles, chat,
agent, sessions, nœuds, approbations, etc. La surface exacte est définie par
les schémas TypeBox réexportés depuis packages/gateway-protocol/src/schema.ts.