Gateway Service Runbook

Zuletzt aktualisiert: 09.12.2025

Was ist das Gateway?

  • Der dauerhaft laufende Prozess, der die Baileys/Telegram-Verbindung und die Control/Event-Ebene verwaltet.
  • Ersetzt den alten gateway-Befehl. CLI-Einstiegspunkt: openclaw gateway.
  • Läuft bis zum Stoppen; beendet sich mit Fehlercode bei fatalen Fehlern, damit der Supervisor neu startet.

Lokal starten

openclaw gateway --port 18789
# für vollständige Debug/Trace-Logs in stdio:
openclaw gateway --port 18789 --verbose
# wenn der Port belegt ist, Listener beenden und dann starten:
openclaw gateway --force
# Dev-Loop (Auto-Reload bei TS-Änderungen):
pnpm gateway:watch
  • Config Hot Reload überwacht ~/.openclaw/openclaw.json (oder OPENCLAW_CONFIG_PATH).
    • Standardmodus: gateway.reload.mode="hybrid" (sichere Änderungen hot-applyen, bei kritischen neu starten).
    • Hot Reload nutzt In-Process-Restart via SIGUSR1 wenn nötig.
    • Deaktivieren mit gateway.reload.mode="off".
  • Bindet WebSocket Control Plane an 127.0.0.1:<port> (Standard 18789).
  • Der gleiche Port bedient auch HTTP (Control UI, Hooks, A2UI). Single-Port-Multiplex.
  • Startet standardmäßig einen Canvas-Dateiserver auf canvasHost.port (Standard 18793), der http://<gateway-host>:18793/__openclaw__/canvas/ aus ~/.openclaw/workspace/canvas bereitstellt. Deaktivieren mit canvasHost.enabled=false oder OPENCLAW_SKIP_CANVAS_HOST=1.
  • Loggt nach stdout; nutze launchd/systemd um den Dienst am Leben zu halten und Logs zu rotieren.
  • Mit --verbose werden Debug-Logs (Handshakes, req/res, Events) aus der Log-Datei auch in stdio gespiegelt — nützlich beim Troubleshooting.
  • --force nutzt lsof um Listener auf dem gewählten Port zu finden, sendet SIGTERM, loggt was beendet wurde, und startet dann das Gateway (schlägt fehl wenn lsof fehlt).
  • Wenn du unter einem Supervisor läufst (launchd/systemd/Mac-App Child-Process-Modus), sendet ein Stop/Restart typischerweise SIGTERM; ältere Builds zeigen das als pnpm ELIFECYCLE Exit-Code 143 (SIGTERM), was ein normales Herunterfahren ist, kein Crash.
  • SIGUSR1 löst einen In-Process-Restart aus wenn autorisiert (Gateway Tool/Config Apply/Update, oder aktiviere commands.restart für manuelle Restarts).
  • Gateway-Auth ist standardmäßig erforderlich: setze gateway.auth.token (oder OPENCLAW_GATEWAY_TOKEN) oder gateway.auth.password. Clients müssen connect.params.auth.token/password senden, außer bei Tailscale Serve Identity.
  • Der Wizard generiert jetzt standardmäßig einen Token, auch auf Loopback.
  • Port-Priorität: --port > OPENCLAW_GATEWAY_PORT > gateway.port > Standard 18789.

Remote-Zugriff

  • Tailscale/VPN bevorzugt; ansonsten SSH-Tunnel:
    ssh -N -L 18789:127.0.0.1:18789 user@host
  • Clients verbinden sich dann über den Tunnel zu ws://127.0.0.1:18789.
  • Wenn ein Token konfiguriert ist, müssen Clients ihn in connect.params.auth.token mitschicken, auch über den Tunnel.

Mehrere Gateways (gleicher Host)

Normalerweise nicht nötig: Ein Gateway kann mehrere Messaging-Channels und Agents bedienen. Nutze mehrere Gateways nur für Redundanz oder strikte Isolation (z.B. Rescue-Bot).

