Gateway 服务运维手册

最后更新: 2025-12-09

它是什么

  • 一个常驻进程,负责管理单一的 Baileys/Telegram 连接以及控制/事件平面。
  • 替代了旧版的 gateway 命令。CLI 入口: openclaw gateway
  • 会一直运行直到停止;遇到致命错误时会以非零状态退出,这样监控程序会自动重启它。

如何运行(本地)

openclaw gateway --port 18789
# 在标准输出中显示完整的调试/追踪日志:
openclaw gateway --port 18789 --verbose
# 如果端口被占用,先终止监听进程再启动:
openclaw gateway --force
# 开发循环(TS 文件变化时自动重载):
pnpm gateway:watch
  • 配置热重载会监听 ~/.openclaw/openclaw.json(或 OPENCLAW_CONFIG_PATH)。
    • 默认模式: gateway.reload.mode="hybrid"(安全变更热应用,关键变更重启)。
    • 热重载在需要时通过 SIGUSR1 信号触发进程内重启。
    • gateway.reload.mode="off" 禁用。
  • 绑定 WebSocket 控制平面到 127.0.0.1:<port>(默认 18789)。
  • 同一端口也提供 HTTP 服务(控制 UI、hooks、A2UI)。单端口多路复用。
  • 默认在 canvasHost.port(默认 18793)上启动 Canvas 文件服务器,从 ~/.openclaw/workspace/canvas 提供 http://<gateway-host>:18793/__openclaw__/canvas/ 服务。用 canvasHost.enabled=falseOPENCLAW_SKIP_CANVAS_HOST=1 禁用。
  • 日志输出到 stdout;用 launchd/systemd 保持运行并轮转日志。
  • 传入 --verbose 可以在排查问题时将调试日志(握手、请求/响应、事件)从日志文件镜像到标准输出。
  • --force 使用 lsof 查找占用指定端口的监听进程,发送 SIGTERM,记录被终止的进程,然后启动 Gateway(如果缺少 lsof 会快速失败)。
  • 如果你在监控程序下运行(launchd/systemd/mac app 子进程模式),停止/重启通常会发送 SIGTERM;旧版本可能会显示 pnpm ELIFECYCLE 退出码 143(SIGTERM),这是正常关闭,不是崩溃。
  • SIGUSR1 在授权时触发进程内重启(Gateway 工具/配置应用/更新,或启用 commands.restart 手动重启)。
  • Gateway 认证默认是必需的: 设置 gateway.auth.token(或 OPENCLAW_GATEWAY_TOKEN)或 gateway.auth.password。客户端必须发送 connect.params.auth.token/password,除非使用 Tailscale Serve 身份。
  • 向导现在默认生成 token,即使在 loopback 上也是如此。
  • 端口优先级: --port > OPENCLAW_GATEWAY_PORT > gateway.port > 默认 18789

远程访问

  • 推荐 Tailscale/VPN;否则用 SSH 隧道:
    ssh -N -L 18789:127.0.0.1:18789 user@host
  • 客户端通过隧道连接到 ws://127.0.0.1:18789
  • 如果配置了 token,客户端必须在 connect.params.auth.token 中包含它,即使通过隧道也要。

多个 Gateway(同一主机)

通常不需要: 一个 Gateway 可以服务多个消息 Channel 和 Agent。只在需要冗余或严格隔离时(例如: 救援机器人)才使用多个 Gateway。

如果你隔离状态 + 配置并使用唯一端口,是支持的。完整指南: 多个 Gateway

服务名称支持 profile:

  • macOS: bot.molt.<profile>(旧版 com.openclaw.* 可能仍然存在)
  • Linux: openclaw-gateway-<profile>.service
  • Windows: OpenClaw Gateway (<profile>)

安装元数据嵌入在服务配置中:

  • OPENCLAW_SERVICE_MARKER=openclaw
  • OPENCLAW_SERVICE_KIND=gateway
  • OPENCLAW_SERVICE_VERSION=<version>

救援机器人模式: 保持第二个 Gateway 隔离,使用自己的 profile、状态目录、Workspace 和基础端口间隔。完整指南: 救援机器人指南

Dev profile (--dev)

快速路径: 运行完全隔离的开发实例(配置/状态/Workspace),不影响你的主要设置。

