构建 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:
如果现有 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 的共享引导身份验证,然后让设备配对铸造客户端令牌:
- 在客户端中持久化 Ed25519 设备身份。
- 等待
connect.challenge,将其ts用作设备证明的signedAt, 对与 challenge 绑定的设备负载进行签名,并发送connect,其中包含请求的操作员角色、作用域以及用于引导身份验证的共享 Gateway 令牌或密码。收到的 WebSocket challenge 如果没有非负整数ts,则无效。明确支持connect.challenge出现之前的 Gateway 的客户端,仅可在其无 challenge 路径上使用本地时间。 - 如果 Gateway 返回结构化的
PAIRING_REQUIRED详细信息,请显示请求 ID,并根据error.details.recommendedNextStep暂停或重试。 - 在 Gateway 宿主上,使用
openclaw devices list查看请求,然后 使用openclaw devices approve <requestId>批准该确切的当前请求。 - 重新连接,并将
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 可以返回类型化拒绝,而纯文本模型运行在达到其卸载上限后可以省略额外图像,并且仍能完成请求。这些值是连接时快照,因此在每次重连时重新读取它们。
重连后恢复状态¶
将每次成功重连视为对持久化历史和当前内存中运行状态的新投影:
- 使用你的列表参数重新建立
sessions.subscribe,以便在同一响应中接收当前名册,如下方所述。同时重新建立所选会话的sessions.messages.subscribe订阅。 - 调用
chat.history获取所选sessionKey,并用返回的messages投影替换本地持久化行。 - 如果存在
inFlightRun,采用其runId、缓冲的text和可选的plan。即使text为空,也要采用该运行。 - 将
sessionInfo.hasActiveRun视为聚合的直接会话活动。当activeRunIds存在时,它是完整的精确活动集合;因此空数组可证明会话处于空闲状态。当hasActiveRun为 true 且activeRunIds被省略时,表示另一个运行时所有者处于活动状态,但其精确运行标识不可用。在增量合并事件中,省略表示无变化,null是仅事件墓碑,会将缓存的精确 ID 清除为不可用,而数组会替换缓存(包括用于已证明空闲的[])。仅关联客户端本地拥有或从请求、历史响应或事件中接收到的运行 ID,并且永远不要选择列表中的第一个条目作为所有者。 - 仅当观察者摘要的精确
runId存在于activeRunIds中时,才显示观察者标题或运行检查器链接。仅有聚合活动不会使保留的摘要变为当前。 - 根据
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 连接解析图像:
- 使用当前
sessionKey、可选的agentId以及该块的artifactId调用artifacts.download。 - 在
expiresAt之前使用返回的短期url。该 URL 的范围仅限于该确切由 transcript 支持的 artifact,并且不包含可重用的 Gateway 或设备凭据。 - 从 Gateway 源获取它,使用与活动连接相同的 TLS pin 和反向代理头。将响应验证为图像,并强制 12 MiB 源大小限制以及有界解码缩略图。
- 如果 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