Initial commit: OpenClaw Skill Collection

6 custom skills (assign-task, dispatch-webhook, daily-briefing,
task-capture, qmd-brain, tts-voice) with technical documentation.
Compatible with Claude Code, OpenClaw, Codex CLI, and OpenCode.
This commit is contained in:
2026-03-13 10:58:30 +08:00
commit 4c966a3ad2
884 changed files with 140761 additions and 0 deletions

85
chapters/03-services.md Normal file
View File

@@ -0,0 +1,85 @@
# 3. 服務安裝紀錄
### 3.1 安裝前置準備
**問題:安裝腳本需要 root 權限**
```bash
# 錯誤方式process substitution + sudo 不相容)
sudo bash <(curl -sL kejilion.sh) app OpenClaw
# 正確方式
curl -sL kejilion.sh -o /tmp/kejilion.sh && sudo bash /tmp/kejilion.sh app OpenClaw
```
**問題Webmin apt repo GPG key 失效導致 apt update 失敗**
```bash
sudo rm -f /etc/apt/sources.list.d/webmin.list
sudo apt-get update
# 然後手動裝 Node.js 22
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
```
### 3.2 CLIProxyAPI
安裝來源:`sudo bash /tmp/kejilion.sh app CLIProxyAPI`
安裝後設定:
- WebUI`http://192.168.31.169:8317/management.html`
- Docker restart policy`unless-stopped`
### 3.3 OpenClaw
安裝來源:`curl -fsSL https://openclaw.ai/install.sh | bash`
**啟動問題(腳本預期 tmux後改為 systemd**
腳本用 `pgrep -f "openclaw gateway"` 判斷是否運行,原本用 pm2 啟動會比對失敗。最終改用 systemd
```ini
# /etc/systemd/system/openclaw.service
[Unit]
Description=OpenClaw Gateway
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
Environment=NODE_OPTIONS=--dns-result-order=ipv4first
ExecStartPre=/bin/sh -c 'tmux kill-session -t gateway 2>/dev/null; true'
ExecStart=/usr/bin/openclaw gateway
ExecStop=/usr/bin/openclaw gateway stop
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
```
```bash
sudo systemctl daemon-reload
sudo systemctl enable openclaw.service
sudo systemctl start openclaw.service
```
### 3.4 nginx
安裝來源:`/home/web/docker-compose.yml`(已有 Docker Compose 管理)
**問題:系統 nginx 佔用 port 80**
```bash
sudo systemctl stop nginx
sudo systemctl disable nginx
sudo docker restart nginx
```
### 3.5 設備配對Browser → OpenClaw
```bash
# 查看待審核配對請求
sudo openclaw devices list
# 核准配對
sudo openclaw devices approve <request-id>
```

312
chapters/04-known-issues.md Normal file
View File

@@ -0,0 +1,312 @@
# 4. 已知問題與修復
### 4.1 Node.js 22/24 fetch 無法連線 Telegram API
**症狀**`Telegram: failed - fetch failed`,但 curl 可以正常連線
**根因**Node.js 22+ 的 `fetch`(基於 undici`autoSelectFamily`happy eyeballs優先嘗試 IPv6。伺服器沒有可用的 IPv6 對外連線。
**修復(三層)**
1. 系統層停用 IPv6
```bash
# 永久設定(/etc/sysctl.conf
net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6=1
```
2. gateway.env 加入 NODE_OPTIONS
```
NODE_OPTIONS=--dns-result-order=ipv4first --no-network-family-autoselection
```
3. openclaw.json config 層覆蓋(**Node 24 必須,因 OpenClaw 內部 hardcode `autoSelectFamily:true`**
```json
{ "channels": { "telegram": { "network": { "autoSelectFamily": false, "dnsResultOrder": "ipv4first" } } } }
```
**注意**sysctl + NODE_OPTIONS 在 Node 22 就夠了,但 Node 24 的 undici 不吃這些設定,必須用 openclaw.json config 覆蓋(見 §4.13)。
### 4.2 OpenClaw 腳本顯示「未運行」
**症狀**`sudo bash kejilion.sh app OpenClaw` 顯示「已安裝 未運行」,但 Gateway 實際在跑
**根因**:腳本用 `pgrep -f "openclaw gateway"` 判斷,但 pm2/systemd 啟動的進程名稱不符
**修復**:改用 tmux 啟動(若要讓腳本正確識別),或改用 systemd推薦
### 4.3 Docker nginx 開機後無法啟動
**症狀**`nginx: bind() to 0.0.0.0:80 failed (98: Address in use)`
**根因**:系統安裝的 nginx`/usr/sbin/nginx`)設為 enabled開機時搶先佔用 port 80
**修復**
```bash
sudo systemctl stop nginx
sudo systemctl disable nginx
```
### 4.4 Multi-Agent Config Schema 與文件不符v2026.2.17
**症狀**:修改 `openclaw.json` 後 Gateway 啟動失敗,報 `Unrecognized key: "agentId"``bindings.0.match: Invalid input`
**根因**:官方文件範例使用舊版 schema與實際 v2026.2.17 不相容
**正確格式**
- `agents.list[].id`(不是 `agentId`
- `bindings[]` 需要 `{ "agentId": "xxx", "match": { "channel": "telegram", "accountId": "yyy" } }`
- 詳見 [06-config.md 6.2 節](06-config.md)
### 4.5 新 Bot /start 無配對碼回應
**症狀**:在新 Telegram Bot 按 /start 沒有任何回應
**根因**:按 /start 時 Gateway 尚未載入新 Bot TokenTelegram update 被消耗但無人處理
**修復**:確保 config 已正確 + Gateway 重啟成功後再按 /start
### 4.6 使用 accounts 後主 Bot 通道不啟動2026-02-25
**症狀**`openclaw channels list` 只顯示 `life-bot`,主 Bot@Cimon168_bot)不啟動,啟動日誌無 `[default] starting provider` 訊息
**根因**:當 `channels.telegram.accounts` 區塊存在時OpenClaw 只啟動 `accounts` 裡明確列出的帳號。頂層 `botToken` 不再被視為獨立通道。
**修復**:將主 Bot token 從頂層移入 `accounts.default`
```json
"accounts": {
"default": {
"botToken": "<主 Bot Token>"
},
"life-bot": {
"botToken": "<生活 Bot Token>"
}
}
```
修改後重啟:`systemctl --user restart openclaw-gateway`
### 4.7 Multi-Agent 後 workspace skills 消失2026-02-25
**症狀**Gateway 重啟後 `openclaw skills list` 只顯示 bundled skillsworkspace skillsdaily-briefing、qmd-brain、task-capture消失。Agent 回覆不認識這些 skills。
**根因**`agents.list` 只有具名 agent`life-assistant`)時,隱含的預設 agentmain不會觸發 workspace skills 掃描。OpenClaw 只對 `agents.list` 中明確列出的 agent 執行 workspace 目錄的 skills 發現。
**修復**:在 `agents.list` 明確加入 `main` agent並在 `bindings` 加入 `default → main` 綁定:
```json
"agents": {
"list": [
{
"id": "main",
"name": "主 Agent",
"model": { "primary": "cliapi/gpt-5.3-codex" },
"workspace": "/home/selig/.openclaw/workspace"
},
{ "id": "life-assistant", "..." }
]
},
"bindings": [
{ "agentId": "main", "match": { "channel": "telegram", "accountId": "default" } },
{ "agentId": "life-assistant", "match": { "channel": "telegram", "accountId": "life-bot" } }
]
```
修改後重啟:`systemctl --user restart openclaw-gateway`
**驗證**:檢查啟動 log 是否有 workspace skills 的 sanitization 記錄:
```bash
journalctl --user -u openclaw-gateway --since "1 min ago" --no-pager | grep daily-briefing
```
### 4.8 OpenClaw WebUI 配對問題
**症狀**`https://oclaw.nature.edu.kg/#token=...` 顯示 "backend not paired yet"
**修復**:在後端核准配對請求
```bash
sudo openclaw devices list # 查看 pending request ID
sudo openclaw devices approve <request-id>
```
### 4.9 升級 2026.2.25 後 Gateway 啟動失敗2026-02-27
**症狀**`Error: Unsafe fallback OpenClaw temp dir: /tmp/openclaw-1000`
**根因**:新版加強 temp 目錄安全檢查,要求 `/tmp/openclaw-<UID>` 權限必須 `700`owner-only舊版建立的目錄權限為 `775`
**修復**
```bash
chmod 700 /tmp/openclaw-1000 # selig (UID 1000)
# root 的 temp dir 也需清理
sudo rm -rf /tmp/openclaw-0 && sudo mkdir -p /tmp/openclaw-0 && sudo chmod 700 /tmp/openclaw-0
```
### 4.10 升級後 `google-antigravity-auth` plugin 警告2026-02-27
**症狀**`plugin removed: google-antigravity-auth (stale config entry ignored)`
**根因**`google-antigravity-auth` plugin 已從 2026.2.25 移除,但 `openclaw.json` 仍有殘留設定。
**修復**:從 `openclaw.json``plugins.entries` 刪除 `google-antigravity-auth` 條目。此 plugin 用於 OpenClaw 直連 Google API 認證,與 CLIProxyAPI 代理的 Gemini 模型無關。
### 4.11 `sudo openclaw skills list` 偵測不到 selig 環境的 CLI2026-02-27
**症狀**`coding-agent``summarize` 顯示 `✗ missing`,但實際 CLI 已安裝。
**根因**`sudo openclaw` 以 root 執行PATH 不含 selig 的 `~/.local/bin` 和 nvm 路徑。
**修復**:使用 `openclaw skills list`(不加 sudo即可正確偵測。Gateway 以 selig user service 運行,不受影響。
### 4.12 Browser control 連線逾時2026-03-02
**症狀**Telegram Agent 嘗試操控瀏覽器時報 `Browser control service 連線逾時15 秒)`
**根因**(多層問題):
1. **Node service 未安裝**OpenClaw 的瀏覽器控制需要 Node Host service 作為 Gateway 和本機瀏覽器之間的 relay
2. **Node service 未配對**:首次連線 Gateway 時需經過 device pairing 核准
3. **缺少 DISPLAY 環境變數**Gateway 和 Node service 的 systemd unit 都沒有 `DISPLAY=:99`,導致無法操控 Xvfb 上的瀏覽器
4. **Snap Chromium 限制**Ubuntu snap 版 Chromium 的包裝器會剝掉 `--load-extension``--remote-debugging-port` 旗標,無法載入 OpenClaw 擴充套件或啟用 CDP
**修復**
```bash
# 1. 安裝 Node service 並加入 DISPLAY
openclaw node install
# 編輯 ~/.config/systemd/user/openclaw-node.service 加入 Environment=DISPLAY=:99
# 2. 在 gateway.env 加入 DISPLAYGateway service 也要加
echo 'DISPLAY=:99' >> ~/.config/openclaw/gateway.env
# 編輯 ~/.config/systemd/user/openclaw-gateway.service 加入 Environment=DISPLAY=:99
# 3. 啟動 Node service 並配對
systemctl --user daemon-reload
systemctl --user enable --now openclaw-node.service
openclaw devices list # 等待 pending request
openclaw devices approve <id> # 核准
# 4. 改用 Playwright Chromium非 snap支援 CDP 直連)
# 建立 playwright-chrome.service 並啟用
systemctl --user enable --now playwright-chrome.service
# 5. 建立 cdp-direct profile 設為預設
openclaw browser create-profile --name cdp-direct --cdp-url http://127.0.0.1:18801
# openclaw.json → browser.defaultProfile: "cdp-direct"
# 6. 重啟 Gateway
systemctl --user restart openclaw-gateway
```
### 4.16 Agent browser tool timeout — `openclaw` profile 啟動失敗2026-03-11
**症狀**CLI 的 `openclaw browser navigate` 正常,但 Agent 透過 tool call 使用瀏覽器時 15 秒 timeout
```
[tools] browser failed: timed out. Restart the OpenClaw gateway...
```
**根因**v2026.3.7 內建了 `openclaw` browser profileport 18800Gateway 啟動時會嘗試用 `detectedPath``/usr/bin/chromium-browser`snap 版)啟動這個 profile。snap Chromium 會剝掉 `--remote-debugging-port` 參數,導致 CDP 永遠無法建立。`openclaw browser profiles` 顯示此 profile 為 `stopped` 狀態。
**關鍵差異**CLI 指令走 `defaultProfile`cdp-direct但 agent tool call 可能嘗試使用 `openclaw` profile。
**修復**
1.`openclaw.json``browser.profiles` 覆寫 `openclaw` profile讓它指向 Playwright CDP
```json
{
"browser": {
"profiles": {
"openclaw": {
"cdpUrl": "http://127.0.0.1:18801",
"color": "#FF4500"
}
}
}
}
```
2. 確認 Gateway service 有 `Environment=DISPLAY=:99``~/.config/systemd/user/openclaw-gateway.service`
**驗證**
```bash
openclaw browser profiles
# 三個 profilecdp-direct、chrome、openclaw都應顯示 runningport 18801
```
### 4.13 Node.js 24 undici autoSelectFamily 導致 Telegram 連線逾時2026-03-02
**症狀**Gateway 重啟後 Telegram 持續 `Network request failed`,但 `curl` 可正常連線 Telegram API
**根因**Node.js 24 的 `fetch()`undici`autoSelectFamily`happy eyeballs會同時嘗試 IPv4/IPv6。即使系統 sysctl 停用 IPv6 + `NODE_OPTIONS=--dns-result-order=ipv4first`OpenClaw 內部(`ssrf-D_av5wos.js`hardcode `autoSelectFamily: true`,覆蓋了 NODE_OPTIONS。
**修復**:在 `openclaw.json` 用 config 層級覆蓋:
```json
{
"channels": {
"telegram": {
"network": {
"autoSelectFamily": false,
"dnsResultOrder": "ipv4first"
}
}
}
}
```
同時在 `gateway.env` 的 NODE_OPTIONS 加入 `--no-network-family-autoselection`(雙保險)。
**驗證**Gateway log 應顯示 `autoSelectFamily=false (config)`
### 4.14 GPU driver suspend/resume 死鎖導致 Bot 全卡2026-03-02
**症狀**:所有 Telegram Bot 收到訊息後無回應,`nvidia-smi` 掛起不返回
**根因(三層連鎖故障)**
1. **系統觸發 suspend/resume**`nvidia-sleep.sh` 在 kernel 的 `uvm_suspend()` 死鎖(狀態 `Ds` 不可中斷)
2. **GPU driver 無法存取** → llama-embed 的 port 11435 雖然 listen但 embedding 請求永遠無回應
3. **memory-lancedb-pro 的 `before_agent_start` hook 阻塞** → 每個 agent 啟動時呼叫 embedding API 做 autoRecall因 llama-embed 無回應而無限等待,導致所有 agent 卡死
**診斷流程**
```bash
# 1. 確認 GPU 死鎖
timeout 5 nvidia-smi || echo "GPU driver 死鎖"
# 2. 確認 llama-embed 無回應
timeout 5 curl -s http://127.0.0.1:11435/v1/embeddings \
-H "Content-Type: application/json" \
-d '{"input":"test","model":"nomic-embed-text-v1.5"}' || echo "embedding 無回應"
# 3. 確認殘留 process
ps aux | grep nvidia-sleep # 看到 Ds 狀態 = 死鎖
ps aux | grep llama-server # 可能有殘留舊 process 占住 port
```
**緊急修復(免重開機讓 Bot 恢復)**
```bash
# 關閉 autoRecall讓 agent 不依賴 embedding 即可啟動
openclaw config set plugins.entries.memory-lancedb-pro.config.autoRecall false
# Gateway 會自動偵測 config 變更並重啟
```
**根治**:重開機修復 GPU driver
**預防**:停用系統休眠
```bash
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
```
### 4.15 Embedding 容錯策略2026-03-02
llama-embedGPU是唯一的 production embedding 路徑。Ollama CPU 模式雖有 `nomic-embed-text`port 11434~1.4s/call但在 4 核心 + 高 load 系統上會拖垮效能,**不適合作為常態 fallback**。
**容錯層級**(由 `~/clawd/scripts/embed-health.sh` 自動執行cron */30 分鐘2026-03-02 已實作):
| 層級 | 條件 | 動作 |
|------|------|------|
| 正常 | llama-embed port 11435 回應 < 2s | `autoRecall: true`, `autoCapture: true` |
| 降級 | llama-embed 無回應或逾時 | 自動設定 `autoRecall: false`, `autoCapture: false`Telegram 通知使用者 |
| 恢復 | 重開機後 llama-embed 恢復 | 自動設定 `autoRecall: true`, `autoCapture: true`Telegram 通知 |
**設計原則**
- 不使用 Ollama CPU fallbackCPU 資源不足)
- 不使用線上 embedding API隱私考量 + 增加外部依賴)
- embedding 掛了 = 記憶暫停,不影響 Bot 核心回覆功能
- 健康檢查腳本放入 crontab 每 30 分鐘執行