openclaw --dev setup
openclaw --dev gateway --allow-unconfigured
# 然后针对开发实例:
openclaw --dev status
openclaw --dev health

默认值(可通过环境变量/标志/配置覆盖):

  • OPENCLAW_STATE_DIR=~/.openclaw-dev
  • OPENCLAW_CONFIG_PATH=~/.openclaw-dev/openclaw.json
  • OPENCLAW_GATEWAY_PORT=19001(Gateway WS + HTTP)
  • 浏览器控制服务端口 = 19003(派生: gateway.port+2,仅 loopback)
  • canvasHost.port=19005(派生: gateway.port+4)
  • 当你在 --dev 下运行 setup/onboard 时,agents.defaults.workspace 默认变为 ~/.openclaw/workspace-dev

派生端口(经验法则):

  • 基础端口 = gateway.port(或 OPENCLAW_GATEWAY_PORT / --port)
  • 浏览器控制服务端口 = 基础端口 + 2(仅 loopback)
  • canvasHost.port = 基础端口 + 4(或 OPENCLAW_CANVAS_HOST_PORT / 配置覆盖)
  • 浏览器 profile CDP 端口从 browser.controlPort + 9 .. + 108 自动分配(每个 profile 持久化)。

每个实例的检查清单:

  • 唯一的 gateway.port
  • 唯一的 OPENCLAW_CONFIG_PATH
  • 唯一的 OPENCLAW_STATE_DIR
  • 唯一的 agents.defaults.workspace
  • 独立的 WhatsApp 号码(如果使用 WA)

每个 profile 的服务安装:

openclaw --profile main gateway install
openclaw --profile rescue gateway install

示例:

OPENCLAW_CONFIG_PATH=~/.openclaw/a.json OPENCLAW_STATE_DIR=~/.openclaw-a openclaw gateway --port 19001
OPENCLAW_CONFIG_PATH=~/.openclaw/b.json OPENCLAW_STATE_DIR=~/.openclaw-b openclaw gateway --port 19002

协议(运维视角)

  • 完整文档: Gateway 协议Bridge 协议(旧版)
  • 客户端的强制首帧: req {type:"req", id, method:"connect", params:{minProtocol,maxProtocol,client:{id,displayName?,version,platform,deviceFamily?,modelIdentifier?,mode,instanceId?}, caps, auth?, locale?, userAgent? } }
  • Gateway 回复 res {type:"res", id, ok:true, payload:hello-ok }(或 ok:false 带错误,然后关闭)。
  • 握手后:
    • 请求: {type:"req", id, method, params}{type:"res", id, ok, payload|error}
    • 事件: {type:"event", event, payload, seq?, stateVersion?}
  • 结构化的 presence 条目: {host, ip, version, platform?, deviceFamily?, modelIdentifier?, mode, lastInputSeconds?, ts, reason?, tags?[], instanceId? }(对于 WS 客户端,instanceId 来自 connect.client.instanceId)。
  • agent 响应是两阶段的: 首先 res 确认 {runId,status:"accepted"},然后在运行完成后最终 res {runId,status:"ok"|"error",summary};流式输出作为 event:"agent" 到达。

方法(初始集合)

  • health — 完整健康快照(与 openclaw health --json 形状相同)。
  • status — 简短摘要。
  • system-presence — 当前 presence 列表。
  • system-event — 发布 presence/系统注释(结构化)。
  • send — 通过活动 Channel 发送消息。
  • agent — 运行 Agent 回合(在同一连接上流式返回事件)。
  • node.list — 列出已配对 + 当前连接的节点(包括 capsdeviceFamilymodelIdentifierpairedconnected 和广告的 commands)。
  • node.describe — 描述节点(能力 + 支持的 node.invoke 命令;适用于已配对节点和当前连接的未配对节点)。
  • node.invoke — 在节点上调用命令(例如 canvas.*camera.*)。
  • node.pair.* — Pairing 生命周期(requestlistapproverejectverify)。

另见: Presence 了解 presence 如何生成/去重以及为什么稳定的 client.instanceId 很重要。

