브리지 프로토콜 (레거시 노드 전송 계층)
Bridge 프로토콜은 레거시 노드 전송 방식(TCP JSONL)입니다. 새 노드 클라이언트는 이 방식 대신 통합된 Gateway WebSocket 프로토콜을 사용해야 합니다. 새 operator나 node client를 만든다면 Gateway protocol을 사용하세요. 참고: 현재 OpenClaw 빌드는 더 이상 TCP bridge listener를 포함하지 않습니다. 이 문서는 역사적 참고용으로만 유지되며, 레거시bridge.* config keys도 현재 config schema에 포함되지 않습니다.
Why we have both
과거에 bridge와 WebSocket을 함께 둔 이유는 다음과 같습니다.- Security boundary: 전체 gateway API surface 대신 작은 allowlist만 노출했습니다.
- Pairing + node identity: node admission은 gateway가 소유하고, per-node token과 연결됐습니다.
- Discovery UX: nodes는 LAN에서 Bonjour로 gateway를 찾거나 tailnet을 통해 직접 연결할 수 있었습니다.
- Loopback WS: SSH로 터널링하지 않는 한 전체 WS control plane은 로컬에 머물렀습니다.
Transport
- TCP, 한 줄에 하나의 JSON 객체를 쓰는 JSONL 형식입니다.
- 선택적으로 TLS를 지원했습니다 (
bridge.tls.enabled가 true일 때). - 레거시 기본 listener port는
18790이었습니다. 현재 빌드는 TCP bridge를 시작하지 않습니다.
bridgeTls=1과 bridgeTlsSha256이 포함됐습니다. 단, Bonjour/mDNS TXT records는 인증되지 않으므로, 명시적인 사용자 의도나 별도 검증 없이 광고된 fingerprint를 authoritative pin처럼 취급하면 안 됩니다.
Handshake + pairing
- 클라이언트가 node metadata와 token(이미 paired된 경우)을 담아
hello를 보냅니다. - paired되지 않았다면 gateway는
error(NOT_PAIRED/UNAUTHORIZED)를 돌려줍니다. - 클라이언트가
pair-request를 보냅니다. - gateway는 승인을 기다린 뒤
pair-ok와hello-ok를 보냅니다.
hello-ok는 serverName을 반환하며, 경우에 따라 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)
invoke/invoke-res: node commands (canvas.*,camera.*,screen.record,location.get,sms.send)event: subscribed sessions의 chat updatesping/pong: keepalive
src/gateway/server-bridge.ts에 있었지만 지금은 제거됐습니다.
Exec lifecycle events
nodes는system.run 활동을 표면화하기 위해 exec.finished 또는 exec.denied 이벤트를 보낼 수 있습니다. 이 이벤트는 gateway 안에서 system events로 매핑됩니다. 레거시 nodes는 exec.started를 보낼 수도 있습니다.
Payload fields (명시되지 않은 항목은 선택 사항):
sessionKey(필수): system event를 받을 agent sessionrunId: 그룹화를 위한 고유 exec idcommand: 원시 또는 포맷된 command stringexitCode,timedOut,success,output: 완료 상세 (finished전용)reason: 거부 사유 (denied전용)
Tailnet usage
- bridge를 tailnet IP에 바인딩하려면
~/.openclaw/openclaw.json에서bridge.bind: "tailnet"을 사용했습니다. - clients는 MagicDNS name이나 tailnet IP로 연결했습니다.
- Bonjour는 네트워크를 넘지 않으므로 필요하면 수동 host/port 또는 wide-area DNS-SD를 사용했습니다.