155
chapters/05-agents.md Normal file
View File

@@ -0,0 +1,155 @@
# 5. Agent Team 架構設計
### 5.1 行動任務 Team
#### 架構圖
```
使用者 (Telegram)
┌──────────────────────────────────────────────────┐
│ OpenClaw (x550v) │
│ Skill 庫assign-task, dispatch-webhook, │
│ project-review, code-review │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ 主 Agent (main) │ │
│ │ Model: Gemini Flash│ │
│ │ 收 Telegram 訊息 │ │
│ └──────┬──────────────┘ │
└────────────────┼─────────────────────────────────┘
│ 分派任務Skill / Webhook / API
┌────────┴────────────────┐
│ │
┌───────▼──────────┐ ┌──────────▼─────────────┐
│ VPS-A │ │ VPS-B │
│ Claude Code │ │ OpenCode / Other LLMs │
│ (Opus/Sonnet) │ │ (Codex / Gemini / …) │
│ │ │ │
│ 角色:專案經理 │ │ 角色:專案經理/執行者 │
│ ・主要專案開發 │ │ ・其他專案開發 │
│ ・Webhook 接收 │ │ ・Webhook 接收 │
│ ・回報結果 │ │ ・回報結果 │
└──────────────────┘ └────────────────────────┘
│ │
└──────────┬──────────────┘
執行結果回傳 Telegram
```
#### 角色說明
| 角色 | 模型 | 位置 | 職責 |
|------|------|------|------|
| 協調者 (Coordinator) | Gemini Flash | OpenClaw x550v | 接收需求,分派任務,彙整回報 |
| 專案經理-A (PM-A) | Claude Code Opus | VPS-A | 主要專案規劃、架構設計、任務分派 |
| 專案經理-B (PM-B) | OpenCode Codex | VPS-B | 其他專案規劃、多 LLM 調度 |
| 開發執行者 | Sonnet / Gemini / 其他 | VPS-A/B | 實際寫程式、測試、文件 |
#### 任務流程
```
1. 使用者在 Telegram 描述任務
2. OpenClaw 主 agent 接收,判斷任務類型
3. 呼叫 assign-task skill
├── 主要專案 → 觸發 VPS-A Webhook (Claude Code)
└── 其他專案 → 觸發 VPS-B Webhook (OpenCode)
4. PM 接收任務,制定計劃,分派給執行者
5. 執行者完成任務,回報 PM
6. PM 整理結果,透過 API 回傳 OpenClaw
7. OpenClaw 回報使用者Telegram
```
#### Webhook 設計
**VPS-A Webhook Endpoint**Claude Code 接收端)
```
POST https://vps-a.example.com/webhook/openclaw
Headers:
X-OpenClaw-Token: <shared-secret>
Content-Type: application/json
Body:
{
"task_id": "task-uuid",
"type": "project_development",
"project": "project-name",
"description": "任務描述",
"priority": "high|normal|low",
"context": { ... },
"callback_url": "https://oclaw.nature.edu.kg/webhook/callback",
"callback_token": "<session-token>"
}
```
**回傳格式**
```json
{
"task_id": "task-uuid",
"status": "completed|failed|in_progress",
"summary": "執行摘要",
"artifacts": ["file1.py", "README.md"],
"next_steps": ["部署測試", "code review"]
}
```
### 5.2 生活安排 Team
#### 架構圖
```
使用者 (Telegram)
┌──────────────────────────────────────────────┐
│ OpenClaw 生活安排 Agent │
│ Model: Gemini Flash / Claude Sonnet │
│ │
│ Skill 庫: │
│ ・calendar-check 行事曆查詢 │
│ ・schedule-plan 行程規劃 │
│ ・daily-briefing 每日摘要 │
│ ・reminder-set 提醒設定 │
│ ・task-capture 快速記錄待辦 │
└──────────────────────────────────────────────┘
├── Google Calendar API
├── 天氣 API
├── cron (OpenClaw 內建排程)
└── Telegram 推送
```
#### 功能說明
| 功能 | 觸發方式 | 說明 |
|------|---------|------|
| 每日簡報 | cron 每早 8:00 | 今日行程 + 天氣 + 待辦摘要 |
| 行程安排 | Telegram 指令 | 新增/查詢 Google Calendar |
| 提醒設定 | Telegram 指令 | 設定 cron job 定時提醒 |
| 快速待辦 | Telegram 指令 | 記錄到 workspace/TODO.md |
| 週報 | cron 每週日晚 | 本週完成事項彙整 |
#### Cron Job 設定範例
```bash
# 每日 8:00 早安簡報
openclaw cron add \
--name "daily-briefing" \
--cron "0 8 * * *" \
--session main \
--system-event "請執行每日簡報:查詢今日行程、天氣,整理待辦事項,用繁體中文發送到 Telegram"
# 每週日 21:00 週報
openclaw cron add \
--name "weekly-review" \
--cron "0 21 * * 0" \
--session main \
--system-event "請整理本週完成的工作、學習重點,以及下週計劃,發送週報到 Telegram"
```

