Gateway-Protokoll (WebSocket)
Das Gateway-WS-Protokoll ist die einzige Kontrollebene + Node-Transport für OpenClaw. Alle Clients (CLI, Web-UI, macOS-App, iOS/Android-Nodes, Headless-Nodes) verbinden sich per WebSocket und geben Rolle und Scope beim Handshake an.
Transport
- WebSocket, Text-Frames mit JSON-Payloads.
- Der erste Frame muss eine
connect-Anfrage sein.
Handshake (connect)
Gateway → Client (Pre-Connect-Challenge):
{
"type": "event",
"event": "connect.challenge",
"payload": { "nonce": "…", "ts": 1737264000000 }
}Client → Gateway:
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"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": "…"
}
}
}Gateway → Client:
{
"type": "res",
"id": "…",
"ok": true,
"payload": { "type": "hello-ok", "protocol": 3, "policy": { "tickIntervalMs": 15000 } }
}Wenn ein Device-Token ausgestellt wird, enthält hello-ok zusätzlich:
{
"auth": {
"deviceToken": "…",
"role": "operator",
"scopes": ["operator.read", "operator.write"]
}
}Node-Beispiel
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"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": "…"
}
}
}Framing
- Request:
{type:"req", id, method, params} - Response:
{type:"res", id, ok, payload|error} - Event:
{type:"event", event, payload, seq?, stateVersion?}
Seiteneffekt-Methoden erfordern Idempotency-Keys (siehe Schema).
Rollen + Scopes
Rollen
operator= Kontrollebenen-Client (CLI/UI/Automation).node= Fähigkeiten-Host (Kamera/Bildschirm/Canvas/system.run).
Scopes (operator)
Gängige Scopes:
operator.readoperator.writeoperator.adminoperator.approvalsoperator.pairing
Caps/commands/permissions (node)
Nodes melden Fähigkeits-Claims beim Verbinden:
caps: übergeordnete Fähigkeitskategorien.commands: Command-Allowlist für Invoke.permissions: granulare Schalter (z. B.screen.record,camera.capture).
Der Gateway behandelt diese als Claims und erzwingt serverseitige Allowlists.
Presence
system-presenceliefert Einträge, die nach Geräte-Identität keyed sind.- Presence-Einträge enthalten
deviceId,rolesundscopes, damit UIs eine Zeile pro Gerät anzeigen können, auch wenn es sich sowohl als operator als auch als node verbindet.
Node-Helfer-Methoden
- Nodes können
skills.binsaufrufen, um die aktuelle Liste der Skill-Executables für Auto-Allow-Checks zu holen.
Exec-Genehmigungen
- Wenn eine Exec-Anfrage eine Genehmigung braucht, sendet der Gateway
exec.approval.requested. - Operator-Clients lösen das durch Aufruf von
exec.approval.resolve(erfordert Scopeoperator.approvals).
Versionierung
PROTOCOL_VERSIONliegt insrc/gateway/protocol/schema.ts.- Clients senden
minProtocol+maxProtocol; der Server lehnt Abweichungen ab. - Schemas + Modelle werden aus TypeBox-Definitionen erzeugt:
pnpm protocol:genpnpm protocol:gen:swiftpnpm protocol:check
Auth
- Ist
CLAWDBOT_GATEWAY_TOKEN(oder--token) gesetzt, mussconnect.params.auth.tokenübereinstimmen, sonst wird der Socket geschlossen. - Nach dem Pairing stellt der Gateway einen Device-Token aus, der auf Rolle + Scopes der Verbindung begrenzt ist. Er wird in
hello-ok.auth.deviceTokenzurückgegeben und sollte vom Client für spätere Verbindungen gespeichert werden. - Device-Tokens können über
device.token.rotateunddevice.token.revokerotiert/widerrufen werden (erfordert Scopeoperator.pairing).
Geräte-Identität + Pairing
- Nodes sollten eine stabile Geräte-Identität (
device.id) angeben, abgeleitet von einem Keypair-Fingerprint. - Gateways stellen Tokens pro Gerät + Rolle aus.
- Pairing-Genehmigungen sind für neue Geräte-IDs nötig, außer lokale Auto-Genehmigung ist aktiviert.
- Lokale Verbindungen umfassen Loopback und die eigene Tailnet-Adresse des Gateway-Hosts (damit Same-Host-Tailnet-Binds weiter auto-genehmigen können).
- Alle WS-Clients müssen während
connecteinedevice-Identität mitsenden (operator + node). Die Control-UI darf sie nur weglassen, wenngateway.controlUi.allowInsecureAuthaktiviert ist (odergateway.controlUi.dangerouslyDisableDeviceAuthfür Break-Glass). - Nicht-lokale Verbindungen müssen die vom Server gelieferte
connect.challenge-Nonce signieren.
TLS + Pinning
- TLS wird für WS-Verbindungen unterstützt.
- Clients können optional den Gateway-Zertifikats-Fingerprint pinnen (siehe Konfiguration
gateway.tlssowiegateway.remote.tlsFingerprintoder CLI--tls-fingerprint).
Geltungsbereich
Dieses Protokoll exponierte die vollständige Gateway-API (Status, Kanäle, Modelle, Chat, Agent, Sitzungen, Nodes, Genehmigungen usw.). Die genaue Oberfläche ist in den TypeBox-Schemas in src/gateway/protocol/schema.ts definiert.