Kiến trúc Gateway
Cập nhật lần cuối: 22/01/2026
Tổng quan
- Một Gateway duy nhất chạy lâu dài sẽ quản lý tất cả các kênh nhắn tin (WhatsApp qua Baileys, Telegram qua grammY, Slack, Discord, Signal, iMessage, WebChat).
- Các client điều khiển (macOS app, CLI, web UI, automation) kết nối tới Gateway qua WebSocket trên địa chỉ bind đã cấu hình (mặc định
127.0.0.1:18789). - Node (macOS/iOS/Android/headless) cũng kết nối qua WebSocket, nhưng khai báo
role: nodevới các capability và command cụ thể. - Mỗi host chỉ có một Gateway; đây là nơi duy nhất mở WhatsApp session.
- Một canvas host (mặc định
18793) phục vụ HTML và A2UI có thể chỉnh sửa bởi Agent.
Các thành phần và luồng hoạt động
Gateway (daemon)
- Duy trì kết nối với các provider.
- Cung cấp WS API có kiểu dữ liệu rõ ràng (request, response, server-push event).
- Validate các frame đầu vào theo JSON Schema.
- Phát ra các event như
agent,chat,presence,health,heartbeat,cron.
Client (mac app / CLI / web admin)
- Mỗi client có một kết nối WS.
- Gửi request (
health,status,send,agent,system-presence). - Subscribe các event (
tick,agent,presence,shutdown).
Node (macOS / iOS / Android / headless)
- Kết nối tới cùng WS server với
role: node. - Cung cấp device identity trong
connect; Pairing dựa trên thiết bị (rolenode) và việc phê duyệt được lưu trong device pairing store. - Cung cấp các command như
canvas.*,camera.*,screen.record,location.get.
Chi tiết protocol:
WebChat
- UI tĩnh sử dụng Gateway WS API để lấy lịch sử chat và gửi tin nhắn.
- Trong các setup từ xa, kết nối qua cùng SSH/Tailscale tunnel như các client khác.
Vòng đời kết nối (single client)
Client Gateway
| |
|---- req:connect -------->|
|<------ res (ok) ---------| (hoặc res error + close)
| (payload=hello-ok chứa snapshot: presence + health)
| |
|<------ event:presence ---|
|<------ event:tick -------|
| |
|------- req:agent ------->|
|<------ res:agent --------| (ack: {runId,status:"accepted"})
|<------ event:agent ------| (streaming)
|<------ res:agent --------| (final: {runId,status,summary})
| |
Wire protocol (tóm tắt)
- Transport: WebSocket, text frame với JSON payload.
- Frame đầu tiên bắt buộc phải là
connect. - Sau khi handshake:
- Request:
{type:"req", id, method, params}→{type:"res", id, ok, payload|error} - Event:
{type:"event", event, payload, seq?, stateVersion?}
- Request:
- Nếu
OPENCLAW_GATEWAY_TOKEN(hoặc--token) được set,connect.params.auth.tokenphải khớp, nếu không socket sẽ đóng. - Idempotency key bắt buộc cho các method có side-effect (
send,agent) để retry an toàn; server giữ một dedupe cache tạm thời. - Node phải include
role: "node"cộng với caps/commands/permissions trongconnect.
Pairing + local trust
- Tất cả WS client (operator + node) đều include device identity khi
connect. - Device ID mới cần được phê duyệt pairing; Gateway sẽ cấp device token cho các lần connect sau.
- Kết nối local (loopback hoặc địa chỉ tailnet của chính gateway host) có thể được auto-approve để giữ UX mượt mà trên cùng host.
- Kết nối non-local phải ký
connect.challengenonce và cần phê duyệt rõ ràng. - Gateway auth (
gateway.auth.*) vẫn áp dụng cho tất cả kết nối, dù local hay remote.
Chi tiết: Gateway protocol, Pairing, Security.
Protocol typing và codegen
- TypeBox schema định nghĩa protocol.
- JSON Schema được generate từ các schema đó.
- Swift model được generate từ JSON Schema.
Remote access
- Khuyên dùng: Tailscale hoặc VPN.
- Cách khác: SSH tunnel
ssh -N -L 18789:127.0.0.1:18789 user@host - Cùng handshake + auth token áp dụng qua tunnel.
- TLS + optional pinning có thể được bật cho WS trong các setup remote.
Operations snapshot
- Khởi động:
openclaw gateway(foreground, log ra stdout). - Health check:
healthqua WS (cũng có tronghello-ok). - Giám sát: launchd/systemd để auto-restart.
Các bất biến (invariant)
- Chỉ có đúng một Gateway điều khiển một Baileys session trên mỗi host.
- Handshake là bắt buộc; bất kỳ frame đầu tiên nào không phải JSON hoặc không phải connect sẽ bị đóng ngay.
- Event không được replay; client phải refresh khi có gap.