1. 从聊天窗口到无人值守:OpenClaw Headless Agent 到底在跑什么
OpenClaw 是一套把「对话入口」和「执行内核」拆开的 Headless Agent 系统。你看到的可能只是一个 IM 聊天窗口,但底下跑着的是一套能分支、能回放、能压缩、不丢状态的执行引擎。它适合谁?适合那些需要 Agent 在无人值守环境下持续跑任务的人——比如定时巡检服务器、自动整理日志、长期跟踪某个数据源变化,而不是问一句答一句就结束。
我第一次接触 OpenClaw 时,最直观的感受是:它不像一个「更聪明的聊天机器人」,而更像一个可以挂在后台、按心跳醒来的工程进程。它的核心不是 Prompt 写得多花哨,而是把「执行」当成一等公民。Pi 内核负责模型抽象、推理循环、工具调度和流式输出;OpenClaw 在系统层负责 IM 接入、会话分支、权限审计和沙盒策略。两者职责清晰,SDK 内嵌而不是黑盒 RPC,所以会话生命周期完全可控,工具调用可审计。
长期运行的关键在于两层持久化:sessions.json做轻量索引,*.jsonltranscript 做只追加的事件日志。聊天、工具调用、压缩摘要全部落盘。会话不是一条线,而是一棵树,通过id/parentId形成分支结构。主线稳定执行,支线用来修 Bug 或试方案,支线结果可以摘要回主线。这一步极大降低了「调试污染主上下文」的成本。
再加上HEARTBEAT.md让 Agent 在没人找它时也会醒来,本质上就是 Agent 世界里的 Cron:定期巡检、状态检查、主动提醒。配合全量日志、自省能力和人机回环,无界面系统也能保持可控。下面我会从 SDK 初始化、进程守护、健康检查、断线重连到状态恢复,一步步给出可复制的配置和验证动作。
2. TaoToken 前置:给 OpenClaw 准备稳定的模型接入层
OpenClaw 本身不绑定某一家模型,它通过统一的模型抽象层去调用后端。如果你希望 Agent 长期稳定运行,模型接入层就不能今天换一个 Key、明天换一个地址。我建议把模型接入统一收敛到 TaoToken 上,这样 Base URL、Key、Model ID 三件套固定下来,OpenClaw 的配置就不用反复改。
TaoToken 的官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api 。注意 API 地址后面不加 UTM 参数,直接写https://taotoken.net/api即可。你需要先在控制台创建一个 API Key,控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,Key 管理页面在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
拿到 Key 之后,建议先做一次模型对话验证,确认 Key 和网络都正常。模型对话入口是 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。如果你打算长期跑编码类 Agent,可以了解 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,Claude Code 相关说明在 https://taotoken.net/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
这里要强调一点:OpenClaw 的稳定性不只取决于它自己的进程守护,还取决于模型接入层是否稳定。如果 Base URL 经常变、Key 经常失效,再好的守护脚本也救不回来。所以先把三件套固定下来:
| 配置项 | 值 |
|---|---|
| Base URL | https://taotoken.net/api |
| API Key | 在控制台创建,形如sk-... |
| Model ID | 按文档选择,例如claude-sonnet-4-20250514或平台支持的等价模型 |
把这三件套写进 OpenClaw 的模型配置里,后面所有守护、重连、恢复逻辑都围绕它展开。如果你用的是 Claude Code 或 Cline MCP 这类工具,同样需要把 Base URL、Key、Model ID 三件套写全,不能只填 Key。
3. 可复制配置:OpenClaw SDK 初始化与进程守护
这一节给出可以直接复制的配置片段。先看 OpenClaw 的 SDK 初始化。假设你把 OpenClaw 放在/opt/openclaw,配置文件放在/opt/openclaw/config/。模型接入部分建议单独抽一个model.toml,避免和会话配置混在一起。
# /opt/openclaw/config/model.toml [provider] name = "taotoken" base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" model_id = "claude-sonnet-4-20250514" timeout_seconds = 120 max_retries = 3 retry_backoff_ms = 800 [heartbeat] enabled = true interval_seconds = 300 file = "/opt/openclaw/HEARTBEAT.md" [storage] sessions_index = "/opt/openclaw/data/sessions.json" transcript_dir = "/opt/openclaw/data/transcripts" compress_threshold_tokens = 24000对应的 SDK 初始化代码可以这样写。注意这里用的是伪代码风格,具体函数名按你实际使用的 SDK 调整,但结构是一致的:
import os from openclaw import Gateway, PiEngine, SessionStore os.environ["TAOTOKEN_API_KEY"] = os.environ.get("TAOTOKEN_API_KEY", "") engine = PiEngine( base_url="https://taotoken.net/api", api_key=os.environ["TAOTOKEN_API_KEY"], model_id="claude-sonnet-4-20250514", timeout=120, max_retries=3, ) store = SessionStore( index_path="/opt/openclaw/data/sessions.json", transcript_dir="/opt/openclaw/data/transcripts", ) gateway = Gateway( engine=engine, store=store, heartbeat_file="/opt/openclaw/HEARTBEAT.md", heartbeat_interval=300, ) gateway.start()进程守护用 systemd 最省心。写一个/etc/systemd/system/openclaw.service:
[Unit] Description=OpenClaw Headless Agent After=network-online.target Wants=network-online.target [Service] Type=simple User=openclaw WorkingDirectory=/opt/openclaw Environment=TAOTOKEN_API_KEY=sk-your-key-here ExecStart=/usr/bin/python3 /opt/openclaw/run_gateway.py Restart=always RestartSec=5 StartLimitIntervalSec=0 StandardOutput=append:/var/log/openclaw/stdout.log StandardError=append:/var/log/openclaw/stderr.log [Install] WantedBy=multi-user.targetRestart=always配合RestartSec=5保证进程崩溃后 5 秒内拉起。StartLimitIntervalSec=0避免频繁重启被 systemd 限流。日志单独落盘,方便后面排查。
健康检查脚本建议单独写一个/opt/openclaw/healthcheck.sh:
#!/usr/bin/env bash set -euo pipefail GATEWAY_URL="http://127.0.0.1:8787/health" LOG_FILE="/var/log/openclaw/health.log" TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") if curl -fsS --max-time 10 "$GATEWAY_URL" > /tmp/openclaw_health.json; then echo "$TIMESTAMP OK $(cat /tmp/openclaw_health.json)" >> "$LOG_FILE" exit 0 else echo "$TIMESTAMP FAIL gateway unreachable" >> "$LOG_FILE" systemctl restart openclaw.service exit 1 fi再配一个 cron 或 systemd timer,每 60 秒跑一次健康检查。这样即使 Gateway 假死,也能被拉回来。
4. 验证请求与成功结果:断线重连与状态恢复怎么测
配置写完不算完,必须验证。第一步,启动服务并确认进程状态:
sudo systemctl daemon-reload sudo systemctl enable --now openclaw.service sudo systemctl status openclaw.service --no-pager看到active (running)之后,手动触发一次健康检查:
curl -sS http://127.0.0.1:8787/health | jq .正常返回类似:
{ "status": "ok", "uptime_seconds": 42, "sessions_loaded": 3, "last_heartbeat": "2025-01-01T00:00:00Z", "model_provider": "taotoken" }第二步,验证模型接入是否真的通。可以直接用 curl 打一次 TaoToken 的接口:
curl -sS https://taotoken.net/api/v1/messages \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "max_tokens": 64, "messages": [{"role": "user", "content": "ping"}] }' | jq .如果返回里有content字段,说明 Key 和 Base URL 都没问题。如果这里就报 401,先别急着调 OpenClaw,先把 Key 问题解决。
第三步,验证断线重连。手动杀掉 Gateway 进程,观察 systemd 是否在 5 秒内拉起:
sudo pkill -f run_gateway.py sleep 8 sudo systemctl status openclaw.service --no-pager第四步,验证状态恢复。在杀掉进程之前,先让 Agent 跑一个带工具调用的会话,然后查看 transcript 文件:
ls -lh /opt/openclaw/data/transcripts/ tail -n 5 /opt/openclaw/data/transcripts/<session-id>.jsonl重启后再次查询同一个 session,确认历史事件还在,并且sessions.json里的last_event_id能对上。如果 transcript 是只追加的,恢复时只需要从最后一个事件继续,不会丢状态。
第五步,验证心跳。等一个心跳周期(默认 300 秒),查看日志里是否有 heartbeat 记录:
grep -i heartbeat /var/log/openclaw/stdout.log | tail -n 5如果心跳正常触发,说明 Agent 在没人找它的时候也会醒来执行巡检任务。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
长期运行最容易踩的坑集中在接入层和进程层。下面按真实报错逐条排查。
401 Unauthorized。最常见的原因是 Key 没写对或者环境变量没生效。先确认TAOTOKEN_API_KEY在 systemd 的Environment=里写对了,注意不要有多余空格。然后在服务里打印一次环境变量长度做校验:
sudo systemctl show openclaw.service -p Environment如果 Key 是对的还报 401,检查 Base URL 是不是写成了https://taotoken.net/api/带尾斜杠,有些 SDK 拼接路径时会出问题,建议统一写成https://taotoken.net/api。
local proxy failed。这个报错通常出现在 SDK 尝试走本地代理但代理没起来的时候。先确认你没有在环境变量里设置HTTP_PROXY/HTTPS_PROXY指向一个不存在的本地端口。检查:
env | grep -i proxy如果有残留的代理变量,在 systemd 里显式清掉:
Environment=HTTP_PROXY= Environment=HTTPS_PROXY= Environment=NO_PROXY=127.0.0.1,localhostreading choices 相关报错。这类报错一般出现在解析模型返回结构时,说明返回体不是预期的 JSON 结构。先用第 4 节的 curl 命令直接打一次接口,确认返回是标准结构。如果 curl 正常但 OpenClaw 报错,检查 SDK 版本是否和模型返回格式匹配,必要时升级 SDK。
OAuth 相关报错。如果你用的是 Claude Code 或 Cline MCP 这类带 OAuth 流程的工具,报 OAuth 错误通常是因为没有把 Base URL、Key、Model ID 三件套写全。以 Claude Code 为例,需要同时配置:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-your-key-here", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }Cline MCP 的配置类似,Base URL 指向https://taotoken.net/api,Key 用控制台创建的 Key,Model ID 按文档填。Codex 的auth.json同样需要三件套齐全,缺一个都会在 OAuth 或鉴权阶段失败。
进程反复重启。如果systemctl status显示不断重启,先看 stderr 日志:
tail -n 50 /var/log/openclaw/stderr.log常见原因是数据目录权限不对,openclaw用户没有写transcripts目录的权限。修一下:
sudo chown -R openclaw:openclaw /opt/openclaw/data sudo chmod -R 750 /opt/openclaw/data心跳不触发。检查HEARTBEAT.md是否存在且可读,以及heartbeat_interval是否被设成了 0。如果文件路径写错,Gateway 启动时不会报致命错误,但心跳会静默失效,所以启动后一定要 grep 一次日志确认。
6. 长期稳定运行的经验与接入入口
把 OpenClaw 跑稳,核心就三件事:模型接入层固定、进程守护到位、状态持久化可靠。模型接入层用 TaoToken 的 Base URL、Key、Model ID 三件套锁死,避免频繁换配置;进程守护用 systemd 的Restart=always加健康检查脚本双保险;状态持久化靠sessions.json加*.jsonltranscript 的只追加设计,重启后从最后一个事件继续。
如果你还没拿到 Key,先去控制台创建:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。接入过程中遇到鉴权或路径问题,对照接入文档排查:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。想先验证模型是否通,用模型对话入口打一次请求:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。如果你打算让 Agent 长期跑编码或自动化任务,Coding Plan 更适合持续调用场景:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
最后留一个实用技巧:每次改完配置,不要直接重启生产服务,先在本地用curl打一次模型接口,确认三件套没问题,再systemctl restart。这样能把大部分接入层问题挡在重启之前,减少无谓的进程抖动。