1. 从“你问它才答”到“它自己找活干”:OpenClaw 自动化工作流到底解决什么问题
如果你已经用 OpenClaw 搭过一个能查数据库、能搜网页、能写文件的 Agent,大概率会遇到同一个瓶颈:它很聪明,但太被动。你不发消息,它就静静待着;你忘了问日报,它就永远不生成;工具报错了,它回一句“抱歉出错了”,然后等你手动重试。这种状态下的 Agent 更像一个高级问答框,而不是能替你分担重复劳动的“数字员工”。
OpenClaw 自动化工作流要解决的就是这个断层。它把三样东西拼在一起:Hooks 负责在 Agent 生命周期的关键节点自动执行指令,定时任务负责在没人说话的时候按 Cron 表达式唤醒 Agent,Multi-MCP 负责让 Agent 在一次任务里串联多个工具服务器完成跨系统操作。三者组合之后,Agent 的行为模式从“请求-响应”变成“事件-执行-记录”,你睡觉的时候它也能拉数据、生成报告、推送通知、出错自愈。
这套东西适合谁?适合已经跑通 OpenClaw 基础部署、接入了至少一个 MCP 工具、并且手里有重复性日常任务的开发者。比如每天要从 PostgreSQL 拉销售数据写日报、每小时要检查一次服务健康状态、GitHub PR 合并后要自动更新 Changelog。这些事单次做不费劲,但天天做就是消耗。把它们交给 Hooks + 定时任务 + Multi-MCP 组成的链路,才是“数字员工”真正开始上班的时刻。
下面我会按可复制的顺序,先讲清楚 Hooks 的配置怎么写、定时任务的 Cron 表达式怎么填、Multi-MCP 怎么注册,然后给出一条从触发到执行结果的完整验证动作,最后把常见报错逐个拆开。所有配置片段都可以直接粘到~/.openclaw/openclaw.json里改路径和 Key 就能跑。
2. 前置准备:统一 Key/API 通道与 OpenClaw 环境自检
在写 Hooks 和定时任务之前,先把模型调用通道理顺。OpenClaw 的 Agent 在自动化任务里会频繁调用模型做推理和摘要,如果每个 MCP 工具或每个 Agent 各自配一套 Key,后面排障会非常痛苦。我习惯的做法是走一个统一的 API 通道,把 Base URL 和 Key 集中管理,Agent 和工具都从这里取。
TaoToken 的接入方式就是这种统一通道:官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api 。你需要在 OpenClaw 的模型 provider 配置里把baseUrl指向这个 API 地址,apiKey填你在控制台生成的 Key。控制台和 Key 管理页面分别是 https://taotoken.net/console 和 https://taotoken.net/api-keys ,模型对话调试入口在 https://taotoken.net/models ,接入文档在 https://taotoken.net/doc 。如果你后面要跑长期编码或 Agent 类任务,Coding Plan 页面在 https://taotoken.net/coding-plan ,Claude Code 相关接入在 https://taotoken.net/claude-code 。
配置模型 provider 的片段长这样,路径是~/.openclaw/openclaw.json下的models.providers:
{ "models": { "providers": { "taotoken": { "baseUrl": "https://taotoken.net/api", "apiKey": "${TAOTOKEN_API_KEY}", "models": [ { "id": "claude-sonnet-4-20250514", "reasoning": true, "contextWindow": 200000, "maxTokens": 8192 } ] } } } }这里TAOTOKEN_API_KEY建议放在环境变量里,不要硬编码进 JSON。OpenClaw 支持${VAR}语法读取环境变量,这样你换 Key 的时候只改.env或 shell profile,不用动配置文件。
环境自检用openclaw doctor,它会检查 Gateway 是否运行、MCP 服务器是否可达、模型 provider 是否能连通、Scheduler 是否启用。如果这一步就报local proxy failed或401,先别往下写 Hooks,把通道问题解决掉。openclaw doctor的输出里会明确告诉你哪个 provider 连不上、哪个 MCP 进程没起来。
另外确认你的 OpenClaw 版本支持scheduler和hooks字段。老版本可能只有mcpServers和channels,没有scheduler和agents.defaults.hooks。用openclaw --version看一下,如果版本太旧,先升级再继续。前置准备做完之后,你的openclaw.json里至少应该有models.providers、mcpServers、agents.defaults这三块,后面加 Hooks 和 Scheduler 都是往这个结构里补。
3. 可复制配置:Hooks 触发点、Cron 表达式与 Multi-MCP 注册
这一节是整篇的核心,所有片段都可以直接复制。先讲 Hooks 的配置结构,再讲定时任务的 Cron 表达式,最后讲 Multi-MCP 的注册方式。
3.1 Hooks 配置:afterResponse 与 onError
Hooks 写在agents.defaults.hooks下面,每个 Hook 点是一个对象,包含enabled、instruction、可选的script、maxRetries、condition、tools。instruction是你写给 Agent 的自然语言指令,Agent 会在对应生命周期节点执行它。script是可选的 shell 脚本路径,用于异步通知这类不该阻塞主流程的操作。
{ "agents": { "defaults": { "hooks": { "afterResponse": { "enabled": true, "instruction": "检查刚才的对话是否包含以下内容:\n1. 技术决策(选择了某个方案/工具/架构)\n2. TODO 或待办事项\n3. 用户表达的偏好或规范\n4. 重要的日期或截止时间\n\n如果包含以上任何一项,将其简洁地追加写入 memory/ 今天的日志文件中。\n格式:## HH:MM - 类别\\n- 具体内容\n\n如果对话只是闲聊或简单问答,不需要记录。", "condition": "message.length > 100" }, "onError": { "enabled": true, "instruction": "分析错误类型并按以下策略处理:\n\n1. 暂时性错误(timeout, rate_limit, connection_refused, 5xx):\n - 等待 3 秒后自动重试一次\n - 重试时可尝试换用备选工具\n\n2. 认证错误(401, 403, invalid_key):\n - 不要重试\n - 记录到 memory/errors.md\n - 告诉用户需要更新凭证\n\n3. 数据错误(invalid_json, parse_error):\n - 检查输入参数是否正确\n - 调整参数后重试一次\n\n4. 未知错误:\n - 记录完整错误信息到 memory/errors.md\n - 通知用户并建议检查日志", "maxRetries": 1, "notifyScript": "~/.openclaw/hooks/error-notify.sh" } } } } }condition字段用message.length > 100过滤掉短对话,避免每条消息都触发 Hook。notifyScript指向一个 shell 脚本,在重试也失败后执行,用来发通知。脚本内容如下,路径是~/.openclaw/hooks/error-notify.sh:
#!/bin/bash # ~/.openclaw/hooks/error-notify.sh # 接收参数:$1=错误类型 $2=错误消息 $3=工具名称 ERROR_TYPE="${1:-unknown}" ERROR_MSG="${2:-no message}" TOOL_NAME="${3:-unknown tool}" TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') curl -s -X POST "https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_WEBHOOK_KEY" \ -H "Content-Type: application/json" \ -d "{ \"msg_type\": \"interactive\", \"card\": { \"header\": { \"title\": {\"tag\": \"plain_text\", \"content\": \"OpenClaw Agent 错误告警\"}, \"template\": \"red\" }, \"elements\": [{ \"tag\": \"div\", \"text\": { \"tag\": \"lark_md\", \"content\": \"**时间**: ${TIMESTAMP}\n**工具**: ${TOOL_NAME}\n**错误类型**: ${ERROR_TYPE}\n**错误消息**: ${ERROR_MSG}\" } }] } }" > /dev/null 2>&1 &注意脚本末尾的&,它让 curl 在后台执行,不阻塞 Agent 主流程。Hook 脚本必须加执行权限:chmod +x ~/.openclaw/hooks/*.sh。
3.2 定时任务:Cron 表达式与 scheduler 配置
定时任务写在scheduler.tasks数组里,每个任务包含id、cron、timezone、agent、message、timeout、可选的dependsOn和onFailure。
{ "scheduler": { "enabled": true, "tasks": [ { "id": "daily-data-collection", "cron": "30 8 * * 1-5", "timezone": "Asia/Shanghai", "agent": "personal", "message": "执行每日数据采集:查询 PostgreSQL 获取昨日注册/活跃/流失用户数、收入和退款数据。搜索品牌提及和竞品动态。把原始数据保存到 ~/reports/data/daily-{date}.json。", "timeout": "10m" }, { "id": "daily-report", "cron": "0 9 * * 1-5", "timezone": "Asia/Shanghai", "agent": "personal", "message": "基于 ~/reports/data/daily-{date}.json 的数据生成日报。分析趋势,标记异常。保存到 ~/reports/daily-{date}.md。发送摘要到飞书群。", "timeout": "10m", "dependsOn": "daily-data-collection" }, { "id": "hourly-healthcheck", "cron": "0 * * * *", "agent": "devops", "message": "运行数据库健康检查和网站健康检查。如果有警告或异常,发送到 Telegram。如果一切正常,不需要通知。", "timeout": "5m" } ] } }Cron 表达式是五段式:分 时 日 月 周。常用写法对照如下:
| 表达式 | 含义 |
|---|---|
0 9 * * * | 每天 09:00 |
0 9 * * 1-5 | 工作日 09:00 |
*/30 * * * * | 每 30 分钟 |
0 */2 * * * | 每 2 小时 |
0 9,18 * * * | 每天 09:00 和 18:00 |
0 10 * * 1 | 每周一 10:00 |
0 0 1 * * | 每月 1 号 00:00 |
dependsOn保证daily-report在daily-data-collection完成后再执行,避免数据还没落盘就开始分析。onFailure: "notify"让任务失败时触发通知,沉默的失败最可怕。
3.3 Multi-MCP 注册:多个工具服务器协同
Multi-MCP 的注册写在mcpServers下面,每个服务器一个键,包含command、args、可选的env。下面注册了 PostgreSQL、Brave Search、Filesystem、GitHub 四个服务器:
{ "mcpServers": { "postgres": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-postgres"], "env": { "POSTGRES_CONNECTION_STRING": "${POSTGRES_CONNECTION_STRING}" } }, "brave-search": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-brave-search"], "env": { "BRAVE_API_KEY": "${BRAVE_API_KEY}" } }, "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/workspace", "/home/user/reports"] }, "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" } } } }注册完之后,Agent 在一次任务里可以按 Skill 指令串联多个 MCP。比如“查 PostgreSQL 拿数据 → AI 分析 → 用 Filesystem 写报告 → 用 exec 调 curl 发飞书”。你不需要显式编排调用顺序,只要在 Skill 的 Workflow 里写清楚步骤,Agent 会自己选工具。但对关键路径,建议在 Skill 里明确指定工具名,比如“使用 PostgreSQL MCP 的 query 工具查询数据,不要用 exec + psql”,避免 Agent 走弯路。
三件套确认:Base URL 是https://taotoken.net/api,Key 从 https://taotoken.net/api-keys 生成,Model ID 填claude-sonnet-4-20250514或你实际使用的模型。这三个值在models.providers.taotoken里必须齐全,否则 Agent 在自动化任务里调模型会直接 401。
4. 验证请求:从触发到执行结果的完整链路
配置写完不代表能跑。这一节给一条从手动触发到看到结果的验证动作,确保 Hooks、定时任务、Multi-MCP 三段都通。
4.1 验证 Hooks 是否触发
先手动发一条超过 100 字符的消息,触发afterResponseHook。用openclaw message命令:
openclaw message --agent personal \ "我们决定用 Redis 做缓存层,过期时间统一设为 15 分钟。另外 TODO:下周三之前完成缓存穿透的防护方案,记得加上布隆过滤器。"发送后观察日志:
openclaw logs --follow --filter hooks如果 Hook 正常触发,日志里会出现afterResponse hook triggered,然后 Agent 会执行instruction里的记录动作。检查memory/目录下今天的日志文件:
cat memory/$(date +%Y-%m-%d).md预期看到类似内容:
## 14:30 - 技术决策 - 缓存层选用 Redis - 统一过期时间:15 分钟 ## 14:30 - TODO - 下周三之前完成缓存穿透防护方案 - 加上布隆过滤器如果日志里没有hook triggered,检查agents.defaults.hooks.afterResponse.enabled是否为true,以及condition是否把消息过滤掉了。
4.2 验证定时任务是否执行
不要等 Cron 到点,用openclaw scheduler run手动触发:
openclaw scheduler run daily-data-collection然后看执行历史:
openclaw scheduler history daily-data-collection --last 5预期输出:
2026-03-25 08:30 completed (2m 14s) 2026-03-24 08:30 completed (1m 58s) 2026-03-21 08:30 partial (PostgreSQL timeout, fallback used)再看任务日志,确认 Multi-MCP 调用链:
openclaw scheduler log daily-data-collection --run-id 2026-03-25-0830日志里应该能看到 PostgreSQL MCP 的 query 调用、Brave Search 的搜索调用、Filesystem 的 write_file 调用。如果某个 MCP 没被调用,检查 Skill 的 Workflow 描述是否清晰,或者 Agent 是否选错了工具。
4.3 验证 Multi-MCP 协同
跑一次完整的日报生成,观察跨 MCP 调用:
openclaw message --agent personal \ "生成昨日销售报告(使用 daily-sales-report Skill)"预期链路:PostgreSQL MCP 查询订单数据 → AI 分析趋势 → Filesystem MCP 写入~/reports/daily-sales-2026-03-25.md→ exec 调 curl 发飞书通知 → afterResponse Hook 记录到 Memory。
检查报告文件:
ls -la ~/reports/daily-sales-*.md head -30 ~/reports/daily-sales-$(date +%Y-%m-%d).md如果报告生成了但飞书没收到,检查FEISHU_WEBHOOK_URL环境变量和 curl 命令的 JSON 格式。如果报告没生成,看openclaw logs --follow --filter mcp里 PostgreSQL MCP 是否连接成功。
4.4 验证 onError 自愈
故意制造一个错误,比如把 PostgreSQL 连接串改错,然后触发任务:
openclaw scheduler run daily-data-collection观察日志:
openclaw logs --follow --filter hooks预期看到onError hook triggered→ 判断为暂时性错误 → 等待 3 秒 → 重试一次 → 如果还失败 → 写入memory/errors.md→ 执行error-notify.sh→ 飞书群收到告警卡片。
检查错误记录:
cat memory/errors.md如果重试成功,日志里会显示retry succeeded,任务继续执行。如果重试失败,告警脚本应该发出通知。这一步验证通过,说明你的“数字员工”具备了出错自愈和告警能力。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
自动化链路跑起来之后,报错基本集中在这几类。逐个拆开。
5.1 401 Unauthorized
报错长这样:
Error: 401 Unauthorized {"error":{"type":"authentication_error","message":"invalid api key"}}原因通常是TAOTOKEN_API_KEY没设置、设置错了、或者环境变量没被 OpenClaw 读到。排查步骤:先确认环境变量存在,echo $TAOTOKEN_API_KEY看有没有值;再确认openclaw.json里写的是${TAOTOKEN_API_KEY}而不是硬编码的旧 Key;最后确认 OpenClaw 进程启动时加载了环境变量,如果你用 systemd 或 launchd 启动,环境变量要写在 service 文件里,不是 shell profile 里。
修复后重启 Gateway:openclaw gateway restart,再跑openclaw doctor确认 provider 连通。
5.2 local proxy failed
报错长这样:
Error: local proxy failed: dial tcp 127.0.0.1:7890: connect: connection refused这是 OpenClaw 尝试走本地代理但代理没启动。检查你的环境变量里有没有HTTP_PROXY、HTTPS_PROXY、ALL_PROXY指向一个没运行的本地端口。如果有,要么启动对应服务,要么在 OpenClaw 配置里显式禁用代理。在openclaw.json的gateway段加:
{ "gateway": { "proxy": { "enabled": false } } }然后重启 Gateway。如果你确实需要代理才能访问外部 API,确保代理服务在 OpenClaw 启动前已经运行。
5.3 reading choices 报错
报错长这样:
Error: reading choices: unexpected end of JSON input这是模型返回的响应体不完整,通常是流式响应被中断或 API 返回了非 JSON 内容。排查:先看openclaw logs --follow --filter model里模型请求的原始响应;如果是超时导致,把timeout调大;如果是 API 返回了 HTML 错误页(比如 502),检查 Base URL 是否正确指向https://taotoken.net/api而不是别的地址。另外确认maxTokens没设得过大导致响应被截断。
5.4 OAuth 相关报错
如果你用 Claude Code 或某些需要 OAuth 的工具,可能遇到:
Error: OAuth token expired Error: invalid_grant这类报错说明 OAuth 凭证过期或刷新失败。Claude Code 的接入方式参考 https://taotoken.net/claude-code ,按文档重新走一遍授权流程。如果是 Codex 的auth.json,检查文件路径和 token 有效期。OAuth 类问题不要靠重试解决,重试只会一直失败,必须重新授权。
5.5 Hook 脚本没执行
报错不明显,但日志里没有 Hook 触发记录。排查:确认脚本有执行权限chmod +x ~/.openclaw/hooks/*.sh;确认script路径是绝对路径或~开头的路径;确认enabled是true;确认condition没把当前消息过滤掉。如果 Hook 触发了但脚本没跑,看openclaw logs --follow --filter hooks里有没有script execution failed。
5.6 定时任务重复执行
如果你跑了多个 Gateway 实例,Cron 任务会在每个实例上各触发一次。排查:ps aux | grep openclaw看有几个 Gateway 进程;确保只有一个实例启用了scheduler.enabled: true。多实例部署时,Scheduler 应该只在主实例上启用,其他实例设scheduler.enabled: false。
5.7 Webhook 返回 401
外部系统调 Webhook 时返回 401,说明Authorization: Bearer的 token 和gateway.webhooks.auth.token不匹配。检查两边是否一致,注意不要有多余空格。测试命令:
curl -X POST http://localhost:18789/hook/deploy \ -H "Authorization: Bearer $WEBHOOK_AUTH_TOKEN" \ -H "Content-Type: application/json" \ -d '{"repository":"myapp","ref":"main","status":"success"}'如果返回 404,检查routes[].path是否匹配;如果返回 500,看 Gateway 日志里 Agent 执行是否报错。
6. 把重复操作交出去:统一通道接入与长期运行建议
走到这里,你的 OpenClaw 已经具备了一个“数字员工”的基本形态:Hooks 在生命周期节点自动记录和自愈,定时任务在无人值守时唤醒 Agent,Multi-MCP 让一次任务串联多个系统。剩下的就是让它稳定跑下去。
统一 Key/API 通道是长期运行的关键。所有模型调用走 https://taotoken.net/api ,Key 在 https://taotoken.net/api-keys 管理,接入文档在 https://taotoken.net/doc 。这样你换模型、调额度、排障都只在一个地方操作,不用在多个 provider 之间来回切换。模型对话调试用 https://taotoken.net/models ,长期编码或 Agent 任务用 https://taotoken.net/coding-plan ,Claude Code 接入参考 https://taotoken.net/claude-code 。
几个实测下来有用的习惯:新自动化工作流先手动触发几天,确认无副作用再开 Cron;每个定时任务都设timeout,没有超时的任务可能永远跑下去;关键任务设onFailure: "notify",沉默的失败最可怕;Hook 保持轻量,afterResponse里不要做同步网络请求,必须异步的逻辑用后台脚本;自动化任务的结果写入 Memory,这样后续人工对话能感知到自动任务做了什么。
最后一步,把openclaw status加进你的日常检查:
openclaw status # Gateway: running (uptime: 14d 3h) # Channels: 4 active # MCP Servers: 3 healthy # Scheduler: 3 tasks (2 active, 1 completed today) # Watchers: 1 active # Memory: 47 files indexed, last sync: 2 min ago看到 Scheduler 和 MCP Servers 都是健康状态,说明你的数字员工正在按时上班。