Major changes: - Add HandList.tsx component for left sidebar - Add HandTaskPanel.tsx for middle content area - Restructure Sidebar tabs: 分身/HANDS/Workflow - Remove Hands tab from RightPanel - Localize all UI text to Chinese - Archive legacy OpenClaw documentation - Add Hands integration lessons document - Update feature checklist with new components UI improvements: - Left sidebar now shows Hands list with status icons - Middle area shows selected Hand's tasks and results - Consistent styling with Tailwind CSS - Chinese status labels and buttons Documentation: - Create docs/archive/openclaw-legacy/ for old docs - Add docs/knowledge-base/hands-integration-lessons.md - Update docs/knowledge-base/feature-checklist.md - Update docs/knowledge-base/README.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
959 lines
27 KiB
Markdown
959 lines
27 KiB
Markdown
# OpenClaw 线上知识库
|
||
|
||
**版本**: 1.0.0
|
||
**最后更新**: 2026-03-12
|
||
**目的**: 为 ZClaw 项目提供全面、结构化的 OpenClaw 抷术参考
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [核心概念](#核心概念)
|
||
2. [系统架构](#系统架构)
|
||
3. [Gateway 协议](#gateway-协议)
|
||
4. [配置系统](#配置系统)
|
||
5. [Skills 与 Tools](#skills-与-tools)
|
||
6. [插件开发](#插件开发)
|
||
7. [多 Agent 路由](#多-agent-路由)
|
||
8. [安全与沙箱](#安全与沙箱)
|
||
9. [Heartbeat 机制](#heartbeat-机制)
|
||
10. [Channels 通道系统](#channels-通道系统)
|
||
11. [最佳实践](#最佳实践)
|
||
|
||
12. [ZClaw 映射指南](#zclaw-映射指南)
|
||
|
||
---
|
||
|
||
## 核心概念
|
||
|
||
### OpenClaw 是什么?
|
||
|
||
OpenClaw 是一个 **自托管的 AI Agent 硴关**,不是简单的"聊天 UI + 模型接入器"。
|
||
|
||
**核心定位**:
|
||
- **自托管**: 运行在你自己的硬件上,你的规则
|
||
- **多通道**: 一个 Gateway 同时服务 WhatsApp、Telegram、Discord、飞书等多个渠道
|
||
- **Agent 原生**: 为编码 Agent 构建,支持工具调用、会话、记忆、多 Agent 路由
|
||
- **开源**: MIT 许可,社区驱动
|
||
|
||
**关键洞察**: OpenClaw 的核心价值是 **执行 + 持续性 + 可控性**:
|
||
- **执行**: 能真正读写文件、跑命令、控浏览器、发消息
|
||
- **持续性**: 不只是一次性问答,而是可长期运转的 Agent
|
||
- **可控性**: 用户能看到配置、文本指令、工作区与约束,而不是黑盒
|
||
|
||
### Agent 的真正含义
|
||
|
||
在 OpenClaw 中,一个 Agent 包含:
|
||
- 一个 `agentId`
|
||
- 一个独立 workspace / agentDir
|
||
- 一组 bootstrap 文件 (`AGENTS.md`、`SOUL.md`、`USER.md`、`IDENTITY.md`)
|
||
- 一套工具与 sandbox 规则
|
||
- 一套 session 历史
|
||
- 一组可能的 channel bindings
|
||
- 一种人格 / 工作方式 / 角色定位
|
||
|
||
### Bootstrap 文件职责
|
||
|
||
| 文件 | 职责 | 内容示例 |
|
||
|------|------|----------|
|
||
| `AGENTS.md` | 操作规范与行为准则 | 会话启动 checklist、安全规范、工具使用规则 |
|
||
| `SOUL.md` | 身份、气质、边界 | Core Truths、Boundaries、Vibe、Continuity |
|
||
| `USER.md` | 关于用户的信息 | 用户习惯、上下文、沟通偏好、时区 |
|
||
| `IDENTITY.md` | Agent 外显身份 | Name、Emoji、Avatar、Vibe |
|
||
| `HEARTBEAT.md` | 心跳任务指令 | 定时检查任务、触发条件、投递目标 |
|
||
|
||
---
|
||
|
||
## 系统架构
|
||
|
||
### 四层架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 应用层 (Application) │
|
||
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||
│ │WhatsApp │ │Telegram │ │ Discord │ │ 飞书 │ │
|
||
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
|
||
│ │ │ │ │ │
|
||
│ └────────────┴────────────┴────────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌───────────────────────────────────────────────────────┐ │
|
||
│ │ Gateway (中枢) │ │
|
||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
|
||
│ │ │ WebSocket │ │ HTTP API │ │ Config │ │ │
|
||
│ │ │ Server │ │ Server │ │ Manager │ │ │
|
||
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌───────────────────────────────────────────────────────┐ │
|
||
│ │ Agent Runtime │ │
|
||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
|
||
│ │ │ Skills │ │ Tools │ │ Memory │ │ │
|
||
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌───────────────────────────────────────────────────────┐ │
|
||
│ │ LLM Providers │ │
|
||
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
|
||
│ │ │ Claude │ │ GPT-4 │ │ GLM │ │ Qwen │ │ │
|
||
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │
|
||
│ └───────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### Gateway 职责
|
||
|
||
Gateway 是 OpenClaw 的真正控制面板:
|
||
|
||
- WebSocket 协议握手与会话维持
|
||
- Agent 运行时管理
|
||
- Session/stream 事件分发
|
||
- Channels 消息收发
|
||
- 配置热加载与配置 RPC
|
||
- Skills / Tools / Plugins / Heartbeat 协调
|
||
- Device auth / pairing / scopes
|
||
|
||
### Workspace 结构
|
||
|
||
```
|
||
~/.openclaw/
|
||
├── openclaw.json # 主配置文件
|
||
├── .env # 环境变量
|
||
├── workspace/ # 默认工作区
|
||
│ ├── AGENTS.md
|
||
│ ├── SOUL.md
|
||
│ ├── USER.md
|
||
│ ├── IDENTITY.md
|
||
│ ├── memory.md
|
||
│ └── memory/
|
||
│ └── YYYY-MM-DD.md
|
||
├── agents/ # 多 Agent 状态目录
|
||
│ └── <agentId>/
|
||
│ ├── agent/
|
||
│ │ └── auth-profiles.json
|
||
│ └── sessions/
|
||
│ └── <sessionKey>.jsonl
|
||
└── skills/ # 托管技能目录
|
||
```
|
||
|
||
---
|
||
|
||
## Gateway 协议
|
||
|
||
### WebSocket 帧类型
|
||
|
||
```typescript
|
||
// 请求帧
|
||
interface GatewayRequest {
|
||
type: 'req';
|
||
id: string;
|
||
method: string;
|
||
params?: Record<string, any>;
|
||
}
|
||
|
||
// 响应帧
|
||
interface GatewayResponse {
|
||
type: 'res';
|
||
id: string;
|
||
ok: boolean;
|
||
payload?: any;
|
||
error?: any;
|
||
}
|
||
|
||
// 事件帧
|
||
interface GatewayEvent {
|
||
type: 'event';
|
||
event: string;
|
||
payload?: any;
|
||
seq?: number;
|
||
}
|
||
```
|
||
|
||
### 握手流程
|
||
|
||
```
|
||
客户端 Gateway
|
||
│ │
|
||
│────── WebSocket Connect ────▶│
|
||
│ │
|
||
│◀───── connect.challenge ─────│ (包含 nonce)
|
||
│ │
|
||
│────── connect request ──────▶│ (包含 device 签名)
|
||
│ │
|
||
│◀───── connect response ──────│ (成功/失败)
|
||
│ │
|
||
│◀═══════ 事件流 ═══════════════│ (agent, chat, etc.)
|
||
│ │
|
||
```
|
||
|
||
### Device 认证
|
||
|
||
```typescript
|
||
// 签名载荷格式 (v2)
|
||
const payload = [
|
||
'v2',
|
||
deviceId,
|
||
clientId,
|
||
clientMode,
|
||
role,
|
||
scopes.join(','),
|
||
String(signedAt),
|
||
token || '',
|
||
nonce,
|
||
].join('|');
|
||
|
||
// 使用 Ed25519 签名
|
||
const signature = nacl.sign.detached(messageBytes, secretKey);
|
||
```
|
||
|
||
### 连接参数
|
||
|
||
```typescript
|
||
interface ConnectParams {
|
||
minProtocol: 3;
|
||
maxProtocol: 3;
|
||
client: {
|
||
id: string; // 客户端标识
|
||
version: string; // 客户端版本
|
||
platform: string; // Win32/Darwin/Linux
|
||
mode: 'operator' | 'node';
|
||
};
|
||
role: 'operator' | 'node';
|
||
scopes: string[]; // ['operator.read', 'operator.write']
|
||
auth?: { token?: string };
|
||
device: {
|
||
id: string; // 设备 ID (公钥指纹)
|
||
publicKey: string; // Base64 编码的公钥
|
||
signature: string; // 签名
|
||
signedAt: number; // 签名时间戳
|
||
nonce: string; // 服务器提供的 nonce
|
||
};
|
||
}
|
||
```
|
||
|
||
### 核心 RPC 方法
|
||
|
||
| 方法 | 描述 | 参数 |
|
||
|------|------|------|
|
||
| `agent` | 发送消息给 Agent | `message`, `sessionKey?`, `model?` |
|
||
| `health` | 获取健康状态 | - |
|
||
| `status` | 获取 Gateway 状态 | - |
|
||
| `config.get` | 获取配置 | `path` |
|
||
| `config.patch` | 更新配置 | `path`, `value` |
|
||
| `send` | 通过渠道发送消息 | `channel`, `chatId`, `text` |
|
||
|
||
### Agent 流事件
|
||
|
||
```typescript
|
||
interface AgentStreamEvent {
|
||
stream: 'assistant' | 'tool' | 'lifecycle';
|
||
delta?: string; // 增量文本
|
||
content?: string; // 完整内容
|
||
tool?: string; // 工具名称
|
||
phase?: 'start' | 'end' | 'error';
|
||
runId?: string; // 运行 ID
|
||
error?: string; // 错误信息
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 配置系统
|
||
|
||
### 配置文件位置
|
||
|
||
```
|
||
~/.openclaw/openclaw.json # 主配置
|
||
~/.openclaw/.env # 环境变量
|
||
```
|
||
|
||
### 配置层级与优先级
|
||
|
||
```
|
||
agents.defaults.* # 全局默认
|
||
↓ 覆盖
|
||
agents.list[].* # 每个 Agent 的覆盖
|
||
↓ 覆盖
|
||
channels.defaults.* # 全渠道默认
|
||
↓ 覆盖
|
||
channels.<channel>.* # 单渠道覆盖
|
||
↓ 覆盖
|
||
channels.<channel>.accounts.<id>.* # 账号级覆盖
|
||
```
|
||
|
||
### 热加载模式
|
||
|
||
| 模式 | 行为 |
|
||
|------|------|
|
||
| `hybrid` (默认) | 安全更改即时生效,关键更改自动重启 |
|
||
| `hot` | 只热应用安全更改,需重启时记录警告 |
|
||
| `restart` | 任何更改都重启 Gateway |
|
||
| `off` | 禁用文件监控,手动重启生效 |
|
||
|
||
### CLI 配置命令
|
||
|
||
```bash
|
||
# 查看配置
|
||
openclaw config get agents.defaults.workspace
|
||
|
||
# 设置配置
|
||
openclaw config set agents.defaults.heartbeat.every "2h"
|
||
|
||
# 删除配置
|
||
openclaw config unset tools.web.search.apiKey
|
||
|
||
# 配置向导
|
||
openclaw configure
|
||
|
||
# 完整设置向导
|
||
openclaw onboard
|
||
```
|
||
|
||
### 环境变量引用
|
||
|
||
```json
|
||
{
|
||
"gateway": {
|
||
"auth": {
|
||
"token": "${OPENCLAW_GATEWAY_TOKEN}"
|
||
}
|
||
},
|
||
"models": {
|
||
"providers": {
|
||
"openai": {
|
||
"apiKey": "${OPENAI_API_KEY}"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Skills 与 Tools
|
||
|
||
### Skills 加载位置与优先级
|
||
|
||
1. **Bundled skills**: 安装包自带
|
||
2. **Managed/local skills**: `~/.openclaw/skills`
|
||
3. **Workspace skills**: `<workspace>/skills`
|
||
4. **Extra dirs**: `skills.load.extraDirs` 配置
|
||
|
||
**优先级**: workspace > managed > bundled > extraDirs
|
||
|
||
### SKILL.md 格式
|
||
|
||
```markdown
|
||
---
|
||
name: my-skill
|
||
description: 技能描述
|
||
homepage: https://example.com
|
||
user-invocable: true
|
||
disable-model-invocation: false
|
||
---
|
||
|
||
# 技能标题
|
||
|
||
技能说明内容...
|
||
|
||
Use {baseDir} to reference skill folder path.
|
||
```
|
||
|
||
### Skills vs Tools 区别
|
||
|
||
| 概念 | 描述 | 示例 |
|
||
|------|------|------|
|
||
| **Skills** | 任务说明 + 规则 + 可选脚本的组合 | 代码审查、文档生成 |
|
||
| **Tools** | 类型化的可执行能力 | `exec`, `read`, `write`, `browser` |
|
||
|
||
### 内置 Tools
|
||
|
||
```json
|
||
{
|
||
"tools": {
|
||
"exec": { "shell": true },
|
||
"web": {
|
||
"search": { "enabled": true }
|
||
},
|
||
"browser": { "enabled": true },
|
||
"read": {},
|
||
"write": {},
|
||
"edit": {}
|
||
}
|
||
}
|
||
```
|
||
|
||
### MCP 支持
|
||
|
||
OpenClaw 原生支持 MCP (Model Context Protocol):
|
||
- 给 Agent 扩展新的上下文来源与工具面
|
||
- 让技能可以调用标准化外部能力
|
||
- 让模型在不写死工具的情况下复用第三方协议能力
|
||
|
||
---
|
||
|
||
## 插件开发
|
||
|
||
### 插件结构
|
||
|
||
```
|
||
my-plugin/
|
||
├── openclaw.plugin.json # 必需: 插件清单
|
||
├── index.ts # 入口文件
|
||
├── package.json
|
||
└── dist/
|
||
```
|
||
|
||
### openclaw.plugin.json
|
||
|
||
```json
|
||
{
|
||
"id": "my-plugin",
|
||
"name": "My Plugin",
|
||
"version": "1.0.0",
|
||
"description": "Plugin description",
|
||
"main": "dist/index.js",
|
||
"skills": ["./skills"],
|
||
"config": {
|
||
"enabled": {
|
||
"type": "boolean",
|
||
"default": true
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 插件 API
|
||
|
||
```typescript
|
||
interface PluginAPI {
|
||
config: Record<string, any>;
|
||
|
||
// 注册 Gateway RPC 方法
|
||
registerGatewayMethod(
|
||
method: string,
|
||
handler: (ctx: RpcContext) => void
|
||
): void;
|
||
|
||
// 注册钩子
|
||
registerHook(
|
||
event: string,
|
||
handler: (...args: any[]) => any,
|
||
meta?: Record<string, any>
|
||
): void;
|
||
}
|
||
|
||
interface RpcContext {
|
||
params: Record<string, any>;
|
||
respond(ok: boolean, payload: any): void;
|
||
}
|
||
```
|
||
|
||
### ZClaw 插件示例
|
||
|
||
```typescript
|
||
// plugins/zclaw-ui/index.ts
|
||
export default function register(api: PluginAPI) {
|
||
// 注册自定义 RPC 方法
|
||
api.registerGatewayMethod('zclaw.clones.list', ({ respond }) => {
|
||
const data = readZclawData();
|
||
respond(true, { clones: data.clones });
|
||
});
|
||
|
||
// 注册启动钩子
|
||
api.registerHook('gateway:startup', async () => {
|
||
console.log('[ZCLAW] Plugin loaded');
|
||
});
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 多 Agent 路由
|
||
|
||
### 路由规则 (按优先级)
|
||
|
||
1. `peer` 精确匹配 (DM/group/channel id)
|
||
2. `parentPeer` 继承匹配 (thread 继承)
|
||
3. `guildId + roles` (Discord 角色路由)
|
||
4. `guildId` (Discord)
|
||
5. `teamId` (Slack)
|
||
6. `accountId` 规则
|
||
7. channel-level 匹配 (`accountId: "*"`)
|
||
8. fallback 到默认 Agent
|
||
|
||
### Binding 配置
|
||
|
||
```json
|
||
{
|
||
"bindings": [
|
||
{
|
||
"agentId": "work",
|
||
"match": {
|
||
"channel": "whatsapp",
|
||
"accountId": "personal",
|
||
"peer": { "kind": "direct", "id": "+15551234567" }
|
||
}
|
||
},
|
||
{
|
||
"agentId": "main",
|
||
"match": { "channel": "whatsapp" }
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 多 Agent 配置示例
|
||
|
||
```json
|
||
{
|
||
"agents": {
|
||
"list": [
|
||
{
|
||
"id": "home",
|
||
"default": true,
|
||
"workspace": "~/.openclaw/workspace-home"
|
||
},
|
||
{
|
||
"id": "work",
|
||
"workspace": "~/.openclaw/workspace-work",
|
||
"model": "anthropic/claude-opus-4-6"
|
||
}
|
||
]
|
||
},
|
||
"bindings": [
|
||
{ "agentId": "home", "match": { "channel": "whatsapp", "accountId": "personal" } },
|
||
{ "agentId": "work", "match": { "channel": "whatsapp", "accountId": "biz" } }
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 安全与沙箱
|
||
|
||
### 沙箱模式
|
||
|
||
| 模式 | 描述 |
|
||
|------|------|
|
||
| `off` | 无沙箱,直接执行 |
|
||
| `write` | 只沙箱写操作 |
|
||
| `all` | 所有操作都在沙箱中执行 |
|
||
|
||
### 工具策略
|
||
|
||
```json
|
||
{
|
||
"agents": {
|
||
"list": [
|
||
{
|
||
"id": "family",
|
||
"sandbox": { "mode": "all" },
|
||
"tools": {
|
||
"allow": ["read", "exec"],
|
||
"deny": ["write", "browser"]
|
||
}
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 安全检查清单
|
||
|
||
- [ ] 无硬编码密钥 (使用 env 引用)
|
||
- [ ] DM 访问控制已配置
|
||
- [ ] 群聊 mention 规则已设置
|
||
- [ ] 工具权限最小化
|
||
- [ ] 沙箱模式适当
|
||
- [ ] Gateway 端口不对外暴露
|
||
|
||
---
|
||
|
||
## Heartbeat 机制
|
||
|
||
### 概念
|
||
|
||
Heartbeat 不是简单的 cron,而是 **定期触发一个完整 Agent turn**:
|
||
- 默认读取 `HEARTBEAT.md`
|
||
- 如果没事做,返回 `HEARTBEAT_OK`
|
||
- 可以配置投递目标 (`none`、`last` 或具体渠道)
|
||
- 可以设置 active hours
|
||
- 支持 per-agent 覆盖
|
||
|
||
### 配置
|
||
|
||
```json
|
||
{
|
||
"agents": {
|
||
"defaults": {
|
||
"heartbeat": {
|
||
"every": "1h",
|
||
"activeHours": { "start": "09:00", "end": "18:00" },
|
||
"deliverTo": "last"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### HEARTBEAT.md 示例
|
||
|
||
```markdown
|
||
# 心跳任务
|
||
|
||
每小时检查:
|
||
1. 是否有待处理的提醒
|
||
2. 是否需要发送日报
|
||
3. 日历事件提醒
|
||
|
||
如果无事可做,回复 HEARTBEAT_OK
|
||
```
|
||
|
||
---
|
||
|
||
## Channels 通道系统
|
||
|
||
### 支持的通道
|
||
|
||
| 通道 | 多账号 | 描述 |
|
||
|------|--------|------|
|
||
| WhatsApp | ✅ | 通过 Web WhatsApp |
|
||
| Telegram | ✅ | Bot API |
|
||
| Discord | ✅ | Bot + Guild |
|
||
| 飞书 | ✅ | 企业自建应用 |
|
||
| Slack | ✅ | Bot + Workspace |
|
||
| iMessage | ❌ | macOS only |
|
||
| Signal | ✅ | 通过 signald |
|
||
|
||
### 通道配置结构
|
||
|
||
```json
|
||
{
|
||
"channels": {
|
||
"whatsapp": {
|
||
"enabled": true,
|
||
"dmPolicy": "pairing",
|
||
"allowFrom": ["+15555550123"],
|
||
"accounts": {
|
||
"personal": {
|
||
"authDir": "~/.openclaw/credentials/whatsapp/personal"
|
||
},
|
||
"biz": {
|
||
"authDir": "~/.openclaw/credentials/whatsapp/biz"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 访问控制
|
||
|
||
```json
|
||
{
|
||
"channels": {
|
||
"whatsapp": {
|
||
"dmPolicy": "allowlist",
|
||
"allowFrom": ["+15555550123"],
|
||
"groups": {
|
||
"*": { "requireMention": true }
|
||
}
|
||
}
|
||
},
|
||
"messages": {
|
||
"groupChat": {
|
||
"mentionPatterns": ["@openclaw", "小龙虾"]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 最佳实践
|
||
|
||
### 1. 配置管理
|
||
|
||
```bash
|
||
# 使用 CLI 而非直接编辑 JSON
|
||
openclaw config set agents.defaults.model "anthropic/claude-sonnet-4-6"
|
||
|
||
# 验证配置
|
||
openclaw doctor
|
||
|
||
# 查看日志
|
||
openclaw logs --follow
|
||
```
|
||
|
||
### 2. Agent 隔离
|
||
|
||
- 每个 Agent 使用独立 workspace
|
||
- 不共享 `agentDir` (会导致 auth/session 冲突)
|
||
- 敏感 Agent 启用沙箱
|
||
|
||
### 3. 密钥管理
|
||
|
||
```json
|
||
// 使用环境变量引用
|
||
{
|
||
"models": {
|
||
"providers": {
|
||
"openai": {
|
||
"apiKey": "${OPENAI_API_KEY}"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. 错误处理
|
||
|
||
- Gateway 连接是协议适配工程,不是简单的 ws 连接
|
||
- 实现指数退避重连
|
||
- 正确处理 `connect.challenge`
|
||
|
||
---
|
||
|
||
## ZClaw 映射指南
|
||
|
||
### 设置页面对应关系
|
||
|
||
| ZClaw 页面 | OpenClaw 子系统 | 真实目标 |
|
||
|-----------|-----------------|----------|
|
||
| 通用 | 系统级设置 | 控制连接状态、系统级行为开关 |
|
||
| 模型与 API | providers / model defaults | 管理 provider 配置、主模型与 fallback |
|
||
| MCP 服务 | Tools / MCP | 定义 Agent 可接入的外部能力 |
|
||
| 技能 | Skills | 管理 Agent 可调用的工作流知识库 |
|
||
| IM 频道 | Channels | 管理消息来源和路由规则 |
|
||
| 工作区 | Workspace / Sandbox | 确定 Agent 执行边界 |
|
||
| 数据与隐私 | Data / Telemetry | 明确数据存储位置和隐私设置 |
|
||
| 分身/快速配置 | Agents / Bindings | 创建/配置新的 Agent 实例 |
|
||
|
||
### ZClaw 自定义 RPC 方法
|
||
|
||
```typescript
|
||
// plugins/zclaw-ui 注册的方法
|
||
client.listClones() // zclaw.clones.list
|
||
client.createClone(opts) // zclaw.clones.create
|
||
client.updateClone(id, opts) // zclaw.clones.update
|
||
client.deleteClone(id) // zclaw.clones.delete
|
||
client.getUsageStats() // zclaw.stats.usage
|
||
client.getSessionStats() // zclaw.stats.sessions
|
||
client.getWorkspaceInfo() // zclaw.workspace.info
|
||
client.getPluginStatus() // zclaw.plugins.status
|
||
client.getQuickConfig() // zclaw.config.quick
|
||
client.listSkills() // zclaw.skills.list
|
||
```
|
||
|
||
### 分身 (Clone) = Agent 实例
|
||
|
||
```typescript
|
||
interface CloneConfig {
|
||
id: string;
|
||
name: string;
|
||
role?: string;
|
||
nickname?: string;
|
||
scenarios?: string[];
|
||
model?: string;
|
||
workspaceDir?: string;
|
||
workspaceResolvedPath?: string;
|
||
restrictFiles?: boolean;
|
||
privacyOptIn?: boolean;
|
||
userName?: string;
|
||
userRole?: string;
|
||
bootstrapReady?: boolean;
|
||
bootstrapFiles?: Array<{ name: string; path: string; exists: boolean }>;
|
||
}
|
||
```
|
||
|
||
### 判断标准
|
||
|
||
> 如果一个页面改动之后,没有改变 OpenClaw Runtime 的真实行为、真实配置、真实路由、真实工作区或真实 Agent 上下文,那它大概率还只是"演示 UI",不是系统能力。
|
||
|
||
---
|
||
|
||
## ZCLAW 桌面 Gateway 握手排障案例(2026-03)
|
||
|
||
### 症状演进
|
||
|
||
1. 初始表现为桌面端长时间停留在“握手中...”
|
||
2. 修正握手客户端身份后,错误表象变成 `WebSocket connection failed`
|
||
3. 修复候选地址 fallback 的错误覆盖后,暴露出真实错误 `origin not allowed`
|
||
4. 自动补齐 `gateway.controlUi.allowedOrigins` 后,错误继续推进为 `pairing required`
|
||
|
||
### 已确认的排查结论
|
||
|
||
- `gateway.auth.token` 已正确从 `openclaw.json` 读取并注入桌面端连接
|
||
- Tauri 调试版实际运行的是 `target/debug/resources/openclaw-runtime`
|
||
- Gateway WebSocket 握手客户端身份需满足当前 schema:
|
||
- `client.id=cli`
|
||
- `client.mode=cli`
|
||
- `role=operator`
|
||
- 浏览器 / WebView 环境与 Node 探针的关键差异是会附带 `Origin`
|
||
- Tauri WebView 需要被加入:
|
||
- `gateway.controlUi.allowedOrigins`
|
||
- `http://tauri.localhost`
|
||
- `tauri://localhost`
|
||
- 当 `origin not allowed` 被解决后,Gateway 会继续要求对当前设备完成 pairing
|
||
|
||
### 有效的排障方法
|
||
|
||
#### 1. 先分离“网络失败”和“协议失败”
|
||
|
||
如果 UI 只显示 `WebSocket connection failed`,先检查连接代码是否在多个候选地址之间 fallback,并把更早的握手错误覆盖掉。
|
||
ZCLAW 的处理方式是:
|
||
|
||
- 仅对以下错误继续尝试下一个候选地址:
|
||
- `WebSocket connection failed`
|
||
- `Gateway handshake timed out`
|
||
- `WebSocket closed before handshake completed`
|
||
- 对握手 / 鉴权 / schema 错误立即停止 fallback,原样暴露给 UI
|
||
|
||
#### 2. 用独立协议探针验证 Gateway 真正接受的握手参数
|
||
|
||
在本案例中,Node 探针证明了:
|
||
|
||
- `cli/cli/operator` 是可接受的客户端身份
|
||
- 设备 `deviceId` 必须和 `publicKey` 的派生规则一致
|
||
- 仅靠终端探针成功并不能证明 Tauri WebView 一定能连通,因为 WebView 会额外带 `Origin`
|
||
|
||
#### 3. 优先检查本地 Gateway 的 pending / paired devices
|
||
|
||
可用命令:
|
||
|
||
```powershell
|
||
openclaw devices list --json
|
||
```
|
||
|
||
本案例中,`pairing required` 发生时,`devices list` 已能看到当前桌面端的 pending 请求,说明:
|
||
|
||
- 连接已到达 Gateway
|
||
- 当前缺的是“批准这台设备”,不是 token 或网络
|
||
|
||
### ZCLAW 当前修复策略
|
||
|
||
#### A. 连接前自动准备本地 Gateway
|
||
|
||
桌面端在 Tauri 运行时连接前,先调用本地准备逻辑:
|
||
|
||
- 确保 `gateway.controlUi.allowedOrigins` 包含:
|
||
- `http://tauri.localhost`
|
||
- `tauri://localhost`
|
||
- 如果配置被修改且 Gateway 正在运行,自动重启 Gateway 使配置生效
|
||
|
||
#### B. 握手遇到 `pairing required` 时自动批准本机桌面设备
|
||
|
||
当前策略只在**本地 loopback Gateway** 下启用:
|
||
|
||
- 仅匹配 `ws://127.0.0.1:*` 或 `ws://localhost:*`
|
||
- 前端读取当前桌面端持久化的 `deviceId/publicKey`
|
||
- Tauri 侧调用:
|
||
|
||
```powershell
|
||
openclaw devices list --json
|
||
openclaw devices approve <requestId> --json --token <token> --url <url>
|
||
```
|
||
|
||
- 只批准同时匹配以下条件的 pending request:
|
||
- `deviceId`
|
||
- `publicKey`
|
||
- 批准成功后立即重试连接
|
||
|
||
### 后续遇到同类问题时的最短排障顺序
|
||
|
||
1. 确认当前运行的是目标 `desktop.exe`
|
||
2. 确认 `openclaw.json` 中有 `gateway.auth.token`
|
||
3. 确认 WebView localStorage 已持久化 `zclaw_gateway_url` / `zclaw_gateway_token`
|
||
4. 把握手错误原样暴露,不要让 fallback 覆盖
|
||
5. 若报 `origin not allowed`:
|
||
- 检查 `gateway.controlUi.allowedOrigins`
|
||
6. 若报 `pairing required`:
|
||
- 检查 `openclaw devices list --json`
|
||
- 看当前桌面设备是否进入 `pending`
|
||
7. 如果 pending 存在,优先做“只批准本机当前设备”的自动化,而不是直接放宽所有设备
|
||
|
||
---
|
||
|
||
## ZCLAW 桌面聊天 / 模型配置协议错配案例(2026-03)
|
||
|
||
### 症状
|
||
|
||
- 桌面端显示 Gateway 已连接,但发送消息立即失败
|
||
- 常见错误文案为:
|
||
- `invalid agent params: must have required property 'idempotencyKey'`
|
||
- `invalid agent params: must NOT have additional properties: model`
|
||
- 模型与 API 页面可以切换本地显示值,但不会改变 Gateway 的真实默认模型
|
||
|
||
### 根因
|
||
|
||
- ZCLAW 桌面端此前仍按旧协议调用 `agent`:
|
||
- 发送了顶层 `model`
|
||
- 没有发送必填 `idempotencyKey`
|
||
- 当前 OpenClaw runtime 的 `agent` schema 已变更为:
|
||
- `message` 必填
|
||
- `idempotencyKey` 必填
|
||
- `model` 不是允许的顶层字段
|
||
- 桌面端“模型切换”之前只是本地 Zustand 状态,没有写回 Gateway 配置,因此不会影响真实运行时行为
|
||
|
||
### 有效排查方法
|
||
|
||
1. 不要只看仓库里的旧 client 封装,要直接核对当前实际 runtime 的 schema
|
||
2. 如果仓库源码里搜不到新字段(如 `idempotencyKey`),优先检查打包后的 `openclaw-runtime`
|
||
3. 在本案例中,真实约束来自 runtime 中的 `AgentParamsSchema`:
|
||
- `message: NonEmptyString`
|
||
- `idempotencyKey: NonEmptyString`
|
||
- `agentId/sessionKey/...` 可选
|
||
- `additionalProperties: false`
|
||
4. 对模型配置,不要只改前端本地状态;应优先确认 runtime 是否已暴露:
|
||
- `models.list`
|
||
- `config.get`
|
||
- `config.apply`
|
||
|
||
### ZCLAW 当前修复策略
|
||
|
||
- `desktop/src/lib/gateway-client.ts`
|
||
- `chat()` 改为发送 `idempotencyKey`
|
||
- 停止发送非法顶层 `model`
|
||
- 新增 `models.list` / `config.get` / `config.apply` 客户端接口
|
||
- `desktop/src/store/chatStore.ts`
|
||
- 发送消息时不再把本地 `clone_*` 直接当作 runtime `agentId`
|
||
- 继续保留前端会话与分身关联信息,避免 UI 上下文丢失
|
||
- `desktop/src/components/Settings/ModelsAPI.tsx`
|
||
- 改为基于真实 Gateway 配置读写默认模型与中文模型插件 Provider 配置
|
||
- `desktop/src/components/ChatArea.tsx`
|
||
- 聊天输入区模型下拉改为通过 `config.apply` 更新 Gateway 默认模型,而不是只切本地显示
|
||
|
||
### 当前结论
|
||
|
||
- 如果错误同时出现 `missing idempotencyKey` 和 `unexpected property model`,优先判断为“桌面端协议版本落后于当前 runtime”
|
||
- 如果模型切换只改变 UI 文案、不会改变新会话的实际模型,说明它仍是“演示态”,应改为落到 `config.get/config.apply`
|
||
|
||
---
|
||
|
||
## 参考资料
|
||
|
||
### 官方文档
|
||
|
||
- [OpenClaw 官方文档](https://docs.openclaw.ai/)
|
||
- [Gateway 配置参考](https://docs.openclaw.ai/gateway/configuration)
|
||
- [Multi-Agent 路由](https://docs.openclaw.ai/concepts/multi-agent)
|
||
- [Skills 文档](https://docs.openclaw.ai/tools/skills)
|
||
- [Heartbeat 文档](https://docs.openclaw.ai/gateway/heartbeat)
|
||
|
||
### 社区资源
|
||
|
||
- [OpenClaw 中文指南](https://yeasy.gitbook.io/openclaw_guide/)
|
||
- [awesome-openclaw-skills](https://github.com/VoltAgent/awesome-openclaw-skills)
|
||
- [OpenClaw 源码解析](https://www.ququ123.top/2026/03/openclaw-gateway-startup/)
|
||
|
||
### ZClaw 内部参考
|
||
|
||
- `docs/openclaw-deep-dive.md` - 深度分析
|
||
- `config/openclaw.default.json` - 默认配置
|
||
- `plugins/zclaw-ui/index.ts` - 插件实现
|
||
- `desktop/src/lib/gateway-client.ts` - 客户端实现
|