先认清真实 API 边界
OpenClaw 不是一组围绕消息、记忆和“动态注册 Python 函数”设计的 REST 资源。它的核心集成边界是长期运行的 Gateway:Gateway 持有消息渠道连接、会话状态、Agent 运行、审批流程和节点状态,并通过 WebSocket 暴露带类型约束的请求、响应与事件。
因此,生产接入需要解决的不是“拼出一个 HTTP 请求”,而是完整客户端生命周期:
- 建立并维护有状态连接;
- 生成设备身份并完成配对;
- 按功能申请 Operator 权限;
- 区分“请求已接受”和“任务已完成”;
- 在断线后恢复订阅并核对权威状态;
- 同时锁定客户端包版本与 Wire 协议版本。
截至 2026 年 10 月 3 日,官方客户端开发文档给出的已验证稳定包是 @openclaw/[email protected] 和 @openclaw/[email protected],对应 Wire v4。包版本与 Wire 版本是两个不同的兼容维度,不能只锁其中一个。
如果还不了解 Gateway、会话、记忆与工具之间的关系,可先阅读 OpenClaw AI Agent 完全指南。本文只回答一个更具体的问题:业务系统如何按照官方合约可靠地接入 OpenClaw。
两种集成面如何选择
OpenClaw 当前有两类语义明显不同的入口。
| 集成面 | 适用场景 | 调用方必须负责 |
|---|---|---|
| Gateway WebSocket/RPC | 聊天客户端、控制台、会话列表、审批、节点管理、流式 Agent 运行 | 连接生命周期、设备身份、配对、权限、事件顺序与断线恢复 |
POST /tools/invoke |
可信服务调用少量经过审核的工具 | 可信网络入口、共享令牌保护、业务授权、工具白名单、审计与超时 |
不要把 /tools/invoke 包装成一套“OpenClaw REST API”。它默认拒绝 Shell、进程执行和文件系统变更等危险工具,设计目标就是受限调用。反过来,如果需求只是内网服务触发一个明确动作,也不必为了“统一”而模拟完整聊天客户端。
选择依据应是交互语义:
- 需要会话、流式事件、订阅、审批或持久设备身份时,使用 Gateway 协议。
- 一个可信服务只需要调用极小工具面时,评估
/tools/invoke。 - 最终用户或不同租户权限不同时,在 OpenClaw 前增加业务自有 API 和授权层。
Gateway 协议的核心模型
官方 Gateway 架构文档定义了三类顶层 WebSocket 文本帧:
{"type":"req","id":"req-17","method":"chat.send","params":{"sessionKey":"main","message":"总结本次事故"}}
{"type":"res","id":"req-17","ok":true,"payload":{"runId":"run-92","status":"accepted"}}
{"type":"event","event":"agent","payload":{"runId":"run-92","phase":"completed"},"seq":481,"stateVersion":73}
客户端的第一帧必须是 connect。握手成功后,Gateway 返回 hello-ok,其中包含协商结果、初始快照和能力元数据。hello-ok.features.methods 可用于发现方法,但不能证明调用权限;最终还要同时满足角色、已批准 Scope、设备配对、工具策略和方法自身规则。
接受请求不等于任务完成
agent 或 chat.send 返回 accepted,只代表 Gateway 接受了工作,不能证明:
- 模型已经完成响应;
- 所有工具都执行成功;
- 消息渠道已经投递;
- 对应业务动作已经生效。
应用必须用返回的 runId 关联后续事件,并查询会话或任务的权威状态。建议在业务状态机中明确区分:
requested -> accepted -> running -> terminal
-> waiting_for_approval
-> failed
-> cancelled
如果收到 RPC ACK 就把订单、通知或工单标成成功,断线与异步失败会直接制造错误数据。
用版本化结构建模协议帧
Go 服务即使不使用官方 TypeScript 客户端,也应保留相同的结构和语义:
package main
import (
"encoding/json"
"fmt"
)
type RequestFrame struct {
Type string `json:"type"`
ID string `json:"id"`
Method string `json:"method"`
Params any `json:"params"`
}
type AgentParams struct {
SessionKey string `json:"sessionKey"`
Message string `json:"message"`
IdempotencyKey string `json:"idempotencyKey"`
}
func main() {
frame := RequestFrame{
Type: "req",
ID: "req-17",
Method: "agent",
Params: AgentParams{
SessionKey: "incident-review",
Message: "基于已审批的事故证据生成摘要。",
IdempotencyKey: "incident-2026-10-03-v1",
},
}
payload, err := json.Marshal(frame)
if err != nil {
panic(err)
}
fmt.Println(string(payload))
}
实际传输层应使用成熟的 WebSocket 库,并完成四件事:按锁定版本的 Schema 校验入站帧、拒绝不兼容 Wire 版本、限制消息大小、保留 Gateway 结构化错误。把所有错误压成一段字符串,会丢失“需要配对、缺少 Scope、可以重试、必须终止”等关键决策信息。
鉴权、设备配对与 Scope
引导鉴权解决“谁可以开始连接”,设备配对绑定长期设备身份,Scope 约束已配对操作者可以调用什么。三者不是同一个控制点。
官方客户端流程可以归纳为:
- 生成并持久化 Ed25519 设备身份。
- 接收
connect.challenge,对包含 Challenge 的设备载荷签名。 - 发送
connect,携带角色、请求的 Scope,以及配置好的 Gateway Token 或密码。 - 收到
PAIRING_REQUIRED时,向用户展示请求 ID,并停止特权操作。 - 操作者核对并批准这一个明确请求。
- 重新连接,保存 Gateway 签发且绑定角色与 Scope 的设备 Token。
角色或 Scope 扩大时会产生新的待审批请求。仅轮换 Token 不会扩大权限。
按用户动作申请最小权限
| 客户端能力 | 对应的最小相关 Scope |
|---|---|
| 查看历史、会话、模型状态 | operator.read |
| 发送聊天、修改普通会话 | operator.write |
| 展示或处理执行/插件审批 | operator.approvals |
| 回答 Agent 的交互式问题 | operator.questions |
| 管理已配对设备或节点 | operator.pairing |
| 修改管理配置 | operator.admin |
只读大屏不应持有审批或管理权限;无法完整展示审批对象和参数的聊天端,也不应申请批准能力。为了开发方便一次申请全部 Scope,会让配对审核失去意义。
节点还有第二层边界:设备配对允许节点建立连接,节点能力审批决定它能暴露哪些命令。已经配对的节点新增命令后,仍需重新审批,并继续受 Gateway 命令策略约束。
断线恢复与副作用去重
网络可能在任意两个观测点之间中断。客户端发出请求后断线,没有看到 ACK,并不代表 Gateway 没有接受该请求。
可靠恢复流程是:
- 发送前持久化客户端请求 ID、幂等键、会话键和最后看到的序列号或状态版本;
- 使用同一个设备身份和设备 Token 重连;
- 恢复事件订阅;
- 获取权威会话历史或任务状态;
- 先核对已有 Run,再决定是否重试;
- 重试副作用请求时复用同一个幂等键。
Gateway 要求 send、agent 等副作用方法携带幂等键,并维护短期去重缓存。短期缓存不是永久业务账本。发送账单、发布公告、修改外部对象等动作,仍需由业务系统保存长期 Operation ID,并在下游实现幂等。
事件也不应假定“严格只到一次”。存在 seq 或 stateVersion 时,应检测缺口与陈旧更新;发现缺口后重新拉取权威状态,而不是自行猜测丢失事件。
安全使用 /tools/invoke
受限 HTTP 端点适合可信内网服务触发明确动作:
curl --fail-with-body \
--request POST \
--header "Authorization: Bearer ${OPENCLAW_GATEWAY_TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"tool": "message",
"action": "send",
"idempotencyKey": "maintenance-2026-10-03-v1",
"args": {
"channel": "telegram",
"target": "ops-room",
"message": "已审批的维护窗口开始。"
}
}' \
"http://127.0.0.1:18789/tools/invoke"
应根据锁定版本再次核对字段,且绝不能因为存在这个端点就把 18789 端口暴露到公网。共享 Gateway Bearer 代表较宽的操作者权限,应将端点限制在 Loopback、私网、认证服务网格或业务代理之后,并由代理继续执行:
- 调用方与租户身份校验;
- 精确到工具和 Action 的白名单;
- 有界参数 Schema;
- 速率与并发限制;
- 出站网络约束;
- 审计 ID 与日志脱敏;
- 高影响动作的人工确认。
OpenClaw 的工具限制是纵深防御,不能替代业务系统对“哪个用户能向哪个频道发送什么”的授权判断。
升级前必须验证什么
一套可维护的集成至少记录四个版本:
| 版本 | 影响范围 |
|---|---|
| Gateway Release | 服务端行为与方法集合 |
| Gateway Client Package | 重连、设备身份与宿主集成 |
| Protocol Package / Wire Version | 帧结构与兼容规则 |
| 业务合约版本 | 产品真正依赖的方法、事件、Scope 与错误类型 |
每次升级前,至少回放以下兼容性用例:
- 新设备配对与第二次无感重连;
- 只读客户端无法执行写操作;
- Agent 请求从 Accepted 走到终态;
- ACK 丢失后的幂等恢复;
- 需要审批的动作;
- 被撤销的设备 Token;
- 未知方法或不兼容帧;
- 事件缺口后的权威状态恢复。
生产环境应固定精确版本。浮动 latest 或宽松依赖范围,会把协议升级变成未经评审的线上变更。
生产检查清单
- Gateway 只监听 Loopback 或可信私网;远程管理通过 SSH 或 VPN。
- 设备私钥与 Token 存入系统钥匙串或 Secret Manager。
- 读、写、审批、配对与管理客户端按职责拆分。
- 限制帧大小、队列深度、重连频率与事件保留量。
- 保留结构化错误码、请求 ID 与 Run ID。
- 消息正文和工具参数进入可观测系统前完成脱敏。
- 测试撤销、断线和状态恢复,不只验证首次握手。
- 接入业务系统前阅读 AI Agent 工具安全指南。
- 定时与多步骤任务参见 OpenClaw 自动化工作流指南。
- 容器化运维参见 OpenClaw Docker 部署指南。
一手资料
总结
可靠的 OpenClaw 接入应从 Gateway 的有状态协议出发,而不是围绕不存在的 REST 资源开发。设备要配对,客户端只申请最小 Scope,ACK 与完成事件必须分开,断线后先核对权威状态,所有副作用都要具备业务级幂等。/tools/invoke 只适合作为可信服务之间的窄入口,并由业务授权层继续收紧权限。这样才能让 AI Agent 成为可测试的系统组件,而不是一个无边界控制面。