Files
openclaw/docs/gateway/bridge-protocol.md

83 lines
2.9 KiB
Markdown
Raw Normal View History

2026-01-12 04:44:14 +00:00
---
summary: "Bridge protocol (legacy nodes): TCP JSONL, pairing, scoped RPC"
2026-01-12 04:44:14 +00:00
read_when:
- Building or debugging node clients (iOS/Android/macOS node mode)
- Investigating pairing or bridge auth failures
- Auditing the node surface exposed by the gateway
---
# Bridge protocol (legacy node transport)
2026-01-12 04:44:14 +00:00
The Bridge protocol is a **legacy** node transport (TCP JSONL). New node clients
should use the unified Gateway WebSocket protocol instead.
2026-01-12 04:44:14 +00:00
If you are building an operator or node client, use the
2026-01-12 04:44:14 +00:00
[Gateway protocol](/gateway/protocol).
## Why we have both
- **Security boundary**: the bridge exposes a small allowlist instead of the
full gateway API surface.
- **Pairing + node identity**: node admission is owned by the gateway and tied
to a per-node token.
- **Discovery UX**: nodes can discover gateways via Bonjour on LAN, or connect
directly over a tailnet.
- **Loopback WS**: the full WS control plane stays local unless tunneled via SSH.
## Transport
- TCP, one JSON object per line (JSONL).
2026-01-16 05:28:33 +00:00
- Optional TLS (when `bridge.tls.enabled` is true).
2026-01-12 04:44:14 +00:00
- Gateway owns the listener (default `18790`).
2026-01-16 05:28:33 +00:00
When TLS is enabled, discovery TXT records include `bridgeTls=1` plus
`bridgeTlsSha256` so nodes can pin the certificate.
2026-01-12 04:44:14 +00:00
## Handshake + pairing
1) Client sends `hello` with node metadata + 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` returns `serverName` and may include `canvasHostUrl`.
## Frames
Client → Gateway:
- `req` / `res`: scoped gateway RPC (chat, sessions, config, health, voicewake, skills.bins)
- `event`: node signals (voice transcript, agent request, chat subscribe, exec lifecycle)
2026-01-12 04:44:14 +00:00
Gateway → Client:
- `invoke` / `invoke-res`: node commands (`canvas.*`, `camera.*`, `screen.record`,
`location.get`, `sms.send`)
- `event`: chat updates for subscribed sessions
- `ping` / `pong`: keepalive
Exact allowlist is enforced in `src/gateway/server-bridge.ts`.
## Exec lifecycle events
Nodes can emit `exec.started`, `exec.finished`, or `exec.denied` events to surface
system.run activity. These are mapped to system events in the gateway.
Payload fields (all optional unless noted):
- `sessionKey` (required): agent session to receive the system event.
- `runId`: unique exec id for grouping.
- `command`: raw or formatted command string.
- `exitCode`, `timedOut`, `success`, `output`: completion details (finished only).
- `reason`: denial reason (denied only).
2026-01-12 04:44:14 +00:00
## Tailnet usage
- Bind the bridge to a tailnet IP: `bridge.bind: "tailnet"` in
`~/.clawdbot/clawdbot.json`.
- Clients connect via MagicDNS name or tailnet IP.
- Bonjour does **not** cross networks; use manual host/port or wide-area DNSSD
when needed.
## Versioning
Bridge is currently **implicit v1** (no min/max negotiation). Backwardcompat
is expected; add a bridge protocol version field before any breaking changes.