Möglich wenn du State + Config isolierst und eindeutige Ports verwendest. Vollständige Anleitung: Mehrere Gateways.

Service-Namen sind profilabhängig:

  • macOS: bot.molt.<profile> (Legacy com.openclaw.* kann noch existieren)
  • Linux: openclaw-gateway-<profile>.service
  • Windows: OpenClaw Gateway (<profile>)

Install-Metadaten sind in der Service-Config eingebettet:

  • OPENCLAW_SERVICE_MARKER=openclaw
  • OPENCLAW_SERVICE_KIND=gateway
  • OPENCLAW_SERVICE_VERSION=<version>

Rescue-Bot-Pattern: Halte ein zweites Gateway isoliert mit eigenem Profil, State-Verzeichnis, Workspace und Port-Abstand. Vollständige Anleitung: Rescue-Bot-Guide.

Dev-Profil (--dev)

Schneller Weg: Starte eine vollständig isolierte Dev-Instanz (Config/State/Workspace) ohne dein primäres Setup zu berühren.

openclaw --dev setup
openclaw --dev gateway --allow-unconfigured
# dann die Dev-Instanz ansprechen:
openclaw --dev status
openclaw --dev health

Standardwerte (können via env/flags/config überschrieben werden):

  • OPENCLAW_STATE_DIR=~/.openclaw-dev
  • OPENCLAW_CONFIG_PATH=~/.openclaw-dev/openclaw.json
  • OPENCLAW_GATEWAY_PORT=19001 (Gateway WS + HTTP)
  • Browser Control Service Port = 19003 (abgeleitet: gateway.port+2, nur Loopback)
  • canvasHost.port=19005 (abgeleitet: gateway.port+4)
  • agents.defaults.workspace wird standardmäßig ~/.openclaw/workspace-dev wenn du setup/onboard unter --dev ausführst.

Abgeleitete Ports (Faustregeln):

  • Basis-Port = gateway.port (oder OPENCLAW_GATEWAY_PORT / --port)
  • Browser Control Service Port = Basis + 2 (nur Loopback)
  • canvasHost.port = Basis + 4 (oder OPENCLAW_CANVAS_HOST_PORT / Config-Override)
  • Browser-Profil CDP-Ports werden automatisch von browser.controlPort + 9 .. + 108 zugewiesen (pro Profil persistiert).

Checkliste pro Instanz:

  • eindeutiger gateway.port
  • eindeutiger OPENCLAW_CONFIG_PATH
  • eindeutiger OPENCLAW_STATE_DIR
  • eindeutiger agents.defaults.workspace
  • separate WhatsApp-Nummern (wenn WA genutzt wird)

Service-Installation pro Profil:

openclaw --profile main gateway install
openclaw --profile rescue gateway install

Beispiel:

OPENCLAW_CONFIG_PATH=~/.openclaw/a.json OPENCLAW_STATE_DIR=~/.openclaw-a openclaw gateway --port 19001
OPENCLAW_CONFIG_PATH=~/.openclaw/b.json OPENCLAW_STATE_DIR=~/.openclaw-b openclaw gateway --port 19002

Protokoll (Operator-Sicht)

  • Vollständige Docs: Gateway-Protokoll und Bridge-Protokoll (Legacy).
  • Pflicht-Frame vom Client zuerst: req {type:"req", id, method:"connect", params:{minProtocol,maxProtocol,client:{id,displayName?,version,platform,deviceFamily?,modelIdentifier?,mode,instanceId?}, caps, auth?, locale?, userAgent? } }.
  • Gateway antwortet mit res {type:"res", id, ok:true, payload:hello-ok } (oder ok:false mit Fehler, dann schließt es).
  • Nach dem Handshake:
    • Requests: {type:"req", id, method, params}{type:"res", id, ok, payload|error}
    • Events: {type:"event", event, payload, seq?, stateVersion?}
  • Strukturierte Presence-Einträge: {host, ip, version, platform?, deviceFamily?, modelIdentifier?, mode, lastInputSeconds?, ts, reason?, tags?[], instanceId? } (für WS-Clients kommt instanceId von connect.client.instanceId).
  • agent-Responses sind zweistufig: erst res Ack {runId,status:"accepted"}, dann ein finales res {runId,status:"ok"|"error",summary} nach Abschluss des Runs; gestreamte Ausgabe kommt als event:"agent".

