跳转至

网关架构

概述

  • 单个长期存活的 Gateway 拥有所有消息界面(WhatsApp 通过 Baileys,Telegram 通过 grammY,Slack、Discord、Signal、iMessage、WebChat)。
  • 控制平面客户端(macOS 应用、CLI、Web UI、自动化)通过 WebSocket 连接到 配置绑定主机上的 Gateway(默认 127.0.0.1:18789)。
  • Nodes(macOS/iOS/Android/headless)也通过 WebSocket 连接,但 声明 role: node 并带有显式 caps/commands。
  • 每个主机一个 Gateway。它是唯一打开 WhatsApp 会话的地方。
  • 托管 widget 界面 由 Gateway HTTP 服务器在以下路径下提供:
  • /__openclaw__/canvas/(托管 widget 文档)
  • /__openclaw__/a2ui/(A2UI 渲染器资源)

它使用与 Gateway 相同的端口(默认 18789)。

组件与流程

Gateway(守护进程)

  • 维护提供商连接。
  • 暴露类型化 WS API(请求、响应、服务器推送事件)。
  • 根据 JSON Schema 验证入站帧。
  • 发出诸如 agent、chat、presence、health、heartbeat、cron 等事件。

客户端(mac 应用 / CLI / Web 管理)

  • 每个客户端一个 WS 连接。
  • 发送请求(health、status、send、agent、system-presence)。
  • 订阅事件(tick、agent、presence、shutdown)。

Nodes(macOS / iOS / Android / headless)

  • 以 role: node 连接到 同一个 WS 服务器。
  • 在 connect 中提供设备身份。配对是 基于设备 的(角色 node),并且 审批保存在设备配对存储中。
  • 暴露诸如 camera.*、screen.record 和 location.get 等命令。 macOS 应用还暴露 canvas.* 下的 widget 面板命令。

协议详情:Gateway 协议

WebChat

  • 使用 Gateway WS API 处理聊天历史和发送的静态 UI。
  • 在远程设置中,通过与其他客户端相同的 SSH/Tailscale 隧道连接。

连接生命周期(单个客户端)

sequenceDiagram
    participant Client
    participant Gateway

    Client->>Gateway: req:connect
    Gateway-->>Client: res (ok)
    Note right of Gateway: or res error + close
    Note left of Client: payload=hello-ok<br>snapshot: presence + health

    Gateway-->>Client: event:presence
    Gateway-->>Client: event:tick

    Client->>Gateway: req:agent
    Gateway-->>Client: res:agent<br>ack {runId, status:"accepted"}
    Gateway-->>Client: event:agent<br>(streaming)
    Gateway-->>Client: res:agent<br>final {runId, status, summary}

线路协议(摘要)

  • 传输:WebSocket,文本帧,JSON 负载。
  • 第一个帧 必须 是 connect。
  • 握手后:
  • 请求:{type:"req", id, method, params} → {type:"res", id, ok, payload|error}
  • 事件:{type:"event", event, payload, seq?, stateVersion?}
  • hello-ok.features.methods / events 是发现元数据,而不是 每个可调用 helper 路由的生成转储。
  • 共享密钥认证接受配置的秘密,位于 connect.params.auth.token 或 connect.params.auth.password。 gateway.auth.mode 选择配置的值(gateway.auth.token 或 gateway.auth.password),而不是必需的线路字段。
  • 携带身份的模式,例如 Tailscale Serve (gateway.auth.allowTailscale: true)或非回环 gateway.auth.mode: "trusted-proxy",从请求头而不是 connect.params.auth.* 满足认证。
  • 私有入口 gateway.auth.mode: "none" 完全禁用共享密钥认证。 请勿在公共或不受信任的入口上启用该模式。
  • 具有副作用的方法(send、agent)需要幂等键,以便安全重试。服务器保留短期去重缓存。
  • Nodes 必须在 connect 中包含 role: "node" 以及 caps/commands/permissions。

配对与本地信任

  • 所有 WS 客户端(操作员 + Nodes)在 connect 中包含 设备身份。
  • 新设备 ID 需要配对审批。Gateway 为后续连接颁发 设备令牌。
  • 直接本地回环连接可以自动批准,以保持同主机体验顺畅。
  • OpenClaw 还有一个狭窄的后端/容器本地自连接路径,用于 受信任的共享密钥 helper 流程。
  • Tailnet 和 LAN 连接,包括同主机 tailnet 绑定,仍然需要 显式配对审批。
  • 所有连接都必须对 connect.challenge 随机数签名。签名负载 v3 还绑定 platform 和 deviceFamily。Gateway 在重连时固定已配对元数据, 并要求元数据变更时进行修复配对。
  • 非本地 连接仍需要显式审批。
  • Gateway 认证(gateway.auth.*)仍然适用于 所有 连接,无论本地还是 远程。

详情:Gateway 协议、配对、 安全。

协议类型与代码生成

  • TypeBox 模式定义协议。
  • JSON Schema 从这些模式生成。
  • Swift 模型从 JSON Schema 生成。

远程访问

  • 首选:Tailscale 或 VPN。
  • 替代方案:SSH 隧道
ssh -N -L 18789:127.0.0.1:18789 user@gateway-host
  • 相同的握手 + 认证令牌适用于隧道。
  • 在远程设置中,可以为 WS 启用 TLS + 可选固定。

运维快照

  • 启动:openclaw gateway(前台,日志输出到 stdout)。
  • 健康:通过 WS 的 health(也包含在 hello-ok 中)。
  • 监督:使用 launchd/systemd 自动重启。

定时工作与关闭

Gateway 内核拥有一个 GatewayScheduler,用于已注册的维护和 cron 唤醒。所有者接收该实例并注册任务;一个主机定时器驱动下一次唤醒。对于持久性工作,存储保留截止时间,其所有者在启动时重建计划,而不是持久化第二个调度器状态。

睡眠后,迟到的唤醒会为每次可运行、到期的注册项在该次唤醒中分派一次。周期性注册会等待其回调和跟踪工作完成,然后才开始下一个间隔;错过的 tick 会被合并。墙钟时间弥补睡眠,而经过时间使相对延迟和节奏在时钟向后校正时继续推进。重新调度默认替换等待中的任务;mode: "earliest" 为同一任务 ID 保留更早的墙钟和经过截止时间,因此陈旧读取无法推迟已经承诺的唤醒。

beginClose() 关闭调度准入,取消待处理的唤醒,并发出关闭信号。stop() 会等待已在运行的回调以及由其异步作用域跟踪的工作完成;Gateway 生命周期负责外层关闭预算和资源拆除。请求截止时间、流本地定时器和子进程清理仍由其操作所有者负责。SQLite WAL 检查点定时器仍由存储所有者负责。

不变量

  • 每个主机上,恰好一个 Gateway 控制单个 Baileys 会话。
  • 握手是强制的。任何非 JSON 或非 connect 的首帧都会导致强制关闭。
  • 事件不会重放。客户端在出现间隙时必须刷新。
  • 代理循环 — 详细的代理执行周期
  • 网关协议 — WebSocket 协议契约
  • 队列 — 命令队列和并发
  • 安全 — 信任模型和加固
  • 网络 — OpenClaw 如何跨 localhost、LAN 和 tailnet 连接、配对并保护设备的核心枢纽

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw