OpenClaw Gateway 协议定义了节点与 Gateway 之间的 WebSocket RPC 通信规范,包括连接握手、请求响应模式和事件推送机制。
概述
Gateway 协议基于 WebSocket 实现双向 RPC 通信。所有消息都使用 JSON 格式,并通过 AJV (Another JSON Schema Validator) 进行严格的协议验证,确保消息格式的正确性和一致性。
消息类型
协议定义了三种主要消息类型:
1. 请求消息 (Request)
客户端发送到服务器的 RPC 请求:
{
"type": "req",
"id": "unique-request-id",
"method": "method-name",
"params": {
// 方法特定的参数
}
}
2. 响应消息 (Response)
服务器对请求的响应:
// 成功响应
{
"type": "res",
"id": "matching-request-id",
"ok": true,
"payload": {
// 响应数据
}
}
// 错误响应
{
"type": "res",
"id": "matching-request-id",
"ok": false,
"error": {
"code": "ERROR_CODE",
"message": "错误描述"
}
}
3. 事件消息 (Event)
服务器主动推送给客户端的事件:
{
"type": "event",
"event": "event-name",
"payload": {
// 事件数据
},
"seq": 123, // 可选: 事件序列号
"stateVersion": 456 // 可选: 状态版本
}
连接握手
客户端连接 Gateway 时必须首先完成握手流程:
握手请求
{
"type": "req",
"id": "connect-1",
"method": "connect",
"params": {
"auth": {
"token": "your-auth-token"
// 或 "password": "your-password"
},
"clientInfo": {
"name": "my-client",
"version": "1.0.0"
}
}
}
握手响应
{
"type": "res",
"id": "connect-1",
"ok": true,
"payload": {
"sessionId": "session-uuid",
"gatewayVersion": "0.9.0",
"capabilities": ["tool-execution", "streaming"]
}
}
必需步骤
连接握手是强制要求的。在成功完成
connect 握手之前,Gateway 不会处理任何其他 RPC 请求。常用 RPC 方法
配置管理
// 应用配置
{
"type": "req",
"id": "req-1",
"method": "config.apply",
"params": {
"config": {
"agents": {
"defaults": {
"model": "gpt-4"
}
}
}
}
}
// 修补配置
{
"type": "req",
"id": "req-2",
"method": "config.patch",
"params": {
"path": "/agents/defaults/model",
"value": "claude-3-opus"
}
}
工具执行
{
"type": "req",
"id": "req-3",
"method": "tools.invoke",
"params": {
"tool": "exec",
"args": {
"command": "ls -la"
}
}
}
会话管理
// 创建会话
{
"type": "req",
"id": "req-4",
"method": "session.create",
"params": {
"agentId": "default"
}
}
// 发送消息
{
"type": "req",
"id": "req-5",
"method": "session.sendMessage",
"params": {
"sessionId": "session-uuid",
"message": {
"role": "user",
"content": "Hello, OpenClaw!"
}
}
}
事件订阅
客户端可以订阅 Gateway 推送的事件:
常见事件类型
tool.started- 工具开始执行tool.completed- 工具执行完成agent.response- AI 助手响应session.updated- 会话状态更新config.changed- 配置变更
事件示例
// 工具执行事件
{
"type": "event",
"event": "tool.started",
"payload": {
"toolName": "exec",
"requestId": "req-3",
"timestamp": "2025-12-09T10:00:00Z"
},
"seq": 100
}
// 配置变更事件
{
"type": "event",
"event": "config.changed",
"payload": {
"path": "/agents/defaults/model",
"oldValue": "gpt-4",
"newValue": "claude-3-opus"
},
"stateVersion": 457
}
协议验证
所有消息都通过 JSON Schema 进行验证:
验证规则
- 类型检查:
type字段必须是 "req"、"res" 或 "event" - ID 匹配: 响应消息的
id必须匹配请求的id - 方法存在:
method必须是已注册的 RPC 方法 - 参数格式:
params必须符合方法定义的 schema
错误处理
// 协议错误响应
{
"type": "res",
"id": "req-6",
"ok": false,
"error": {
"code": "INVALID_PARAMS",
"message": "参数验证失败: params.command 是必需的",
"details": {
"field": "params.command",
"constraint": "required"
}
}
}
连接保活
为确保连接活跃,协议支持心跳机制:
// 客户端发送 ping
{
"type": "req",
"id": "ping-1",
"method": "ping",
"params": {}
}
// Gateway 响应 pong
{
"type": "res",
"id": "ping-1",
"ok": true,
"payload": {
"timestamp": "2025-12-09T10:00:00Z"
}
}
流式传输
对于长时间运行的操作,协议支持流式响应:
// 请求流式响应
{
"type": "req",
"id": "stream-1",
"method": "agent.chat",
"params": {
"message": "写一个长故事",
"stream": true
}
}
// 流式响应块
{
"type": "event",
"event": "stream.chunk",
"payload": {
"requestId": "stream-1",
"chunk": "很久以前...",
"done": false
}
}
// 流结束
{
"type": "event",
"event": "stream.chunk",
"payload": {
"requestId": "stream-1",
"chunk": "...结束。",
"done": true
}
}
安全考虑
安全建议
- 强制认证: 所有连接必须通过握手认证
- 消息验证: 使用 AJV 进行严格的 schema 验证
- 请求限流: 实施请求速率限制防止滥用
- 连接加密: 在生产环境使用 WSS (WebSocket Secure)
实现示例
JavaScript/TypeScript 客户端
const ws = new WebSocket('ws://localhost:18789');
// 连接握手
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'req',
id: 'connect-1',
method: 'connect',
params: {
auth: { token: 'your-token' }
}
}));
};
// 处理消息
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'res') {
console.log('响应:', msg);
} else if (msg.type === 'event') {
console.log('事件:', msg);
}
};
// 发送请求
function sendRequest(method, params) {
const id = `req-${Date.now()}`;
ws.send(JSON.stringify({
type: 'req',
id,
method,
params
}));
return id;
}
Python 客户端
import asyncio
import websockets
import json
async def connect_gateway():
uri = "ws://localhost:18789"
async with websockets.connect(uri) as ws:
# 握手
await ws.send(json.dumps({
"type": "req",
"id": "connect-1",
"method": "connect",
"params": {
"auth": {"token": "your-token"}
}
}))
# 接收消息
async for message in ws:
msg = json.loads(message)
if msg["type"] == "res":
print(f"响应: {msg}")
elif msg["type"] == "event":
print(f"事件: {msg}")
asyncio.run(connect_gateway())
调试技巧
# 启用协议调试日志
openclaw --debug gateway
# 查看 WebSocket 流量
openclaw gateway --log-level trace
# 使用 wscat 测试协议
npm install -g wscat
wscat -c ws://localhost:18789