docs: add protocol docs

This commit is contained in:
Peter Steinberger
2026-01-12 04:44:14 +00:00
parent dfe5c03ba3
commit 986ff8c59f
8 changed files with 170 additions and 3 deletions

View File

@@ -11,9 +11,11 @@ Last updated: 2026-01-05
- A single longlived **Gateway** owns all messaging surfaces (WhatsApp via
Baileys, Telegram via grammY, Slack, Discord, Signal, iMessage, WebChat).
- All clients (macOS app, CLI, web UI, automations) connect to the Gateway over
**one transport: WebSocket** on the configured bind host (default
- Control-plane clients (macOS app, CLI, web UI, automations) connect to the
Gateway over **WebSocket** on the configured bind host (default
`127.0.0.1:18789`).
- **Nodes** (macOS/iOS/Android) use the **Bridge** protocol (TCP JSONL) instead
of the WebSocket control plane.
- One Gateway per host; it is the only place that opens a WhatsApp session.
- A **bridge** (default `18790`) is used for nodes (macOS/iOS/Android).
- A **canvas host** (default `18793`) serves agenteditable HTML and A2UI.
@@ -36,6 +38,10 @@ Last updated: 2026-01-05
- Pair with the Gateway to receive a token.
- Expose commands like `canvas.*`, `camera.*`, `screen.record`, `location.get`.
Protocol details:
- [Gateway protocol](/gateway/protocol)
- [Bridge protocol](/gateway/bridge-protocol)
### WebChat
- Static UI that uses the Gateway WS API for chat history and sends.
- In remote setups, connects through the same SSH/Tailscale tunnel as other

View File

@@ -635,6 +635,8 @@
"group": "Gateway & Ops",
"pages": [
"gateway",
"gateway/protocol",
"gateway/bridge-protocol",
"gateway/pairing",
"gateway/gateway-lock",
"environment",

View File

@@ -0,0 +1,67 @@
---
summary: "Bridge protocol (nodes): TCP JSONL, pairing, scoped RPC"
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 (Node transport)
The Bridge protocol is a **narrow, authenticated** transport for nodes
(iOS/Android/macOS node mode). It keeps the Gateway WS control plane loopbackonly
and exposes only a scoped set of methods for nodes.
If you are building an operator client (CLI, web UI, automations), use the
[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).
- Gateway owns the listener (default `18790`).
## 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)
- `event`: node signals (voice transcript, agent request, chat subscribe)
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`.
## 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.

View File

@@ -21,6 +21,10 @@ The design goal is to keep all network discovery/advertising in the **Node Gatew
- **Bridge (direct transport)**: a LAN/tailnet-facing endpoint owned by the gateway that allows authenticated clients/nodes to call a scoped subset of gateway methods. The bridge exists so the gateway can remain loopback-only.
- **SSH transport (fallback)**: remote control by forwarding `127.0.0.1:18789` over SSH.
Protocol details:
- [Gateway protocol](/gateway/protocol)
- [Bridge protocol](/gateway/bridge-protocol)
## Why we keep both “direct” and SSH
- **Direct bridge** is the best UX on the same network and within a tailnet:

View File

@@ -103,6 +103,7 @@ CLAWDBOT_CONFIG_PATH=~/.clawdbot/b.json CLAWDBOT_STATE_DIR=~/.clawdbot-b clawdbo
```
## Protocol (operator view)
- Full docs: [Gateway protocol](/gateway/protocol) and [Bridge protocol](/gateway/bridge-protocol).
- Mandatory first frame from client: `req {type:"req", id, method:"connect", params:{minProtocol,maxProtocol,client:{id,displayName?,version,platform,deviceFamily?,modelIdentifier?,mode,instanceId?}, caps, auth?, locale?, userAgent? } }`.
- Gateway replies `res {type:"res", id, ok:true, payload:hello-ok }` (or `ok:false` with an error, then closes).
- After handshake:

86
docs/gateway/protocol.md Normal file
View File

@@ -0,0 +1,86 @@
---
summary: "Gateway WebSocket protocol: handshake, frames, versioning"
read_when:
- Implementing or updating gateway WS clients
- Debugging protocol mismatches or connect failures
- Regenerating protocol schema/models
---
# Gateway protocol (WebSocket)
The Gateway WS protocol is the **full control plane** for Clawdbot. It is
loopback-only by default and is intended for local clients (CLI, web UI,
automations).
If you are building a **node client** (iOS/Android/macOS node mode), use the
[Bridge protocol](/gateway/bridge-protocol) instead.
## Transport
- WebSocket, text frames with JSON payloads.
- First frame **must** be a `connect` request.
## Handshake (connect)
Client → Gateway:
```json
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"client": {
"id": "cli",
"version": "1.2.3",
"platform": "macos",
"mode": "operator"
},
"caps": [],
"auth": { "token": "…" },
"locale": "en-US",
"userAgent": "clawdbot-cli/1.2.3"
}
}
```
Gateway → Client:
```json
{
"type": "res",
"id": "…",
"ok": true,
"payload": { "type": "hello-ok", "protocol": 3, "policy": { "tickIntervalMs": 15000 } }
}
```
## Framing
- **Request**: `{type:"req", id, method, params}`
- **Response**: `{type:"res", id, ok, payload|error}`
- **Event**: `{type:"event", event, payload, seq?, stateVersion?}`
Side-effecting methods require **idempotency keys** (see schema).
## Versioning
- `PROTOCOL_VERSION` lives in `src/gateway/protocol/schema.ts`.
- Clients send `minProtocol` + `maxProtocol`; the server rejects mismatches.
- Schemas + models are generated from TypeBox definitions:
- `pnpm protocol:gen`
- `pnpm protocol:gen:swift`
- `pnpm protocol:check`
## Auth
- If `CLAWDBOT_GATEWAY_TOKEN` (or `--token`) is set, `connect.params.auth.token`
must match or the socket is closed.
## Scope
This protocol exposes the **full gateway API** (status, providers, models,
chat, agent, sessions, nodes, etc.). The exact surface is defined by the
TypeBox schemas in `src/gateway/protocol/schema.ts`.

View File

@@ -8,7 +8,7 @@ read_when:
# Nodes
A **node** is a companion device (iOS/Android today) that connects to the Gateway over the **Bridge** and exposes a command surface (e.g. `canvas.*`, `camera.*`, `system.*`) via `node.invoke`.
A **node** is a companion device (iOS/Android today) that connects to the Gateway over the **Bridge** and exposes a command surface (e.g. `canvas.*`, `camera.*`, `system.*`) via `node.invoke`. Bridge protocol details: [Bridge protocol](/gateway/bridge-protocol).
macOS can also run in **node mode**: the menubar app connects to the Gateways bridge and exposes its local canvas/camera commands as a node (so `clawdbot nodes …` works against this Mac).

View File

@@ -13,6 +13,7 @@ read_when:
- Gateway required: yes (run it on macOS, Linux, or Windows via WSL2).
- Install: [Getting Started](/start/getting-started) + [Pairing](/gateway/pairing).
- Gateway: [Runbook](/gateway) + [Configuration](/gateway/configuration).
- Protocols: [Bridge protocol](/gateway/bridge-protocol) (nodes) and [Gateway protocol](/gateway/protocol) (control plane).
## System control
System control (launchd/systemd) lives on the Gateway host. See [Gateway](/gateway).