421
chapters/06-config.md Normal file
View File

@@ -0,0 +1,421 @@
# 6. OpenClaw 設定參考
### 6.1 主設定結構 `/root/.openclaw/openclaw.json`
```json5
{
"meta": { "lastTouchedVersion": "2026.2.25" },
// Agent 預設設定
"agents": {
"defaults": {
"model": {
"primary": "google-antigravity/gemini-3-flash"
},
"workspace": "/root/.openclaw/workspace",
"compaction": { "mode": "safeguard" },
"maxConcurrent": 4,
"subagents": { "maxConcurrent": 8 }
}
},
// Telegram 頻道
"channels": {
"telegram": {
"enabled": true,
"botToken": "<your-bot-token>",
"dmPolicy": "pairing", // 只有配對裝置可以 DM
"groupPolicy": "allowlist",
"streamMode": "partial"
}
},
// Gateway 設定
"gateway": {
"port": 18789,
"mode": "local",
"bind": "loopback", // 只接受本機連線,由 nginx 代理
"auth": {
"mode": "token",
"token": "<access-token>"
}
},
// 訊息設定
"messages": {
"ackReactionScope": "group-mentions"
}
}
```
### 6.2 多 Agent / 多模型設定(獨立 Bot Token 方案)
> **踩坑紀錄2026-02-24 ~ 02-25v2026.2.17**
> - 文件範例用 `agentId`,但實際 schema 要用 **`id`**(否則報 `Unrecognized key: "agentId"`
> - `bindings` 需要 **`match` 包裝層**,不是直接放 `channel` / `accountId`
> - 新 Bot 必須**先完成 config + 重啟 Gateway 後**才按 `/start`,否則配對碼不會回傳
> - 各獨立 agent 的 `auth-profiles.json` 不會自動共享,需手動複製
> - **2026-02-25 新增)** 當使用 `accounts` 區塊後,頂層 `botToken` **不再被當作獨立通道啟動**。所有 Bot包含主 Bot都必須放入 `accounts` 內,否則 `channels list` 不會列出、provider 也不會啟動。主 Bot 建議使用 `"default"` 作為 accountId。
> - **2026-02-25 新增)** `agents.list` 只有具名 agent如 life-assistant**隱含的預設 agent 不會掃描 workspace skills**。必須在 `agents.list` 明確加入 `main` agent含 workspace 路徑),並在 `bindings` 加入 `{ "agentId": "main", "match": { "channel": "telegram", "accountId": "default" } }` 綁定。否則 workspace skills如 daily-briefing不會載入。
#### 正確的 config 格式(已驗證可用)
```json5
{
// 1. channels所有 Bot Token 都放在 accounts 下
// 頂層 botToken 在使用 accounts 後不再啟動為獨立通道
"channels": {
"telegram": {
"enabled": true,
"dmPolicy": "pairing",
"groupPolicy": "allowlist",
"streamMode": "partial",
"accounts": {
"default": { // 主 Bot@Cimon168_bot
"botToken": "<主 Bot Token>"
},
"life-bot": { // accountId自訂名稱
"botToken": "<新 Bot Token>" // @Cimon_life_bot
}
}
}
},
// 2. agents.list用 "id" 不是 "agentId"
// 主 agent 也必須明確列出,否則 workspace skills 不會載入
"agents": {
"list": [
{
"id": "main", // 主 agent必須明確列出
"name": "主 Agent",
"model": { "primary": "cliapi/gpt-5.3-codex" },
"workspace": "/home/selig/.openclaw/workspace"
},
{
"id": "life-assistant", // <- 必須用 "id"
"name": "生活助理",
"model": { "primary": "cliapi/gpt-5.3-codex" },
"workspace": "/home/selig/.openclaw/agents/life-assistant"
}
],
"defaults": { "..." }
},
// 3. bindingsmatch 包裝層channel + accountId 放 match 內)
// 每個 account 都需要綁定到對應 agent
"bindings": [
{
"agentId": "main", // 主 Bot → main agent
"match": {
"channel": "telegram",
"accountId": "default"
}
},
{
"agentId": "life-assistant", // 這裡用 agentId
"match": { // <- 必須有 match 物件
"channel": "telegram",
"accountId": "life-bot" // 對應 accounts 裡的 key
}
}
]
}
```
#### 安裝步驟
```bash
# 1. BotFather /newbot → 取得 Token
# 2. 建立 agent 目錄
mkdir -p ~/.openclaw/agents/<agent-name>/{agent,sessions}
# 3. 修改 ~/.openclaw/openclaw.json按上方格式
# 4. 重啟 Gateway
systemctl --user restart openclaw-gateway
# 5. 確認 log 無錯誤
journalctl --user -u openclaw-gateway --since "30 sec ago" --no-pager
# 6. 在 Telegram 新 Bot 發送 /start → 取得配對碼
# 7. 配對
openclaw pairing approve telegram <CODE>
```
#### 目前已部署的 Agent
| Agent ID | Bot | 用途 | Model |
|----------|-----|------|-------|
| main | @Cimon168_bot | 工作/專案/協調 | cliapi/gpt-5.3-codex |
| life-assistant | @Cimon_life_bot | 生活安排 | cliapi/gpt-5.3-codex |
### 6.3 CLIProxyAPI 連線設定
CLIProxyAPI 作為 OpenAI-compatible proxy讓 OpenClaw 可以使用多種 AI 帳號:
```json5
// 在 openclaw.json 加入 custom provider
{
"models": {
"providers": {
"cliapi": {
"baseUrl": "http://127.0.0.1:8317/v1",
"apiKey": "<management-key>",
"api": "openai-completions"
}
}
}
}
```
CLIProxyAPI 管理介面:`http://192.168.31.169:8317/management.html`
### 6.3.1 CLIProxyAPI LLM 輪換規則
> 原始碼位置:`sdk/cliproxy/auth/selector.go`、`config.yaml`
#### 輪換策略Round-Robin按請求次數
**不是依時間輪換**,而是每一個 API request 進來就推進一格。
```
每個 (provider, model) 組合 → 獨立計數器 (cursor)
cursor → 每次請求 +1
選取available[cursor % len(available)]
```
目前設定(`/home/docker/CLIProxyAPI/config.yaml`
```yaml
routing:
strategy: "round-robin" # 另一選項fill-first固定燒第一個帳號
request-retry: 3 # 失敗後最多重試 3 次(自動換下一個憑證)
max-retry-interval: 30 # 冷卻等待上限 30 秒
quota-exceeded:
switch-project: true # Quota 超限時自動切換帳號
switch-preview-model: true
```
#### 失敗重試Fallback
觸發條件HTTP 狀態碼):`403 / 408 / 500 / 502 / 503 / 504`
- 遇到錯誤 → cursor 繼續推進 → 下次自動選到不同憑證
- 不是獨立的「備援」邏輯,而是 round-robin 繼續走的自然結果
#### 冷卻機制Quota 超限)
- 憑證觸發 **429** → 進入冷卻,指數退避(底數 1s上限 30min
- 冷卻中的憑證從可用池排除round-robin 只從未冷卻憑證中選
- 冷卻時間到後自動恢復可用
#### 活躍 Provider目前
| Provider | 模型類型 |
|----------|---------|
| Grok (xai) | grok-4 系列、grok-code、grok-imagine |
| api.navy | qwen3.5、claude-sonnet-4.6、text-embedding |
### 6.3.2 CLIProxyAPI 模型清單自動更新
當 CLIProxyAPI 新增/移除 AI provider 後OpenClaw 不會自動偵測到新模型。需要更新 `openclaw.json` 中的 `models.providers.cliapi.models` 陣列。
**自動更新腳本**`~/clawd/scripts/refresh-llm-list.sh`
```bash
# 手動執行
bash ~/clawd/scripts/refresh-llm-list.sh
# 排程:每週日 02:00crontab
0 2 * * 0 /home/selig/clawd/scripts/refresh-llm-list.sh >> /var/log/refresh-llm-list.log 2>&1
```
**腳本流程**
1. 從 CLIProxyAPI `/v1/models` 取得最新模型清單
2. 依模型名稱自動分級high/mid/low → 不同 cost 設定)
3. 備份 `openclaw.json``openclaw.json.bak`
4. 更新模型陣列,保留其他設定不變
5. 重啟 Gateway
6. 輸出差異(新增/移除的模型)
**日誌**`/var/log/refresh-llm-list.log`
**模型分級規則**
| 級別 | 關鍵字 | input cost | contextWindow |
|------|--------|-----------|---------------|
| high | opus, pro-high, thinking, codex-max, pro-preview | 0.3 | 1M |
| mid | sonnet, grok, qwen, 預設 | 0.14 | 128K |
| low | haiku, flash-lite, embedding, mini | 0.07 | 128K |
| GPT | gpt-* | 0.2 | 128K |
### 6.3.3 發送 Telegram 訊息(通知 Agent
```bash
# 發送訊息到指定群組或用戶
sudo openclaw message send --channel telegram --target <chat-id> -m "訊息內容"
# 群組 ID 對照
# kaiwu開物-5178404192
# tiangong天工-5249018181
# yucheng玉成-5296222979
# 範例:通知開物群組
sudo openclaw message send --channel telegram --target -5178404192 -m "preview 網站已上線"
# 附帶圖片
sudo openclaw message send --channel telegram --target -5178404192 -m "截圖" --media /path/to/image.png
# 靜音發送(不觸發通知音)
sudo openclaw message send --channel telegram --target -5178404192 -m "背景通知" --silent
```
### 6.4 Session Scope 設定
```json5
{
"agents": {
"defaults": {
"session": {
// 推薦:每個 Telegram 用戶獨立 session防止資訊洩漏
"dmScope": "per-channel-peer",
// 每日 04:00 自動重置 session
"reset": { "schedule": "0 4 * * *" }
}
}
}
}
```
### 6.5 Auth Profiles模型認證
位置:`/root/.openclaw/agents/main/auth-profiles.json`
```json5
{
"version": 1,
"profiles": {
"anthropic:manual": {
"type": "token",
"provider": "anthropic",
"token": "sk-ant-..."
},
"cliapi:main": {
"type": "api-key",
"provider": "openai-compat",
"apiKey": "<key>",
"baseUrl": "http://127.0.0.1:8317/v1"
}
}
}
```
### 6.6 Heartbeat心跳巡查
Agent 定期自動觸發巡查,執行 `HEARTBEAT.md` 中定義的任務。
**預設間隔**(原始碼邏輯):
- `gateway.auth.mode = "oauth"``1h`
- 其他模式token、local`30m`
**設定方式**
```json5
{
"agents": {
"defaults": {
"heartbeat": {
"every": "30m" // 所有 agent 預設間隔(支援 "15m", "1h", "2h" 等)
}
},
"list": [
{
"id": "main",
"heartbeat": {
"every": "15m" // 個別 agent 覆寫
}
}
]
}
}
```
**指令**
```bash
# 查看目前設定
openclaw config get agents.defaults.heartbeat
# 修改全域間隔
openclaw config set agents.defaults.heartbeat.every "15m"
# 修改單一 agent需知道 list index如 main 是 index 0
openclaw config set agents.list.0.heartbeat.every "20m"
```
**巡查內容**:定義在各 agent workspace 的 `HEARTBEAT.md`,例如:
- `~/.openclaw/workspace/HEARTBEAT.md`(主 agent
- `~/.openclaw/agents/life-assistant/HEARTBEAT.md`(生活助理)
**Telegram 頻道 heartbeat 可見性**
```json5
{
"channels": {
"telegram": {
"heartbeat": "silent" // "visible" | "silent" | "hidden"
}
}
}
```
### 6.7 Exec Approvals指令執行審批
Agent 執行 shell 指令(`exec` tool時的安全策略。**兩個地方都需要設定**
#### 主控制:`openclaw.json` → `tools.exec`
這是**真正的 policy 控制點**,決定 agent 能否自動執行指令:
```json5
{
"tools": {
"exec": {
"security": "full", // "deny" | "allowlist" | "full"
"ask": "off" // "off" | "on-miss" | "always"
}
}
}
```
| security | 行為 |
|----------|------|
| `deny` | 封鎖所有 execsandbox 預設) |
| `allowlist` | 只允許白名單內的指令(**gateway/node 未設時的預設值** |
| `full` | 允許所有指令 |
| ask | 行為 |
|-----|------|
| `off` | 永不詢問 |
| `on-miss` | 指令不在白名單時才詢問(**預設值** |
| `always` | 每次都詢問 |
```bash
# 設定指令
openclaw config set tools.exec.security full
openclaw config set tools.exec.ask off
# 重啟 Gateway 生效
systemctl --user restart openclaw-gateway
```
#### 輔助儲存:`~/.openclaw/exec-approvals.json`
儲存 allowlist已核准的指令清單和 socket 資訊,**不是主要 policy 控制點**
```bash
# 查看
openclaw approvals get
# 設定(覆寫整個檔案)
openclaw approvals set --stdin < file.json
```
> **踩坑2026-03-02**:只設定 `exec-approvals.json` 的 `defaults.security=full` + `defaults.ask=off` **不會生效**。必須在 `openclaw.json` 的 `tools.exec` 設定才是真正的控制點。未設定 `tools.exec` 時,預設為 `security: "allowlist"` + `ask: "on-miss"`,導致 Telegram agent 每次執行指令都需要手動批准,而 Telegram 無法批准 → 120 秒超時。
#### Safe Bins免審批的安全指令
以下 stdin-only 工具即使在 `allowlist` 模式下也不需要白名單:
- `jq`, `cat`, `head`, `tail`, `cut`, `uniq`, `tr`, `wc`
- 可透過 `tools.exec.safeBins` 自訂
- 信任目錄:`/bin`, `/usr/bin`(可透過 `tools.exec.safeBinTrustedDirs` 擴充)

140
chapters/07-skills.md Normal file
View File

@@ -0,0 +1,140 @@
# 7. Skill 庫說明
Skills 位置:`~/.openclaw/workspace/skills/` 或 OpenClaw 官方 skill 庫
### 7.1 行動任務 Skills
| Skill | 功能 | 觸發方式 |
|-------|------|---------|
| `assign-task` | 分析任務,分派給 VPS-A 或 VPS-B | 使用者描述任務 |
| `dispatch-webhook` | 發送 Webhook 到 VPS等待回應 | assign-task 呼叫 |
| `project-status` | 查詢進行中的專案狀態 | 使用者查詢 |
| `code-review-request` | 提交 code review 請求 | 開發完成後 |
### 7.2 生活安排 Skills
| Skill | 功能 | 觸發方式 |
|-------|------|---------|
| `daily-briefing` | 每日簡報(行程+天氣+待辦) | cron 08:00 |
| `calendar-check` | 查詢 Google Calendar | 使用者查詢 |
| `schedule-plan` | 安排行程 | 使用者指令 |
| `reminder-set` | 設定定時提醒 | 使用者指令 |
| `task-capture` | 快速記錄待辦 | 使用者指令 |
### 7.3 ClawHub Skills已安裝
| Skill | 功能 | 來源 | 備註 |
|-------|------|------|------|
| `skill-vetter` | 安裝前安全審查(檢查權限範圍、可疑模式、風險分級) | ClawHub | 純指引型,無需額外設定 |
| `tavily-tool` | Tavily 網頁搜尋/探索,附來源引用摘要 | ClawHub | 需 `TAVILY_API_KEY`(已設於 `gateway.env`,透過 `EnvironmentFile` 載入) |
> **ClawHub 帳號**`@selika`GitHub: sovaha@gmail.com登入方式`npx clawhub login --token <token> --no-browser`
> **Python 依賴**`tavily-python 0.7.23`(已安裝於 `~/.openclaw/venv/`
> **踩坑**2026-03-11Gateway service 原本沒有 `EnvironmentFile``gateway.env` 的變數不會進入 Gateway 進程。修復service 加 `EnvironmentFile=/home/selig/.config/openclaw/gateway.env`
> **踩坑**2026-03-11skill 用 symlink 分發到 agent workspace 會被 Gateway 安全機制擋掉(`Skipping skill path that resolves outside its configured root`),必須用 `cp -r` 複製
### 7.4 Bundled Skills已啟用
| Skill | 功能 | 依賴 CLI | 備註 |
|-------|------|---------|------|
| `coding-agent` | 分派 coding 任務給 Claude Code/Codex/OpenCode | `claude``~/.local/bin/claude` | 需 bash pty:true |
| `summarize` | 摘要 URL/影片/Podcast 內容 | `summarize``~/.local/bin/summarize` → nvm | `@steipete/summarize` npm 套件 |
> **注意**bundled skills 的 CLI 安裝在 nvm 路徑時,需 symlink 到 `~/.local/bin/` 才能被 Gateway 的 PATH 找到。
> Gateway service PATH`%h/.local/bin:/usr/local/bin:/usr/bin:/bin`
### 7.5 知識庫 Skills
| Skill | 功能 | 觸發方式 |
|-------|------|---------|
| `qmd-brain` | 第二大腦搜尋BM25 + pgvector 語意) | 搜尋、查找、recall、之前說過... |
#### qmd-brain 架構
```
使用者 Telegram 查詢
┌─────────────────────────────────────────────┐
│ qmd-brain skill │
│ 1. qmd search → BM25 全文搜尋 (SQLite) │
│ 2. embed_to_pg → 語意搜尋 (PostgreSQL) │
│ └─ CLIProxyAPI text-embedding-ada-002 │
└─────────────────────────────────────────────┘
夜間排程02:00
qmd embed → 更新本地索引
embed_to_pg embed → 更新 PG 向量庫
```
#### 相關路徑
```
/home/selig/apps/qmd-pg/
├── embed_to_pg.py # 向量寫入/搜尋 Python 腳本
├── nightly-embed.sh # 夜間排程腳本
└── venv/ # Python 虛擬環境
PostgreSQL:
database: qmd_brain
table: brain_documents (vector(1536), HNSW)
user: qmd_user
qmd:
collections: selig-home (/home/selig)
index: ~/.cache/qmd/index.sqlite
```
### 7.6 Skill 格式說明
每個 Skill 由兩個檔案組成:
**SKILL.mdFrontmatter + 說明)**
```yaml
---
name: skill-name # 必填kebab-case和資料夾同名
description: 一句話說明用途 # 必填,顯示在 skills list
triggers: # 必填,空陣列 = 僅供內部呼叫
- "關鍵字1"
- "關鍵字2"
tools: # 必填,宣告可用工具
- exec
- web_fetch
internal: false # 選填true = 對使用者隱藏
---
# Skill 標題
## 功能說明
詳細說明 Skill 的功能、輸入、輸出...
```
**handler.ts實作**
```typescript
export async function handler(ctx: any) {
const message = ctx.message?.text || ctx.message?.content || '';
// skill 邏輯...
return {
reply: '回覆文字(支援 Markdown',
metadata: { key: 'value' }, // 選填,結構化資料
files: ['/tmp/output.wav'], // 選填,附件檔案路徑
};
}
```
> 注意:不可 import 第三方 npm 套件skill 環境無 node_modules外部依賴改用 `execSync('curl ...')` 呼叫。
### 7.7 語音合成 Skilltts-voice
| Skill | 功能 | 觸發方式 |
|-------|------|---------|
| `tts-voice` | 文字轉語音LuxTTS Voice Cloning48kHz | tts、文字轉語音、語音合成、唸出來、說出來 |
- 呼叫本機 LuxTTS APIlocalhost:7860自動取得登入 cookie
- 支援修飾詞:慢速/快速/高品質
- 原始碼:`/home/selig/openclaw-skill/skills/tts-voice/`
### 7.8 Skill 開發指南
完整的 Skill 開發教學(含 SKILL.md 格式、handler.ts 寫法、觸發機制、context 物件、回傳格式、安裝驗證、實戰範例、常見踩坑)請參考:
`/home/selig/openclaw-skill/create-skill.md`

70
chapters/08-plugins.md Normal file
View File

@@ -0,0 +1,70 @@
# 8. Plugin 說明
### 8.1 memory-lancedb-pro對話記憶
**功能**:自動從 OpenClaw 對話中捕捉偏好、事實、決策,並在後續對話中自動召回相關記憶。
**與 qmd-brain 的差異**
| | qmd-brain | memory-lancedb-pro |
|---|-----------|-------------------|
| 資料來源 | ~/home 的 markdown 文件 | OpenClaw 對話本身 |
| 觸發方式 | 手動「搜尋」「recall」 | 自動捕捉+自動召回 |
| 儲存 | PostgreSQL pgvector | LanceDB本地檔案 |
| Embedding | llama-embed本地 GPU | llama-embed本地 GPU |
| 作用域 | 單一 collection | per-agentglobal + agent:xxx |
**設定摘要**
```json5
// openclaw.json → plugins.entries.memory-lancedb-pro
{
"enabled": true,
"config": {
"embedding": {
"provider": "openai-compatible",
"apiKey": "ollama",
"model": "nomic-embed-text-v1.5",
"baseURL": "http://127.0.0.1:11435/v1",
"dimensions": 768
},
"dbPath": "/home/selig/.openclaw/memory-lancedb-pro/data",
"autoCapture": true, // 自動從對話提取記憶
"autoRecall": true, // 查詢前自動注入相關記憶
"captureAssistant": false, // 不記錄 assistant 的回覆
"retrieval": {
"mode": "hybrid", // 向量 + BM25 混合
"vectorWeight": 0.7,
"bm25Weight": 0.3,
"rerank": "lightweight" // 不需外部 API
},
"scopes": {
"default": "global",
"agentAccess": {
"main": ["global", "agent:main"],
"kaiwu": ["global", "agent:kaiwu"],
"tiangong": ["global", "agent:tiangong"],
"yucheng": ["global", "agent:yucheng"],
"life-assistant": ["global", "agent:life-assistant"]
}
}
}
}
```
**相關路徑**
```
~/.openclaw/plugins/memory-lancedb-pro/ # plugin 原始碼
~/.openclaw/memory-lancedb-pro/data/ # LanceDB 資料庫
```
**維運注意**
- 改 plugin `.ts` 後必須清 jiti 快取:`rm -rf /tmp/jiti/`,再重啟 Gateway
- 只改 `openclaw.json` config 不需清 jiti直接重啟即可
- 舊版 `memory-lancedb` 已設為 `enabled: false`,不會衝突
- **`autoRecall``before_agent_start` hook 是同步阻塞的**。若 embedding API 無回應,所有 agent 會卡死。llama-embed 異常時必須立即關閉 `autoRecall`(見 04-known-issues.md §4.14、§4.15
- 容錯腳本 `~/clawd/scripts/embed-health.sh`已實作cron */30 分鐘)自動偵測 + 降級 + 通知
**記憶鐵律**(寫入 AGENTS.mdagent 每個 session 都會遵守):
1. 踩坑後立即存雙層記憶Technical + Principle
2. 記憶條目 < 500 字元,原子化,不存大段摘要
3. 遇錯先 `memory_recall` 再重試
4.`.ts` 必清 `/tmp/jiti/`

146
chapters/09-browser.md Normal file
View File

@@ -0,0 +1,146 @@
# 9. Browser Control 瀏覽器控制
### 9.1 架構總覽
```
Telegram Agent 發出瀏覽器指令
┌──────────────────────────────────────────────┐
│ OpenClaw Gateway (port 18789) │
│ browser.request → 轉發給 Node Host │
└──────────────┬───────────────────────────────┘
│ WebSocket
┌──────────────▼───────────────────────────────┐
│ OpenClaw Node Host │
│ systemd user: openclaw-node.service │
│ browser relay接收 Gateway 指令 │
│ caps: browser, system │
└──────────────┬───────────────────────────────┘
│ CDP (Chrome DevTools Protocol)
┌──────────────▼───────────────────────────────┐
│ Playwright Chromium (port 18801) │
│ systemd user: playwright-chrome.service │
│ binary: ~/.cache/ms-playwright/chromium-1208 │
│ user-data: ~/.openclaw/browser/playwright-data│
│ DISPLAY=:99 (Xvfb) │
└───────────────────────────────────────────────┘
```
### 9.2 服務組成
| 服務 | systemd unit | 功能 | 環境要求 |
|------|-------------|------|---------|
| Node Host | `openclaw-node.service` | Gateway <-> Chrome relay | `DISPLAY=:99` |
| Playwright Chrome | `playwright-chrome.service` | Chromium 實例CDP port 18801 | `DISPLAY=:99` |
### 9.3 Browser Profile
| Profile 名稱 | Driver | Port | 用途 | 狀態 |
|-------------|--------|------|------|------|
| `cdp-direct` | openclaw (CDP) | 18801 | **預設**CLI 使用),直連 Playwright Chromium | 使用中 |
| `chrome` | openclaw (CDP) | 18801 | **覆寫為 CDP**Agent 透過 Node Host 操控時固定走此 profile | 使用中 |
| `openclaw` | openclaw (CDP) | 18801 | **覆寫為 CDP**(原為 Gateway 內建 port 18800會嘗試啟動 snap Chromium 而失敗) | 使用中 |
設定位置:`~/.openclaw/openclaw.json``browser.defaultProfile: "cdp-direct"`
> **踩坑 1**`defaultProfile` 只影響 CLI 指令。Agent 透過 Node Host 操控瀏覽器時**固定走 `chrome` profile**,因此必須在 `browser.profiles` 中覆寫 `chrome` 的 `cdpUrl` 指向 Playwright CDPport 18801否則會走 extension relay 模式而報錯。
>
> **踩坑 2**v2026.3.7 內建 `openclaw` profileport 18800Gateway 會嘗試用 detectedPath`/usr/bin/chromium-browser`snap 版啟動瀏覽器。snap Chromium 會剝掉 CDP 參數導致永遠啟動失敗agent tool call 15 秒後 timeout。**修復**:在 `browser.profiles` 覆寫 `openclaw` profile讓它也指向 Playwright CDPport 18801
### 9.4 常用指令
```bash
# 狀態查看
openclaw browser status # 查看預設 profile 狀態
openclaw browser profiles # 列出所有 profile
openclaw nodes status # Node Host 連線狀態
# 分頁操作
openclaw browser tabs # 列出分頁
openclaw browser open <url> # 開新分頁
openclaw browser navigate <url> # 當前分頁導航
openclaw browser focus <tab-id> # 切換分頁
openclaw browser close <tab-id> # 關閉分頁
# 截圖與快照
openclaw browser screenshot # 截圖
openclaw browser screenshot --full-page # 完整頁面截圖
openclaw browser snapshot # AI 可讀的頁面快照(預設 ai 格式)
openclaw browser snapshot --format aria # Accessibility tree 格式
# 互動操作
openclaw browser click <ref> # 點擊元素
openclaw browser type <ref> "text" # 輸入文字
openclaw browser press Enter # 按鍵
openclaw browser hover <ref> # 滑鼠 hover
openclaw browser fill --fields '[...]' # 表單填寫
# 其他
openclaw browser pdf # 存成 PDF
openclaw browser console --level error # 查看 console 錯誤
openclaw browser evaluate --fn '...' # 執行 JavaScript
```
### 9.5 安裝步驟(從零開始)
```bash
# 1. 確保 Xvfb 在運行DISPLAY=:99
pgrep -la Xvfb
# 2. 安裝 Playwright 瀏覽器(如未安裝)
npx playwright install chromium
# 3. 安裝 OpenClaw Node service
openclaw node install
# 手動加入 DISPLAY=:99 到 service 檔案
# ~/.config/systemd/user/openclaw-node.service → Environment=DISPLAY=:99
# 4. 確保 gateway.env 也有 DISPLAY=:99
echo 'DISPLAY=:99' >> ~/.config/openclaw/gateway.env
# 5. 啟動 Node service 並配對
systemctl --user daemon-reload
systemctl --user enable --now openclaw-node.service
# 等待 Node 連上 Gateway 後出現 pending device
openclaw devices list # 查看 pending request
openclaw devices approve <id> # 核准配對
# 6. 建立 Playwright Chrome service
# 見 ~/.config/systemd/user/playwright-chrome.service
systemctl --user enable --now playwright-chrome.service
# 7. 建立 cdp-direct browser profile
openclaw browser create-profile --name cdp-direct --cdp-url http://127.0.0.1:18801 --driver openclaw
# 8. 設為預設 profile並覆寫 chrome + openclaw profile
# 在 openclaw.json 的 browser 區塊:
# "defaultProfile": "cdp-direct"
# "profiles": {
# "cdp-direct": { "cdpUrl": "http://127.0.0.1:18801", "color": "#00AAFF" },
# "chrome": { "cdpUrl": "http://127.0.0.1:18801", "color": "#00AA00" },
# "openclaw": { "cdpUrl": "http://127.0.0.1:18801", "color": "#FF4500" }
# }
# chrome profile 必須覆寫Agent 透過 Node Host 固定走此 profile
# openclaw profile 必須覆寫,否則 Gateway 嘗試用 snap Chromium 啟動而 timeout
# 9. 重啟 Gateway
systemctl --user restart openclaw-gateway
# 10. 驗證
openclaw browser status
openclaw browser navigate https://example.com
openclaw browser screenshot
```
### 9.6 已知問題
| 問題 | 原因 | 修復 |
|------|------|------|
| Snap Chromium 不支援 `--load-extension` / `--remote-debugging-port` | snap 沙箱會剝掉安全相關旗標 | 改用 Playwright Chromium非 snap直接二進位 |
| Node service `pairing required` | 首次連線需經 Gateway 核准 | `openclaw devices approve <id>` |
| Browser start timeout | Node/Gateway 缺少 `DISPLAY` 環境變數 | 在 service 和 gateway.env 加 `DISPLAY=:99`Gateway service 本身也需要 `Environment=DISPLAY=:99` |
| `openclaw browser start --browser-profile chrome` 需要點擴充套件 | `chrome` profile 使用 extension relay 模式 | 改用 `cdp-direct` profileCDP 直連,不需擴充套件) |
| Port 18800 被 Gateway 佔用 | `openclaw` profile 預設使用 18800 | 自訂 port 使用 18801 |
| Agent 操控瀏覽器仍報 extension relay 錯誤 | `defaultProfile` 只影響 CLIAgent 透過 Node Host 固定走 `chrome` profile | 在 `openclaw.json``browser.profiles` 覆寫 `chrome``cdpUrl` 指向 Playwright CDP port 18801 |
| Agent browser tool timeoutv2026.3.72026-03-11 | 內建 `openclaw` profile 嘗試用 snap Chromium 啟動detectedPath: `/usr/bin/chromium-browser`snap 會剝掉 `--remote-debugging-port` 導致 CDP 永遠無法建立 | 在 `browser.profiles` 覆寫 `openclaw` profile 的 `cdpUrl` 指向 Playwright CDP port 18801同時確認 Gateway service 有 `Environment=DISPLAY=:99` |