Methoden (initiales Set)

  • health — vollständiger Health-Snapshot (gleiche Form wie openclaw health --json).
  • status — kurze Zusammenfassung.
  • system-presence — aktuelle Presence-Liste.
  • system-event — Presence/System-Notiz posten (strukturiert).
  • send — Nachricht über den/die aktiven Channel(s) senden.
  • agent — Agent-Turn ausführen (streamt Events zurück auf derselben Verbindung).
  • node.list — gepaarte + aktuell verbundene Nodes auflisten (enthält caps, deviceFamily, modelIdentifier, paired, connected und beworbene commands).
  • node.describe — Node beschreiben (Capabilities + unterstützte node.invoke-Befehle; funktioniert für gepaarte Nodes und aktuell verbundene ungepaarte Nodes).
  • node.invoke — Befehl auf einem Node ausführen (z.B. canvas.*, camera.*).
  • node.pair.* — Pairing-Lifecycle (request, list, approve, reject, verify).

Siehe auch: Presence für wie Presence erzeugt/dedupliziert wird und warum eine stabile client.instanceId wichtig ist.

Events

  • agent — gestreamte Tool/Output-Events vom Agent-Run (seq-getaggt).
  • presence — Presence-Updates (Deltas mit stateVersion) an alle verbundenen Clients gepusht.
  • tick — periodischer Keepalive/No-Op um Liveness zu bestätigen.
  • shutdown — Gateway beendet sich; Payload enthält reason und optionales restartExpectedMs. Clients sollten reconnecten.

WebChat-Integration

  • WebChat ist eine native SwiftUI-UI, die direkt mit dem Gateway WebSocket für History, Sends, Abort und Events kommuniziert.
  • Remote-Nutzung geht durch denselben SSH/Tailscale-Tunnel; wenn ein Gateway-Token konfiguriert ist, schickt der Client ihn beim connect mit.
  • Die macOS-App verbindet sich über einen einzelnen WS (geteilte Verbindung); sie hydratisiert Presence aus dem initialen Snapshot und lauscht auf presence-Events um die UI zu aktualisieren.

Typing und Validierung

  • Der Server validiert jeden eingehenden Frame mit AJV gegen JSON Schema, das aus den Protokoll-Definitionen generiert wird.
  • Clients (TS/Swift) konsumieren generierte Types (TS direkt; Swift via den Generator des Repos).
  • Protokoll-Definitionen sind die Source of Truth; Schema/Models neu generieren mit:
    • pnpm protocol:gen
    • pnpm protocol:gen:swift

Connection Snapshot

  • hello-ok enthält einen snapshot mit presence, health, stateVersion und uptimeMs plus policy {maxPayload,maxBufferedBytes,tickIntervalMs}, damit Clients sofort rendern können ohne extra Requests.
  • health/system-presence bleiben für manuelles Refresh verfügbar, sind aber beim Connect nicht erforderlich.

Fehlercodes (res.error-Form)

  • Fehler nutzen { code, message, details?, retryable?, retryAfterMs? }.
  • Standard-Codes:
    • NOT_LINKED — WhatsApp nicht authentifiziert.
    • AGENT_TIMEOUT — Agent hat nicht innerhalb der konfigurierten Deadline geantwortet.
    • INVALID_REQUEST — Schema/Param-Validierung fehlgeschlagen.
    • UNAVAILABLE — Gateway fährt herunter oder eine Dependency ist nicht verfügbar.

