Por qué existía
- Límite de seguridad: exponía una pequeña lista de permitidos en lugar de toda la superficie de la API del Gateway.
- Emparejamiento + identidad de nodo: la admisión de nodos era propiedad del Gateway y estaba vinculada a un token por nodo.
- UX de descubrimiento: los nodos podían descubrir gateways mediante Bonjour en la LAN, o conectarse directamente a través de una tailnet.
- WS de loopback: el plano de control WS completo permanecía local salvo que se tunelizara mediante SSH.
Transporte
- TCP, un objeto JSON por línea (JSONL).
- TLS opcional (
bridge.tls.enabled: true). - El puerto de listener predeterminado era
18790.
bridgeTls=1 más bridgeTlsSha256 como pista no secreta. Los registros TXT de Bonjour/mDNS no están autenticados; los clientes no podían tratar la huella anunciada como un pin autoritativo sin otra verificación fuera de banda.
Handshake y emparejamiento
- El cliente envía
hellocon metadatos del nodo más el token (si ya está emparejado). - Si no está emparejado, el Gateway responde
error(NOT_PAIRED/UNAUTHORIZED). - El cliente envía
pair-request. - El Gateway espera la aprobación y luego envía
pair-okyhello-ok.
hello-ok solía devolver serverName; las superficies de Plugin alojadas ahora se anuncian mediante pluginSurfaceUrls en el protocolo Gateway actual (Canvas/A2UI usa pluginSurfaceUrls.canvas).
Frames
Cliente a Gateway:req/res: RPC de Gateway acotado (chat, sesiones, configuración, estado, voicewake, skills.bins).event: señales del nodo (transcripción de voz, solicitud de agente, suscripción a chat, ciclo de vida de exec).
invoke/invoke-res: comandos de nodo (canvas.*,camera.*,screen.record,location.get,sms.send).event: actualizaciones de chat para sesiones suscritas.ping/pong: keepalive.
src/gateway/server-bridge.ts (eliminado).
Eventos del ciclo de vida de exec
Los nodos emitíanexec.finished para exponer actividad de system.run completada, asignada a eventos del sistema por el Gateway (los nodos heredados también podían emitir exec.started). exec.denied marcaba un intento denegado de system.run como una denegación terminal sin encolar un evento del sistema ni activar trabajo de agente.
Campos de payload (todos opcionales salvo que se indique lo contrario):
| Campo | Notas |
|---|---|
sessionKey | Obligatorio. Sesión de agente para correlación de eventos y, para exec.finished, entrega de eventos del sistema. |
runId | ID de exec único para agrupación. |
command | Cadena de comando sin procesar o formateada. |
exitCode, timedOut, output | Detalles de finalización (solo finalizados). |
reason | Motivo de denegación (solo denegados). |
Uso histórico de tailnet
- Vincula el puente a una IP de tailnet:
bridge.bind: "tailnet"en~/.openclaw/openclaw.json(solo histórico;bridge.*ya no es configuración válida). - Los clientes se conectaban mediante un nombre MagicDNS o una IP de tailnet.
- Bonjour no cruza redes; de lo contrario, se requería DNS-SD de área amplia o un host/puerto manual.