Skip to main content
The TCP bridge has been removed. Current OpenClaw builds do not ship the bridge listener, and bridge.* config keys are no longer in the schema. This page is historical reference only. Use the Gateway protocol for all node/operator clients.

Why it existed

  • Security boundary: exposed a small allowlist instead of the full gateway API surface.
  • Pairing + node identity: node admission was owned by the gateway and tied to a per-node token.
  • Discovery UX: nodes could discover gateways via Bonjour on LAN, or connect directly over a tailnet.
  • Loopback WS: the full WS control plane stayed local unless tunneled via SSH.

Transport

  • TCP, one JSON object per line (JSONL).
  • Optional TLS (bridge.tls.enabled: true).
  • Default listener port was 18790.
When TLS was enabled, discovery TXT records included bridgeTls=1 plus bridgeTlsSha256 as a non-secret hint. Bonjour/mDNS TXT records are unauthenticated; clients could not treat the advertised fingerprint as an authoritative pin without other out-of-band verification.

Handshake and pairing

  1. Client sends hello with node metadata plus token (if already paired).
  2. If not paired, gateway replies error (NOT_PAIRED / UNAUTHORIZED).
  3. Client sends pair-request.
  4. Gateway waits for approval, then sends pair-ok and hello-ok.
hello-ok used to return serverName; hosted plugin surfaces are now advertised through pluginSurfaceUrls on the current Gateway protocol (Canvas/A2UI uses pluginSurfaceUrls.canvas).

Frames

Client to gateway:
  • req / res: scoped gateway RPC (chat, sessions, config, health, voicewake, skills.bins).
  • event: node signals (voice transcript, agent request, chat subscribe, exec lifecycle).
Gateway to client:
  • invoke / invoke-res: node commands (canvas.*, camera.*, screen.record, location.get, sms.send).
  • event: chat updates for subscribed sessions.
  • ping / pong: keepalive.
Allowlist enforcement lived in src/gateway/server-bridge.ts (removed).

Exec lifecycle events

Nodes emitted exec.finished to surface completed system.run activity, mapped to system events by the gateway (legacy nodes could also emit exec.started). exec.denied marked a denied system.run attempt as a terminal denial without enqueuing a system event or waking agent work. Payload fields (all optional unless noted):

Historical tailnet usage

  • Bind the bridge to a tailnet IP: bridge.bind: "tailnet" in ~/.openclaw/openclaw.json (historical only; bridge.* is no longer valid config).
  • Clients connected via MagicDNS name or tailnet IP.
  • Bonjour does not cross networks; wide-area DNS-SD or a manual host/port was required otherwise.

Versioning

The bridge was implicit v1, with no min/max negotiation. Current node/operator clients use the WebSocket Gateway protocol, which does negotiate a protocol version range.