Ir al contenido

Conecta OpenClaw mediante WebSocket: Guía de protocolo

¿Alguna vez has intentado sincronizar una CLI, una interfaz web y varios nodos remotos sin que la comunicación se vuelva un caos? Gestionar diferentes protocolos para cada cliente suele ser un dolor de cabeza que complica el mantenimiento y la escalabilidad de cualquier sistema distribuido.

El protocolo de Gateway por WebSocket (WS) de OpenClaw soluciona esto actuando como el único plano de control y transporte de nodos. Todos los clientes, ya sea la CLI, la UI web o los nodos de iOS y Android, se conectan mediante WebSocket y declaran su función y permisos al iniciar la conexión.

  • WebSocket, frames de texto con payloads JSON.
  • El primer frame debe ser una solicitud connect.

Gateway → Client (desafío previo a la conexión):

{
"type": "event",
"event": "connect.challenge",
"payload": { "nonce": "…", "ts": 1737264000000 }
}

Client → Gateway:

{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"client": {
"id": "cli",
"version": "1.2.3",
"platform": "macos",
"mode": "operator"
},
"role": "operator",
"scopes": ["operator.read", "operator.write"],
"caps": [],
"commands": [],
"permissions": {},
"auth": { "token": "…" },
"locale": "en-US",
"userAgent": "openclaw-cli/1.2.3",
"device": {
"id": "device_fingerprint",
"publicKey": "…",
"signature": "…",
"signedAt": 1737264000000,
"nonce": "…"
}
}
}

Gateway → Client:

{
"type": "res",
"id": "…",
"ok": true,
"payload": { "type": "hello-ok", "protocol": 3, "policy": { "tickIntervalMs": 15000 } }
}

Cuando se emite un token de dispositivo, hello-ok también incluye:

{
"auth": {
"deviceToken": "…",
"role": "operator",
"scopes": ["operator.read", "operator.write"]
}
}
{
"type": "req",
"id": "…",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"client": {
"id": "ios-node",
"version": "1.2.3",
"platform": "ios",
"mode": "node"
},
"role": "node",
"scopes": [],
"caps": ["camera", "canvas", "screen", "location", "voice"],
"commands": ["camera.snap", "canvas.navigate", "screen.record", "location.get"],
"permissions": { "camera.capture": true, "screen.record": false },
"auth": { "token": "…" },
"locale": "en-US",
"userAgent": "openclaw-ios/1.2.3",
"device": {
"id": "device_fingerprint",
"publicKey": "…",
"signature": "…",
"signedAt": 1737264000000,
"nonce": "…"
}
}
}
  • Request: {type:"req", id, method, params}
  • Response: {type:"res", id, ok, payload|error}
  • Event: {type:"event", event, payload, seq?, stateVersion?}

Los métodos que generan efectos secundarios requieren idempotency keys (consulta el schema).

  • operator: cliente del plano de control (CLI, UI o automatización).
  • node: host de capacidades (camera, screen, canvas, system.run).

Alcances comunes:

  • operator.read
  • operator.write
  • operator.admin
  • operator.approvals
  • operator.pairing

