跳转至

构建 Gateway 客户端

Use the published Gateway packages to build operator dashboards, WebChat clients, and other third-party applications. This guide covers the client lifecycle around the wire contract: authentication, capabilities, reconnect recovery, history, subscriptions, and version upgrades.

For frame shapes, the handshake, errors, and the complete method surface, read the Gateway protocol specification.

安装包

使用精确版本固定安装已验证的稳定版本 2026.8.1:

npm install --save-exact @openclaw/gateway-client@2026.8.1 @openclaw/gateway-protocol@2026.8.1

如果现有 lockfile 仍将任一包固定到保留的 0.0.0 构件,请重新运行上述命令以替换它。这些保留构件没有可运行入口点或 TypeScript 声明。

包版本遵循 OpenClaw 发布列车,并且独立于线路协议版本。2026.8.1 包导出线路版本 4;这并不保证与每个 Gateway 发布版本兼容。根 openclaw CLI 有自己的包版本和 dist-tags。请一起固定并测试客户端和 Gateway 版本,并在升级前检查 线路版本规则。2026.8.1 客户端精确固定协议包 2026.8.1。

  • @openclaw/gateway-protocol 提供模式、运行时验证器、TypeScript 类型、客户端身份和能力注册表、结构化错误读取器以及协议版本常量。 其 npm tarball 还包含生成的 protocol.schema.json 机器可读契约。请将其作为文件下载;它不是导出的包导入子路径。
  • @openclaw/gateway-client 是参考连接实现。导入包根以使用 Node 客户端,导入 @openclaw/gateway-client/browser 以使用浏览器安全的协议、设备身份验证和重连辅助功能。

这些包发布声明 Node.js >=22.19.0。Node 入口包含 ws 传输;设备身份、签名和设备令牌存储通过 GatewayClientHostDeps 仍由宿主拥有。浏览器宿主提供 WebSocket 适配器,以及用于设备身份和设备令牌的持久化存储和签名回调。

选择作用域并配对设备

一个同时渲染审批提示的完整交互式聊天客户端应请求 role: "operator",并包含以下作用域:

作用域 用途
operator.read chat.history、sessions.list、sessions.subscribe、模型状态和只读事件
operator.write chat.send 和普通会话变更
operator.approvals 列出、显示和解决 exec 或插件审批

仅当客户端处理交互式问题时添加 operator.questions, 仅当它管理已配对设备或节点时添加 operator.pairing,仅当执行 config.patch 等管理操作时添加 operator.admin。 操作员作用域参考 定义了完整的方法规则和审批时规则。

不要通过手动编辑 openclaw.json 来为每个客户端创建 bearer token。使用 openclaw configure --section gateway 或 openclaw onboard --gateway-auth ... 选项配置 Gateway 的共享引导身份验证,然后让设备配对铸造客户端令牌:

  1. 在客户端中持久化 Ed25519 设备身份。
  2. 等待 connect.challenge,将其 ts 用作设备证明的 signedAt, 对与 challenge 绑定的设备负载进行签名,并发送 connect,其中包含请求的操作员角色、作用域以及用于引导身份验证的共享 Gateway 令牌或密码。收到的 WebSocket challenge 如果没有非负整数 ts,则无效。明确支持 connect.challenge 出现之前的 Gateway 的客户端,仅可在其无 challenge 路径上使用本地时间。
  3. 如果 Gateway 返回结构化的 PAIRING_REQUIRED 详细信息,请显示请求 ID,并根据 error.details.recommendedNextStep 暂停或重试。
  4. 在 Gateway 宿主上,使用 openclaw devices list 查看请求,然后 使用 openclaw devices approve <requestId> 批准该确切的当前请求。
  5. 重新连接,并将 hello-ok.auth.deviceToken 与协商后的角色和作用域一起持久化。在后续连接中使用该设备令牌。

作用域或角色升级会创建一个新的待处理配对请求。令牌轮换不能扩大已批准的配对契约。有关批准、轮换和吊销命令,请参阅 Devices CLI。

