关于 openclaw-config
openclaw-config 是面向 OpenClaw 运维人员的排障与配置操作手册,涵盖网关、消息渠道、定时任务、记忆和会话。它提供可复制的命令,用于诊断故障、检查安全设置及安全编辑配置。
主要功能
- 01网关与渠道健康检查
- 02WhatsApp、Telegram、Signal 排障
- 03定时任务与记忆诊断
- 04搜索会话及消息内容
- 05备份、编辑与恢复配置
- 06检查渠道安全策略
适用场景
- 01排查消息渠道无响应或断连
- 02定位失败的定时任务
- 03查找历史会话与消息
- 04更改渠道策略并恢复配置
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ adisinghstudent/ ara.so --skill openclaw-config安装后在 Claude Code 中输入/openclaw-config确认已加载。
详细介绍
OpenClaw 运维手册
诊断并解决实际问题。这里的每条命令都经过测试,可以正常运行。
快速健康检查
出现任何异常时,先运行此检查。复制并粘贴整个代码块:
echo "=== GATEWAY ===" && \
ps aux | grep -c "[o]penclaw" && \
echo "=== CONFIG JSON ===" && \
python3 -m json.tool ~/.openclaw/openclaw.json > /dev/null 2>&1 && echo "JSON: OK" || echo "JSON: BROKEN" && \
echo "=== CHANNELS ===" && \
cat ~/.openclaw/openclaw.json | jq -r '.channels | to_entries[] | "\(.key): policy=\(.value.dmPolicy // "n/a") enabled=\(.value.enabled // "implicit")"' && \
echo "=== PLUGINS ===" && \
cat ~/.openclaw/openclaw.json | jq -r '.plugins.entries | to_entries[] | "\(.key): \(.value.enabled)"' && \
echo "=== CREDS ===" && \
ls ~/.openclaw/credentials/whatsapp/default/ 2>/dev/null | wc -l | xargs -I{} echo "WhatsApp keys: {} files" && \
for d in ~/.openclaw/credentials/telegram/*/; do bot=$(basename "$d"); [ -f "$d/token.txt" ] && echo "Telegram $bot: OK" || echo "Telegram $bot: MISSING"; done && \
[ -f ~/.openclaw/credentials/bird/cookies.json ] && echo "Bird cookies: OK" || echo "Bird cookies: MISSING" && \
echo "=== CRON ===" && \
cat ~/.openclaw/cron/jobs.json | jq -r '.jobs[] | "\(.name): enabled=\(.enabled) status=\(.state.lastStatus // "never") \(.state.lastError // "")"' && \
echo "=== RECENT ERRORS ===" && \
tail -10 ~/.openclaw/logs/gateway.err.log 2>/dev/null && \
echo "=== MEMORY DB ===" && \
sqlite3 ~/.openclaw/memory/main.sqlite "SELECT COUNT(*) || ' chunks, ' || (SELECT COUNT(*) FROM files) || ' files indexed' FROM chunks;" 2>/dev/null
文件一览
~/.openclaw/
├── openclaw.json # MAIN CONFIG — channels, auth, gateway, plugins, skills
├── openclaw.json.bak* # Auto-backups (.bak, .bak.1, .bak.2 ...)
├── exec-approvals.json # Exec approval socket config
│
├── agents/main/
│ ├── agent/auth-profiles.json # Anthropic auth tokens
│ └── sessions/
│ ├── sessions.json # SESSION INDEX — keys are like agent:main:whatsapp:+1234
│ └── *.jsonl # Session transcripts (one JSON per line)
│
├── workspace/ # Agent workspace (git-tracked)
│ ├── SOUL.md # Personality, writing style, tone rules
│ ├── IDENTITY.md # Name, creature type, vibe
│ ├── USER.md # Owner context and preferences
│ ├── AGENTS.md # Session behavior, memory rules, safety
│ ├── BOOT.md # Boot instructions (autopilot notification protocol)
│ ├── HEARTBEAT.md # Periodic task checklist (empty = skip heartbeat)
│ ├── MEMORY.md # Curated long-term memory (main session only)
│ ├── TOOLS.md # Contacts, SSH hosts, device nicknames
│ ├── memory/ # Daily logs: YYYY-MM-DD.md, topic-chat.md
│ └── skills/ # Workspace-level skills
│
├── memory/main.sqlite # Vector memory DB (Gemini embeddings, FTS5 search)
│
├── logs/
│ ├── gateway.log # Runtime: startup, channel init, config reload, shutdown
│ ├── gateway.err.log # Errors: connection drops, API failures, timeouts
│ └── commands.log # Command execution log
│
├── cron/
│ ├── jobs.json # Job definitions (schedule, payload, delivery target)
│ └── runs/ # Per-job run logs: {job-uuid}.jsonl
│
├── credentials/
│ ├── whatsapp/default/ # Baileys session: ~1400 app-state-sync-key-*.json files
│ ├── telegram/{botname}/token.txt # Bot tokens (one per bot account)
│ └── bird/cookies.json # X/Twitter auth cookies
│
├── extensions/{name}/ # Custom plugins (TypeScript)
│ ├── openclaw.plugin.json # {"id", "channels", "configSchema"}
│ ├── index.ts # Entry point
│ └── src/ # channel.ts, actions.ts, runtime.ts, types.ts
│
├── identity/ # device.json, device-auth.json
├── devices/ # paired.json, pending.json
├── media/inbound/ # Received images, audio files
├── media/browser/ # Browser screenshots
├── browser/openclaw/user-data/ # Chromium profile (~180MB)
├── tools/signal-cli/ # Signal CLI binary
├── subagents/runs.json # Sub-agent execution log
├── canvas/index.html # Web canvas UI
└── telegram/
├── update-offset-coder.json # {"lastUpdateId": N} — Telegram polling cursor
└── update-offset-sales.json # Reset these to 0 to replay missed messages
故障排查:WhatsApp
“我发了消息,但没有收到回复”
这是最常见的问题。消息已送达,但机器人没有回复。按以下顺序检查:
# 1. Is the bot actually running?
grep -i "whatsapp.*starting\|whatsapp.*listening" ~/.openclaw/logs/gateway.log | tail -5
# 2. Check for 408 timeout drops (WhatsApp web disconnects frequently)
grep -i "408\|499\|retry" ~/.openclaw/logs/gateway.err.log | tail -10
# If you see "Web connection closed (status 408). Retry 1/12" — this is normal,
# it auto-recovers. But if retries reach 12/12, the session dropped completely.
# 3. Check for cross-context messaging blocks
grep -i "cross-context.*denied" ~/.openclaw/logs/gateway.err.log | tail -10
# Common: "Cross-context messaging denied: action=send target provider "whatsapp" while bound to "signal""
# This means the agent was in a Signal session and tried to reply on WhatsApp.
# FIX: The message needs to come through in the WhatsApp session context, not Signal.
# 4. Check the session exists for that contact
cat ~/.openclaw/agents/main/sessions/sessions.json | jq -r 'to_entries[] | select(.key | test("whatsapp")) | "\(.key) | \(.value.origin.label // "?")"'
# 5. Check if the sender is allowed
cat ~/.openclaw/openclaw.json | jq '.channels.whatsapp | {dmPolicy, allowFrom, selfChatMode, groupPolicy}'
# If dmPolicy is "allowlist" and the sender isn't in allowFrom, message is silently dropped.
# 6. Check if it's a group message (groups are disabled by default)
cat ~/.openclaw/openclaw.json | jq '.channels.whatsapp.groupPolicy'
# "disabled" means ALL group messages are ignored.
# 7. Check for lane congestion (agent busy with another task)
grep "lane wait exceeded" ~/.openclaw/logs/gateway.err.log | tail -5
# If the agent is stuck on a long LLM call, new messages queue up.
# 8. Check for agent run timeout
grep "embedded run timeout" ~/.openclaw/logs/gateway.err.log | tail -5
# Hard limit is 600s (10 min). If the agent's response takes longer, it's killed.
“WhatsApp 完全断开连接”
# Check credential files exist (should be ~1400 files)
ls ~/.openclaw/credentials/whatsapp/default/ | wc -l
# If 0 files: session was never created or got wiped
# Fix: re-pair with `openclaw configure`
# Check for QR/pairing events
grep -i "pair\|link\|qr\|scan\|logged out" ~/.openclaw/logs/gateway.log | tail -10
# Check for Baileys errors
grep -i "baileys\|DisconnectReason\|logout\|stream:error" ~/.openclaw/logs/gateway.err.log | tail -20
# Nuclear fix: delete credentials and re-pair
# rm -rf ~/.openclaw/credentials/whatsapp/default/
# openclaw configure
故障排查:Telegram
“机器人出了问题/会忘事”
有两个看起来相同的独立问题:
# 1. Check for config validation errors (THE COMMON ONE)
grep -i "telegram.*unrecognized\|telegram.*invalid\|telegram.*policy" ~/.openclaw/logs/gateway.err.log | tail -10
# Known issue: the keys "token" and "username" under accounts are not recognized.
# The correct field is "botToken", not "token".
# 2. Check the actual config
cat ~/.openclaw/openclaw.json | jq '.channels.telegram'
# Verify each bot has "botToken" (not "token") and "name" fields.
# 3. Check polling status — bots die after getUpdates timeout
grep -i "telegram.*exit\|telegram.*timeout\|getUpdates" ~/.openclaw/logs/gateway.err.log | tail -10
# "[telegram] [sales] channel exited: Request to 'getUpdates' timed out after 500 seconds"
# This means the bot lost connection to Telegram's API and stopped listening.
# Fix: restart gateway — `openclaw gateway restart`
# 4. Check the polling offset (if bot "forgets" or replays old messages)
cat ~/.openclaw/telegram/update-offset-coder.json
cat ~/.openclaw/telegram/update-offset-sales.json
# If lastUpdateId is stuck or 0, the bot will reprocess old messages.
# To skip to latest: the gateway sets this automatically on restart.
# 5. Check if both bots are starting
grep -i "telegram.*starting\|telegram.*coder\|telegram.*sales" ~/.openclaw/logs/gateway.log | tail -10
# 6. "Bot forgets" — this is usually a session issue, not Telegram
# Each Telegram user gets their own session in sessions.json.
# Check if the session exists:
cat ~/.openclaw/agents/main/sessions/sessions.json | jq -r 'to_entries[] | select(.key | test("telegram")) | "\(.key) | \(.value.origin.label // "?")"'
# 7. Check if compaction happened (context window pruned = "forgot")
SESS_ID="paste-session-id"
grep '"compaction"' ~/.openclaw/agents/main/sessions/$SESS_ID.jsonl | wc -l
# If compaction count > 0, old messages were pruned from context.
# The agent's compaction mode is:
cat ~/.openclaw/openclaw.json | jq '.agents.defaults.compaction'
Telegram 配置修复模板
# Correct Telegram config structure:
cat ~/.openclaw/openclaw.json | jq '.channels.telegram = {
"enabled": true,
"accounts": {
"coder": {
"name": "Bot Display Name",
"enabled": true,
"botToken": "your-bot-token-here"
},
"sales": {
"name": "Sales Bot Name",
"enabled": true,
"botToken": "your-bot-token-here"
}
},
"dmPolicy": "pairing",
"groupPolicy": "disabled"
}' > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
故障排查:Signal
“Signal RPC 发送消息失败”
这会导致 cron 任务和跨渠道通知无法运行。
# 1. Check if signal-cli process is alive
ps aux | grep "[s]ignal-cli"
# 2. Check the RPC endpoint
grep -i "signal.*starting\|signal.*8080\|signal.*rpc" ~/.openclaw/logs/gateway.log | tail -10
# Should see: "[signal] [default] starting provider (http://127.0.0.1:8080)"
# 3. Check for connection instability
grep -i "HikariPool\|reconnecting\|SSE stream error\|terminated" ~/.openclaw/logs/gateway.err.log | tail -10
# "HikariPool-1 - Thread starvation or clock leap detected" = signal-cli internal DB issue
# "SSE stream error: TypeError: terminated" = lost connection to signal-cli daemon
# 4. Check for rate limiting
grep -i "signal.*rate" ~/.openclaw/logs/gateway.err.log | tail -5
# "Signal RPC -5: Failed to send message due to rate limiting"
# 5. Check for wrong target format
grep -i "unknown target" ~/.openclaw/logs/gateway.err.log | tail -5
# "Unknown target "adi" for Signal. Hint: <E.164|uuid:ID|...>"
# The agent must use phone numbers (+1...) or uuid: format, not names.
# 6. Fix profile name warning spam
grep -c "No profile name set" ~/.openclaw/logs/gateway.err.log
# If high count: run signal-cli updateProfile to set a name
# 7. Test signal-cli directly
ACCT=$(cat ~/.openclaw/openclaw.json | jq -r '.channels.signal.account')
echo "Account: $ACCT"
# signal-cli -a $ACCT send -m "test" +TARGET_NUMBER
# 8. Check if the signal-cli daemon needs restart
# The gateway manages signal-cli as a subprocess.
# Restart the whole gateway: openclaw gateway restart
故障排查:Cron 任务
# 1. Overview of all jobs
cat ~/.openclaw/cron/jobs.json | jq -r '.jobs[] | "\(.enabled | if . then "ON " else "OFF" end) \(.state.lastStatus // "never" | if . == "error" then "FAIL" elif . == "ok" then "OK " else . end) \(.name)"'
# 2. Failing jobs with error details
cat ~/.openclaw/cron/jobs.json | jq '.jobs[] | select(.state.lastStatus == "error") | {name, error: .state.lastError, lastRun: (.state.lastRunAtMs | . / 1000 | todate), id}'
# 3. Read the actual run log for a failing job
JOB_ID="paste-job-uuid-here"
tail -20 ~/.openclaw/cron/runs/$JOB_ID.jsonl | python3 -c "
import sys, json
for line in sys.stdin:
try:
obj = json.loads(line)
if obj.get('type') == 'message':
role = obj['message']['role']
text = ''.join(c.get('text','') for c in obj['message'].get('content',[]) if isinstance(c,dict))
if text.strip():
print(f'[{role}] {text[:300]}')
except: pass
"
# 4. Common cron failure causes:
# - "Signal RPC -1" → Signal daemon down, see Signal section above
# - "gateway timeout after 10000ms" → gateway was restarting when cron fired
# - "Brave Search 429" → free tier rate limit hit (2000 req/month)
# - "embedded run timeout" → job took longer than 600s
# 5. Next scheduled run times
cat ~/.openclaw/cron/jobs.json | jq -r '.jobs[] | select(.enabled) | "\(.name): \((.state.nextRunAtMs // 0) | . / 1000 | todate)"'
# 6. Disable a broken job temporarily
cat ~/.openclaw/cron/jobs.json | jq '(.jobs[] | select(.name == "JOB_NAME")).enabled = false' > /tmp/cron.json && mv /tmp/cron.json ~/.openclaw/cron/jobs.json
故障排查:记忆/“它忘了”
记忆系统分为 3 层。当 Agent “忘了”时,其中一层出现了故障:
第 1 层:上下文窗口(会话内)
# Check compaction count for a session (compaction = old messages pruned)
grep -c '"compaction"' ~/.openclaw/agents/main/sessions/SESSION_ID.jsonl
# 7 compactions = the agent has "forgotten" its earliest messages 7 times.
# Check compaction mode
cat ~/.openclaw/openclaw.json | jq '.agents.defaults.compaction'
# "safeguard" = only compacts when hitting context limit
第 2 层:工作区记忆文件
# What daily memory files exist
ls -la ~/.openclaw/workspace/memory/
# What's in MEMORY.md (long-term curated)
cat ~/.openclaw/workspace/MEMORY.md
# Search memory files for something specific
grep -ri "KEYWORD" ~/.openclaw/workspace/memory/
第 3 层:向量记忆数据库(SQLite + Gemini 嵌入)
# What files are indexed
sqlite3 ~/.openclaw/memory/main.sqlite "SELECT path, size, datetime(mtime/1000, 'unixepoch') as modified FROM files;"
# How many chunks (text fragments) exist
sqlite3 ~/.openclaw/memory/main.sqlite "SELECT COUNT(*) FROM chunks;"
# Search chunks by text (FTS5 full-text search)
sqlite3 ~/.openclaw/memory/main.sqlite "SELECT substr(text, 1, 200) FROM chunks_fts WHERE chunks_fts MATCH 'KEYWORD' LIMIT 5;"
# Check embedding config
sqlite3 ~/.openclaw/memory/main.sqlite "SELECT value FROM meta WHERE key='memory_index_meta_v1';" | python3 -m json.tool
# Check for Gemini embedding rate limits (breaks indexing)
grep -i "gemini.*batch.*failed\|RESOURCE_EXHAUSTED\|429" ~/.openclaw/logs/gateway.err.log | tail -10
# "embeddings: gemini batch failed (2/2); disabling batch" = indexing degraded
# Rebuild memory index (re-index all workspace files)
# Delete the DB and restart gateway — it will rebuild:
# rm ~/.openclaw/memory/main.sqlite && openclaw gateway restart
搜索会话
查找某人的对话
# Search session index by name (case-insensitive)
cat ~/.openclaw/agents/main/sessions/sessions.json | jq -r 'to_entries[] | select(.value.origin.label // "" | test("NAME"; "i")) | "\(.value.sessionId) | \(.value.lastChannel) | \(.value.origin.label)"'
按渠道查找会话
cat ~/.openclaw/agents/main/sessions/sessions.json | jq -r 'to_entries[] | select(.value.lastChannel == "whatsapp") | "\(.value.sessionId) | \(.value.origin.label // .key)"'
# Replace "whatsapp" with: signal, telegram, or check .key for cron sessions
最近的会话
cat ~/.openclaw/agents/main/sessions/sessions.json | jq -r '[to_entries[] | {id: .value.sessionId, updated: .value.updatedAt, label: (.value.origin.label // .key), ch: (.value.lastChannel // "cron")}] | sort_by(.updated) | reverse | .[:10][] | "\(.updated | . / 1000 | todate) | \(.ch) | \(.label)"'
搜索所有会话中的消息内容
# Quick: find which session files contain a keyword
grep -l "KEYWORD" ~/.openclaw/agents/main/sessions/*.jsonl
# Detailed: show matching messages with timestamps
grep "KEYWORD" ~/.openclaw/agents/main/sessions/*.jsonl | python3 -c "
import sys, json
for line in sys.stdin:
path, data = line.split(':', 1)
try:
obj = json.loads(data)
if obj.get('type') == 'message':
role = obj['message']['role']
text = ''.join(c.get('text','') for c in obj['message'].get('content',[]) if isinstance(c,dict))
if text.strip():
sid = path.split('/')[-1].replace('.jsonl','')[:8]
ts = obj.get('timestamp','')[:19]
print(f'{ts} [{sid}] [{role}] {text[:200]}')
except: pass
" | head -30
阅读特定会话的记录
# Last 30 messages from a session
tail -50 ~/.openclaw/agents/main/sessions/SESSION_ID.jsonl | python3 -c "
import sys, json
for line in sys.stdin:
try:
obj = json.loads(line)
if obj.get('type') == 'message':
role = obj['message']['role']
text = ''.join(c.get('text','') for c in obj['message'].get('content',[]) if isinstance(c,dict))
if text.strip() and role != 'toolResult':
print(f'[{role}] {text[:300]}')
print()
except: pass
"
编辑配置
安全编辑流程
始终先备份,再用 jq 编辑,然后重启。
cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak.manual
jq 'YOUR_EDIT_HERE' ~/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
openclaw gateway restart
常见编辑
# Switch WhatsApp to allowlist
jq '.channels.whatsapp.dmPolicy = "allowlist" | .channels.whatsapp.allowFrom = ["+1XXXXXXXXXX"]' ~/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
# Enable WhatsApp autopilot (bot responds as you to everyone)
jq '.channels.whatsapp += {dmPolicy: "open", selfChatMode: false, allowFrom: ["*"]}' ~/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
# Add number to Signal allowlist
jq '.channels.signal.allowFrom += ["+1XXXXXXXXXX"]' ~/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
# Change model
jq '.agents.defaults.models = {"anthropic/claude-sonnet-4": {"alias": "sonnet"}}' ~/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
# Set concurrency
jq '.agents.defaults.maxConcurrent = 10 | .agents.defaults.subagents.maxConcurrent = 10' ~/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
# Disable a plugin
jq '.plugins.entries.imessage.enabled = false' ~/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
从备份恢复
# Latest backup
cp ~/.openclaw/openclaw.json.bak ~/.openclaw/openclaw.json
# List all backups by date
ls -lt ~/.openclaw/openclaw.json.bak*
# Validate JSON before restart
python3 -m json.tool ~/.openclaw/openclaw.json > /dev/null && echo "OK" || echo "BROKEN"
# Nuclear reset
openclaw configure
渠道安全模式
| 模式 | 行为 | 风险 |
|---|---|---|
open + allowFrom: ["*"] | 任何人都能发消息,机器人会回复所有人 | 高 — 消耗 API 额度,机器人会以你的身份发言 |
allowlist + allowFrom: ["+1..."] | 只有列出的号码可以通过 | 低 — 控制明确 |
pairing | 未知发件人会收到一个代码,由你批准 | 低 — 需要经过批准 |
disabled | 渠道完全关闭 | 无 |
检查当前安全状态
cat ~/.openclaw/openclaw.json | jq '{
whatsapp: {policy: .channels.whatsapp.dmPolicy, from: .channels.whatsapp.allowFrom, groups: .channels.whatsapp.groupPolicy, selfChat: .channels.whatsapp.selfChatMode},
signal: {policy: .channels.signal.dmPolicy, from: .channels.signal.allowFrom, groups: .channels.signal.groupPolicy},
telegram: {policy: .channels.telegram.dmPolicy, groups: .channels.telegram.groupPolicy, bots: [.channels.telegram.accounts | to_entries[] | "\(.key)=\(.value.enabled)"]},
imessage: {enabled: .channels.imessage.enabled, policy: .channels.imessage.dmPolicy}
}'
工作区文件
| 文件 | 内容 | 编辑时机 |
|---|---|---|
SOUL.md | 个性:语气、风格(“不用长破折号,随意使用小写”) | 更改机器人的说话方式时 |
IDENTITY.md | 名称(Jarvis)、生物类型、表情符号 | 更改品牌形象时 |
USER.md | 所有者信息、偏好 | 用户背景信息发生变化时 |
AGENTS.md | 操作规则:记忆协议、安全、群聊行为、心跳指令 | 更改机器人行为时 |
BOOT.md | 启动指令(自动驾驶通知协议:WA → Signal) | 更改启动时的行为时 |
HEARTBEAT.md | 定期检查清单(为空 = 不调用心跳 API) | 添加/移除定期任务时 |
MEMORY.md | 精选的长期记忆(仅在主会话/直接会话中加载) | 由机器人自行管理 |
TOOLS.md | 联系人、SSH 主机、设备昵称 | 添加本地工具备注时 |
memory/*.md | 每日原始日志、特定主题的聊天日志 | 由机器人自动写入 |
会话 JSONL 格式
每个 .jsonl 文件每行包含一个 JSON 对象。类型:
| 类型 | 内容 |
|---|---|
session | 会话标头:id、时间戳、cwd |
message | 对话轮次:角色(user/assistant/toolResult)、内容、模型、用量 |
custom | 元数据:model-snapshot、openclaw.cache-ttl |
compaction | 上下文窗口已裁剪(丢弃了较早的消息) |
model_change | 会话中途切换了模型 |
thinking_level_change | 调整了思考级别 |
会话索引(sessions.json)中的键:
- 模式:
agent:main:{channel}:{contact}或agent:main:cron:{job-uuid} - 字段:
sessionId(UUID = 文件名)、lastChannel、origin.label(人类可读名称)、origin.from(规范地址)、updatedAt(epoch 毫秒)、chatType(direct/group)
Gateway 启动顺序
正常启动大约需要 3 秒:
[heartbeat] started
[gateway] listening on ws://127.0.0.1:18789
[browser/service] Browser control service ready
[hooks] loaded 3 internal hook handlers (boot-md, command-logger, session-memory)
[whatsapp] [default] starting provider
[signal] [default] starting provider (http://127.0.0.1:8080)
[telegram] [coder] starting provider
[telegram] [sales] starting provider
[whatsapp] Listening for personal WhatsApp inbound messages.
[signal] signal-cli: Started HTTP server on /127.0.0.1:8080
如果缺少任何一行,说明对应组件未能启动。请检查 gateway.err.log。
常见错误模式
| 错误 | 含义 | 解决方法 |
|---|---|---|
Web connection closed (status 408) | WhatsApp Web 超时,自动重试最多 12 次 | 通常会自动恢复。如果达到 12/12,请重启网关 |
Signal RPC -1: Failed to send message | signal-cli 守护进程连接丢失 | 重启网关 |
Signal RPC -5: Failed to send message due to rate limiting | Signal 速率限制 | 等待后重试,降低消息发送频率 |
No profile name set(signal-cli WARN) | 日志会被大量刷屏,但无害 | signal-cli -a +ACCOUNT updateProfile --given-name "Name" |
Cross-context messaging denied | Agent 尝试跨频道发送消息 | 这不是 bug,而是安全防护措施。消息必须来自正确频道的会话 |
getUpdates timed out after 500 seconds | Telegram 机器人丢失轮询连接 | 重启网关 |
Unrecognized keys: "token", "username" | Telegram 机器人配置键错误 | 在 openclaw.json 中使用 botToken,而不是 token |
RESOURCE_EXHAUSTED(Gemini 429) | 嵌入速率限制 | 减少工作区文件变动,或升级 Gemini 配额 |
lane wait exceeded | Agent 被较长的大模型调用阻塞 | 等待;如果卡住超过 2 分钟,则重启 |
embedded run timeout: timeoutMs=600000 | Agent 响应超过 10 分钟 | 将任务拆分成更小的部分 |
gateway timeout after 10000ms | 重启期间网关无法访问 | 网关关闭时触发了 Cron——这是暂时现象 |
扩展 OpenClaw
OpenClaw 有 4 个扩展层,每一层解决不同的问题:
| 层 | 内容 | 位置 | 添加方式 |
|---|---|---|---|
| 技能 | Agent 按需加载的知识和工作流 | /opt/homebrew/lib/node_modules/openclaw/skills/ 或 ~/.openclaw/workspace/skills/ | clawdhub install <slug> 或 npx add-skill <repo> |
| 扩展 | 自定义频道插件(TypeScript) | ~/.openclaw/extensions/{name}/ | 创建 openclaw.plugin.json 和 TypeScript 源文件 |
| 频道 | 消息平台(内置) | openclaw.json → channels.* + plugins.entries.* | 在 openclaw.json 中配置并添加凭据 |
| Cron 任务 | 定时自主任务 | ~/.openclaw/cron/jobs.json | Agent 通过工具创建,或直接编辑 jobs.json |
技能:ClawdHub 生态系统
技能是扩展 Agent 知识和能力的主要方式。它们是 Markdown 文件,可包含可选脚本或资源,并会在相关时加载到上下文中。
# Search for skills (vector search across the registry)
clawdhub search "postgres optimization"
clawdhub search "image generation"
# Browse latest skills
clawdhub explore
# Install a skill
clawdhub install supabase-postgres-best-practices
clawdhub install nano-banana-pro
# Install a specific version
clawdhub install my-skill --version 1.2.3
# List what's installed
clawdhub list
# Update all installed skills
clawdhub update --all
# Update a specific skill
clawdhub update my-skill
clawdhub update my-skill --force # overwrite local changes
当前已安装的技能(与 OpenClaw 捆绑):
| 类别 | 技能 |
|---|---|
| 消息 | discord、slack、imsg、wacli、voice-call |
| 社交/网页 | bird(X/Twitter)、blogwatcher、github、trello、notion |
| gog、google-workspace-mcp、goplaces、local-places | |
| 媒体 | nano-banana-pro(Gemini 图像生成)、openai-image-gen、video-frames、gifgrep、pixelation、sag(TTS)、openai-whisper、sherpa-onnx-tts、songsee、camsnap |
| 编码 Agent | coding-agent(Codex/Claude Code/Pi)、ccbg(后台运行器)、tmux |
| 效率工具 | apple-notes、apple-reminders、bear-notes、things-mac、obsidian、himalaya(电子邮件) |
| 智能家居 | openhue(Philips Hue)、eightctl(Eight Sleep)、sonoscli、blucli(BluOS) |
| 开发工具 | github、worktree、starter、desktop、supabase-postgres-best-practices、superdesign |
| 内容 | remotion-best-practices、remotion-fastest-tech-stack、humanizer、summarize、market、buildinpublic |
| 元工具 | skill-creator、clawdhub、find-skills、add-skill、model-usage、session-logs、recentplans、canvas |
创建自己的技能
技能只是一个包含 SKILL.md 的文件夹:
my-skill/
├── SKILL.md # Required: YAML frontmatter + markdown instructions
├── scripts/ # Optional: executable scripts
├── references/ # Optional: docs loaded on demand
└── assets/ # Optional: templates, images
SKILL.md 格式:
---
name: my-skill
description: What this does and WHEN to trigger it. The description is the primary
trigger — the agent reads this to decide whether to load the full skill.
---
# My Skill
Instructions go here. Only loaded AFTER the skill triggers.
Keep under 500 lines. Split large content into references/ files.
核心原则:上下文窗口是一种共享资源。 只包含 Agent 尚不了解的内容。相比冗长的说明,优先使用简洁的示例。
# Publish to ClawdHub
clawdhub login
clawdhub publish ./my-skill --slug my-skill --name "My Skill" --version 1.0.0
# Or publish to GitHub for npx add-skill
# (see add-skill skill for details)
多 Agent 编排
OpenClaw 可以将其他 AI Agent(Codex、Claude Code、Pi)作为后台工作进程启动。借助这一功能,你可以并行执行编码任务、代码审查,或任何适合由多个 Agent 协作完成的工作。
模式: bash pty:true background:true workdir:/path command:"agent 'task'"
# Spawn Codex to build something (background, auto-approve)
bash pty:true workdir:~/project background:true command:"codex exec --full-auto 'Build a REST API for todos'"
# Returns sessionId for tracking
# Spawn Claude Code on a different task
bash pty:true workdir:~/other-project background:true command:"claude 'Refactor the auth module'"
# Monitor all running agents
process action:list
# Check output of a specific agent
process action:log sessionId:XXX
# Send input if agent asks a question
process action:submit sessionId:XXX data:"yes"
# Kill a stuck agent
process action:kill sessionId:XXX
并行审查 PR:
# Fetch all PR refs
git fetch origin '+refs/pull/*/head:refs/remotes/origin/pr/*'
# Launch one agent per PR
bash pty:true workdir:~/project background:true command:"codex exec 'Review PR #86. git diff origin/main...origin/pr/86'"
bash pty:true workdir:~/project background:true command:"codex exec 'Review PR #87. git diff origin/main...origin/pr/87'"
使用 git worktrees 并行修复问题:
git worktree add -b fix/issue-78 /tmp/issue-78 main
git worktree add -b fix/issue-99 /tmp/issue-99 main
bash pty:true workdir:/tmp/issue-78 background:true command:"codex --yolo 'Fix issue #78: description. Commit and push.'"
bash pty:true workdir:/tmp/issue-99 background:true command:"codex --yolo 'Fix issue #99: description. Commit and push.'"
Agent 完成时自动通知:
bash pty:true workdir:~/project background:true command:"codex --yolo exec 'Your task.
When completely finished, run: openclaw gateway wake --text \"Done: summary\" --mode now'"
添加新频道
频道是 Agent 可以通过其进行通信的平台。内置频道包括:WhatsApp、Signal、Telegram、iMessage、Discord、Slack。
启用内置频道:
# 1. Enable the plugin
jq '.plugins.entries.discord.enabled = true' ~/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
# 2. Add channel config
jq '.channels.discord = {enabled: true, dmPolicy: "pairing", groupPolicy: "disabled"}' ~/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
# 3. Add credentials (channel-specific)
# 4. Restart gateway
openclaw gateway restart
构建自定义频道扩展:
~/.openclaw/extensions/{name}/
├── openclaw.plugin.json # {"id": "name", "channels": ["name"], "configSchema": {...}}
├── package.json # Standard npm package
├── index.ts # Entry point
└── src/
├── channel.ts # Inbound message handling + outbound send
├── actions.ts # Tool actions the agent can invoke
├── runtime.ts # Lifecycle: start, stop, health check
├── config-schema.ts # JSON schema for plugin config
└── types.ts # TypeScript types
# List installed extensions
ls ~/.openclaw/extensions/
# View extension manifests
cat ~/.openclaw/extensions/*/openclaw.plugin.json | jq .
# Check extension source files
find ~/.openclaw/extensions/ -name "*.ts" -not -path "*/node_modules/*"
跨频道通信
Agent 可以在一个频道接收消息,并在另一个频道发送消息,但需遵守以下防护措施:
# Check cross-context settings
cat ~/.openclaw/openclaw.json | jq '.tools.message.crossContext'
# allowAcrossProviders: true = agent CAN send across channels
# marker.enabled: false = no "[via Signal]" prefix on cross-channel messages
# If you see "Cross-context messaging denied" errors:
# The agent tried to send from a session bound to channel A to channel B.
# This is a security feature. To allow it:
jq '.tools.message.crossContext.allowAcrossProviders = true' ~/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
BOOT.md 通知协议(已配置): Agent 接收 WhatsApp 消息,在 WhatsApp 上回复,然后向 Signal 发送通知摘要。这是主要的跨频道模式——在一个频道上自动运行,在另一个频道上进行控制。
Canvas:已连接设备的 Web UI
向已连接的 Mac/iOS/Android 节点推送 HTML/游戏/仪表板:
# Check canvas config
cat ~/.openclaw/openclaw.json | jq '.canvasHost // "not configured"'
# List connected nodes
openclaw nodes list
# Present HTML content on a node
# canvas action:present node:<node-id> target:http://localhost:18793/__moltbot__/canvas/my-page.html
# Canvas files live in:
ls ~/.openclaw/canvas/
语音通话
通过 Twilio/Telnyx/Plivo 发起电话呼叫:
# Check if voice-call plugin is enabled
cat ~/.openclaw/openclaw.json | jq '.plugins.entries["voice-call"] // "not configured"'
# CLI usage
openclaw voicecall call --to "+15555550123" --message "Hello"
openclaw voicecall status --call-id <id>
Cron:计划的自主任务
# View all jobs
cat ~/.openclaw/cron/jobs.json | jq '.jobs[] | {name, enabled, schedule: .schedule, channel: .payload.channel, to: .payload.to}'
# Job schedule types:
# "kind": "at", "atMs": <epoch> — one-shot at specific time
# "kind": "every", "everyMs": <ms> — recurring interval
# Job delivery targets:
# channel + to fields determine where results go (signal, whatsapp, telegram)
# sessionTarget: "isolated" = fresh context each run (no memory of previous runs)
# To add a job, the agent creates it via tool, or edit jobs.json:
# See existing jobs as templates in ~/.openclaw/cron/jobs.json
许可证
MIT