Gateway-Architektur
Zuletzt aktualisiert: 22.01.2026
Überblick
- Ein einzelnes, langlebiges Gateway verwaltet alle Messaging-Kanäle (WhatsApp via Baileys, Telegram via grammY, Slack, Discord, Signal, iMessage, WebChat).
- Control-Plane-Clients (macOS-App, CLI, Web-UI, Automationen) verbinden sich mit dem
Gateway über WebSocket auf dem konfigurierten Host (Standard:
127.0.0.1:18789). - Nodes (macOS/iOS/Android/headless) verbinden sich ebenfalls über WebSocket, aber
mit
role: nodeund expliziten Capabilities/Commands. - Ein Gateway pro Host; nur hier wird eine WhatsApp-Session geöffnet.
- Ein Canvas-Host (Standard:
18793) stellt vom Agent bearbeitbare HTML-Seiten und A2UI bereit.
Komponenten und Abläufe
Gateway (Daemon)
- Hält Provider-Verbindungen aufrecht.
- Stellt eine typisierte WS-API bereit (Requests, Responses, Server-Push-Events).
- Validiert eingehende Frames gegen JSON Schema.
- Sendet Events wie
agent,chat,presence,health,heartbeat,cron.
Clients (Mac-App / CLI / Web-Admin)
- Eine WS-Verbindung pro Client.
- Senden Requests (
health,status,send,agent,system-presence). - Abonnieren Events (
tick,agent,presence,shutdown).
Nodes (macOS / iOS / Android / headless)
- Verbinden sich mit dem gleichen WS-Server mit
role: node. - Übermitteln eine Geräte-Identität bei
connect; Pairing ist gerätebasiert (Rollenode) und die Freigabe wird im Device-Pairing-Store gespeichert. - Stellen Commands bereit wie
canvas.*,camera.*,screen.record,location.get.
Protokoll-Details:
WebChat
- Statische UI, die die Gateway-WS-API für Chat-Verlauf und Nachrichten nutzt.
- Bei Remote-Setups verbindet sie sich über denselben SSH/Tailscale-Tunnel wie andere Clients.
Verbindungs-Lebenszyklus (einzelner Client)
Client Gateway
| |
|---- req:connect -------->|
|<------ res (ok) ---------| (oder res error + close)
| (payload=hello-ok enthält Snapshot: presence + health)
| |
|<------ event:presence ---|
|<------ event:tick -------|
| |
|------- req:agent ------->|
|<------ res:agent --------| (ack: {runId,status:"accepted"})
|<------ event:agent ------| (streaming)
|<------ res:agent --------| (final: {runId,status,summary})
| |
Wire-Protokoll (Zusammenfassung)
- Transport: WebSocket, Text-Frames mit JSON-Payloads.
- Der erste Frame muss
connectsein. - Nach dem Handshake:
- Requests:
{type:"req", id, method, params}→{type:"res", id, ok, payload|error} - Events:
{type:"event", event, payload, seq?, stateVersion?}
- Requests:
- Wenn
OPENCLAW_GATEWAY_TOKEN(oder--token) gesetzt ist, mussconnect.params.auth.tokenübereinstimmen, sonst wird der Socket geschlossen. - Idempotency-Keys sind für Methoden mit Seiteneffekten (
send,agent) erforderlich, um sicheres Retry zu ermöglichen; der Server hält einen kurzlebigen Dedupe-Cache. - Nodes müssen
role: "node"plus Caps/Commands/Permissions inconnectangeben.
Pairing + lokales Vertrauen
- Alle WS-Clients (Operators + Nodes) übermitteln eine Geräte-Identität bei
connect. - Neue Geräte-IDs erfordern eine Pairing-Freigabe; das Gateway stellt einen Device-Token für nachfolgende Verbindungen aus.
- Lokale Verbindungen (Loopback oder die eigene Tailnet-Adresse des Gateway-Hosts) können automatisch freigegeben werden, um die UX auf demselben Host flüssig zu halten.
- Nicht-lokale Verbindungen müssen die
connect.challenge-Nonce signieren und erfordern eine explizite Freigabe. - Gateway-Auth (
gateway.auth.*) gilt weiterhin für alle Verbindungen, lokal oder remote.
Details: Gateway-Protokoll, Pairing, Sicherheit.
Protokoll-Typisierung und Codegen
- TypeBox-Schemas definieren das Protokoll.
- JSON Schema wird aus diesen Schemas generiert.
- Swift-Models werden aus dem JSON Schema generiert.
Remote-Zugriff
- Bevorzugt: Tailscale oder VPN.
- Alternative: SSH-Tunnel
ssh -N -L 18789:127.0.0.1:18789 user@host - Derselbe Handshake + Auth-Token gelten auch über den Tunnel.
- TLS + optionales Pinning kann für WS in Remote-Setups aktiviert werden.
Betrieb im Überblick
- Start:
openclaw gateway(Vordergrund, Logs auf stdout). - Health:
healthüber WS (auch inhello-okenthalten). - Supervision: launchd/systemd für Auto-Restart.
Invarianten
- Genau ein Gateway kontrolliert eine einzelne Baileys-Session pro Host.
- Handshake ist Pflicht; jeder nicht-JSON- oder nicht-connect-Frame als erster Frame führt zum sofortigen Schließen.
- Events werden nicht wiederholt; Clients müssen bei Lücken neu laden.