事件

  • agent — 来自 Agent 运行的流式工具/输出事件(带 seq 标签)。
  • presence — Presence 更新(带 stateVersion 的增量)推送到所有连接的客户端。
  • tick — 定期保活/无操作以确认存活。
  • shutdown — Gateway 正在退出;payload 包括 reason 和可选的 restartExpectedMs。客户端应该重新连接。

WebChat 集成

  • WebChat 是原生 SwiftUI UI,直接与 Gateway WebSocket 通信以获取历史、发送、中止和事件。
  • 远程使用通过相同的 SSH/Tailscale 隧道;如果配置了 Gateway token,客户端在 connect 期间包含它。
  • macOS app 通过单个 WS 连接(共享连接);它从初始快照中获取 presence 并监听 presence 事件以更新 UI。

类型和验证

  • 服务器使用 AJV 根据从协议定义生成的 JSON Schema 验证每个入站帧。
  • 客户端(TS/Swift)使用生成的类型(TS 直接使用;Swift 通过仓库的生成器)。
  • 协议定义是真理之源;用以下命令重新生成 schema/模型:
    • pnpm protocol:gen
    • pnpm protocol:gen:swift

连接快照

  • hello-ok 包含一个 snapshot,带有 presencehealthstateVersionuptimeMs,加上 policy {maxPayload,maxBufferedBytes,tickIntervalMs},这样客户端可以立即渲染而无需额外请求。
  • health/system-presence 仍可用于手动刷新,但在连接时不是必需的。

错误码(res.error 形状)

  • 错误使用 { code, message, details?, retryable?, retryAfterMs? }
  • 标准代码:
    • NOT_LINKED — WhatsApp 未认证。
    • AGENT_TIMEOUT — Agent 在配置的截止时间内未响应。
    • INVALID_REQUEST — schema/参数验证失败。
    • UNAVAILABLE — Gateway 正在关闭或依赖项不可用。

保活行为

  • tick 事件(或 WS ping/pong)定期发出,这样客户端知道即使没有流量时 Gateway 也是活着的。
  • 发送/Agent 确认保持为单独的响应;不要为发送重载 tick。

重放 / 间隙

  • 事件不会重放。客户端检测 seq 间隙并应在继续之前刷新(health + system-presence)。WebChat 和 macOS 客户端现在在间隙时自动刷新。

监控(macOS 示例)

  • 使用 launchd 保持服务运行:
    • Program: openclaw 的路径
    • Arguments: gateway
    • KeepAlive: true
    • StandardOut/Err: 文件路径或 syslog
  • 失败时,launchd 会重启;致命的配置错误应该持续退出,这样运维人员会注意到。
  • LaunchAgents 是每用户的,需要登录会话;无头设置使用自定义 LaunchDaemon(未提供)。
    • openclaw gateway install 写入 ~/Library/LaunchAgents/bot.molt.gateway.plist (或 bot.molt.<profile>.plist;旧版 com.openclaw.* 会被清理)。
    • openclaw doctor 审计 LaunchAgent 配置,可以将其更新到当前默认值。

Gateway 服务管理(CLI)

使用 Gateway CLI 进行安装/启动/停止/重启/状态:

openclaw gateway status
openclaw gateway install
openclaw gateway stop
openclaw gateway restart
openclaw logs --follow

注意事项:

  • gateway status 默认使用服务解析的端口/配置探测 Gateway RPC(用 --url 覆盖)。
  • gateway status --deep 添加系统级扫描(LaunchDaemons/系统单元)。
  • gateway status --no-probe 跳过 RPC 探测(网络故障时有用)。
  • gateway status --json 对脚本稳定。
  • gateway status监控运行时(launchd/systemd 运行)与 RPC 可达性(WS 连接 + status RPC)分开报告。
  • gateway status 打印配置路径 + 探测目标,避免”localhost vs LAN 绑定”混淆和 profile 不匹配。
  • gateway status 在服务看起来运行但端口关闭时包含最后的 Gateway 错误行。
  • logs 通过 RPC 跟踪 Gateway 文件日志(不需要手动 tail/grep)。
  • 如果检测到其他类似 Gateway 的服务,CLI 会警告,除非它们是 OpenClaw profile 服务。 我们仍然建议大多数设置每台机器一个 Gateway;使用隔离的 profile/端口实现冗余或救援机器人。参见 多个 Gateway
    • 清理: openclaw gateway uninstall(当前服务)和 openclaw doctor(旧版迁移)。
  • gateway install 在已安装时是无操作;使用 openclaw gateway install --force 重新安装(profile/环境/路径变更)。