connect.params.caps 描述客户端可消费的可选行为。它不会授予授权。请从 GATEWAY_CLIENT_CAPS 导入名称,而不是重复字符串字面量:

import { GATEWAY_CLIENT_CAPS } from "@openclaw/gateway-protocol/client-info";

const caps = [GATEWAY_CLIENT_CAPS.TOOL_EVENTS];

当前注册表包含 agent-kind、approvals、exec-approvals、 inline-widgets、plugin-approvals、run-tool-bindings、session-scoped-events、 task-suggestions、terminal-offset-seq、tool-events、ui-commands 和 usage-refreshing。 仅声明客户端实际实现的能力。

usage-refreshing 允许冷 usage.status 请求立即返回 refreshing: true 和空提供商列表。声明它的客户端必须保持该负载缓存为冷状态,并在短而有界的调度上重新获取。其他客户端保留阻塞式冷读取。

Warning

tool-events 控制实时工具执行流。Gateway 仅将声明此能力的连接注册为某次运行结构化工具事件的接收方。没有它,连接不会收到实时工具事件,并且握手不会报告错误。

能力门控的代理工具是对同一声明的独立用途。如果代理工具需要客户端能力,除非发起客户端已通告所有必需能力,否则 Gateway 会省略该工具。

发送前验证附件

附件限制可由操作员调整,因此不要硬编码它们。读取 hello-ok.policy.attachments,并在上传前在本地验证:

const attachments = hello.policy.attachments;
if (attachments) {
  const ceiling = isImage ? attachments.maxImageBytes : attachments.maxBytes;
  if (file.byteLength > ceiling) rejectLocally();
}

这两个值都是解码后的单个附件上限。仍然要将序列化请求与 policy.maxPayload 进行检查:附件以 base64 传输,因此接近 maxBytes 的文件可能单独就超过帧限制。旧版 Gateway 会省略 policy.attachments;当它不存在时,发送并处理服务器结果。接受的 MIME 类型和逐消息处理不会被通告,因为它们取决于入口点和已解析的模型。Gateway 可以返回类型化拒绝,而纯文本模型运行在达到其卸载上限后可以省略额外图像,并且仍能完成请求。这些值是连接时快照,因此在每次重连时重新读取它们。

重连后恢复状态

将每次成功重连视为对持久化历史和当前内存中运行状态的新投影:

  1. 使用你的列表参数重新建立 sessions.subscribe,以便在同一响应中接收当前名册,如下方所述。同时重新建立所选会话的 sessions.messages.subscribe 订阅。
  2. 调用 chat.history 获取所选 sessionKey,并用返回的 messages 投影替换本地持久化行。
  3. 如果存在 inFlightRun,采用其 runId、缓冲的 text 和可选的 plan。即使 text 为空,也要采用该运行。
  4. 将 sessionInfo.hasActiveRun 视为聚合的直接会话活动。当 activeRunIds 存在时,它是完整的精确活动集合;因此空数组可证明会话处于空闲状态。当 hasActiveRun 为 true 且 activeRunIds 被省略时,表示另一个运行时所有者处于活动状态,但其精确运行标识不可用。在增量合并事件中,省略表示无变化,null 是仅事件墓碑,会将缓存的精确 ID 清除为不可用,而数组会替换缓存(包括用于已证明空闲的 [])。仅关联客户端本地拥有或从请求、历史响应或事件中接收到的运行 ID,并且永远不要选择列表中的第一个条目作为所有者。
  5. 仅当观察者摘要的精确 runId 存在于 activeRunIds 中时,才显示观察者标题或运行检查器链接。仅有聚合活动不会使保留的摘要变为当前。
  6. 根据 payload.runId 和 payload.seq 协调后续的 agent 事件。为每个运行独立维护已接受的最高序列号,忽略已见过的或更低的序列号,并将前向间隙视为重新加载权威历史的原因。

活动运行缓存矩阵

在应用 activeRunIds 之前先对来源进行分类;相同的省略在完整快照和增量差异中具有不同含义。

