Saltar para o conteúdo principal

Arquitetura do Gateway

Última atualização: 2026-01-22

Visão geral

  • Um único Gateway de longa duração controla todas as superfícies de mensagens (WhatsApp via Baileys, Telegram via grammY, Slack, Discord, Signal, iMessage, WebChat).
  • Clientes do plano de controle (app macOS, CLI, UI web, automações) conectam-se ao Gateway via WebSocket no host de bind configurado (padrão 127.0.0.1:18789).
  • Nodes (macOS/iOS/Android/headless) também se conectam via WebSocket, mas declaram role: node com capacidades/comandos explícitos.
  • Um Gateway por host; é o único lugar que abre uma sessão do WhatsApp.
  • O canvas host é servido pelo servidor HTTP do Gateway em:
    • /__openclaw__/canvas/ (HTML/CSS/JS editável pelo agente)
    • /__openclaw__/a2ui/ (host A2UI) Usa a mesma porta do Gateway (padrão 18789).

Componentes e fluxos

Gateway (daemon)

  • Mantém conexões com provedores.
  • Expõe uma API WS tipada (requisições, respostas, eventos enviados pelo servidor).
  • Valida frames de entrada contra JSON Schema.
  • Emite eventos como agent, chat, presence, health, heartbeat, cron.

Clientes (app mac / CLI / admin web)

  • Uma conexão WS por cliente.
  • Enviam requisições (health, status, send, agent, system-presence).
  • Assinam eventos (tick, agent, presence, shutdown).

Nodes (macOS / iOS / Android / headless)

  • Conectam-se ao mesmo servidor WS com role: node.
  • Fornecem uma identidade de dispositivo em connect; o pareamento é baseado em dispositivo (papel node) e a aprovação fica no armazenamento de pareamento de dispositivos.
  • Exponham comandos como canvas.*, camera.*, screen.record, location.get.
Detalhes do protocolo:

WebChat

  • UI estática que usa a API WS do Gateway para histórico de chat e envios.
  • Em configurações remotas, conecta-se pelo mesmo túnel SSH/Tailscale que outros clientes.

Ciclo de vida da conexão (cliente único)

Protocolo de fio (resumo)

  • Transporte: WebSocket, frames de texto com payloads JSON.
  • O primeiro frame deve ser connect.
  • Após o handshake:
    • Requisições: {type:"req", id, method, params}{type:"res", id, ok, payload|error}
    • Eventos: {type:"event", event, payload, seq?, stateVersion?}
  • Se OPENCLAW_GATEWAY_TOKEN (ou --token) estiver definido, connect.params.auth.token deve corresponder ou o socket é fechado.
  • Chaves de idempotência são obrigatórias para métodos com efeitos colaterais (send, agent) para permitir retry com segurança; o servidor mantém um cache de deduplicação de curta duração.
  • Nodes devem incluir role: "node" mais capacidades/comandos/permissões em connect.

Pareamento + confiança local

  • Todos os clientes WS (operadores + nodes) incluem uma identidade de dispositivo em connect.
  • Novos IDs de dispositivo exigem aprovação de pareamento; o Gateway emite um token de dispositivo para conexões subsequentes.
  • Conexões locais (loopback ou o endereço do próprio host do gateway na tailnet) podem ser aprovadas automaticamente para manter a UX no mesmo host fluida.
  • Conexões não locais devem assinar o nonce connect.challenge e exigem aprovação explícita.
  • A autenticação do Gateway (gateway.auth.*) ainda se aplica a todas as conexões, locais ou remotas.
Detalhes: Gateway protocol, Pairing, Security.

Tipagem do protocolo e codegen

  • Esquemas TypeBox definem o protocolo.
  • JSON Schema é gerado a partir desses esquemas.
  • Modelos Swift são gerados a partir do JSON Schema.

Acesso remoto

  • Preferencial: Tailscale ou VPN.
  • Alternativa: túnel SSH
    ssh -N -L 18789:127.0.0.1:18789 user@host
    
  • O mesmo handshake + token de autenticação se aplicam pelo túnel.
  • TLS + pinagem opcional podem ser habilitados para WS em configurações remotas.

Panorama de operações

  • Inicialização: openclaw gateway (foreground, logs para stdout).
  • Saúde: health via WS (também incluído em hello-ok).
  • Supervisão: launchd/systemd para reinício automático.

Invariantes

  • Exatamente um Gateway controla uma única sessão Baileys por host.
  • O handshake é obrigatório; qualquer primeiro frame não‑JSON ou não‑connect resulta em fechamento imediato.
  • Eventos não são reproduzidos; clientes devem atualizar em caso de lacunas.