- Auth module: WeChat OAuth2 scan-to-login flow with terminal QR code - Token persistence to ~/.openclaw/wechat-access-auth.json (chmod 600) - Token resolution: config > saved state > interactive login - Invite code verification (configurable bypass) - Production/test environment support - AGP WebSocket client with heartbeat, reconnect, wake detection - Message handler: Agent dispatch with streaming text and tool calls - Random device GUID generation (persisted, no real machine ID)
8.2 KiB
agentwsserver WebSocket 接口文档 目录 1.概述 2.连接 3.数据协议 (AGP Envelope) 4.下行消息 (服务端 → 客户端) 5.上行消息 (客户端 → 服务端) 6.通用数据结构 7.时序示意
概述 为独立 APP 提供 WebSocket 双向通信能力。 WebSocket 服务 — 运行于 :8080 端口,处理客户端的 WebSocket 长连接 数据协议 — 使用 AGP (Agent Gateway Protocol) 统一消息信封 消息传输 — 所有消息均为 WebSocket Text 帧,内容为 JSON
连接 地址 ws://21.0.62.97:8080/?token={token} Query 参数 参数 类型 必填 说明 token string 否 鉴权 token(当前未校验,后续启用) 连接行为 握手成功后服务端注册连接,同一 guid 的旧连接会被踢下线 空闲超时 5 分钟,超时无消息收发将断开 连接断开后服务端自动清理路由注册 错误场景 场景 行为 缺少 guid 或 user_id 握手拒绝,WebSocket 连接不会建立 URL 解析失败 握手拒绝
数据协议 (AGP Envelope) Envelope 结构 所有 WebSocket 消息(上行和下行)均使用统一的 AGP 信封格式: { "msg_id": "string", "guid": "string", "user_id": "string", "method": "string", "payload": {} } 字段 类型 必填 说明 msg_id string 是 全局唯一消息 ID(UUID),用于幂等去重 guid string 是 设备 GUID user_id string 是 用户账户 ID method string 是 消息类型,见下方枚举 payload object 是 消息载荷(JSON 对象,根据 method 类型而异) Method 枚举 method 方向 说明 session.prompt 服务端 → 客户端 下发用户指令 session.cancel 服务端 → 客户端 取消 Prompt Turn session.update 客户端 → 服务端 流式中间更新 session.promptResponse 客户端 → 服务端 最终结果
下行消息 (服务端 → 客户端) session.prompt — 下发用户指令 { "msg_id": "550e8400-e29b-41d4-a716-446655440000", "guid": "device_001", "user_id": "user_123", "method": "session.prompt", "payload": { "session_id": "550e8400-e29b-41d4-a716-446655440000", "prompt_id": "550e8400-e29b-41d4-a716-446655440001", "agent_app": "openclaw", "content": [ { "type": "text", "text": "帮我查一下今天的天气" } ] } } payload 字段: 字段 类型 必填 说明 session_id string 是 所属 Session ID prompt_id string 是 本次 Turn 唯一 ID agent_app string 是 目标 AI 应用标识,客户端据此路由到本地 AI 应用 content ContentBlock[] 是 用户指令内容(数组) session.cancel — 取消 Prompt Turn { "msg_id": "550e8400-e29b-41d4-a716-446655440001", "guid": "device_001", "user_id": "user_123", "method": "session.cancel", "payload": { "session_id": "550e8400-e29b-41d4-a716-446655440000", "prompt_id": "550e8400-e29b-41d4-a716-446655440001", "agent_app": "openclaw" } } payload 字段: 字段 类型 必填 说明 session_id string 是 所属 Session ID prompt_id string 是 要取消的 Turn ID agent_app string 是 目标 AI 应用标识
上行消息 (客户端 → 服务端) session.update — 流式中间更新 客户端在处理 session.prompt 期间,通过此消息上报中间进度。可多次发送。 update_type 枚举 update_type 说明 使用字段 message_chunk 增量文本/内容(Agent 消息片段) content tool_call AI 正在调用工具 tool_call tool_call_update 工具执行状态变更 tool_call payload 字段 字段 类型 必填 说明 session_id string 是 所属 Session ID prompt_id string 是 所属 Turn ID update_type string 是 更新类型,取值见上方枚举 content ContentBlock 条件 update_type=message_chunk 时使用,单个对象(非数组) tool_call ToolCall 条件 update_type=tool_call 或 tool_call_update 时使用 注意: content 字段为单个 ContentBlock 对象,不是数组。与 session.promptResponse 的 content 数组不同。 示例 — message_chunk(增量文本) { "msg_id": "550e8400-e29b-41d4-a716-446655440002", "guid": "device_001", "user_id": "user_123", "method": "session.update", "payload": { "session_id": "550e8400-e29b-41d4-a716-446655440000", "prompt_id": "550e8400-e29b-41d4-a716-446655440001", "update_type": "message_chunk", "content": { "type": "text", "text": "正在思考中...第一步是..." } } } 示例 — tool_call(工具调用) { "msg_id": "550e8400-e29b-41d4-a716-446655440003", "guid": "device_001", "user_id": "user_123", "method": "session.update", "payload": { "session_id": "550e8400-e29b-41d4-a716-446655440000", "prompt_id": "550e8400-e29b-41d4-a716-446655440001", "update_type": "tool_call", "tool_call": { "tool_call_id": "tc-001", "title": "扫描临时文件", "kind": "execute", "status": "pending" } } } 示例 — tool_call_update(工具状态更新) { "msg_id": "550e8400-e29b-41d4-a716-446655440004", "guid": "device_001", "user_id": "user_123", "method": "session.update", "payload": { "session_id": "550e8400-e29b-41d4-a716-446655440000", "prompt_id": "550e8400-e29b-41d4-a716-446655440001", "update_type": "tool_call_update", "tool_call": { "tool_call_id": "tc-001", "status": "completed", "content": [{ "type": "text", "text": "发现临时文件 2.3GB" }] } } }
session.promptResponse — 最终结果 客户端完成 session.prompt 处理后,上报最终结果。每个 prompt_id 只接受一次最终响应,重复的 msg_id 会被去重。 { "msg_id": "550e8400-e29b-41d4-a716-446655440005", "guid": "device_001", "user_id": "user_123", "method": "session.promptResponse", "payload": { "session_id": "550e8400-e29b-41d4-a716-446655440000", "prompt_id": "550e8400-e29b-41d4-a716-446655440001", "stop_reason": "end_turn", "content": [ { "type": "text", "text": "今天北京晴,气温 15°C" } ] } } payload 字段: 字段 类型 必填 说明 session_id string 是 所属 Session ID prompt_id string 是 所属 Turn ID stop_reason string 是 停止原因 content ContentBlock[] 否 最终结果内容(数组) error string 否 错误描述(stop_reason 为 error / refusal 时附带) stop_reason 枚举: 值 说明 end_turn 正常完成 cancelled 被取消 refusal AI 应用拒绝执行 error 技术错误 错误响应示例 { "msg_id": "550e8400-e29b-41d4-a716-446655440006", "guid": "device_001", "user_id": "user_123", "method": "session.promptResponse", "payload": { "session_id": "550e8400-e29b-41d4-a716-446655440000", "prompt_id": "550e8400-e29b-41d4-a716-446655440001", "stop_reason": "error", "error": "AI 应用执行超时" } }
通用数据结构 ContentBlock — 内容块 { "type": "text", "text": "文本内容" } 字段 类型 必填 说明 type string 是 内容类型,当前仅支持 "text" text string 是 type=text 时必填 ToolCall — 工具调用 { "tool_call_id": "tc-001", "title": "扫描临时文件", "kind": "execute", "status": "in_progress", "content": [{ "type": "text", "text": "发现临时文件 2.3GB" }], "locations": [{ "path": "/tmp" }] } 字段 类型 必填 说明 tool_call_id string 是 工具调用唯一 ID title string 否 工具调用标题(展示用) kind string 否 工具类型 status string 是 工具调用状态 content ContentBlock[] 否 工具调用结果内容 locations Location[] 否 工具操作路径 kind 枚举: 值 说明 read 读取 edit 编辑 delete 删除 execute 执行 search 搜索 fetch 获取 think 思考 other 其他 status 枚举: 值 说明 pending 等待中 in_progress 执行中 completed 已完成 failed 失败 Location — 路径 { "path": "/tmp" } 字段 类型 说明 path string 操作路径
时序示意 正常流程 客户端 (APP) 服务端 | | |--- WS 握手 (guid/user_id) ----->| |<-- 101 Switching Protocols -----| 连接建立 | | |<-- session.prompt (WS Text) ----| 下发指令 | | |--- session.update (WS Text) --->| 流式上报(可多次) |--- session.update (WS Text) --->| | | |--- promptResponse (WS Text) --->| 最终结果 | | |--- 断开 / 超时 ---------------->| 连接清理 取消流程 客户端 (APP) 服务端 | | | (正在处理 session.prompt) | |<-- session.cancel (WS Text) ----| 服务端取消 | | |--- promptResponse (WS Text) --->| stop_reason: "cancelled"