221
chapters/10-operations.md Normal file
View File

@@ -0,0 +1,221 @@
# 10. 維運操作手冊
### 10.1 每日確認指令
```bash
# 快速健康檢查
sudo openclaw health
# 查看所有 Docker 容器
sudo docker ps
# 查看 OpenClaw 服務狀態user service
systemctl --user status openclaw-gateway
# 查看 skills 狀態(不加 sudo
openclaw skills list
```
### 10.2 服務重啟
```bash
sudo docker restart nginx # 重啟 nginx
sudo docker restart cli-proxy-api # 重啟 CLIProxyAPI
sudo systemctl restart openclaw # 重啟 OpenClaw
```
### 10.3 OpenClaw 升級
```bash
# 1. 備份設定
cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.pre-upgrade-$(date +%Y%m%d)
# 2. 停止 Gateway避免升級期間衝突
systemctl --user stop openclaw-gateway
# 3. 下載並執行安裝腳本(自動偵測升級)
# 指定版本OPENCLAW_VERSION=2026.3.7 NO_PROMPT=1
# 安裝 beta加 --beta 旗標
curl -fsSL https://openclaw.ai/install.sh -o /tmp/openclaw-install.sh
sudo OPENCLAW_VERSION=<版本號> NO_PROMPT=1 bash /tmp/openclaw-install.sh
# 4. 修正 temp 目錄權限(新版安全檢查要求 700
chmod 700 /tmp/openclaw-$(id -u)
# 5. 驗證 config JSON 有效
python3 -m json.tool ~/.openclaw/openclaw.json > /dev/null
# 6. 啟動 Gateway
systemctl --user start openclaw-gateway
# 7. 驗證
openclaw --version
systemctl --user status openclaw-gateway
openclaw skills list
```
> **注意**
> - 升級後若出現 plugin 警告(如 `plugin removed: xxx`),需手動從 `openclaw.json` 的 `plugins.entries` 移除過期條目。
> - Doctor 在無 TTY 環境(如 SSH non-interactive會跳過 plugin 更新,這是正常的。
> - v2026.3.7 起 browser control server 預設佔用 `gatewayPort + 2`(即 18791無獨立 config key 可改。若與其他服務衝突需搬移對方。
#### 版本紀錄
| 日期 | 版本 | 備註 |
|------|------|------|
| 2026-02-27 | 2026.2.25 | 升級後 `google-antigravity-auth` plugin 殘留需清理 |
| 2026-02-27 | 2026.2.22 | 回滾skill 作者建議此版較穩) |
| 2026-03-08 | 2026.3.7 | 正式版升級browser control port 18791 與 oclaw-auth 衝突,已將 oclaw-auth 搬至 18793 |
### 10.3.1 CLIProxyAPI 升級
```bash
# 手動升級(需 sudo
cd /home/docker/CLIProxyAPI
sudo git pull --ff-only origin main
sudo docker compose down && sudo docker compose build --no-cache && sudo docker compose up -d
# 驗證
sudo docker compose ps
curl -s -H "Authorization: Bearer <API_KEY>" http://127.0.0.1:8317/v1/models | python3 -c "import json,sys; print(len(json.load(sys.stdin)['data']), 'models')"
```
> **自動更新**`~/clawd/scripts/update-cliproxyapi.sh`root crontab每週日 03:30
> 自動 git pull + docker rebuild日誌 `/var/log/cliproxyapi-update.log`
### 10.3.2 自動更新排程(每週日)
| 時間 | 腳本 | Crontab | 說明 |
|------|------|---------|------|
| 02:00 | `nightly-embed.sh` | selig每天 | 知識庫向量更新 |
| 03:00 | `git pull` OpenClaw Skill | selig | Claude Code skill 更新 |
| 03:30 | `update-cliproxyapi.sh` | root | CLIProxyAPI git pull + Docker rebuild |
| 05:00 | `refresh-llm-list.sh` | selig | 同步 CLIProxyAPI 新模型到 OpenClaw config |
> **順序很重要**CLIProxyAPI 先更新03:30模型列表才能在之後05:00抓到新模型。
### 10.3.3 模型冷卻自動切換
`~/clawd/scripts/model-cooldown-watch.sh`cron 每 12 小時)偵測 CLIProxyAPI 模型 cooldown自動切 fallback 並用 `at` 排程精準恢復。
```bash
# 手動觸發
bash ~/clawd/scripts/model-cooldown-watch.sh
# 查看日誌
cat /var/log/model-cooldown.log
# 查看排程的恢復任務
at -l
```
> **原理**API 回 `model_cooldown` + `reset_seconds` → 批量切受影響 agent 到 `agents.defaults.model.fallbacks[0]` → `at now + (reset_seconds+300)/60 minutes` 排程恢復。不依賴 cron 輪詢恢復,避免浪費 API 請求。
### 10.4 日誌查看
```bash
sudo docker logs nginx --tail 50 # nginx 日誌
sudo docker logs cli-proxy-api --tail 50 # CLIProxyAPI 日誌
sudo journalctl -u openclaw -n 50 -f # OpenClaw 即時日誌
sudo openclaw logs # OpenClaw 結構化日誌
```
### 10.5 OpenClaw 管理指令
```bash
# 設備管理
sudo openclaw devices list
sudo openclaw devices approve <id>
# Session 管理
sudo openclaw status
sudo openclaw status --deep
# Cron 任務
sudo openclaw cron list
sudo openclaw cron add --name "test" --cron "0 8 * * *" --session main --system-event "早安"
sudo openclaw cron run <job-id>
# 模型設定
sudo openclaw models status
sudo openclaw doctor
# 安全審計
sudo openclaw security audit
```
### 10.6 備份
```bash
sudo bash ~/backup.sh
# 產生:~/server-backup-YYYYMMDD_HHMMSS.tar.gz約 80KB
```
### 10.7 在新機器還原
```bash
scp server-backup-*.tar.gz user@新機器:~/
ssh user@新機器
tar -xzf server-backup-*.tar.gz
sudo bash restore.sh ~/server-backup-YYYYMMDD_HHMMSS
```
### 10.8 Crontab
**selig user**`crontab -l`
```
0 2 * * * /home/selig/apps/qmd-pg/nightly-embed.sh # 知識庫向量更新
0 2 * * 0 /home/selig/clawd/scripts/refresh-llm-list.sh # 每週日更新 CLIProxyAPI 模型清單
*/15 * * * ~/.acme.sh/acme.sh --cron # SSL 憑證自動續期
```
**root**`sudo crontab -l`
```
0 0 * * * ~/auto_cert_renewal.sh
0 2 * * * docker exec nginx apk add logrotate && docker exec nginx logrotate -f /etc/logrotate.conf
@reboot iptables-restore < /etc/iptables/rules.v4
```
### 10.9 開機自啟動架構
| 服務 | 機制 |
|------|------|
| Docker 本身 | systemd enabled |
| nginx | Docker restart: always |
| CLIProxyAPI | Docker restart: unless-stopped |
| OpenClaw Gateway | systemd user `openclaw-gateway.service` enabled |
| OpenClaw Node Host | systemd user `openclaw-node.service` enabled |
| Playwright Chrome | systemd user `playwright-chrome.service` enabled |
| iptables 規則 | crontab @reboot |
| IPv6 停用 | /etc/sysctl.conf 永久設定 |
---
## 附錄OpenClaw 重要路徑
```
~/.openclaw/openclaw.json 主設定
~/.openclaw/workspace/ Agent 工作目錄
~/.openclaw/agents/main/ 主 Agent 資料
├── auth-profiles.json LLM 認證
├── sessions/sessions.json Session 狀態
└── sessions/*.jsonl 對話記錄
~/.openclaw/credentials/ 頻道憑證
~/.openclaw/devices/paired.json 已配對裝置
~/.openclaw/cron/jobs.json 排程任務
~/.openclaw/logs/ 日誌
# Browser Control
~/.openclaw/browser/chrome-extension/ Chrome 擴充套件snap 不適用)
~/.openclaw/browser/playwright-data/ Playwright Chrome user-data
~/.openclaw/media/browser/ 截圖輸出目錄
~/.cache/ms-playwright/chromium-1208/ Playwright Chromium 二進位
# systemd user services
~/.config/systemd/user/openclaw-gateway.service Gateway
~/.config/systemd/user/openclaw-node.service Node Host需 DISPLAY=:99
~/.config/systemd/user/playwright-chrome.service Playwright Chrome需 DISPLAY=:99
~/.config/openclaw/gateway.env Gateway 環境變數(含 DISPLAY=:99
/tmp/openclaw-1000/openclaw-YYYY-MM-DD.log 即時日誌(重啟後清除)
```