메인 콘텐츠로 건너뛰기

브리지 프로토콜 (레거시 노드 전송 계층)

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를 시작하지 않습니다.
TLS가 활성화되면 discovery TXT records에 bridgeTls=1bridgeTlsSha256이 포함됐습니다. 단, Bonjour/mDNS TXT records는 인증되지 않으므로, 명시적인 사용자 의도나 별도 검증 없이 광고된 fingerprint를 authoritative pin처럼 취급하면 안 됩니다.

Handshake + pairing

  1. 클라이언트가 node metadata와 token(이미 paired된 경우)을 담아 hello를 보냅니다.
  2. paired되지 않았다면 gateway는 error (NOT_PAIRED/UNAUTHORIZED)를 돌려줍니다.
  3. 클라이언트가 pair-request를 보냅니다.
  4. gateway는 승인을 기다린 뒤 pair-okhello-ok를 보냅니다.
hello-okserverName을 반환하며, 경우에 따라 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)
Gateway → Client:
  • invoke / invoke-res: node commands (canvas.*, camera.*, screen.record, location.get, sms.send)
  • event: subscribed sessions의 chat updates
  • ping / pong: keepalive
레거시 allowlist enforcement는 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 session
  • runId: 그룹화를 위한 고유 exec id
  • command: 원시 또는 포맷된 command string
  • exitCode, 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를 사용했습니다.

Versioning

Bridge는 현재 암묵적인 v1입니다. 최소/최대 버전 협상은 없고, 하위 호환성을 유지하는 것이 전제입니다. breaking changes를 만들기 전에는 bridge protocol version field를 추가해야 합니다.