Keepalive-Verhalten

  • tick-Events (oder WS ping/pong) werden periodisch gesendet, damit Clients wissen, dass das Gateway lebt, auch wenn kein Traffic stattfindet.
  • Send/Agent-Acknowledgements bleiben separate Responses; überlade Ticks nicht für Sends.

Replay / Lücken

  • Events werden nicht replayed. Clients erkennen seq-Lücken und sollten refreshen (health + system-presence) bevor sie fortfahren. WebChat und macOS-Clients machen jetzt Auto-Refresh bei Lücken.

Supervision (macOS-Beispiel)

  • Nutze launchd um den Service am Leben zu halten:
    • Program: Pfad zu openclaw
    • Arguments: gateway
    • KeepAlive: true
    • StandardOut/Err: Dateipfade oder syslog
  • Bei Fehlern startet launchd neu; fatale Fehlkonfiguration sollte weiter exiten, damit der Operator es bemerkt.
  • LaunchAgents sind pro User und erfordern eine eingeloggte Session; für Headless-Setups nutze einen eigenen LaunchDaemon (nicht mitgeliefert).
    • openclaw gateway install schreibt ~/Library/LaunchAgents/bot.molt.gateway.plist (oder bot.molt.<profile>.plist; Legacy com.openclaw.* wird aufgeräumt).
    • openclaw doctor prüft die LaunchAgent-Config und kann sie auf aktuelle Defaults aktualisieren.

Gateway Service Management (CLI)

Nutze die Gateway CLI für install/start/stop/restart/status:

openclaw gateway status
openclaw gateway install
openclaw gateway stop
openclaw gateway restart
openclaw logs --follow

Hinweise:

  • gateway status probt das Gateway RPC standardmäßig mit dem aufgelösten Port/Config des Services (überschreiben mit --url).
  • gateway status --deep fügt System-Level-Scans hinzu (LaunchDaemons/System Units).
  • gateway status --no-probe überspringt den RPC-Probe (nützlich wenn Networking down ist).
  • gateway status --json ist stabil für Scripts.
  • gateway status meldet Supervisor Runtime (launchd/systemd läuft) separat von RPC Reachability (WS Connect + Status RPC).
  • gateway status gibt Config-Pfad + Probe-Target aus um “localhost vs LAN bind”-Verwirrung und Profil-Mismatches zu vermeiden.
  • gateway status zeigt die letzte Gateway-Fehlerzeile wenn der Service läuft aber der Port geschlossen ist.
  • logs tailt das Gateway-Datei-Log via RPC (kein manuelles tail/grep nötig).
  • Wenn andere Gateway-ähnliche Services erkannt werden, warnt die CLI, außer es sind OpenClaw-Profil-Services. Wir empfehlen weiterhin ein Gateway pro Maschine für die meisten Setups; nutze isolierte Profile/Ports für Redundanz oder einen Rescue-Bot. Siehe Mehrere Gateways.
    • Cleanup: openclaw gateway uninstall (aktueller Service) und openclaw doctor (Legacy-Migrationen).
  • gateway install ist ein No-Op wenn bereits installiert; nutze openclaw gateway install --force zum Reinstallieren (Profil/Env/Pfad-Änderungen).

Gebündelte Mac-App:

  • OpenClaw.app kann ein Node-basiertes Gateway-Relay bündeln und einen pro-User LaunchAgent installieren mit Label bot.molt.gateway (oder bot.molt.<profile>; Legacy com.openclaw.*-Labels werden sauber entladen).
  • Zum sauberen Stoppen nutze openclaw gateway stop (oder launchctl bootout gui/$UID/bot.molt.gateway).
  • Zum Neustarten nutze openclaw gateway restart (oder launchctl kickstart -k gui/$UID/bot.molt.gateway).
    • launchctl funktioniert nur wenn der LaunchAgent installiert ist; ansonsten nutze zuerst openclaw gateway install.
    • Ersetze das Label durch bot.molt.<profile> wenn du ein benanntes Profil nutzt.

