OpenClaw Gateway 架构深度解析
第 1 章:引言
1.1 OpenClaw 项目概述
在人工智能快速发展的今天,如何高效地部署、管理和访问分布在不同设备上的 AI 代理已成为一个关键技术挑战。OpenClaw 作为一款开源的远程访问 AI 代理平台,通过创新的架构设计实现了对多设备、多代理的统一管控。无论是运行在家庭服务器上的自动化脚本,还是部署在云端的专业 AI 助手,OpenClaw 都能提供稳定、安全的远程连接能力。
OpenClaw 的核心优势在于其轻量级的部署方式和强大的跨平台兼容性。它不依赖复杂的 VPN 配置,而是利用现有的网络基础设施实现设备发现和连接建立。这种设计使得用户可以轻松地将任意位置的 AI 代理纳入统一的管理体系,极大地降低了运维成本和复杂度。
1.2 Gateway:单一控制平面的设计理念
在 OpenClaw 的架构设计中,Gateway 扮演着至关重要的角色——它作为整个系统的唯一控制平面,负责处理所有的连接管理、协议验证和事件分发工作。这种单一控制平面(Single Control Plane)的设计理念带来了显著的优势:
首先,统一入口简化了客户端的实现复杂度。无论设备位于何种网络环境,客户端只需要与 Gateway 建立连接,无需关心目标设备的具体网络拓扑。其次,集中化的认证和授权机制确保了系统的安全性,所有访问请求都必须通过 Gateway 的验证才能到达目标代理。最后,事件分发的集中处理使得实时状态同步和跨设备协作变得更加可靠。
Gateway 基于 WebSocket 协议构建,选择 WebSocket 是因为它支持全双工通信,能够在单条连接上同时发送请求和接收事件,非常适合需要长时间保持连接状态的 AI 代理场景。
1.3 文章结构说明
本文将深入解析 OpenClaw Gateway 的架构设计与实现细节。第二章介绍 Gateway 的核心职责和整体架构;第三章详细讲解 WebSocket 协议帧结构及其验证机制;第四章阐述连接生命周期与握手协议;第五章探讨事件分发机制的内部原理;第六章深入分析 JSON Schema 验证、心跳断线重连等关键技术要点。
在第七章中,我们将通过完整的客户端代码示例,展示如何实际使用 Gateway 的连接和消息发送功能。第八章总结架构设计亮点,并展望未来的优化方向。
通过本文,读者不仅能够理解 OpenClaw Gateway 的设计理念,还能掌握将其应用于实际项目的能力。让我们正式开始这段技术探索之旅。
第 2 章:Gateway 核心架构
2.1 Gateway 核心职责
OpenClaw Gateway 作为系统的核心通信枢纽,承担着多重关键职责,确保分布式客户端系统的高效协作与安全通信。
2.1.1 渠道连接管理
Gateway 负责管理多种通信渠道的连接生命周期。通过 validateConnectParams 函数验证客户端连接参数,确保连接的合法性和安全性。连接参数包括:
- 客户端身份信息:显示名称、设备族、模型标识符、实例 ID、版本号
- 客户端类型:支持 cli、test、openclaw-control-ui、gateway-client、openclaw-macos、openclaw-ios、openclaw-android、node-host、fingerprint、openclaw-probe 等多种类型
- 客户端模式:支持 node、cli、ui、test、backend、probe 等模式
- 平台信息:操作系统平台标识
- 协议版本协商:支持最小/最大协议版本范围
- 权限范围声明:明确客户端拥有的操作权限
- 认证凭据:支持令牌、密码、设备令牌等多种认证方式
- 设备信息:设备 ID、公钥、签名、签名时间、随机数等硬件认证信息
2.1.2 WebSocket 服务
Gateway 基于 WebSocket 协议提供全双工通信服务。核心处理流程包括:
- 握手验证:首个请求必须是
connect方法,验证连接参数的合法性 - 帧类型识别:区分 RequestFrame、ResponseFrame、EventFrame 三种帧类型
- 会话管理:为每个连接分配唯一标识,维护连接状态、认证信息、订阅关系
- 消息路由:根据请求的方法和参数,路由到相应的业务处理器
- 健康监控:定期刷新健康状态,支持主动探测
- 日志记录:详细记录连接、消息收发、错误等关键事件
2.1.3 协议验证与事件分发
Gateway 实现了严格的协议验证机制,使用 Ajv JSON Schema 验证器:
- 请求帧验证:使用
validateRequestFrame函数验证请求结构 - 响应帧验证:通过
validateResponseFrame确保响应格式正确 - 事件帧验证:使用
validateEventFrame处理各类事件消息 - 业务参数验证:85+ 个专门的验证函数,覆盖所有 API 方法的参数验证
2.2 整体架构描述
Gateway 采用分层架构设计,各层职责明确:
| 层级 | 职责 |
|---|---|
| 接入层 | WebSocket 连接建立、认证授权、协议握手、防护机制 |
| 协议层 | Frame 编解码、JSON Schema 验证、错误处理 |
| 业务层 | 业务方法调用、会话管理、Agent 操作、定时任务 |
| 事件层 | 事件订阅、过滤、分发,维护事件序列号和状态版本 |
| 传输层 | 多种传输方式、消息可靠投递、加密和压缩 |
2.3 核心数据结构
| 数据结构 | 说明 |
|---|---|
| RequestFrame | {type: "req", id, method, params?} |
| ResponseFrame | {type: "res", id, ok, payload?, error?} |
| EventFrame | {type: "event", event, payload?, seq?, stateVersion?} |
| StateVersion | {health: number, presence: number} |
| ErrorShape | {code, message, retryable?, retryAfterMs?, details?} |
2.4 架构优势
- 可扩展性:插件化设计、水平扩展、协议演进、模块化架构
- 可靠性:心跳机制、断线重连、消息确认、熔断器
- 安全性:多层认证、数据加密、审计日志、攻击防护
第 3 章:WebSocket 协议帧结构
OpenClaw Gateway 采用 JSON-over-WebSocket 协议进行通信。协议设计遵循请求 - 响应模式,并支持服务器主动推送事件。
3.1 帧类型定义
以下为简化示意,完整 TypeBox 定义见源码 protocol-schemas.d.ts:
Request Frame(请求帧)【简化示意】
RequestFrame: {
type: "req";
id: string;
method: string;
params?: unknown;
}
Response Frame(响应帧)【简化示意】
ResponseFrame: {
type: "res";
id: string;
ok: boolean;
payload?: unknown;
error?: { code: string; message: string; retryable?: boolean };
}
Event Frame(事件帧)【简化示意】
EventFrame: {
type: "event";
event: string;
payload?: unknown;
seq?: number;
stateVersion?: { presence: number; health: number };
}
3.2 JSON Schema 验证流程
- 接收原始 JSON - 从 WebSocket 接收文本数据
- 解析 JSON - 验证 JSON 格式有效性
- 识别帧类型 - 根据 type 字段判断帧类型
- 选择验证器 - 选择对应的 Schema 验证器
- 执行验证 - 运行 JSON Schema 验证
- 处理错误 - 若验证失败,返回详细错误信息
3.3 协议版本管理
当前协议版本为 v3(源码:PROTOCOL_VERSION: 3)。
版本协商机制:
- 客户端声明版本范围
- 服务器协商版本(HelloOk 响应)
- 版本不匹配拒绝连接
第 4 章:连接生命周期与握手协议
4.1 连接建立流程
客户端 服务器
| |
|-------- connect 请求 ------------->|
| (包含 auth 认证信息) |
| | → 验证认证信息
| | → 协商协议版本
| | → 生成连接 ID
|<------- hello-ok 响应 -------------|
| |
| 连接已建立,可发送请求 |
源码验证:首个请求必须是 connect 方法,否则返回错误:"invalid handshake: first request must be connect"
4.2 ConnectParams 结构
| 字段 | 类型 | 说明 |
|---|---|---|
| minProtocol | number | 最小协议版本 |
| maxProtocol | number | 最大协议版本 |
| client.id | enum | 客户端类型 |
| client.version | string | 客户端版本 |
| client.platform | string | 平台标识 |
| auth.token | string? | Gateway Token |
| auth.password | string? | 密码认证 |
| auth.deviceToken | string? | 设备令牌 |
| scopes | string[]? | 权限范围 |
4.3 HelloOk 响应结构
| 字段 | 类型 | 说明 |
|---|---|---|
| type | "hello-ok" | 响应类型标识 |
| protocol | number | 协商后的协议版本 |
| server.connId | string | 连接 ID |
| features.methods | string[] | 支持的方法列表 |
| features.events | string[] | 支持的事件列表 |
| snapshot | Snapshot | 状态快照 |
| policy.tickIntervalMs | number | 心跳间隔 |
4.4 认证机制
| 认证类型 | 使用场景 | 参数位置 |
|---|---|---|
| Token | 服务端配置的令牌 | auth.token |
| Password | 密码认证 | auth.password |
| Device Token | 设备签名认证 | auth.deviceToken |
第 5 章:事件分发机制
5.1 事件类型体系
| 事件类型 | 说明 |
|---|---|
| Agent 事件 | 运行状态变更、身份信息、摘要数据、文件条目 |
| Chat 事件 | 聊天消息、历史记录、注入消息、发送参数 |
| Presence 事件 | 在线状态条目,包含设备信息、时间戳 |
| Health 事件 | 关闭事件、心跳事件、诊断集成 |
| Tick 事件 | 心跳响应,包含时间戳 {ts: number} |
| Cron 事件 | 定时任务定义、运行日志、任务监控 |
5.2 事件序列号与状态版本
- seq:单调递增序列号,用于事件排序和重复检测
- StateVersion:
{health: number, presence: number}全局状态版本控制
5.3 事件订阅与过滤机制
订阅模型:频道订阅、通配符支持、动态订阅、权限控制
过滤策略:类型过滤、来源过滤、内容过滤、时间过滤、频率限制
分发优化:批量分发、优先级队列、背压控制、压缩传输
第 6 章:技术要点深度解析
6.1 JSON Schema 验证流程
// 验证逻辑伪代码
if (!validateRequestFrame(parsed)) {
send({
type: "res",
id: parsed?.id ?? "invalid",
ok: false,
error: { code: "INVALID_REQUEST", message: "invalid request frame" }
});
return;
}
6.2 心跳机制与断线重连
- TickEvent:服务器定期发送,包含时间戳
- 断线检测:WebSocket close 事件、心跳超时
- 重连策略:指数退避(1s→2s→4s→8s...),上限 60 秒
6.3 请求去重与幂等性处理
多个 API 支持 idempotencyKey 字段实现幂等性:
send方法chat.send方法node.invoke方法
6.4 错误处理与重试机制
错误码体系(源码验证):
| 错误码 | 说明 |
|---|---|
| NOT_LINKED | 渠道未链接 |
| NOT_PAIRED | 设备未配对 |
| AGENT_TIMEOUT | Agent 超时 |
| INVALID_REQUEST | 无效请求 |
| UNAVAILABLE | 服务不可用 |
6.5 源码引用说明
协议定义路径(相对于 node_modules/openclaw/dist/):
plugin-sdk/gateway/protocol/index.d.tsplugin-sdk/gateway/protocol/schema/types.d.tsplugin-sdk/gateway/protocol/schema/protocol-schemas.d.tsplugin-sdk/gateway/protocol/schema/error-codes.d.ts
网关实现:gateway-cli-*.js(编译哈希文件名)
第 7 章:实战案例
7.1 客户端连接示例代码
// client-example.js - OpenClaw Gateway 客户端示例
const WebSocket = require('ws');
class OpenClawClient {
constructor(gatewayUrl, authToken) {
this.gatewayUrl = gatewayUrl;
this.authToken = authToken;
this.ws = null;
this.requestId = 0;
this.pendingRequests = new Map();
this.connected = false;
}
async connect() {
return new Promise((resolve, reject) => {
this.ws = new WebSocket(this.gatewayUrl);
const timeout = setTimeout(() => {
if (!this.connected) {
this.ws.close();
reject(new Error('连接超时'));
}
}, 10000);
this.ws.on('open', () => {
console.log('✓ WebSocket 连接已建立');
this.sendConnect()
.then(helloOk => {
clearTimeout(timeout);
this.connected = true;
resolve(helloOk);
})
.catch(err => {
clearTimeout(timeout);
reject(err);
});
});
this.ws.on('message', (data) => this.handleMessage(data));
this.ws.on('error', (err) => { clearTimeout(timeout); reject(err); });
this.ws.on('close', () => { this.connected = false; });
});
}
async sendConnect() {
return this.sendRequest('connect', {
minProtocol: 3,
maxProtocol: 3,
client: { id: 'cli', version: '1.0.0', platform: 'node' },
auth: { token: this.authToken }
});
}
sendRequest(method, params, timeoutMs = 30000) {
return new Promise((resolve, reject) => {
const id = `req-${++this.requestId}`;
this.pendingRequests.set(id, { resolve, reject });
this.ws.send(JSON.stringify({ id, type: 'req', method, params }));
setTimeout(() => {
if (this.pendingRequests.has(id)) {
this.pendingRequests.delete(id);
reject(new Error(`请求超时:${method}`));
}
}, timeoutMs);
});
}
handleMessage(data) {
const frame = JSON.parse(data.toString());
if (frame.type === 'res') {
const pending = this.pendingRequests.get(frame.id);
if (pending) {
this.pendingRequests.delete(frame.id);
frame.ok ? pending.resolve(frame.payload || frame)
: pending.reject(new Error(frame.error?.message));
}
} else if (frame.type === 'event') {
console.log(`[事件] ${frame.event}`);
}
}
async subscribe(events) {
return this.sendRequest('subscribe', { events });
}
close() { if (this.ws) this.ws.close(); }
}
// 使用示例
async function main() {
const client = new OpenClawClient('ws://localhost:8080/ws', 'your-token');
try {
const helloOk = await client.connect();
console.log('✓ 认证成功,connId:', helloOk.server.connId);
await client.subscribe(['agent', 'chat', 'presence']);
console.log('✓ 客户端就绪');
} catch (error) {
console.error('✗ 错误:', error.message);
} finally {
client.close();
}
}
main();
7.2 消息发送完整流程
- 建立 WebSocket 连接
- 发送 connect 请求(含认证信息)
- 接收 hello-ok 响应
- 订阅事件类型
- 发送业务请求
- 接收响应或事件
7.3 事件监听
| 事件类型 | 说明 |
|---|---|
| agent | Agent 运行状态变更 |
| chat | 聊天消息 |
| presence | 在线状态更新 |
| tick | 心跳响应 |
第 8 章:总结与展望
8.1 架构设计亮点总结
- 统一控制平面架构:Gateway 作为唯一入口,简化客户端实现
- WebSocket 实时通信:全双工通信,支持长时间连接
- JSON Schema 验证:85+ 验证函数,保证数据合法性
- 完善的连接管理:connect 握手、tick 心跳、断线重连
- 事件驱动架构:多种事件类型,灵活的分发体系
8.2 性能优化方向
- 连接池与多 Gateway 部署
- 消息压缩与批量处理
- 缓存层优化
8.3 未来演进路线
- 协议增强(WebTransport)
- 安全性增强(RBAC)
- 生态扩展(多语言 SDK)
- 可观测性提升
OpenClaw Gateway 的设计理念是"简单、稳定、可扩展",将成为连接 AI 代理与现实世界的重要桥梁。
更多推荐


所有评论(0)