客户端缓存 读取路径 类型 必需行为
Web 会话名册 sessions.list、重连水合 快照 替换该行;省略会将缓存的精确 ID 清除为不可用。
Web 所选会话 chat.history.sessionInfo 快照 替换该行投影;省略会清除缓存的精确 ID。
Web 会话事件 sessions.changed、session.message、生命周期快照 增量 省略无效;null 清除;数组替换。
Android 会话名册 sessions.list、重连水合 快照 替换列表行;省略会清除缓存的精确 ID。
Android 所选会话 chat.history.sessionInfo、重连恢复 快照 即使其他部分历史字段正在合并,也要替换 activeRunIds。
Android 会话事件 sessions.changed、session.message、生命周期快照 增量 字段存在性控制替换;null 清除,省略无效。
Apple 会话名册 sessions.list、重连水合 快照 替换实时行;离线缓存会移除瞬态活动运行事实。
Apple 所选会话 chat.history.sessionInfo、重连恢复 快照 同时替换当前行及其运行 ID 投影;省略会清除两者。
Apple 会话事件 sessions.changed、session.message、生命周期快照 增量 在解码过程中保留字段存在性;省略无效,null 清除,数组替换。

外层事件帧还有一个可选的 seq,用于对当前 WebSocket 连接上的事件排序。它会随新连接重置。agent 事件负载内部的 seq 按运行分配,并对该运行的生命周期、助手、计划、工具和其他流事件排序。

渲染生成的图像工件

助手生成的图像以规范的 type: "image" 内容块形式到达。托管块包含稳定的 artifactId、相对于 Gateway 的 url、MIME 类型、尺寸、大小和可访问的替代文本。在转录缓存中保留该引用;不要持久化下载的字节或临时下载 URL。

通过已认证的 WebSocket 连接解析图像:

  1. 使用当前 sessionKey、可选的 agentId 以及该块的 artifactId 调用 artifacts.download。
  2. 在 expiresAt 之前使用返回的短期 url。该 URL 的范围仅限于该确切由 transcript 支持的 artifact,并且不包含可重用的 Gateway 或设备凭据。
  3. 从 Gateway 源获取它,使用与活动连接相同的 TLS pin 和反向代理头。将响应验证为图像,并强制 12 MiB 源大小限制以及有界解码缩略图。
  4. 如果 URL 过期,重复调用 artifacts.download 一次。重连或路由变更会取消旧加载,而不是将其重新指向另一个 Gateway。

没有 artifactId 的旧图像块仍可被现有 Control UI 客户端显示,但原生客户端应显示可读的附件回退,而不是转发共享的所有者凭据。

通过 HTTPS 下载内联 artifact

对于嵌入 transcript 中的 artifact,artifacts.download 通常会在现有连接上返回 encoding: "base64" 和 data。能够访问 Gateway 的 HTTPS 路由的客户端可以传递 transport: "http",以改为接收相对于 Gateway 的 url 和 expiresAt,然后使用 GET 获取原始字节。该路由还支持 HEAD 和单个字节范围。Managed media 保留其现有的 URL 下载路径。

使用活动 Gateway 的 HTTPS 源和已配置的 Control UI 基础路径。TLS 可以在 Gateway 或其反向代理处终止;代理必须转发 /api/artifacts/download/ 以及 WebSocket 升级。仅有一个 wss:// 端点并不能建立 HTTP 可达性。仅使用 WebSocket 的客户端应省略 transport;HTTP 路由不可用的客户端可以不带 transport 重复相同的 RPC,保留所有 session、run、task 和 role 过滤器。

内联下载链接在五分钟之后过期,并属于发出该链接的活动连接和确切 artifact。读取会重新检查访问权限、transcript 成员关系、session 代和内容标识。过期、断开连接、吊销或替换会使链接不可用。应重连并请求新的下载,而不是跨连接保留链接。这些链接不包含可重用的 Gateway 凭据,并且响应会禁用缓存和活动文档执行。

当从活动 Gateway 的 HTTPS 源提供时,Control UI 会启用图像和文本预览。如果 HTTP 获取失败,它会通过同一连接上的内联 RPC 重试。其他连接保留其现有传输行为。二进制 artifact 预览保留 Download 操作,而不是使用过期链接。每次点击都会请求新的下载权限;更改连接或关闭预览会取消进行中的下载。