Supervision (systemd User Unit)

OpenClaw installiert standardmäßig einen systemd User Service auf Linux/WSL2. Wir empfehlen User Services für Single-User-Maschinen (einfacheres Env, pro-User Config). Nutze einen System Service für Multi-User oder Always-On-Server (kein Lingering nötig, geteilte Supervision).

openclaw gateway install schreibt die User Unit. openclaw doctor prüft die Unit und kann sie auf die aktuell empfohlenen Defaults aktualisieren.

Erstelle ~/.config/systemd/user/openclaw-gateway[-<profile>].service:

[Unit]
Description=OpenClaw Gateway (profile: <profile>, v<version>)
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/openclaw gateway --port 18789
Restart=always
RestartSec=5
Environment=OPENCLAW_GATEWAY_TOKEN=
WorkingDirectory=/home/youruser

[Install]
WantedBy=default.target

Aktiviere Lingering (erforderlich damit der User Service Logout/Idle überlebt):

sudo loginctl enable-linger youruser

Onboarding führt das auf Linux/WSL2 aus (kann nach sudo fragen; schreibt /var/lib/systemd/linger). Dann aktiviere den Service:

systemctl --user enable --now openclaw-gateway[-<profile>].service

Alternative (System Service) — für Always-On oder Multi-User-Server kannst du statt einer User Unit eine systemd System Unit installieren (kein Lingering nötig). Erstelle /etc/systemd/system/openclaw-gateway[-<profile>].service (kopiere die Unit oben, ändere WantedBy=multi-user.target, setze User= + WorkingDirectory=), dann:

sudo systemctl daemon-reload
sudo systemctl enable --now openclaw-gateway[-<profile>].service

Windows (WSL2)

Windows-Installationen sollten WSL2 nutzen und dem Linux systemd-Abschnitt oben folgen.

Betriebsprüfungen

  • Liveness: WS öffnen und req:connect senden → erwarte res mit payload.type="hello-ok" (mit Snapshot).
  • Readiness: health aufrufen → erwarte ok: true und einen verlinkten Channel in linkChannel (wenn zutreffend).
  • Debug: auf tick- und presence-Events subscriben; stelle sicher, dass status linked/auth age zeigt; Presence-Einträge zeigen Gateway-Host und verbundene Clients.

Sicherheitsgarantien

  • Gehe standardmäßig von einem Gateway pro Host aus; wenn du mehrere Profile nutzt, isoliere Ports/State und ziele auf die richtige Instanz.
  • Kein Fallback zu direkten Baileys-Verbindungen; wenn das Gateway down ist, schlagen Sends schnell fehl.
  • Non-Connect First Frames oder malformed JSON werden abgelehnt und der Socket wird geschlossen.
  • Graceful Shutdown: shutdown-Event vor dem Schließen senden; Clients müssen Close + Reconnect handhaben.

CLI-Helfer

  • openclaw gateway health|status — Health/Status über den Gateway WS anfragen.
  • openclaw message send --target <num> --message "hi" [--media ...] — via Gateway senden (idempotent für WhatsApp).
  • openclaw agent --message "hi" --to <num> — Agent-Turn ausführen (wartet standardmäßig auf Final).
  • openclaw gateway call <method> --params '{"k":"v"}' — Raw Method Invoker zum Debuggen.
  • openclaw gateway stop|restart — den supervisierten Gateway-Service stoppen/neustarten (launchd/systemd).
  • Gateway-Helfer-Subcommands setzen ein laufendes Gateway auf --url voraus; sie spawnen keins mehr automatisch.

Migrations-Hinweise

  • Stelle Nutzung von openclaw gateway und dem Legacy TCP Control Port ein.
  • Aktualisiere Clients auf das WS-Protokoll mit Pflicht-Connect und strukturierter Presence.