捆绑的 mac app:

  • OpenClaw.app 可以捆绑基于 Node 的 Gateway 中继并安装标记为 bot.molt.gateway(或 bot.molt.<profile>;旧版 com.openclaw.* 标签仍然可以干净卸载)的每用户 LaunchAgent。
  • 要干净地停止它,使用 openclaw gateway stop(或 launchctl bootout gui/$UID/bot.molt.gateway)。
  • 要重启,使用 openclaw gateway restart(或 launchctl kickstart -k gui/$UID/bot.molt.gateway)。
    • launchctl 仅在安装了 LaunchAgent 时有效;否则先使用 openclaw gateway install
    • 运行命名 profile 时将标签替换为 bot.molt.<profile>

监控(systemd 用户单元)

OpenClaw 在 Linux/WSL2 上默认安装 systemd 用户服务。我们 推荐单用户机器使用用户服务(更简单的环境,每用户配置)。 多用户或常驻服务器使用 系统服务(不需要 lingering, 共享监控)。

openclaw gateway install 写入用户单元。openclaw doctor 审计 单元并可以将其更新为当前推荐的默认值。

创建 ~/.config/systemd/user/openclaw-gateway[-<profile>].service:

[Unit]
Description=OpenClaw Gateway (profile: <profile>, v<version>)
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/openclaw gateway --port 18789
Restart=always
RestartSec=5
Environment=OPENCLAW_GATEWAY_TOKEN=
WorkingDirectory=/home/youruser

[Install]
WantedBy=default.target

启用 lingering(必需,这样用户服务在登出/空闲后仍然存活):

sudo loginctl enable-linger youruser

引导在 Linux/WSL2 上运行此命令(可能提示 sudo;写入 /var/lib/systemd/linger)。 然后启用服务:

systemctl --user enable --now openclaw-gateway[-<profile>].service

替代方案(系统服务) - 对于常驻或多用户服务器,你可以 安装 systemd 系统单元而不是用户单元(不需要 lingering)。 创建 /etc/systemd/system/openclaw-gateway[-<profile>].service(复制上面的单元, 切换 WantedBy=multi-user.target,设置 User= + WorkingDirectory=),然后:

sudo systemctl daemon-reload
sudo systemctl enable --now openclaw-gateway[-<profile>].service

Windows (WSL2)

Windows 安装应使用 WSL2 并遵循上面的 Linux systemd 部分。

运维检查

  • 存活性: 打开 WS 并发送 req:connect → 期望 res 带有 payload.type="hello-ok"(带快照)。
  • 就绪性: 调用 health → 期望 ok: truelinkChannel 中的已链接 Channel(如果适用)。
  • 调试: 订阅 tickpresence 事件;确保 status 显示已链接/认证年龄;presence 条目显示 Gateway 主机和已连接客户端。

安全保证

  • 默认假设每台主机一个 Gateway;如果你运行多个 profile,隔离端口/状态并针对正确的实例。
  • 不会回退到直接 Baileys 连接;如果 Gateway 宕机,发送会快速失败。
  • 非连接首帧或格式错误的 JSON 会被拒绝并关闭套接字。
  • 优雅关闭: 在关闭前发出 shutdown 事件;客户端必须处理关闭 + 重新连接。

CLI 辅助工具

  • openclaw gateway health|status — 通过 Gateway WS 请求健康/状态。
  • openclaw message send --target <num> --message "hi" [--media ...] — 通过 Gateway 发送(WhatsApp 幂等)。
  • openclaw agent --message "hi" --to <num> — 运行 Agent 回合(默认等待最终结果)。
  • openclaw gateway call <method> --params '{"k":"v"}' — 用于调试的原始方法调用器。
  • openclaw gateway stop|restart — 停止/重启受监控的 Gateway 服务(launchd/systemd)。
  • Gateway 辅助子命令假设在 --url 上有运行的 Gateway;它们不再自动生成一个。

迁移指南

  • 停用 openclaw gateway 和旧版 TCP 控制端口的使用。
  • 更新客户端以使用强制连接和结构化 presence 的 WS 协议。