使用历史元数据和稳定锚点

chat.history 返回的行可以携带 __openclaw 元数据信封:

  • id 是 transcript 条目标识。将其用于锚定的历史请求,但不要将其作为唯一的显示行键。
  • seq 是正的 transcript 记录序列。一条存储记录可以投影到多个显示行,因此保持具有相同 id 和序列的兄弟项在一起。
  • kind 标识合成行。压缩边界使用 kind: "compaction",当匹配的 checkpoint 记录了这些指标时,可能包含 tokensBefore 和 tokensAfter。

session 重置边界使用 kind: "reset"。它没有 checkpoint token 指标。

使用响应中的 hasMore 和 nextOffset 值向前翻页。数字偏移量描述当前 transcript 投影,因此不要将它们作为跨重置或压缩的长期书签持久化。改为持久化 __openclaw.id。要在已知行周围恢复,使用 messageId 和返回它的 sessionId 调用 chat.history。Gateway 可以从重置归档历史中解析该锚点;锚定响应有意省略数字分页元数据。

使用订阅而不是轮询用量

安装 sessions.changed 监听器,然后每个连接调用一次 sessions.subscribe,并传入你的 sessions.list 参数,例如 { limit: 60, ownerFirst: true }。响应为 { subscribed: true, list },其中 list 是常规的 SessionsListResult 快照。传递 {} 会激活订阅,但仅返回 { subscribed: true },不包含列表。

Gateway 会在读取快照之前激活订阅。因此,事件可能在响应之前到达。跟踪在引导期间接收到的更改,并在需要时通过 sessions.list 刷新跟随响应;不要让快照静默覆盖更新的事件。在每次重连后重新建立此流程。

ownerFirst: true 会将最多 60 个由已认证查看者拥有的匹配 session 前置到常规第一页,并移除该响应内的重复项。它仅在 offset 为零或省略时适用。Gateway 从已认证连接派生查看者身份,而不是客户端提供的身份。共享页面的分页元数据保持不变,因此加载另一页时使用 nextOffset,而不是返回的行数,并按 session key 合并行。参见 会话列表引导。

从后续带键的 sessions.changed 事件的嵌套 session 行中合并,同时使用 agent、session key 和 session ID,以避免将旧生命周期应用到其替换项。快照面向接收连接呈现,并携带当前行元数据、用量和活动 run 状态。

在本地将快照应用到现有名册成员。当行缺失或通知是广泛的、无键的失效时,刷新 sessions.list。删除事件保留被删除的 session ID,并且不携带替换行。同一 session 的别名的通知共享发布顺序。快速替换可能会合并中间通知;广泛失效会跟随压缩后的更新,以便客户端刷新权威名册。当无法准备行元数据时,也会发送相同的刷新通知。 不要轮询 usage.cost 或 sessions.usage 以保持实时 session 列表最新;将这些方法保留用于按需的聚合或详细报告。

回填执行审批

具有 operator.approvals 的客户端应在 hello-ok 完成后立即安装其事件监听器,然后调用 exec.approval.list 以回填早于该连接创建的请求。应按审批 ID 协调列表与实时 exec.approval.requested / exec.approval.resolved 事件,使与列表请求发生竞态的转换既不会丢失,也不会被重新复活。

跟踪协议版本

当前 wire 版本为 4。通用 operator 和 WebChat 客户端必须使用 minProtocol: 4 和 maxProtocol: 4 协商确切的当前版本。只有经过身份验证的节点客户端和轻量级探针具有 N-1 接受窗口,当前为协议 3 到 4。

协议变更优先采用增量方式。protocol.schema.json 包含 since 发布版本元数据以及核心方法所需的 scope 元数据,但对于第三方客户端而言,wire 版本升级仍是一次显式的破坏性事件。固定你所测试的包版本;当 wire 版本变更时,同时升级客户端和 Gateway,并在每次升级前查看 OpenClaw 更新日志。

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