|
|
@@ -0,0 +1,1914 @@
|
|
|
+---
|
|
|
+title: 搭建我的专属AI助手:OpenClaw云服务器部署实战指南
|
|
|
+author: Gamehu
|
|
|
+tags:
|
|
|
+ - OpenClaw
|
|
|
+ - AI
|
|
|
+ - DevOps
|
|
|
+ - 部署
|
|
|
+ - 记录系统优化
|
|
|
+categories:
|
|
|
+ - 工具
|
|
|
+date: 2026-02-27 22:30:00
|
|
|
+updated: 2026-03-06 14:10:00
|
|
|
+---
|
|
|
+
|
|
|
+> 📢 **更新日志**:
|
|
|
+> - 2026-03-06 新增 `Step-3.5-Flash` 接入与会话级 `/model` 切换说明,补充默认模型不切全局、只切当前会话的使用方式。
|
|
|
+> - 2026-03-03 新增"记录系统优化"章节,解决会话文件膨胀问题,添加自动归档和结构化存储方案。
|
|
|
+
|
|
|
+<div class="tag-container">
|
|
|
+ <span class="ai-tag">AI提效</span>
|
|
|
+ <span class="sub-tag">实战踩坑</span>
|
|
|
+</div>
|
|
|
+
|
|
|
+## 写在前面
|
|
|
+
|
|
|
+最近刷到不少 OpenClaw 的文章,演示零成本安装、智能体集群、国内部署经验。我手头正好有台 2 核 3G 的云服务器闲置着,决定动手搭建一个专属 AI 助手。
|
|
|
+
|
|
|
+但这篇文章不是推广,是<span class="highlight-text">真实的部署踩坑记录</span>。整个过程历时数小时,遇到了 OOM 内存不足、配置验证失败、防火墙规则冲突等一系列问题,把完整的解决过程记录下来。
|
|
|
+
|
|
|
+**先说结论**:OpenClaw 确实能跑起来,但需要对 Docker、网络和 Linux 有一定了解,且内存配置要充足。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## OpenClaw 是什么
|
|
|
+
|
|
|
+OpenClaw 是一个开源的个人 AI 助手框架,核心价值在于:**它不是只聊天的 AI,而是能动手干活的 AI**。
|
|
|
+
|
|
|
+核心能力:
|
|
|
+- 在 Telegram、Discord、Slack 等平台接收指令
|
|
|
+- 操作文件系统、执行 Shell 命令、浏览网页
|
|
|
+- 调用 API、读写数据库
|
|
|
+- 跨会话持久化记忆
|
|
|
+
|
|
|
+最重要的是——运行在自己的服务器上,数据完全掌控。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 我的环境
|
|
|
+
|
|
|
+搬瓦工买的一台机器,配置不高,平时捣鼓各种东西的。
|
|
|
+
|
|
|
+| 配置项 | 实际环境 |
|
|
|
+|--------|----------|
|
|
|
+| 系统 | Ubuntu 24.04.2 LTS |
|
|
|
+| CPU | 3 核 |
|
|
|
+| 内存 | 2GB RAM |
|
|
|
+| 磁盘 | 39GB SSD |
|
|
|
+| Docker | 29.2.1 |
|
|
|
+| Docker Compose | v5.1.0 |
|
|
|
+| 公网 IP | your-server-ip |
|
|
|
+
|
|
|
+> ⚠️ **重要提示**:2GB 内存对于源码构建来说不够,需要配置 Swap。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 部署过程实录
|
|
|
+
|
|
|
+### 第一步:安装 Docker
|
|
|
+
|
|
|
+Ubuntu 24.04 下安装 Docker 很顺利:
|
|
|
+
|
|
|
+```bash
|
|
|
+# 更新系统
|
|
|
+apt update && apt upgrade -y
|
|
|
+
|
|
|
+# 安装 Docker
|
|
|
+curl -fsSL https://get.docker.com | sh
|
|
|
+
|
|
|
+# 验证安装
|
|
|
+docker --version # Docker version 29.2.1
|
|
|
+docker compose version # Docker Compose version v5.5.1
|
|
|
+```
|
|
|
+
|
|
|
+国内用户建议配置镜像加速,编辑 `/etc/docker/daemon.json`:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "registry-mirrors": [
|
|
|
+ "https://docker.1ms.run",
|
|
|
+ "https://dockerhub.icu"
|
|
|
+ ]
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 第二步:源码构建(第一个坑:OOM)
|
|
|
+
|
|
|
+官方提供了 Docker 镜像,但我选择从源码构建以获得最新功能:
|
|
|
+
|
|
|
+```bash
|
|
|
+mkdir -p /opt/openclaw
|
|
|
+cd /opt/openclaw
|
|
|
+git clone https://github.com/openclaw/openclaw.git
|
|
|
+cd openclaw
|
|
|
+```
|
|
|
+
|
|
|
+开始构建:
|
|
|
+
|
|
|
+```bash
|
|
|
+docker build -t openclaw:local -f Dockerfile .
|
|
|
+```
|
|
|
+
|
|
|
+<span class="warning">🚨 第一个大坑:构建到 `pnpm install` 时容器被杀</span>
|
|
|
+
|
|
|
+查看日志发现是 **OOM(内存不足)**。2GB RAM 在构建 Node.js 项目时不够用,`pnpm install` 直接占满内存导致进程被系统杀死。
|
|
|
+
|
|
|
+**解决方案:添加 Swap 空间**
|
|
|
+
|
|
|
+```bash
|
|
|
+# 创建 5GB Swap 文件
|
|
|
+dd if=/dev/zero of=/swapfile bs=1G count=5
|
|
|
+chmod 600 /swapfile
|
|
|
+mkswap /swapfile
|
|
|
+swapon /swapfile
|
|
|
+
|
|
|
+# 验证
|
|
|
+free -h
|
|
|
+# 显示:Swap: 5.0Gi
|
|
|
+```
|
|
|
+
|
|
|
+添加 Swap 后重新构建,成功完成。
|
|
|
+
|
|
|
+> 📷 **安装过程 - 添加 Swap 解决 OOM**:
|
|
|
+>
|
|
|
+> 
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 第三步:配置 OpenClaw
|
|
|
+
|
|
|
+创建 `docker-compose.yml`:
|
|
|
+
|
|
|
+```yaml
|
|
|
+version: '3.8'
|
|
|
+
|
|
|
+services:
|
|
|
+ openclaw-gateway:
|
|
|
+ image: openclaw:local
|
|
|
+ container_name: openclaw
|
|
|
+ restart: unless-stopped
|
|
|
+ environment:
|
|
|
+ - HOME=/home/node
|
|
|
+ - NODE_ENV=production
|
|
|
+ volumes:
|
|
|
+ - ./.openclaw:/home/node/.openclaw
|
|
|
+ - ./.openclaw/workspace:/home/node/.openclaw/workspace
|
|
|
+ ports:
|
|
|
+ - "127.0.0.1:18789:18789"
|
|
|
+ - "127.0.0.1:18790:18790"
|
|
|
+ command: ["node", "dist/index.js", "gateway", "--bind", "lan", "--port", "18789"]
|
|
|
+```
|
|
|
+
|
|
|
+<span class="warning">🚨 第二个坑:配置验证极其严格</span>
|
|
|
+
|
|
|
+OpenClaw 对 `openclaw.json` 配置文件的校验非常严格,很多字段在官方文档中没有明确说明,但缺失会导致启动失败。
|
|
|
+
|
|
|
+**我遇到的错误:**
|
|
|
+
|
|
|
+```
|
|
|
+✖ Configuration validation failed:
|
|
|
+ - gateway.mode is required
|
|
|
+ - gateway.controlUi.allowedOrigins is required when using non-loopback bind
|
|
|
+```
|
|
|
+
|
|
|
+**正确的最小配置**(`openclaw.json`):
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "gateway": {
|
|
|
+ "port": 18789,
|
|
|
+ "mode": "local",
|
|
|
+ "controlUi": {
|
|
|
+ "allowedOrigins": ["http://localhost:18789", "http://127.0.0.1:18789"]
|
|
|
+ },
|
|
|
+ "auth": {
|
|
|
+ "token": "your-secure-token-here"
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> 📷 **OpenClaw Web UI 界面**:
|
|
|
+>
|
|
|
+> 
|
|
|
+
|
|
|
+> **关键注意点**:
|
|
|
+> - `gateway.mode` 必须显式设置为 `"local"`
|
|
|
+> - `gateway.controlUi.allowedOrigins` 在使用非 localhost 绑定时是必需的
|
|
|
+> - `gateway.bind` **不能写在 JSON 中**(无效字段),必须通过 CLI 参数 `--bind lan` 设置
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 第四步:配置阿里云百炼模型
|
|
|
+
|
|
|
+我选择使用阿里云百炼的 Coding Plan,配置 kimi-k2.5 作为主力模型:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "models": {
|
|
|
+ "mode": "merge",
|
|
|
+ "providers": {
|
|
|
+ "bailian": {
|
|
|
+ "baseUrl": "https://coding.dashscope.aliyuncs.com/v1",
|
|
|
+ "apiKey": "YOUR_BAILIAN_API_KEY",
|
|
|
+ "api": "openai-completions",
|
|
|
+ "models": [
|
|
|
+ {
|
|
|
+ "id": "kimi-k2.5",
|
|
|
+ "name": "kimi-k2.5",
|
|
|
+ "input": ["text", "image"],
|
|
|
+ "contextWindow": 262144,
|
|
|
+ "maxTokens": 32768
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "id": "qwen3.5-plus",
|
|
|
+ "name": "qwen3.5-plus",
|
|
|
+ "input": ["text", "image"],
|
|
|
+ "contextWindow": 1000000,
|
|
|
+ "maxTokens": 65536
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "agents": {
|
|
|
+ "defaults": {
|
|
|
+ "model": {
|
|
|
+ "primary": "bailian/kimi-k2.5"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 第五步:配置 Telegram Bot
|
|
|
+
|
|
|
+在 [@BotFather](https://t.me/BotFather) 创建 Bot 并获取 Token。
|
|
|
+
|
|
|
+<span class="warning">🚨 第三个坑:配对码过期与 dmPolicy 冲突</span>
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "channels": {
|
|
|
+ "telegram": {
|
|
|
+ "enabled": true,
|
|
|
+ "botToken": "YOUR_BOT_TOKEN_HERE",
|
|
|
+ "allowFrom": ["YOUR_TELEGRAM_USER_ID"]
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+初始配置时我加了 `"dmPolicy": "open"`,结果与 `allowFrom` 白名单冲突,报错:
|
|
|
+
|
|
|
+```
|
|
|
+dmPolicy: open requires allowFrom: ["*"]
|
|
|
+```
|
|
|
+
|
|
|
+**解决方案**:删除 `dmPolicy` 字段,直接使用 `allowFrom` 白名单。
|
|
|
+
|
|
|
+启动服务:
|
|
|
+
|
|
|
+```bash
|
|
|
+docker compose up -d
|
|
|
+docker compose logs -f
|
|
|
+```
|
|
|
+
|
|
|
+看到日志显示 `Telegram channel started` 且没有错误,说明 Bot 已上线。
|
|
|
+
|
|
|
+> 📷 **Telegram Bot 配置成功**:
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 第六步:Google Workspace 集成(扩展能力)
|
|
|
+
|
|
|
+这是 OpenClaw 真正强大的地方——通过 Google Workspace 集成,AI 可以帮你管理邮件、日历、文档。
|
|
|
+
|
|
|
+OpenClaw 使用 `gog` skill 来访问 Google 服务(Gmail、Calendar、Drive、Docs、Sheets)。
|
|
|
+
|
|
|
+#### 6.1 创建 Google Cloud 项目
|
|
|
+
|
|
|
+1. 访问 [Google Cloud Console](https://console.cloud.google.com/)
|
|
|
+2. 创建新项目(例如:`openclaw-integration`)
|
|
|
+3. 启用以下 API:
|
|
|
+ - Gmail API
|
|
|
+ - Google Calendar API
|
|
|
+ - Google Drive API
|
|
|
+ - Google Docs API
|
|
|
+ - Google Sheets API
|
|
|
+
|
|
|
+#### 6.2 配置 OAuth 凭据
|
|
|
+
|
|
|
+1. 进入 **APIs & Services > Credentials**
|
|
|
+2. 点击 **Create Credentials > OAuth client ID**
|
|
|
+3. 选择 **Desktop app** 类型
|
|
|
+4. 记下 **Client ID** 和 **Client Secret**
|
|
|
+
|
|
|
+#### 6.3 配置 MCP 服务器
|
|
|
+
|
|
|
+OpenClaw 通过 MCP (Model Context Protocol) 集成 Google Workspace。
|
|
|
+
|
|
|
+在服务器上创建 MCP 配置文件:
|
|
|
+
|
|
|
+```bash
|
|
|
+mkdir -p /opt/openclaw/.openclaw/mcp
|
|
|
+cat > /opt/openclaw/.openclaw/mcp/google-workspace.json << 'EOF'
|
|
|
+{
|
|
|
+ "mcpServers": {
|
|
|
+ "google-workspace": {
|
|
|
+ "command": "npx",
|
|
|
+ "args": ["-y", "@gongchangio/mcp-google-workspace"],
|
|
|
+ "env": {
|
|
|
+ "GOOGLE_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
|
|
|
+ "GOOGLE_CLIENT_SECRET": "your-client-secret",
|
|
|
+ "GOOGLE_REDIRECT_URI": "http://localhost:18790/oauth2callback"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+EOF
|
|
|
+```
|
|
|
+
|
|
|
+#### 6.4 重启 OpenClaw 并授权
|
|
|
+
|
|
|
+```bash
|
|
|
+cd /opt/openclaw
|
|
|
+docker compose restart
|
|
|
+
|
|
|
+# 查看日志等待授权提示
|
|
|
+docker compose logs -f | grep -i google
|
|
|
+```
|
|
|
+
|
|
|
+首次启动会显示 OAuth 授权链接,在浏览器中打开并授权后,会获得一个 code,将其填回即可。
|
|
|
+
|
|
|
+#### 6.5 实际使用场景
|
|
|
+
|
|
|
+配置完成后,你可以通过 Telegram 让 AI 帮你:
|
|
|
+
|
|
|
+**管理邮件**:
|
|
|
+> "帮我查看今天的重要邮件,并回复需要处理的"
|
|
|
+
|
|
|
+**操作日历**:
|
|
|
+> "帮我查一下下周的会议安排,把周五下午的会议改到周四"
|
|
|
+
|
|
|
+**读写文档**:
|
|
|
+> "读取 Drive 里的 '项目计划.docx',帮我总结要点并更新状态"
|
|
|
+
|
|
|
+<span class="warning">⚠️ 注意:Google OAuth 有权限范围限制</span>
|
|
|
+
|
|
|
+- 个人 Gmail 账户:直接可用
|
|
|
+- Google Workspace(企业账户):需要管理员授权
|
|
|
+- 敏感范围(如删除邮件)需要额外验证
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 第七步:安全加固(重中之重)
|
|
|
+
|
|
|
+<span class="warning">🚨 第四个坑:Docker 绕过 INPUT 链的防火墙规则</span>
|
|
|
+
|
|
|
+我最初的防火墙配置:
|
|
|
+
|
|
|
+```bash
|
|
|
+iptables -I INPUT 1 -p tcp --dport 18789 -s 127.0.0.1 -j ACCEPT
|
|
|
+iptables -I INPUT 2 -p tcp --dport 18789 -j DROP
|
|
|
+```
|
|
|
+
|
|
|
+测试发现:**公网仍然可以访问 Web UI!**
|
|
|
+
|
|
|
+**原因**:Docker 在 `DOCKER` 链中插入了 ACCEPT 规则,且该链在 `INPUT` 链之前被处理。
|
|
|
+
|
|
|
+**正确的解决方案**:使用 `DOCKER-USER` 链
|
|
|
+
|
|
|
+```bash
|
|
|
+# 在 DOCKER-USER 链中插入规则(在 Docker 规则之前执行)
|
|
|
+iptables -I DOCKER-USER 1 -p tcp -s 127.0.0.1 --dport 18789 -j ACCEPT
|
|
|
+iptables -I DOCKER-USER 2 -p tcp --dport 18789 -j DROP
|
|
|
+iptables -I DOCKER-USER 3 -p tcp -s 127.0.0.1 --dport 18790 -j ACCEPT
|
|
|
+iptables -I DOCKER-USER 4 -p tcp --dport 18790 -j DROP
|
|
|
+
|
|
|
+# 保存规则
|
|
|
+iptables-save > /root/iptables-rules.txt
|
|
|
+```
|
|
|
+
|
|
|
+**最终安全策略**:
|
|
|
+
|
|
|
+| 项目 | 状态 |
|
|
|
+|------|------|
|
|
|
+| 配置文件权限 | 容器运行用户可读(避免 `EACCES`) |
|
|
|
+| 公网 Web UI | 通过 `DOCKER-USER` 链完全阻止 |
|
|
|
+| 本地 Web UI | 127.0.0.1 可访问 |
|
|
|
+| Telegram 访问 | 仅白名单用户 ID 可用 |
|
|
|
+| 外部访问方式 | SSH 隧道 |
|
|
|
+
|
|
|
+> 📷 **最后安全检查 - 安全加固结果**:
|
|
|
+>
|
|
|
+> 
|
|
|
+
|
|
|
+**SSH 隧道访问命令**:
|
|
|
+
|
|
|
+```bash
|
|
|
+ssh -N -L 18789:127.0.0.1:18789 root@your-server-ip
|
|
|
+# 然后在本地浏览器访问 http://localhost:18789
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 进阶玩法:持久记忆配置(第9步)
|
|
|
+
|
|
|
+OpenClaw 的持久记忆系统让它能跨会话记住你的偏好、项目信息和个人习惯。这是从"工具"升级为"助手"的关键。
|
|
|
+
|
|
|
+### 记忆文件目录结构
|
|
|
+
|
|
|
+| 路径 | 用途 | 文件类型 |
|
|
|
+|------|------|----------|
|
|
|
+| `/home/node/.openclaw/memory/` | 数据库存储(自动) | `main.sqlite` - 对话历史 |
|
|
|
+| `/home/node/.openclaw/workspace/` | 结构化记忆文件 | `MEMORY.md`, `USER.md` |
|
|
|
+| `/home/node/.openclaw/workspace/memory/` | 每日记忆归档 | `YYYY-MM-DD.md` |
|
|
|
+
|
|
|
+### 核心记忆文件
|
|
|
+
|
|
|
+#### 1. USER.md - 用户档案
|
|
|
+
|
|
|
+```markdown
|
|
|
+# USER.md - About Your Human
|
|
|
+
|
|
|
+- **Name:** Gamehu
|
|
|
+- **What to call them:** Gamehu
|
|
|
+- **Timezone:** Asia/Shanghai (UTC+8)
|
|
|
+
|
|
|
+## Context
|
|
|
+- **职业:** IT 行业,编程 + 团队管理
|
|
|
+- **需求:** 个人助手
|
|
|
+- **风格偏好:** 简单直接,不绕弯子
|
|
|
+```
|
|
|
+
|
|
|
+#### 2. MEMORY.md - 长期记忆
|
|
|
+
|
|
|
+```markdown
|
|
|
+# MEMORY.md - Long-term Memory
|
|
|
+
|
|
|
+## Technical Stack
|
|
|
+- **Primary Languages:** Java, JavaScript, Python, Go
|
|
|
+- **Frameworks:** Spring Boot, React
|
|
|
+- **Cloud:** Alibaba Cloud, AWS
|
|
|
+
|
|
|
+### Preferences
|
|
|
+- **Code Style:** Clean, well-documented
|
|
|
+- **Learning Style:** Hands-on, project-based
|
|
|
+- **Dislikes:** Repetitive small talk
|
|
|
+
|
|
|
+### Current Projects
|
|
|
+- Building personal AI assistant
|
|
|
+- Managing development team
|
|
|
+```
|
|
|
+
|
|
|
+### 如何工作
|
|
|
+
|
|
|
+1. **自动记忆**:所有对话自动存入 SQLite,跨会话保持上下文
|
|
|
+2. **结构化记忆**:AI 主动读取 MEMORY.md 了解你的背景和偏好
|
|
|
+3. **持续更新**:OpenClaw 会定期根据对话更新记忆文件
|
|
|
+
|
|
|
+### 测试持久记忆
|
|
|
+
|
|
|
+给 Bot 发送:
|
|
|
+> "记住我喜欢用 Go 语言写后端服务"
|
|
|
+
|
|
|
+过一段时间再问:
|
|
|
+> "我之前告诉你我喜欢用什么语言?"
|
|
|
+
|
|
|
+如果配置正确,Bot 应该能回答出 **Go**。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 进阶玩法:记录系统优化(第9.5步,新增)
|
|
|
+
|
|
|
+在解决 compaction 卡死问题后,我意识到 OpenClaw 的会话记录管理还有很多优化空间。之前的经历是:会话文件在两天内膨胀到 1.4MB(603 条消息),导致系统卡死。为了防止类似问题再次发生,我设计并部署了一套**结构化的记录管理系统**。
|
|
|
+
|
|
|
+### 为什么需要记录系统优化
|
|
|
+
|
|
|
+| 问题 | 优化前 | 优化后 |
|
|
|
+|------|--------|--------|
|
|
|
+| 会话文件膨胀 | 1.4MB(603条消息) | 每日自动归档,单文件 < 100KB |
|
|
|
+| 数据管理 | 所有文件混在一起 | 结构化分类存储 |
|
|
|
+| 查找历史 | 翻找 JSONL 文件 | Markdown 摘要,一目了然 |
|
|
|
+| 数据备份 | 手动复制 | 自动归档 + 一键导出 |
|
|
|
+
|
|
|
+### 优化后的目录结构
|
|
|
+
|
|
|
+我在 `workspace` 下创建了完整的分类存储结构:
|
|
|
+
|
|
|
+```
|
|
|
+/root/.openclaw/workspace/
|
|
|
+├── memory/ # 记忆类数据
|
|
|
+│ ├── daily/ # 每日摘要 (YYYY-MM-DD.md)
|
|
|
+│ ├── weekly/ # 每周汇总
|
|
|
+│ └── archived/ # 长期归档
|
|
|
+├── records/ # 记录类数据
|
|
|
+│ ├── conversations/ # 对话记录 (按月归档)
|
|
|
+│ │ └── 2026-03/
|
|
|
+│ │ ├── 2026-03-03/ # 当日完整会话
|
|
|
+│ │ └── 2026-03-03-sessions.tar.gz
|
|
|
+│ ├── tasks/ # 任务记录
|
|
|
+│ │ ├── completed/ # 已完成任务
|
|
|
+│ │ └── failed/ # 失败任务
|
|
|
+│ ├── browser/ # 浏览器操作记录
|
|
|
+│ │ ├── screenshots/ # 网页截图
|
|
|
+│ │ └── page-dumps/ # 页面快照
|
|
|
+│ └── files/ # 文件操作日志
|
|
|
+├── outputs/ # 输出类数据
|
|
|
+│ ├── generated/ # AI 生成的文档
|
|
|
+│ ├── exports/ # 导出文件
|
|
|
+│ └── reports/ # 定时报告
|
|
|
+└── logs/ # 日志类
|
|
|
+ ├── system/ # 系统日志 (archive-YYYY-MM-DD.log)
|
|
|
+ ├── model/ # 模型调用记录
|
|
|
+ └── errors/ # 错误日志
|
|
|
+```
|
|
|
+
|
|
|
+### 自动归档脚本
|
|
|
+
|
|
|
+创建 `/root/.openclaw/workspace/archive-daily.sh`:
|
|
|
+
|
|
|
+```bash
|
|
|
+#!/bin/bash
|
|
|
+WORKSPACE="/root/.openclaw/workspace"
|
|
|
+SESSIONS_DIR="/home/node/.openclaw/agents/main/sessions"
|
|
|
+DATE=$(date +"%Y-%m-%d")
|
|
|
+MONTH=$(date +"%Y-%m")
|
|
|
+
|
|
|
+# 创建归档目录
|
|
|
+mkdir -p "$WORKSPACE/records/conversations/$MONTH/$DATE"
|
|
|
+mkdir -p "$WORKSPACE/memory/daily"
|
|
|
+
|
|
|
+# 归档会话文件
|
|
|
+if [ -d "$SESSIONS_DIR" ]; then
|
|
|
+ cp "$SESSIONS_DIR"/*.jsonl "$WORKSPACE/records/conversations/$MONTH/$DATE/" 2>/dev/null || true
|
|
|
+ SESSION_COUNT=$(ls -1 "$SESSIONS_DIR"/*.jsonl 2>/dev/null | wc -l)
|
|
|
+ SIZE=$(du -sb "$SESSIONS_DIR" 2>/dev/null | cut -f1)
|
|
|
+else
|
|
|
+ SESSION_COUNT=0
|
|
|
+ SIZE=0
|
|
|
+fi
|
|
|
+
|
|
|
+# 生成每日摘要 Markdown
|
|
|
+cat > "$WORKSPACE/memory/daily/${DATE}.md" << DAILYMD
|
|
|
+---
|
|
|
+date: ${DATE}
|
|
|
+type: daily-summary
|
|
|
+sessions_count: ${SESSION_COUNT}
|
|
|
+sessions_size_kb: $((${SIZE} / 1024))
|
|
|
+---
|
|
|
+
|
|
|
+# 📅 ${DATE} 对话摘要
|
|
|
+
|
|
|
+## 📊 今日统计
|
|
|
+- **日期**: ${DATE}
|
|
|
+- **星期**: $(date +%A)
|
|
|
+- **会话数**: ${SESSION_COUNT}
|
|
|
+- **数据大小**: $((${SIZE} / 1024)) KB
|
|
|
+
|
|
|
+## 🏷️ 重要标签
|
|
|
+-
|
|
|
+
|
|
|
+## 💡 今日收获
|
|
|
+-
|
|
|
+
|
|
|
+## 📌 待办事项
|
|
|
+- [ ]
|
|
|
+
|
|
|
+---
|
|
|
+DAILYMD
|
|
|
+
|
|
|
+# 记录归档日志
|
|
|
+echo "[$(date)] 归档完成: ${DATE}, ${SESSION_COUNT} 个会话" >> "$WORKSPACE/logs/system/archive-${DATE}.log"
|
|
|
+```
|
|
|
+
|
|
|
+赋予执行权限:
|
|
|
+
|
|
|
+```bash
|
|
|
+chmod +x /root/.openclaw/workspace/archive-daily.sh
|
|
|
+```
|
|
|
+
|
|
|
+### 配置定时任务
|
|
|
+
|
|
|
+添加每天 23:00 自动执行归档:
|
|
|
+
|
|
|
+```bash
|
|
|
+# 添加定时任务
|
|
|
+(crontab -l 2>/dev/null | grep -v archive-daily; echo "0 23 * * * /root/.openclaw/workspace/archive-daily.sh >> /root/.openclaw/workspace/logs/system/cron.log 2>&1") | crontab -
|
|
|
+
|
|
|
+# 查看已配置的定时任务
|
|
|
+crontab -l
|
|
|
+```
|
|
|
+
|
|
|
+### 快捷命令配置
|
|
|
+
|
|
|
+创建 `/root/.openclaw/.aliases.sh`,方便快速查看记录:
|
|
|
+
|
|
|
+```bash
|
|
|
+# 查看今日记录
|
|
|
+alias oc-today='cat /root/.openclaw/workspace/memory/daily/$(date +%Y-%m-%d).md 2>/dev/null || echo "今日记录不存在"'
|
|
|
+
|
|
|
+# 查看昨日记录
|
|
|
+alias oc-yesterday='cat /root/.openclaw/workspace/memory/daily/$(date -d yesterday +%Y-%m-%d 2>/dev/null || date -v-1d +%Y-%m-%d).md 2>/dev/null || echo "昨日记录不存在"'
|
|
|
+
|
|
|
+# 手动执行归档
|
|
|
+alias oc-archive='/root/.openclaw/workspace/archive-daily.sh'
|
|
|
+
|
|
|
+# 查看统计
|
|
|
+alias oc-stats='echo "=== OpenClaw 统计 ===" && echo "会话文件: $(ls -1 /home/node/.openclaw/agents/main/sessions/*.jsonl 2>/dev/null | wc -l)" && echo "每日摘要: $(ls -1 /root/.openclaw/workspace/memory/daily/*.md 2>/dev/null | wc -l)"'
|
|
|
+
|
|
|
+# 查看目录大小
|
|
|
+alias oc-size='du -sh /root/.openclaw/workspace/*/ 2>/dev/null | sort -h'
|
|
|
+```
|
|
|
+
|
|
|
+使用方法:
|
|
|
+
|
|
|
+```bash
|
|
|
+# 加载快捷命令
|
|
|
+source /root/.openclaw/.aliases.sh
|
|
|
+
|
|
|
+# 查看今日记录
|
|
|
+oc-today
|
|
|
+
|
|
|
+# 手动归档
|
|
|
+oc-archive
|
|
|
+
|
|
|
+# 查看统计
|
|
|
+oc-stats
|
|
|
+```
|
|
|
+
|
|
|
+### Docker 容器内配置
|
|
|
+
|
|
|
+为了让 OpenClaw Bot 也能执行归档,在 Docker 容器内创建归档脚本:
|
|
|
+
|
|
|
+```bash
|
|
|
+# 在容器内创建归档命令
|
|
|
+docker exec openclaw-openclaw-gateway-1 bash -c 'cat > /tmp/oc-archive.sh << "EOF"
|
|
|
+#!/bin/bash
|
|
|
+WORKSPACE="/home/node/.openclaw/workspace"
|
|
|
+SESSIONS="/home/node/.openclaw/agents/main/sessions"
|
|
|
+DATE=$(date +"%Y-%m-%d")
|
|
|
+MONTH=$(date +"%Y-%m")
|
|
|
+mkdir -p "$WORKSPACE/records/conversations/$MONTH/$DATE"
|
|
|
+COUNT=0
|
|
|
+if [ -d "$SESSIONS" ]; then
|
|
|
+ cp "$SESSIONS"/*.jsonl "$WORKSPACE/records/conversations/$MONTH/$DATE/" 2>/dev/null || true
|
|
|
+ COUNT=$(ls -1 "$SESSIONS"/*.jsonl 2>/dev/null | wc -l)
|
|
|
+fi
|
|
|
+cat > "$WORKSPACE/memory/daily/$DATE.md" << DAILY
|
|
|
+---
|
|
|
+date: $DATE
|
|
|
+type: daily-summary
|
|
|
+sessions_count: $COUNT
|
|
|
+---
|
|
|
+
|
|
|
+# 📅 $DATE 对话摘要
|
|
|
+
|
|
|
+## 📊 统计
|
|
|
+- 会话数: $COUNT
|
|
|
+
|
|
|
+## 🏷️ 标签
|
|
|
+-
|
|
|
+
|
|
|
+## 💡 收获
|
|
|
+-
|
|
|
+DAILY
|
|
|
+echo "✅ 归档完成: $DATE, $COUNT 个会话"
|
|
|
+EOF
|
|
|
+chmod +x /tmp/oc-archive.sh'
|
|
|
+```
|
|
|
+
|
|
|
+### Telegram Bot 使用
|
|
|
+
|
|
|
+配置完成后,你可以直接在 Telegram 中对 Bot 发送:
|
|
|
+
|
|
|
+| 指令 | 功能 |
|
|
|
+|------|------|
|
|
|
+| "归档今天的对话" | 手动触发归档 |
|
|
|
+| "查看今天的记录" | 显示今日摘要 |
|
|
|
+| "查看昨天的记录" | 显示昨日摘要 |
|
|
|
+| "统计我的对话数量" | 显示统计报告 |
|
|
|
+
|
|
|
+### 每日摘要示例
|
|
|
+
|
|
|
+生成的 Markdown 文件 (`memory/daily/2026-03-03.md`):
|
|
|
+
|
|
|
+```markdown
|
|
|
+---
|
|
|
+date: 2026-03-03
|
|
|
+type: daily-summary
|
|
|
+sessions_count: 5
|
|
|
+sessions_size_kb: 45
|
|
|
+---
|
|
|
+
|
|
|
+# 📅 2026-03-03 对话摘要
|
|
|
+
|
|
|
+## 📊 今日统计
|
|
|
+- **日期**: 2026-03-03
|
|
|
+- **星期**: Tuesday
|
|
|
+- **会话数**: 5
|
|
|
+- **数据大小**: 45 KB
|
|
|
+
|
|
|
+## 🏷️ 重要标签
|
|
|
+- OpenClaw 配置
|
|
|
+- 技能开发
|
|
|
+
|
|
|
+## 💡 今日收获
|
|
|
+- 配置了自动归档系统
|
|
|
+- 解决了会话文件膨胀问题
|
|
|
+
|
|
|
+## 📌 待办事项
|
|
|
+- [ ] 测试归档功能
|
|
|
+- [ ] 配置 Web 画廊
|
|
|
+```
|
|
|
+
|
|
|
+这种结构化的记录管理方式,让你可以:
|
|
|
+1. **快速回顾** - 每天打开 Markdown 文件即可看到当日概况
|
|
|
+2. **防止膨胀** - 自动归档避免会话文件无限增长
|
|
|
+3. **便于导出** - 重要记录可以轻松导出分享
|
|
|
+4. **Telegram 管理** - 直接通过 Bot 指令管理记录
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 进阶玩法:自定义 Skill(第10步)
|
|
|
+
|
|
|
+OpenClaw 的 Skill 系统让你可以扩展 AI 的能力。我把自己的 Hexo 博客做成了 Skill,让 Bot 可以直接帮我创建博客文章。
|
|
|
+
|
|
|
+### 我的 Hexo 博客 Skill
|
|
|
+
|
|
|
+#### 1. 创建脚本
|
|
|
+
|
|
|
+在服务器上创建文章生成脚本 `/opt/hexo-blog/create-post.sh`:
|
|
|
+
|
|
|
+```bash
|
|
|
+#!/bin/bash
|
|
|
+# Hexo Blog Post Creator
|
|
|
+
|
|
|
+BLOG_DIR="/opt/hexo-blog"
|
|
|
+POSTS_DIR="$BLOG_DIR/source/_posts"
|
|
|
+
|
|
|
+# 参数
|
|
|
+TITLE="${1:-新建文章}"
|
|
|
+CATEGORY="${2:-随笔}"
|
|
|
+TAGS="${3:-日常}"
|
|
|
+DATE=$(date +"%Y-%m-%d %H:%M:%S")
|
|
|
+FILENAME=$(echo "$TITLE" | sed 's/ /-/g' | tr '[:upper:]' '[:lower:]')-$(date +"%Y%m%d").md
|
|
|
+
|
|
|
+# 创建目录
|
|
|
+mkdir -p "$POSTS_DIR"
|
|
|
+
|
|
|
+# 创建文章
|
|
|
+cat > "$POSTS_DIR/$FILENAME" << EOF
|
|
|
+---
|
|
|
+title: $TITLE
|
|
|
+author: Gamehu
|
|
|
+date: $DATE
|
|
|
+tags:
|
|
|
+EOF
|
|
|
+
|
|
|
+# 添加标签
|
|
|
+IFS=',' read -ra TAG_ARRAY <<< "$TAGS"
|
|
|
+for tag in "${TAG_ARRAY[@]}"; do
|
|
|
+ echo " - $(echo $tag | xargs)" >> "$POSTS_DIR/$FILENAME"
|
|
|
+done
|
|
|
+
|
|
|
+# 添加分类和正文
|
|
|
+cat >> "$POSTS_DIR/$FILENAME" << EOF
|
|
|
+categories:
|
|
|
+ - $CATEGORY
|
|
|
+---
|
|
|
+
|
|
|
+## 写在前面
|
|
|
+
|
|
|
+$TITLE
|
|
|
+
|
|
|
+<!-- more -->
|
|
|
+
|
|
|
+## 正文
|
|
|
+
|
|
|
+开始写作...
|
|
|
+
|
|
|
+---
|
|
|
+EOF
|
|
|
+
|
|
|
+echo "✅ 文章创建成功: $POSTS_DIR/$FILENAME"
|
|
|
+```
|
|
|
+
|
|
|
+赋予执行权限:
|
|
|
+
|
|
|
+```bash
|
|
|
+chmod +x /opt/hexo-blog/create-post.sh
|
|
|
+```
|
|
|
+
|
|
|
+#### 2. 创建 Skill 文件
|
|
|
+
|
|
|
+OpenClaw 使用 `SKILL.md` 文件(不是 YAML),创建 `~/.openclaw/skills/hexo-blog/SKILL.md`:
|
|
|
+
|
|
|
+```markdown
|
|
|
+---
|
|
|
+name: hexo-blog
|
|
|
+description: Create and manage Hexo blog posts via shell script
|
|
|
+---
|
|
|
+
|
|
|
+# Hexo Blog Skill
|
|
|
+
|
|
|
+Create new blog posts with proper front matter for Hexo.
|
|
|
+
|
|
|
+## Usage
|
|
|
+
|
|
|
+Ask me to create a blog post:
|
|
|
+- "帮我创建一篇博客文章,标题是《XXX》,分类是技术,标签是 OpenClaw,AI"
|
|
|
+- "写一篇新文章,关于 Docker 使用心得"
|
|
|
+
|
|
|
+## Tools
|
|
|
+
|
|
|
+This skill uses the `shell` tool to execute `/opt/hexo-blog/create-post.sh`.
|
|
|
+
|
|
|
+## Example
|
|
|
+
|
|
|
+```bash
|
|
|
+/opt/hexo-blog/create-post.sh "文章标题" "分类" "标签1,标签2"
|
|
|
+```
|
|
|
+```
|
|
|
+
|
|
|
+#### 3. 重启 OpenClaw 加载 Skill
|
|
|
+
|
|
|
+```bash
|
|
|
+docker restart openclaw-openclaw-gateway-1
|
|
|
+```
|
|
|
+
|
|
|
+验证 Skill 是否加载:
|
|
|
+
|
|
|
+```bash
|
|
|
+openclaw skills list
|
|
|
+# 应该显示: ✓ ready │ 📦 hexo-blog │ Create and manage Hexo blog posts...
|
|
|
+```
|
|
|
+
|
|
|
+#### 3. 实际使用
|
|
|
+
|
|
|
+在 **@gamehu_kb_bot** 里直接说:
|
|
|
+
|
|
|
+> "帮我创建一篇博客文章,标题是《OpenClaw 使用心得》,分类是工具,标签是 OpenClaw,AI"
|
|
|
+
|
|
|
+Bot 会自动:
|
|
|
+1. 生成文件名 `openclaw-shi-yong-xin-de-20260302.md`
|
|
|
+2. 创建带完整 Front Matter 的 Markdown 文件
|
|
|
+3. 返回文件路径
|
|
|
+
|
|
|
+### Skill 核心概念
|
|
|
+
|
|
|
+| 组件 | 作用 | 示例 |
|
|
|
+|------|------|------|
|
|
|
+| **Script** | 执行实际任务 | Shell/Python 脚本 |
|
|
|
+| **SKILL.md** | Skill 定义和说明 | Markdown 文件(带 YAML frontmatter) |
|
|
|
+| **Directory** | Skill 存放位置 | `~/.openclaw/skills/<skill-name>/` |
|
|
|
+
|
|
|
+### 更多 Skill 想法
|
|
|
+
|
|
|
+- **Git Helper**: 自动提交、查看状态、创建分支
|
|
|
+- **Docker Manager**: 查看容器日志、重启服务
|
|
|
+- **File Organizer**: 整理下载文件夹、重命名文件
|
|
|
+- **Daily Reporter**: 生成每日工作总结
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 进阶玩法:浏览器控制(第12步)
|
|
|
+
|
|
|
+OpenClaw 内置了浏览器控制功能,让 AI 能够**操作真实浏览器**执行网页任务,比如搜索信息、填写表单、抓取数据等。
|
|
|
+
|
|
|
+<span class="warning">🚨 坑位 14:Docker 镜像默认不包含浏览器</span>
|
|
|
+
|
|
|
+### 问题
|
|
|
+
|
|
|
+Docker 部署后尝试使用浏览器功能时,报错:
|
|
|
+```
|
|
|
+[tools] browser failed: Error: No supported browser found
|
|
|
+(Chrome/Brave/Edge/Chromium on macOS, Linux, or Windows).
|
|
|
+```
|
|
|
+
|
|
|
+### 原因
|
|
|
+
|
|
|
+默认的 `Dockerfile` 不会安装 Chromium/Playwright 浏览器,需要通过 `--build-arg OPENCLAW_INSTALL_BROWSER=1` 参数构建带浏览器的镜像。
|
|
|
+
|
|
|
+### 解决方案:重新构建带浏览器的镜像
|
|
|
+
|
|
|
+#### 1. 停止当前服务
|
|
|
+
|
|
|
+```bash
|
|
|
+cd /opt/openclaw
|
|
|
+docker compose down
|
|
|
+```
|
|
|
+
|
|
|
+#### 2. 构建带浏览器的新镜像
|
|
|
+
|
|
|
+```bash
|
|
|
+# 构建时间约 15-30 分钟,增加约 300MB
|
|
|
+docker build -t openclaw:local-browser -f Dockerfile \
|
|
|
+ --build-arg OPENCLAW_INSTALL_BROWSER=1 \
|
|
|
+ --build-arg OPENCLAW_DOCKER_APT_PACKAGES="chromium xvfb" \
|
|
|
+ .
|
|
|
+```
|
|
|
+
|
|
|
+#### 3. 修改环境变量使用新镜像
|
|
|
+
|
|
|
+编辑 `.env` 文件:
|
|
|
+```bash
|
|
|
+# 修改前
|
|
|
+OPENCLAW_IMAGE=openclaw:local
|
|
|
+
|
|
|
+# 修改后
|
|
|
+OPENCLAW_IMAGE=openclaw:local-browser
|
|
|
+```
|
|
|
+
|
|
|
+#### 4. 启动服务
|
|
|
+
|
|
|
+```bash
|
|
|
+docker compose up -d
|
|
|
+```
|
|
|
+
|
|
|
+#### 5. 验证浏览器安装
|
|
|
+
|
|
|
+```bash
|
|
|
+# 进入容器检查
|
|
|
+docker exec openclaw-openclaw-gateway-1 \
|
|
|
+ ls -la /home/node/.cache/ms-playwright/
|
|
|
+
|
|
|
+# 应该看到:
|
|
|
+# chromium-1208/
|
|
|
+# chromium_headless_shell-1208/
|
|
|
+# ffmpeg-1011/
|
|
|
+```
|
|
|
+
|
|
|
+### 浏览器控制功能
|
|
|
+
|
|
|
+| 功能 | 说明 |
|
|
|
+|------|------|
|
|
|
+| **网页浏览** | 访问指定 URL,获取页面内容 |
|
|
|
+| **表单填写** | 自动填写并提交网页表单 |
|
|
|
+| **信息搜索** | 在搜索引擎或电商网站搜索 |
|
|
|
+| **数据抓取** | 提取网页中的结构化数据 |
|
|
|
+| **截图保存** | 截取网页画面 |
|
|
|
+
|
|
|
+### 使用示例
|
|
|
+
|
|
|
+在 Telegram 中直接发送以下指令:
|
|
|
+
|
|
|
+**搜索信息**:
|
|
|
+> "打开浏览器,访问 GitHub,搜索 'openclaw',告诉我前 3 个结果"
|
|
|
+
|
|
|
+**商品比价**:
|
|
|
+> "帮我在京东上搜索 '机械键盘',找到评分最高的 3 个产品,记录价格"
|
|
|
+
|
|
|
+**数据抓取**:
|
|
|
+> "访问 https://news.ycombinator.com/,提取首页前 10 条新闻的标题和链接"
|
|
|
+
|
|
|
+### 浏览器控制原理
|
|
|
+
|
|
|
+```
|
|
|
+用户指令 → OpenClaw Agent → 浏览器控制服务 → 无头 Chrome → 网页操作 → 结果返回
|
|
|
+```
|
|
|
+
|
|
|
+浏览器控制服务默认监听:`http://127.0.0.1:18791/`
|
|
|
+
|
|
|
+### 注意事项
|
|
|
+
|
|
|
+1. **无头模式**:Docker 部署默认使用 headless 模式(无界面),适合服务器环境
|
|
|
+2. **访问限制**:受限于服务器网络,无法访问需要登录的页面(除非提供 Cookie)
|
|
|
+3. **执行时间**:复杂页面加载可能需要 10-30 秒
|
|
|
+4. **安全提醒**:避免让 Bot 访问敏感网站或输入真实账号密码
|
|
|
+
|
|
|
+### 实践任务
|
|
|
+
|
|
|
+尝试让 Bot 完成以下任务:
|
|
|
+- ✅ 信息收集:从某个网站抓取数据并整理
|
|
|
+- ✅ 表单填写:自动填写一个在线表单
|
|
|
+- ✅ 价格比较:在多个网站比较同一商品的价格
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 进阶玩法:多 Bot 配置(第11步)
|
|
|
+
|
|
|
+OpenClaw 支持配置**多个 Telegram Bot**,每个 Bot 可以绑定不同的 Agent,实现分工协作。
|
|
|
+注意:仅配置 `channels.telegram.accounts` 还不够,想要真正隔离上下文,必须再加 `agents.list + bindings`。
|
|
|
+
|
|
|
+### 我的多 Bot 架构
|
|
|
+
|
|
|
+| Bot | 用户名 | 职责 | 对应 Agent |
|
|
|
+|-----|--------|------|-----------|
|
|
|
+| 主助手 | @GameHuOpenclaw_bot | 通用对话、代码、写作 | main |
|
|
|
+| 新闻助手 | @gamehu_news_bot | 科技新闻、每日简报 | news |
|
|
|
+| 成长助手 | @gamehu_growth_bot | 学习计划、习惯追踪 | growth |
|
|
|
+| 知识库助手 | @gamehu_kb_bot | 文档查询、笔记整理 | kb |
|
|
|
+
|
|
|
+### 配置步骤
|
|
|
+
|
|
|
+#### 1. 在 @BotFather 创建多个 Bot
|
|
|
+
|
|
|
+每个 Bot 都需要独立的 Token:
|
|
|
+
|
|
|
+```
|
|
|
+/main_bot - 主助手
|
|
|
+/news_bot - 新闻助手
|
|
|
+/growth_bot - 成长助手
|
|
|
+/kb_bot - 知识库助手
|
|
|
+```
|
|
|
+
|
|
|
+#### 2. 配置多账号
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "channels": {
|
|
|
+ "telegram": {
|
|
|
+ "enabled": true,
|
|
|
+ "accounts": {
|
|
|
+ "main": {
|
|
|
+ "botToken": "YOUR_MAIN_BOT_TOKEN",
|
|
|
+ "allowFrom": ["YOUR_TELEGRAM_USER_ID"]
|
|
|
+ },
|
|
|
+ "news": {
|
|
|
+ "botToken": "YOUR_NEWS_BOT_TOKEN",
|
|
|
+ "allowFrom": ["YOUR_TELEGRAM_USER_ID"]
|
|
|
+ },
|
|
|
+ "growth": {
|
|
|
+ "botToken": "YOUR_GROWTH_BOT_TOKEN",
|
|
|
+ "allowFrom": ["YOUR_TELEGRAM_USER_ID"]
|
|
|
+ },
|
|
|
+ "kb": {
|
|
|
+ "botToken": "YOUR_KB_BOT_TOKEN",
|
|
|
+ "allowFrom": ["YOUR_TELEGRAM_USER_ID"]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 3. 增加 Agent 路由绑定(关键)
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "agents": {
|
|
|
+ "list": [
|
|
|
+ { "id": "main", "default": true, "workspace": "/home/node/.openclaw/workspace" },
|
|
|
+ { "id": "news", "workspace": "/home/node/.openclaw/workspace-news" },
|
|
|
+ { "id": "growth", "workspace": "/home/node/.openclaw/workspace-growth" },
|
|
|
+ { "id": "kb", "workspace": "/home/node/.openclaw/workspace-kb" }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "bindings": [
|
|
|
+ { "agentId": "main", "match": { "channel": "telegram", "accountId": "main" } },
|
|
|
+ { "agentId": "news", "match": { "channel": "telegram", "accountId": "news" } },
|
|
|
+ { "agentId": "growth", "match": { "channel": "telegram", "accountId": "growth" } },
|
|
|
+ { "agentId": "kb", "match": { "channel": "telegram", "accountId": "kb" } }
|
|
|
+ ]
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> ⚠️ **`workspace` 字段必须显式指定**:每个 agent 需要独立的 workspace 路径,否则多个 agent 共享同一个 workspace,记忆和配置会互相干扰。
|
|
|
+
|
|
|
+这样每个 bot 会落到不同 agent,会话文件分目录保存,记忆文件也完全隔离。
|
|
|
+
|
|
|
+#### 4. 为每个 Agent 创建独立 Workspace
|
|
|
+
|
|
|
+每个 agent 对应一个独立目录,在服务器上创建:
|
|
|
+
|
|
|
+```bash
|
|
|
+mkdir -p /root/.openclaw/workspace-news
|
|
|
+mkdir -p /root/.openclaw/workspace-growth
|
|
|
+mkdir -p /root/.openclaw/workspace-kb
|
|
|
+```
|
|
|
+
|
|
|
+每个目录下的结构:
|
|
|
+
|
|
|
+```bash
|
|
|
+workspace-news/
|
|
|
+├── SOUL.md # Agent 的身份定义
|
|
|
+├── MEMORY.md # 长期记忆
|
|
|
+├── USER.md # 用户信息
|
|
|
+├── AGENTS.md # Agent 行为规范
|
|
|
+└── memory/ # 每日记忆文件
|
|
|
+```
|
|
|
+
|
|
|
+每个 `AGENT.md` 定义该 Bot 的专业领域和行为:
|
|
|
+
|
|
|
+```markdown
|
|
|
+# News Agent
|
|
|
+
|
|
|
+## Role
|
|
|
+你是一个科技新闻助手,专注于提供最新、最有价值的科技资讯。
|
|
|
+
|
|
|
+## Capabilities
|
|
|
+- 追踪科技行业动态
|
|
|
+- 总结技术文章要点
|
|
|
+- 提供每日新闻简报
|
|
|
+
|
|
|
+## Style
|
|
|
+- 简洁明了,重点突出
|
|
|
+- 提供信息来源链接
|
|
|
+- 主动推送重要消息
|
|
|
+```
|
|
|
+
|
|
|
+#### 4. 重启服务
|
|
|
+
|
|
|
+```bash
|
|
|
+docker compose restart
|
|
|
+```
|
|
|
+
|
|
|
+查看日志确认所有 Bot 启动:
|
|
|
+
|
|
|
+```
|
|
|
+[telegram] [main] starting provider (@GameHuOpenclaw_bot)
|
|
|
+[telegram] [news] starting provider (@gamehu_news_bot)
|
|
|
+[telegram] [growth] starting provider (@gamehu_growth_bot)
|
|
|
+[telegram] [kb] starting provider (@gamehu_kb_bot)
|
|
|
+```
|
|
|
+
|
|
|
+### 实际使用效果
|
|
|
+
|
|
|
+- **上下文隔离**:在 @gamehu_growth_bot 聊学习计划,切到 @gamehu_news_bot 问新闻,再回到 growth Bot,它还记得刚才的学习话题
|
|
|
+- **专业化分工**:每个 Bot 专注于自己的领域,回复质量更高
|
|
|
+- **并行对话**:可以同时和多个 Bot 对话,互不干扰
|
|
|
+
|
|
|
+<span class="warning">⚠️ 注意事项</span>
|
|
|
+
|
|
|
+- 多账号配置时,**不要**在顶层设置 `botToken`,全部放在 `accounts` 下
|
|
|
+- 每个 `accountId`(如 main、news、growth、kb)必须是唯一的
|
|
|
+- 账号名不要用 `default`,会和系统默认账号冲突
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 进阶玩法:定时任务推送到指定 Bot(第11.5步)
|
|
|
+
|
|
|
+配置好多 Bot 之后,你可能会发现一个问题:**OpenClaw 里设置的定时任务(cron job),推送结果全都跑到了 main bot,而不是对应的 bot**。
|
|
|
+
|
|
|
+<span class="warning">🚨 坑位 17:定时任务 delivery 缺少 accountId</span>
|
|
|
+
|
|
|
+### 问题现象
|
|
|
+
|
|
|
+在 OpenClaw Web UI 里配了新闻推送任务,时间一到,消息却出现在了 @GameHuOpenclaw_bot(main bot),而不是 @gamehu_news_bot。
|
|
|
+
|
|
|
+### 根本原因
|
|
|
+
|
|
|
+OpenClaw 的定时任务存储在 `~/.openclaw/cron/jobs.json`,每个任务的 `delivery` 字段控制推送目标。**如果只写了 `to`(用户 ID),没有写 `accountId`,OpenClaw 不知道用哪个 bot 账户推送,默认走 main。**
|
|
|
+
|
|
|
+另外,`to` 只负责“推给谁”(用户 / 群 / 频道),`accountId` 负责“用哪个 bot 发”。这两个字段职责不同,缺一不可。
|
|
|
+
|
|
|
+**有问题的配置:**
|
|
|
+
|
|
|
+```json
|
|
|
+"delivery": {
|
|
|
+ "mode": "announce",
|
|
|
+ "channel": "telegram",
|
|
|
+ "to": "YOUR_USER_ID"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 解决方案
|
|
|
+
|
|
|
+在每个 job 的 `delivery` 中加上 `accountId`,同时在 job 顶层加上 `agentId`。建议把执行超时提到 120 秒(字段 `timeoutSeconds`):
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "id": "xxx",
|
|
|
+ "agentId": "news",
|
|
|
+ "name": "每日新闻推送",
|
|
|
+ "timeoutSeconds": 120,
|
|
|
+ "payload": {
|
|
|
+ "kind": "agentTurn",
|
|
|
+ "message": "执行新闻脚本并发送结果给用户"
|
|
|
+ },
|
|
|
+ "delivery": {
|
|
|
+ "mode": "announce",
|
|
|
+ "channel": "telegram",
|
|
|
+ "accountId": "news",
|
|
|
+ "to": "YOUR_USER_ID"
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 推送目标的两种正确姿势
|
|
|
+
|
|
|
+#### 方案 A(推荐):同一个用户,按不同 Bot 身份推送
|
|
|
+
|
|
|
+这种方式最适合你当前“4 个 Bot 各司其职”的场景。`to` 全部写你的用户 ID,`accountId` 分别写 `main/news/growth/kb`,消息会显示来自对应 bot。
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "agentId": "news",
|
|
|
+ "timeoutSeconds": 120,
|
|
|
+ "delivery": {
|
|
|
+ "mode": "announce",
|
|
|
+ "channel": "telegram",
|
|
|
+ "accountId": "news",
|
|
|
+ "to": "YOUR_USER_ID"
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 方案 B:推送到群 / 频道 / 话题
|
|
|
+
|
|
|
+如果要发到频道,不要填 bot 用户名(如 `@gamehu_news_bot`),而是填频道 chat id(通常是 `-100...`)。并确保对应 bot 已加入目标群/频道且有发言权限。
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "agentId": "news",
|
|
|
+ "timeoutSeconds": 120,
|
|
|
+ "delivery": {
|
|
|
+ "mode": "announce",
|
|
|
+ "channel": "telegram",
|
|
|
+ "accountId": "news",
|
|
|
+ "to": "-1001234567890"
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 各任务对应关系
|
|
|
+
|
|
|
+| 任务 | agentId | accountId | 推送到 |
|
|
|
+|------|---------|-----------|--------|
|
|
|
+| 每日新闻推送 | news | news | @gamehu_news_bot |
|
|
|
+| 每日成长提醒 | growth | growth | @gamehu_growth_bot |
|
|
|
+| 每周知识库总结 | kb | kb | @gamehu_kb_bot |
|
|
|
+| 其他通用任务 | main | main | @GameHuOpenclaw_bot |
|
|
|
+
|
|
|
+修改完 `jobs.json` 后重启服务即可生效:
|
|
|
+
|
|
|
+```bash
|
|
|
+cd /opt/openclaw && docker compose restart
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 进阶玩法:接入 Step-3.5-Flash,并支持会话级切换(第11.6步)
|
|
|
+
|
|
|
+最近我把底层模型又补了一档:`Step-3.5-Flash`。但这里有个非常容易搞混的点,我一开始也踩了坑:
|
|
|
+
|
|
|
+<span class="warning">🚨 坑位 18:想要“随时切模型”,不等于要改全局默认模型</span>
|
|
|
+
|
|
|
+如果你直接把 `agents.defaults.model.primary` 全局切到 Step,看起来省事,实际上会把别的会话、别的 Bot,甚至定时任务一起带偏。
|
|
|
+更稳的做法是:
|
|
|
+
|
|
|
+- **全局默认模型继续保持不变**,我这里还是 `bailian/kimi-k2.5`
|
|
|
+- 把 `step/step-3.5-flash` 注册成一个**可选 provider**
|
|
|
+- 需要的时候,直接在 **当前 Telegram 会话** 里发送 `/model ...` 切换
|
|
|
+
|
|
|
+### Step provider 配置示例
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "models": {
|
|
|
+ "mode": "merge",
|
|
|
+ "providers": {
|
|
|
+ "bailian": {
|
|
|
+ "baseUrl": "https://coding.dashscope.aliyuncs.com/v1",
|
|
|
+ "apiKey": "YOUR_BAILIAN_API_KEY",
|
|
|
+ "api": "openai-completions",
|
|
|
+ "models": [
|
|
|
+ {
|
|
|
+ "id": "kimi-k2.5",
|
|
|
+ "name": "kimi-k2.5",
|
|
|
+ "contextWindow": 256000,
|
|
|
+ "maxTokens": 8192
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "kimi": {
|
|
|
+ "baseUrl": "https://api.moonshot.cn/v1",
|
|
|
+ "apiKey": "YOUR_KIMI_API_KEY",
|
|
|
+ "api": "openai-completions",
|
|
|
+ "models": [
|
|
|
+ {
|
|
|
+ "id": "moonshot-v1-128k",
|
|
|
+ "name": "moonshot-v1-128k",
|
|
|
+ "contextWindow": 131072,
|
|
|
+ "maxTokens": 8192
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "step": {
|
|
|
+ "baseUrl": "https://api.stepfun.com/v1",
|
|
|
+ "apiKey": "YOUR_STEP_API_KEY",
|
|
|
+ "api": "openai-completions",
|
|
|
+ "models": [
|
|
|
+ {
|
|
|
+ "id": "step-3.5-flash",
|
|
|
+ "name": "Step 3.5 Flash",
|
|
|
+ "contextWindow": 256000,
|
|
|
+ "maxTokens": 8192
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "agents": {
|
|
|
+ "defaults": {
|
|
|
+ "model": {
|
|
|
+ "primary": "bailian/kimi-k2.5"
|
|
|
+ },
|
|
|
+ "contextTokens": 131072
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 为什么我把 `contextTokens` 调到 131072
|
|
|
+
|
|
|
+这不是说 `kimi-k2.5` 或 `step-3.5-flash` 只能吃 128k,而是为了兼容我现在保留的第三档模型 `moonshot-v1-128k`。
|
|
|
+
|
|
|
+如果你想做到:
|
|
|
+- 默认走百炼
|
|
|
+- 需要时切 Step
|
|
|
+- 偶尔还能切回 Moonshot 做速度/成本对比
|
|
|
+
|
|
|
+那最稳的双档/三档基线,就是把 `contextTokens` 先压在 **131072**。这样:
|
|
|
+
|
|
|
+- `bailian <-> step` 切换时,几乎不会因为窗口变化引发额外压缩
|
|
|
+- 切到 `moonshot-v1-128k` 时,也不会立刻超限
|
|
|
+
|
|
|
+### 当前会话切换命令
|
|
|
+
|
|
|
+直接在 Telegram 里发:
|
|
|
+
|
|
|
+```text
|
|
|
+/models
|
|
|
+/models step
|
|
|
+/model status
|
|
|
+/model step
|
|
|
+/model bailian/kimi-k2.5
|
|
|
+/model kimi/moonshot-v1-128k
|
|
|
+```
|
|
|
+
|
|
|
+这里要强调 3 个边界:
|
|
|
+
|
|
|
+1. **只影响当前会话**
|
|
|
+2. **不会清空 SOUL.md / MEMORY.md / USER.md / AGENTS.md**
|
|
|
+3. **不会影响 cron 定时任务**
|
|
|
+
|
|
|
+也就是说,这种切换本质上是“会话级模型覆盖”,不是“全局改配置”。
|
|
|
+
|
|
|
+### 切模型会不会丢上下文
|
|
|
+
|
|
|
+长期记忆不会丢,工作区画像也不会丢。真正会受影响的是**短期上下文压缩**:
|
|
|
+
|
|
|
+- 从 `bailian/kimi-k2.5` 切到 `step/step-3.5-flash`,因为两边都是大窗口,风险很低
|
|
|
+- 从 `bailian` 或 `step` 切到 `moonshot-v1-128k`,因为窗口更小,下一轮可能触发更激进的 compaction
|
|
|
+
|
|
|
+所以我现在的原则很简单:
|
|
|
+
|
|
|
+- 平时默认:`bailian/kimi-k2.5`
|
|
|
+- 需要测试 Step:`/model step`
|
|
|
+- 需要切回稳定默认:`/model bailian/kimi-k2.5`
|
|
|
+- 需要做小窗口对比:`/model kimi/moonshot-v1-128k`
|
|
|
+
|
|
|
+> ⚠️ 如果你想支持“切换模型 step”这种中文自然语言,而不是 `/model step`,那是另外一层 parser 改造,不是 OpenClaw 开箱即用能力。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 完整配置文件参考
|
|
|
+
|
|
|
+**openclaw.json**(多 Bot 生产版本,已脱敏,包含 compaction 修复):
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "gateway": {
|
|
|
+ "port": 18789,
|
|
|
+ "mode": "local",
|
|
|
+ "controlUi": {
|
|
|
+ "allowedOrigins": ["http://localhost:18789", "http://127.0.0.1:18789"]
|
|
|
+ },
|
|
|
+ "auth": {
|
|
|
+ "token": "your-secure-token-here"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "models": {
|
|
|
+ "mode": "merge",
|
|
|
+ "providers": {
|
|
|
+ "bailian": {
|
|
|
+ "baseUrl": "https://coding.dashscope.aliyuncs.com/v1",
|
|
|
+ "apiKey": "YOUR_BAILIAN_API_KEY",
|
|
|
+ "api": "openai-completions",
|
|
|
+ "models": [
|
|
|
+ {
|
|
|
+ "id": "kimi-k2.5",
|
|
|
+ "name": "kimi-k2.5",
|
|
|
+ "reasoning": false,
|
|
|
+ "input": ["text", "image"],
|
|
|
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
|
|
|
+ "contextWindow": 256000,
|
|
|
+ "maxTokens": 8192
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "kimi": {
|
|
|
+ "baseUrl": "https://api.moonshot.cn/v1",
|
|
|
+ "apiKey": "YOUR_KIMI_API_KEY",
|
|
|
+ "api": "openai-completions",
|
|
|
+ "models": [
|
|
|
+ {
|
|
|
+ "id": "moonshot-v1-128k",
|
|
|
+ "name": "moonshot-v1-128k",
|
|
|
+ "reasoning": false,
|
|
|
+ "input": ["text", "image"],
|
|
|
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
|
|
|
+ "contextWindow": 131072,
|
|
|
+ "maxTokens": 8192
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "step": {
|
|
|
+ "baseUrl": "https://api.stepfun.com/v1",
|
|
|
+ "apiKey": "YOUR_STEP_API_KEY",
|
|
|
+ "api": "openai-completions",
|
|
|
+ "models": [
|
|
|
+ {
|
|
|
+ "id": "step-3.5-flash",
|
|
|
+ "name": "Step 3.5 Flash",
|
|
|
+ "reasoning": false,
|
|
|
+ "input": ["text", "image"],
|
|
|
+ "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
|
|
|
+ "contextWindow": 256000,
|
|
|
+ "maxTokens": 8192
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "agents": {
|
|
|
+ "defaults": {
|
|
|
+ "model": {
|
|
|
+ "primary": "bailian/kimi-k2.5"
|
|
|
+ },
|
|
|
+ "contextTokens": 131072,
|
|
|
+ "compaction": {
|
|
|
+ "mode": "safeguard",
|
|
|
+ "reserveTokensFloor": 24000,
|
|
|
+ "identifierPolicy": "strict",
|
|
|
+ "memoryFlush": {
|
|
|
+ "enabled": true,
|
|
|
+ "softThresholdTokens": 6000
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "list": [
|
|
|
+ { "id": "main", "default": true },
|
|
|
+ { "id": "news" },
|
|
|
+ { "id": "growth" },
|
|
|
+ { "id": "kb" }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "bindings": [
|
|
|
+ { "agentId": "main", "match": { "channel": "telegram", "accountId": "main" } },
|
|
|
+ { "agentId": "news", "match": { "channel": "telegram", "accountId": "news" } },
|
|
|
+ { "agentId": "growth", "match": { "channel": "telegram", "accountId": "growth" } },
|
|
|
+ { "agentId": "kb", "match": { "channel": "telegram", "accountId": "kb" } }
|
|
|
+ ],
|
|
|
+ "session": {
|
|
|
+ "scope": "per-sender",
|
|
|
+ "reset": {
|
|
|
+ "mode": "idle",
|
|
|
+ "idleMinutes": 30
|
|
|
+ },
|
|
|
+ "maintenance": {
|
|
|
+ "mode": "enforce",
|
|
|
+ "pruneAfter": "7d",
|
|
|
+ "maxEntries": 120
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "channels": {
|
|
|
+ "telegram": {
|
|
|
+ "enabled": true,
|
|
|
+ "dmPolicy": "pairing",
|
|
|
+ "groupPolicy": "allowlist",
|
|
|
+ "historyLimit": 30,
|
|
|
+ "accounts": {
|
|
|
+ "main": {
|
|
|
+ "botToken": "YOUR_MAIN_BOT_TOKEN",
|
|
|
+ "allowFrom": ["YOUR_TELEGRAM_USER_ID"],
|
|
|
+ "dmPolicy": "pairing",
|
|
|
+ "groupPolicy": "allowlist",
|
|
|
+ "streaming": "off"
|
|
|
+ },
|
|
|
+ "news": {
|
|
|
+ "botToken": "YOUR_NEWS_BOT_TOKEN",
|
|
|
+ "allowFrom": ["YOUR_TELEGRAM_USER_ID"],
|
|
|
+ "dmPolicy": "pairing",
|
|
|
+ "groupPolicy": "allowlist",
|
|
|
+ "streaming": "off"
|
|
|
+ },
|
|
|
+ "growth": {
|
|
|
+ "botToken": "YOUR_GROWTH_BOT_TOKEN",
|
|
|
+ "allowFrom": ["YOUR_TELEGRAM_USER_ID"],
|
|
|
+ "dmPolicy": "pairing",
|
|
|
+ "groupPolicy": "allowlist",
|
|
|
+ "streaming": "off"
|
|
|
+ },
|
|
|
+ "kb": {
|
|
|
+ "botToken": "YOUR_KB_BOT_TOKEN",
|
|
|
+ "allowFrom": ["YOUR_TELEGRAM_USER_ID"],
|
|
|
+ "dmPolicy": "pairing",
|
|
|
+ "groupPolicy": "allowlist",
|
|
|
+ "streaming": "off"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> ⚠️ **关键提示**:
|
|
|
+> 1. 如果你保留多档模型可切换,`contextTokens` 不要盲目拉满;我现在用 `131072` 作为三档模型共存时的安全基线。
|
|
|
+> 2. **浏览器功能**:默认镜像不包含 Chromium,需要使用 `--build-arg OPENCLAW_INSTALL_BROWSER=1` 构建 `openclaw:local-browser` 镜像
|
|
|
+> 3. 多 Bot 场景必须配置 `bindings`,否则 direct chat 默认会落到主会话桶,容易串上下文。
|
|
|
+> 4. 如果你临时切到 `moonshot-v1-128k`,继续保持 `contextTokens <= 131072`,避免再次出现 compaction 超限。
|
|
|
+
|
|
|
+**单 Bot 简化版(含 compaction 修复):**
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "gateway": {
|
|
|
+ "port": 18789,
|
|
|
+ "mode": "local",
|
|
|
+ "controlUi": {
|
|
|
+ "allowedOrigins": ["http://localhost:18789", "http://127.0.0.1:18789"]
|
|
|
+ },
|
|
|
+ "auth": {
|
|
|
+ "token": "your-secure-token"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "models": {
|
|
|
+ "providers": {
|
|
|
+ "bailian": {
|
|
|
+ "baseUrl": "https://coding.dashscope.aliyuncs.com/v1",
|
|
|
+ "apiKey": "YOUR_API_KEY",
|
|
|
+ "models": [{
|
|
|
+ "id": "kimi-k2.5",
|
|
|
+ "contextWindow": 256000,
|
|
|
+ "maxTokens": 8192
|
|
|
+ }]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "agents": {
|
|
|
+ "defaults": {
|
|
|
+ "model": { "primary": "bailian/kimi-k2.5" },
|
|
|
+ "contextTokens": 131072,
|
|
|
+ "compaction": {
|
|
|
+ "mode": "safeguard",
|
|
|
+ "reserveTokensFloor": 24000
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "session": {
|
|
|
+ "reset": {
|
|
|
+ "mode": "idle",
|
|
|
+ "idleMinutes": 30
|
|
|
+ },
|
|
|
+ "maintenance": {
|
|
|
+ "mode": "enforce",
|
|
|
+ "pruneAfter": "7d",
|
|
|
+ "maxEntries": 120
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "channels": {
|
|
|
+ "telegram": {
|
|
|
+ "enabled": true,
|
|
|
+ "historyLimit": 30,
|
|
|
+ "botToken": "YOUR_BOT_TOKEN",
|
|
|
+ "allowFrom": ["YOUR_USER_ID"]
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 踩坑总结
|
|
|
+
|
|
|
+| 坑位 | 问题 | 解决方案 |
|
|
|
+|------|------|----------|
|
|
|
+| 1 | 构建时 OOM | 添加 5GB Swap 空间 |
|
|
|
+| 2 | `gateway.mode` 缺失 | 必须显式设置 `"mode": "local"` |
|
|
|
+| 3 | `controlUi.allowedOrigins` 缺失 | 非 localhost 绑定时必须配置 |
|
|
|
+| 4 | `gateway.bind` 配置无效 | 必须使用 CLI 参数 `--bind lan` |
|
|
|
+| 5 | Telegram 配对失败 | 删除 `dmPolicy`,使用 `allowFrom` 白名单 |
|
|
|
+| 6 | 防火墙不生效 | 使用 `DOCKER-USER` 链而非 `INPUT` 链 |
|
|
|
+| 7 | Google OAuth 授权失败 | 确保 Redirect URI 与配置完全一致 |
|
|
|
+| 8 | MCP 服务器无法启动 | 检查 npx 是否可用,网络是否通畅 |
|
|
|
+| 9 | 多 Bot 配置时 `default` 账号冲突 | 避免使用 `default` 作为 accountId,改用 `main`、`news` 等 |
|
|
|
+| 10 | 多 Bot 顶层 `botToken` 被覆盖 | 使用 `accounts` 时,顶层不要设置 `botToken` |
|
|
|
+| 11 | Skill 脚本权限不足 | 确保脚本有执行权限 `chmod +x script.sh` |
|
|
|
+| 12 | Skill 中文字符处理 | 使用 `echo | sed` 处理中文文件名,避免乱码 |
|
|
|
+| 13 | Compaction 卡死导致无响应 | 配置合理 `contextTokens` + 设置 `historyLimit` + 启用 `session.maintenance` |
|
|
|
+| 14 | Docker 镜像无浏览器 | 使用 `--build-arg OPENCLAW_INSTALL_BROWSER=1` 重新构建镜像 |
|
|
|
+| 15 | 镜像体积过大 (5.7GB) | 使用多阶段构建 + node:22-bookworm-slim 基础镜像 |
|
|
|
+| 16 | 会话记录膨胀失控 | 部署结构化记录系统 + 每日自动归档 + 分类存储 |
|
|
|
+| 17 | 定时任务推送全到 main bot | `jobs.json` 每个 job 加 `agentId` + `delivery.accountId` |
|
|
|
+| 18 | 想切 Step 却误改全局默认模型 | 保持默认模型不动,使用 `/model ...` 做会话级切换 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 镜像优化指南(第15坑)
|
|
|
+
|
|
|
+### 问题:镜像体积过大
|
|
|
+
|
|
|
+OpenClaw 默认构建的镜像体积巨大:
|
|
|
+- `openclaw:local`: **4.4GB**
|
|
|
+- `openclaw:local-browser`: **5.7GB**
|
|
|
+
|
|
|
+在 2GB 内存的服务器上,光是镜像就占满了磁盘。
|
|
|
+
|
|
|
+### 原因分析
|
|
|
+
|
|
|
+| 问题 | 说明 | 占用 |
|
|
|
+|------|------|------|
|
|
|
+| **单阶段构建** | 构建依赖和生产代码混在一起 | ~1GB |
|
|
|
+| **未清理 devDependencies** | 开发依赖未删除 | ~500MB |
|
|
|
+| **bookworm 基础镜像** | 完整 Debian 系统 | ~1GB |
|
|
|
+| **Chromium + Playwright** | 浏览器全套 | ~1.7GB |
|
|
|
+
|
|
|
+### 解决方案:多阶段构建
|
|
|
+
|
|
|
+创建 `Dockerfile.optimized`:
|
|
|
+
|
|
|
+```dockerfile
|
|
|
+# ============================================================================
|
|
|
+# 阶段1:构建阶段
|
|
|
+# ============================================================================
|
|
|
+FROM node:22-bookworm AS builder
|
|
|
+
|
|
|
+WORKDIR /app
|
|
|
+RUN corepack enable
|
|
|
+
|
|
|
+# 复制依赖文件
|
|
|
+COPY package.json pnpm-lock.yaml ./
|
|
|
+RUN pnpm install --frozen-lockfile
|
|
|
+
|
|
|
+# 复制源码并构建
|
|
|
+COPY . .
|
|
|
+RUN pnpm build && pnpm ui:build
|
|
|
+
|
|
|
+# 关键:清理开发依赖,只保留生产依赖
|
|
|
+RUN pnpm prune --prod
|
|
|
+
|
|
|
+# ============================================================================
|
|
|
+# 阶段2:生产阶段 - 使用精简基础镜像
|
|
|
+# ============================================================================
|
|
|
+FROM node:22-bookworm-slim AS production
|
|
|
+
|
|
|
+# 只安装必需的系统依赖
|
|
|
+RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
|
+ ca-certificates curl git \
|
|
|
+ && rm -rf /var/lib/apt/lists/*
|
|
|
+
|
|
|
+WORKDIR /app
|
|
|
+
|
|
|
+# 从构建阶段只复制必要文件
|
|
|
+COPY --from=builder /app/dist ./dist
|
|
|
+COPY --from=builder /app/node_modules ./node_modules
|
|
|
+COPY --from=builder /app/package.json ./
|
|
|
+COPY --from=builder /app/openclaw.mjs ./
|
|
|
+
|
|
|
+# 使用非 root 用户运行
|
|
|
+RUN groupadd -r nodeuser && useradd -r -g nodeuser nodeuser
|
|
|
+RUN chown -R nodeuser:nodeuser /app
|
|
|
+USER nodeuser
|
|
|
+
|
|
|
+ENV NODE_ENV=production
|
|
|
+EXPOSE 18789 18790
|
|
|
+
|
|
|
+CMD ["node", "openclaw.mjs", "gateway", "--allow-unconfigured"]
|
|
|
+```
|
|
|
+
|
|
|
+### 构建优化版镜像
|
|
|
+
|
|
|
+```bash
|
|
|
+cd /opt/openclaw
|
|
|
+
|
|
|
+# 构建轻量级版本 (2-3GB)
|
|
|
+docker build \
|
|
|
+ --target production \
|
|
|
+ -t openclaw:slim \
|
|
|
+ -f Dockerfile.optimized \
|
|
|
+ .
|
|
|
+
|
|
|
+# 构建浏览器版本 (3-4GB)
|
|
|
+docker build \
|
|
|
+ --target browser \
|
|
|
+ -t openclaw:slim-browser \
|
|
|
+ -f Dockerfile.optimized \
|
|
|
+ .
|
|
|
+```
|
|
|
+
|
|
|
+### 优化效果对比
|
|
|
+
|
|
|
+| 镜像 | 原体积 | 优化后 | 节省 |
|
|
|
+|------|--------|--------|------|
|
|
|
+| `openclaw:local` | 4.4GB | `openclaw:slim` **2.5GB** | **43%** ↓ |
|
|
|
+| `openclaw:local-browser` | 5.7GB | `openclaw:slim-browser` **3.5GB** | **39%** ↓ |
|
|
|
+
|
|
|
+### 使用优化版镜像
|
|
|
+
|
|
|
+修改 `.env` 文件:
|
|
|
+
|
|
|
+```bash
|
|
|
+# 轻量级版本(推荐日常使用)
|
|
|
+OPENCLAW_IMAGE=openclaw:slim
|
|
|
+
|
|
|
+# 或浏览器版本(需要网页自动化时)
|
|
|
+# OPENCLAW_IMAGE=openclaw:slim-browser
|
|
|
+```
|
|
|
+
|
|
|
+然后重启服务:
|
|
|
+
|
|
|
+```bash
|
|
|
+docker compose up -d
|
|
|
+```
|
|
|
+
|
|
|
+### 进一步优化建议
|
|
|
+
|
|
|
+1. **使用 Alpine 基础镜像**(极致精简)
|
|
|
+ ```dockerfile
|
|
|
+ FROM node:22-alpine
|
|
|
+ # 可将体积降至 < 1.5GB
|
|
|
+ # 但可能有兼容性问题
|
|
|
+ ```
|
|
|
+
|
|
|
+2. **启用 Docker 镜像压缩**
|
|
|
+ ```bash
|
|
|
+ docker build --compress ...
|
|
|
+ ```
|
|
|
+
|
|
|
+3. **定期清理无用镜像**
|
|
|
+ ```bash
|
|
|
+ docker image prune -a
|
|
|
+ ```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 重大坑位详解:Compaction 卡死问题(第13坑)
|
|
|
+
|
|
|
+部署运行几天后,我遇到了一个**极其隐蔽但致命**的问题:Telegram Bot 突然不响应了,或者响应需要等 5 分钟以上。
|
|
|
+
|
|
|
+### 现象
|
|
|
+
|
|
|
+- 发送消息后 Bot 无响应
|
|
|
+- 日志卡在 `embedded run compaction start` 不动
|
|
|
+- 服务重启后短暂正常,很快又卡死
|
|
|
+
|
|
|
+### 根因分析
|
|
|
+
|
|
|
+深度诊断后发现了**两个根本原因**:
|
|
|
+
|
|
|
+#### 根因 1:contextTokens 不匹配
|
|
|
+
|
|
|
+OpenClaw 默认上下文预算与实际模型窗口不一致时,会导致系统误判可用空间,compaction 后仍然超限(日志显示使用了 145.7%)。
|
|
|
+
|
|
|
+所以一定要注意不同的模型一定要修改响应的配置。
|
|
|
+
|
|
|
+#### 根因 2:无 historyLimit 限制
|
|
|
+
|
|
|
+所有历史消息(603 条)全部进入上下文,而不是只取最近的几十条。两天内会话文件膨胀到 1.4MB,每次 compaction 都要扫描全部历史。
|
|
|
+
|
|
|
+#### 触发因素:输出被频繁截断
|
|
|
+
|
|
|
+`maxTokens` 配得过小会让长任务反复截断并补发,间接加速会话膨胀。它不是唯一根因,但会放大卡顿问题。
|
|
|
+
|
|
|
+### 解决方案
|
|
|
+
|
|
|
+需要添加三组关键配置:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "agents": {
|
|
|
+ "defaults": {
|
|
|
+ "contextTokens": 131072,
|
|
|
+ "compaction": {
|
|
|
+ "mode": "safeguard",
|
|
|
+ "reserveTokensFloor": 24000,
|
|
|
+ "identifierPolicy": "strict",
|
|
|
+ "memoryFlush": {
|
|
|
+ "enabled": true,
|
|
|
+ "softThresholdTokens": 6000
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "session": {
|
|
|
+ "scope": "per-sender",
|
|
|
+ "reset": {
|
|
|
+ "mode": "idle",
|
|
|
+ "idleMinutes": 30
|
|
|
+ },
|
|
|
+ "maintenance": {
|
|
|
+ "mode": "enforce",
|
|
|
+ "pruneAfter": "7d",
|
|
|
+ "maxEntries": 120
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "channels": {
|
|
|
+ "telegram": {
|
|
|
+ "enabled": true,
|
|
|
+ "historyLimit": 30,
|
|
|
+ "accounts": {
|
|
|
+ ...
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 关键配置说明
|
|
|
+
|
|
|
+| 配置项 | 值 | 作用 |
|
|
|
+|--------|-----|------|
|
|
|
+| `agents.defaults.contextTokens` | 131072 | 多档模型共存时更稳,切回 `moonshot-v1-128k` 也不容易超限 |
|
|
|
+| `agents.defaults.compaction.mode` | safeguard | 启用保护模式,预留安全空间 |
|
|
|
+| `session.maintenance.mode` | enforce | 强制清理 7 天前的旧会话 |
|
|
|
+| `session.maintenance.maxEntries` | 120 | 最多保留 120 个会话 |
|
|
|
+| `channels.telegram.historyLimit` | 30 | 每次请求最多带 30 条历史 |
|
|
|
+
|
|
|
+### 多 Bot 配置注意
|
|
|
+
|
|
|
+上面的 `historyLimit` 和 `session` 配置放在 `channels.telegram` 级别,会对所有 4 个 Bot 统一生效。如果需要不同 Bot 不同策略,可以在每个 `account` 下单独设置 `historyLimit`。
|
|
|
+
|
|
|
+### 多模型切换补充说明
|
|
|
+
|
|
|
+后来我又把 `step/step-3.5-flash` 接进来了。这里最重要的经验是:
|
|
|
+**别为了切模型去改全局默认模型,直接用 `/model ...` 切当前会话就够了。**
|
|
|
+
|
|
|
+原因很简单:
|
|
|
+- 改全局会影响别的 Bot 和别的会话
|
|
|
+- 还可能把 cron 定时任务一起带偏
|
|
|
+- 当前会话切换则只影响自己这一条对话链
|
|
|
+
|
|
|
+我现在的实际用法:
|
|
|
+
|
|
|
+```text
|
|
|
+/model step
|
|
|
+/model bailian/kimi-k2.5
|
|
|
+/model kimi/moonshot-v1-128k
|
|
|
+/model status
|
|
|
+```
|
|
|
+
|
|
|
+其中:
|
|
|
+- `bailian <-> step` 风险最低
|
|
|
+- 切到 `moonshot-v1-128k` 时,最容易触发短期上下文压缩
|
|
|
+- 但长期记忆文件不会丢
|
|
|
+
|
|
|
+### 修复后的效果
|
|
|
+
|
|
|
+- 响应时间从 5 分钟+ 降至 3-20 秒
|
|
|
+- 会话文件大小控制在 10KB 以内
|
|
|
+- 服务连续运行 14 小时+ 无卡死
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 实际使用体验
|
|
|
+
|
|
|
+部署完成后,通过 Telegram 与 Bot 对话:
|
|
|
+
|
|
|
+### 修复前(问题阶段)
|
|
|
+- 响应速度:最初很快,2 天后变成 5 分钟+
|
|
|
+- 稳定性:运行 2 天后完全卡死
|
|
|
+- 原因:compaction 机制被大会话文件阻塞
|
|
|
+
|
|
|
+### 修复后(当前状态)
|
|
|
+- 响应速度:**3-20 秒**,正常可用
|
|
|
+- 稳定性:连续运行 14 小时+ 无故障
|
|
|
+- 内存占用:约 800MB-1.2GB
|
|
|
+- 功能:文件操作、Shell 命令、网页浏览全部正常
|
|
|
+
|
|
|
+### 关键优化点
|
|
|
+
|
|
|
+配置 `contextTokens`、`historyLimit` 和 `session.maintenance` 后,OpenClaw 从"两天必挂"变成"长期稳定运行"。这是生产环境部署的**必选项**,不是可选项。
|
|
|
+
|
|
|
+> 📷 **Telegram 实际对话效果**:
|
|
|
+>
|
|
|
+> 
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 安全建议
|
|
|
+
|
|
|
+1. **永远不要**将 `openclaw.json` 提交到 Git
|
|
|
+2. **配置文件权限**:最小权限原则,但必须保证容器运行用户可读
|
|
|
+3. **Web UI 访问**:仅通过 SSH 隧道,不要暴露在公网
|
|
|
+4. **Telegram 白名单**:严格控制 `allowFrom` 列表
|
|
|
+5. **定期更新**:关注 OpenClaw 安全公告
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 参考资源
|
|
|
+
|
|
|
+- [OpenClaw 官网](https://openclaw.ai/)
|
|
|
+- [GitHub 仓库](https://github.com/openclaw/openclaw)
|
|
|
+- [阿里云百炼](https://bailian.console.aliyun.com/)
|
|
|
+- [X - @elvissun](https://x.com/elvissun/status/2025920521871716562)
|
|
|
+- [X - @stark_nico99](https://x.com/stark_nico99/status/2026235176150581282)
|
|
|
+- [X - @AI_Jasonyu](https://x.com/AI_Jasonyu/status/2026455606970954087)
|