6.2 Gateway协议

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

相关资源