El scope del método es solo el primer filtro. Algunos comandos de barra ejecutados mediante chat.send aplican verificaciones más estrictas. Por ejemplo, las escrituras persistentes de /config set y /config unset requieren operator.admin.

  • system-presence devuelve entradas indexadas por la identidad del dispositivo.
  • Las entradas incluyen deviceId, roles y scopes. Esto permite que las interfaces muestren una sola fila por dispositivo aunque esté conectado como operator y node a la vez.
  • Los nodos pueden llamar a skills.bins para obtener la lista actual de ejecutables de habilidades y realizar verificaciones automáticas.
  • Los operadores pueden llamar a tools.catalog (operator.read) para obtener el catálogo de herramientas en tiempo real de un agente. La respuesta incluye herramientas agrupadas y metadatos de procedencia:
    • source: core o plugin
    • pluginId: propietario del plugin si source="plugin"
    • optional: indica si una herramienta de plugin es opcional
  • Los operadores pueden llamar a tools.effective (operator.read) para obtener el inventario de herramientas efectivas de una sesión.
    • Se requiere sessionKey.
    • El Gateway deriva el contexto de ejecución confiable desde la sesión en el servidor.
    • La respuesta está limitada a la sesión y refleja lo que la conversación activa puede usar en ese momento.
  • Cuando una solicitud de ejecución necesita aprobación, el Gateway emite exec.approval.requested.
  • Los clientes de tipo operator resuelven esto llamando a exec.approval.resolve (requiere el scope operator.approvals).
  • Para host=node, exec.approval.request debe incluir systemRunPlan (con argv, cwd, rawCommand y metadatos de sesión). Si falta, la solicitud se rechaza.
  • Las solicitudes de agent pueden incluir deliver=true para pedir una entrega externa.
  • bestEffortDeliver=false mantiene un comportamiento estricto: si el destino no se resuelve o es solo interno, devuelve INVALID_REQUEST.
  • bestEffortDeliver=true permite ejecutar solo en la sesión cuando no se encuentra una ruta de entrega externa (útil en chats web o configuraciones multicanal ambiguas).
  • PROTOCOL_VERSION se define en src/gateway/protocol/schema.ts.
  • Los clientes envían minProtocol y maxProtocol; el servidor rechaza si no hay coincidencia.
  • Los esquemas y modelos se generan con TypeBox:
    • pnpm protocol:gen
    • pnpm protocol:gen:swift
    • pnpm protocol:check
  • Si OPENCLAW_GATEWAY_TOKEN (o --token) está configurado, connect.params.auth.token debe coincidir o el socket se cerrará.
  • Tras el emparejamiento, el Gateway emite un device token limitado al rol y alcances de la conexión. Se devuelve en hello-ok.auth.deviceToken y el cliente debe guardarlo.
  • Los tokens de dispositivo se pueden rotar o revocar mediante device.token.rotate y device.token.revoke (requiere operator.pairing).
  • Los fallos de autenticación incluyen error.details.code y sugerencias de recuperación:
    • error.details.canRetryWithDeviceToken (booleano)
    • error.details.recommendedNextStep (retry_with_device_token, update_auth_configuration, wait_then_retry, etc.)

Si ocurre un AUTH_TOKEN_MISMATCH, los clientes confiables pueden reintentar una vez con el token de dispositivo guardado. Si falla, deben detener los reintentos automáticos y guiar al usuario.

  • Los nodos deben incluir una identidad estable (device.id) basada en la huella de un par de claves.
  • El Gateway emite tokens por dispositivo y rol.
  • Se requiere aprobación para nuevos IDs de dispositivo, a menos que la auto-aprobación local esté activa.
  • Las conexiones locales incluyen loopback y la dirección de tailnet del host del Gateway.
  • Todos los clientes WS deben incluir la identidad device al conectar. La UI de control solo puede omitirlo si:
    • gateway.controlUi.allowInsecureAuth=true (para compatibilidad con HTTP inseguro en localhost).
    • gateway.controlUi.dangerouslyDisableDeviceAuth=true (solo para emergencias, reduce drásticamente la seguridad).

Para clientes antiguos, connect devuelve códigos en error.details.code con una razón estable en error.details.reason.

Errores comunes de migración:

Mensajedetails.codedetails.reasonSignificado
device nonce requiredDEVICE_AUTH_NONCE_REQUIREDdevice-nonce-missingFalta device.nonce.
device nonce mismatchDEVICE_AUTH_NONCE_MISMATCHdevice-nonce-mismatchEl nonce es antiguo o incorrecto.
device signature invalidDEVICE_AUTH_SIGNATURE_INVALIDdevice-signatureLa firma no coincide con el payload v2.
device signature expiredDEVICE_AUTH_SIGNATURE_EXPIREDdevice-signature-staleEl timestamp firmado está fuera de rango.
device identity mismatchDEVICE_AUTH_DEVICE_ID_MISMATCHdevice-id-mismatchdevice.id no coincide con la clave pública.
device public key invalidDEVICE_AUTH_PUBLIC_KEY_INVALIDdevice-public-keyError en el formato de la clave pública.

Para una migración correcta, espera siempre a connect.challenge, firma el payload v3 (que incluye platform y deviceFamily) y envía el mismo nonce en los parámetros de conexión.

  • Las conexiones WS admiten TLS.
  • Puedes hacer pinning de la huella del certificado del Gateway mediante la configuración gateway.tls o el flag --tls-fingerprint.

Este protocolo expone toda la API del Gateway (estado, canales, modelos, chat, agentes, sesiones, nodos y aprobaciones). La superficie exacta está definida por los esquemas TypeBox en src/gateway/protocol/schema.ts.

AI Setup Assistant

OpenClaw

OpenClaw Expert

Sigues atascado?

Si esta pagina no resolvio tu caso, pregunta a OpenClaw Expert para pasos concretos.