OpenClaw 自动化工作流实战:用 Hooks + 定时任务 + Multi-MCP 构建“数字员工“

OpenClaw 自动化工作流实战:用 Hooks + 定时任务 + Multi-MCP 构建"数字员工"

⚡ 你的 OpenClaw Agent 还在等你发消息才动?本文教你让它自己动起来------定时拉数据、自动分析、主动报告、出错自愈。从被动应答到主动干活,Agent 真正变成 7×24 的数字员工

📑 文章目录

  1. 从"被动助手"到"主动员工"
  2. [自动化三大支柱:Hooks + 定时任务 + 事件驱动](#自动化三大支柱:Hooks + 定时任务 + 事件驱动)
  3. [Hooks 深度解析:Agent 生命周期的每个拦截点](#Hooks 深度解析:Agent 生命周期的每个拦截点)
  4. [实战一:afterResponse Hook------自动记录决策日志](#实战一:afterResponse Hook——自动记录决策日志)
  5. [实战二:onError Hook------错误自愈与告警](#实战二:onError Hook——错误自愈与告警)
  6. [实战三:Tool Hooks------拦截危险操作](#实战三:Tool Hooks——拦截危险操作)
  7. [定时任务:让 Agent 按时上班](#定时任务:让 Agent 按时上班)
  8. [实战四:每日自动从 PostgreSQL 拉数据生成报告](#实战四:每日自动从 PostgreSQL 拉数据生成报告)
  9. 实战五:监控网站变更,自动推送到飞书
  10. [事件驱动:外部系统触发 Agent](#事件驱动:外部系统触发 Agent)
  11. [Multi-MCP 编排:让多个工具协同工作](#Multi-MCP 编排:让多个工具协同工作)
  12. 实战六:完整的"数字员工"工作流
  13. 调试、监控与最佳实践

1. 从"被动助手"到"主动员工"

如果你跟着我之前的系列文章走到了这里,你的 OpenClaw Agent 已经非常强大了:

复制代码
你已经拥有的能力(之前的文章):

✅ 本地部署                     ← 龙虾机器人部署指南
✅ MCP 工具连接                 ← MCP 集成实战
✅ 搜索互联网                   ← Tavily 集成 / Agent-Reach
✅ 记忆系统                     ← Memory 深度解析
✅ 本地模型推理                 ← Ollama 实战
✅ Skills 扩展                  ← Skills 开发指南
✅ 安全加固                     ← 安全加固完全指南
✅ 多平台接入                   ← 多平台接入全指南

但有一个根本性的局限:Agent 只在你发消息时才工作

复制代码
现在(被动模式):

🧑 你发消息 → 🤖 Agent 回复 → 🧑 你再发 → 🤖 再回复
              ↑                              ↑
         你不说话,Agent 就不动             一切靠你推动

目标(主动模式):

⏰ 每天 9:00  → 🤖 Agent 自动拉取昨日数据,生成报告,发到飞书
📡 网站变更   → 🤖 Agent 自动检测,摘要变更,推送到 Telegram
❌ 工具报错   → 🤖 Agent 自动重试,失败则降级,同时通知你
📝 对话结束   → 🤖 Agent 自动把关键决策写入 Memory

OpenClaw 有一套完整的自动化基础设施来实现这个目标。它主要由三个部分组成:Hooks (生命周期钩子)、定时任务 (Cron/Scheduler)和事件驱动(外部触发)。


2. 自动化三大支柱:Hooks + 定时任务 + 事件驱动

复制代码
┌──────────────────────────────────────────────────────────┐
│                  OpenClaw 自动化架构                       │
│                                                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │  🪝 Hooks    │  │  ⏰ 定时任务  │  │  📡 事件驱动    │  │
│  │             │  │             │  │                 │  │
│  │ 拦截 Agent  │  │ Cron 表达式 │  │ Webhook 触发    │  │
│  │ 生命周期    │  │ 定时触发    │  │ 文件监视触发    │  │
│  │ 事件        │  │ Agent 任务  │  │ 消息触发        │  │
│  └──────┬──────┘  └──────┬──────┘  └────────┬────────┘  │
│         │                │                   │           │
│         └────────────────┼───────────────────┘           │
│                          ▼                               │
│                 ┌────────────────┐                        │
│                 │  OpenClaw      │                        │
│                 │  Agent         │                        │
│                 │  (执行引擎)    │                        │
│                 └───────┬────────┘                        │
│                         │                                │
│              ┌──────────┼──────────┐                     │
│              ▼          ▼          ▼                     │
│         🔧 MCP 工具  📁 文件系统  💬 IM 平台              │
│         PostgreSQL   读写文件     Telegram                │
│         Brave Search 执行脚本     飞书                    │
│         Notion       Git 操作     Discord                │
└──────────────────────────────────────────────────────────┘
支柱 触发方式 适用场景
Hooks Agent 内部事件(回复后、出错时、工具调用前后) 日志、自愈、审计、拦截
定时任务 时间(Cron 表达式) 日报、数据同步、健康检查
事件驱动 外部信号(Webhook、文件变更、消息) CI/CD 通知、监控报警、自动化流水线

3. Hooks 深度解析:Agent 生命周期的每个拦截点

Hooks 是 OpenClaw 自动化的核心基础设施。它们让你在 Agent 生命周期的关键时刻注入自定义逻辑------不需要修改 Agent 代码,不需要编写插件。

3.1 Hook 的本质

Hook 在 OpenClaw 中是 Markdown 指令和可选脚本的组合,在特定生命周期事件时执行。Hook 不是"代码回调"------它是你写给 Agent 的一条指令,告诉它在某个时机做某件事。

3.2 可用的 Hook 点

OpenClaw 的 Context Engine 在其整个生命周期中暴露钩子。

Hook 名称 触发时机 典型用途
onSessionStart 新会话开始时 加载上下文、设置环境
onSessionEnd 会话结束时 保存状态、清理资源
afterResponse Agent 每次回复后 日志记录、决策追踪
onError 工具调用或推理出错时 自愈、降级、告警
beforeToolCall 工具调用前 参数验证、权限检查、拦截
afterToolCall 工具调用后 结果记录、后处理
onCompaction 上下文压缩前 Memory Flush 的扩展
prepareSubagentSpawn SubAgent 启动前 注入上下文、限制权限
onSubagentEnded SubAgent 结束后 收集结果、合并状态

3.3 Hook 的配置方式

Hook 可以在多个层级配置。优先级从高到低:Agent 级别(agents.list[].hooks)→ 默认级别(agents.defaults.hooks)→ Skill 内嵌(SKILL.md 中声明)。

jsonc 复制代码
// ~/.openclaw/openclaw.json
{
  "agents": {
    "defaults": {
      "hooks": {
        "afterResponse": {
          "enabled": true,
          "instruction": "记录本次对话中的关键决策到 memory/ 目录",
          "script": "~/.openclaw/hooks/after-response.sh"
        },
        "onError": {
          "enabled": true,
          "instruction": "分析错误原因。如果是暂时性错误(网络超时、API 限流),自动重试一次。如果是持久性错误,记录到 memory/errors.md 并通知用户。",
          "maxRetries": 1
        }
      }
    }
  }
}

3.4 Hook 的执行模型

Hook 执行是同步阻塞的------afterResponse Hook 必须完成后,Agent 才会处理下一条用户消息。保持 Hook 精简,避免在关键路径上做重操作。长时间运行的 Hook 会阻塞会话。

对于需要异步处理的 Hook(如发送通知、写入远程数据库),用脚本在后台执行:

bash 复制代码
#!/bin/bash
# ~/.openclaw/hooks/after-response.sh
# 后台异步发送通知,不阻塞 Agent
nohup curl -s -X POST "https://hooks.feishu.cn/your-webhook" \
  -H "Content-Type: application/json" \
  -d "{\"msg_type\":\"text\",\"content\":{\"text\":\"Agent 完成了一次回复\"}}" \
  > /dev/null 2>&1 &

4. 实战一:afterResponse Hook------自动记录决策日志

4.1 场景

你希望 Agent 在每次回复后,自动把对话中的关键决策、技术选型、TODO 项写入 Memory,而不需要你每次都说"记住这个"。

4.2 配置

jsonc 复制代码
{
  "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"
        }
      }
    }
  }
}

4.3 效果

复制代码
💬 你:我们决定用 Redis 做缓存层,过期时间统一设为 15 分钟

🤖 Agent:好的,Redis 缓存方案确认...(正常回复)

  [afterResponse Hook 触发]
  [自动写入 memory/2026-03-25.md]

--- memory/2026-03-25.md 新增内容 ---
## 14:30 - 技术决策
- 缓存层选用 Redis
- 统一过期时间:15 分钟

4.4 与 Memory 系统的联动

如果你读过我之前的 Memory 系统深度解析,你会发现这个 Hook 本质上是把 Memory Flush(压缩前才触发)的逻辑提前到了每次回复后。区别是:

机制 触发时机 记录内容
Memory Flush 上下文即将压缩时 抢救性存档,避免丢失
afterResponse Hook 每次回复后 主动记录关键信息
用户手动"记住这个" 用户触发 精确记录指定内容

三者互补,不冲突。


5. 实战二:onError Hook------错误自愈与告警

5.1 场景

MCP 工具调用偶尔会失败------网络超时、API 限流、数据库连接中断。你不希望 Agent 遇到错误就卡住或返回"抱歉出错了",你希望它能自动重试、降级、并在必要时通知你。

5.2 配置

jsonc 复制代码
{
  "agents": {
    "defaults": {
      "hooks": {
        "onError": {
          "enabled": true,
          "instruction": "分析错误类型并按以下策略处理:\n\n1. 暂时性错误(timeout, rate_limit, connection_refused, 5xx):\n   - 等待 3 秒后自动重试一次\n   - 重试时可尝试换用备选工具(如 web_search 失败,试 web_fetch)\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"
        }
      }
    }
  }
}

5.3 告警脚本

bash 复制代码
#!/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 &

5.4 效果

复制代码
🤖 Agent 尝试调用 PostgreSQL MCP 查询数据...
❌ 连接超时 (connection_refused)

  [onError Hook 触发]
  → 判定为暂时性错误
  → 等待 3 秒
  → 自动重试...
  ✅ 重试成功,返回数据

--- 如果重试也失败 ---

  [onError Hook 再次触发]
  → 已达最大重试次数
  → 写入 memory/errors.md
  → 执行 error-notify.sh → 飞书群收到告警卡片
  → 告诉用户:"PostgreSQL 连接失败,已记录错误并通知运维"

6. 实战三:Tool Hooks------拦截危险操作

6.1 场景

你给了 Agent exec 权限(allowlist 模式),但你仍然担心某些特定命令的参数可能导致问题。例如,rm 在白名单内,但你想在 Agent 删除超过 10 个文件时自动拦截并要求确认。

6.2 配置

jsonc 复制代码
{
  "agents": {
    "defaults": {
      "hooks": {
        "beforeToolCall": {
          "enabled": true,
          "instruction": "在 exec 工具调用前检查以下规则:\n\n1. 如果命令包含 rm 且作用于多个文件(通配符或列表),要求用户显式确认\n2. 如果命令包含 DROP TABLE 或 DELETE FROM(无 WHERE),立即阻止并告警\n3. 如果命令向外部 IP 发送数据(curl POST 到非 localhost),要求确认\n4. 如果命令修改 /etc/ 或 ~/.ssh/ 下的文件,立即阻止\n\n不满足以上规则的命令正常放行。",
          "tools": ["exec"]
        },
        "afterToolCall": {
          "enabled": true,
          "instruction": "在 exec 工具调用后,如果返回码非 0,记录失败命令和错误输出到 memory/ 今天的日志中,包含完整命令和 stderr。",
          "tools": ["exec"]
        }
      }
    }
  }
}

6.3 效果

复制代码
🤖 Agent 准备执行:rm -rf /tmp/build-*

  [beforeToolCall Hook 触发]
  → 检测到 rm + 通配符
  
🤖 Agent:检测到批量删除操作。将删除 /tmp/build-* 下所有匹配文件。
          确认执行?(是/否)

💬 你:是

🤖 Agent:[执行 rm -rf /tmp/build-*]
          ✅ 已删除 23 个临时构建目录

  [afterToolCall Hook 触发]
  → 返回码 0,正常,不记录

7. 定时任务:让 Agent 按时上班

Hooks 解决了"Agent 内部事件"的自动化。但如果你想让 Agent 在没有人发消息的情况下主动工作------比如每天早上 9 点生成报告------你需要定时任务。

7.1 方案选择

OpenClaw 通过 Scheduler 支持定时任务。有三种实现方式:

方案 原理 复杂度 适用场景
系统 Cron + CLI crontab 定时调用 openclaw message ⭐ 最简单 Linux/Mac 个人用
内置 Scheduler openclaw.json 中声明定时任务 ⭐⭐ 推荐 多任务、需管理
外部编排(n8n/Temporal) 外部系统通过 Webhook 触发 ⭐⭐⭐ 复杂 企业级工作流

7.2 方案一:系统 Cron + CLI(最快上手)

bash 复制代码
# 编辑 crontab
crontab -e

# 每天早上 9:00 让 Agent 生成日报
0 9 * * * /usr/local/bin/openclaw message --agent personal \
  "生成昨天的工作日报,包括 git 提交、PR 状态、TODO 进展。保存到 ~/reports/ 并发送到飞书群。" \
  >> /var/log/openclaw-cron.log 2>&1

# 每小时检查一次网站变更
0 * * * * /usr/local/bin/openclaw message --agent monitor \
  "检查 https://docs.example.com/changelog 是否有更新。如果有,摘要变更并发送到 Telegram。" \
  >> /var/log/openclaw-cron.log 2>&1

# 每周一早上 10:00 生成周报
0 10 * * 1 /usr/local/bin/openclaw message --agent personal \
  "生成上周的周报,格式参照 weekly-report Skill。" \
  >> /var/log/openclaw-cron.log 2>&1

openclaw message 命令向指定 Agent 发送一条消息并等待完成。它利用了 OpenClaw 的非交互命令接口。

7.3 方案二:内置 Scheduler

jsonc 复制代码
// ~/.openclaw/openclaw.json
{
  "scheduler": {
    "enabled": true,
    "tasks": [
      {
        "id": "daily-report",
        "cron": "0 9 * * *",           // 每天 09:00
        "timezone": "Asia/Shanghai",
        "agent": "personal",
        "message": "生成昨天的工作日报。收集 git log、GitHub PR、memory/ 中的记录。保存到 ~/reports/daily-{date}.md 并发送到飞书群。",
        "timeout": "10m",
        "onFailure": "notify"
      },
      {
        "id": "db-healthcheck",
        "cron": "*/30 * * * *",         // 每 30 分钟
        "agent": "devops",
        "message": "运行数据库健康检查(db-healthcheck Skill)。如果有警告或严重问题,发送到 Telegram。",
        "timeout": "5m"
      },
      {
        "id": "weekly-summary",
        "cron": "0 10 * * 1",           // 每周一 10:00
        "agent": "personal",
        "message": "生成上周周报。格式参照 weekly-report Skill。发送到飞书并抄送邮件。",
        "timeout": "15m"
      }
    ]
  }
}

7.4 Cron 表达式速查

复制代码
┌─────── 分 (0-59)
│ ┌───── 时 (0-23)
│ │ ┌─── 日 (1-31)
│ │ │ ┌─ 月 (1-12)
│ │ │ │ ┌─ 周几 (0-7, 0/7=周日)
│ │ │ │ │
* * * * *

常用表达式:
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

8. 实战四:每日自动从 PostgreSQL 拉数据生成报告

8.1 目标架构

复制代码
⏰ 每天 09:00
    │
    ▼
🤖 Agent 启动定时任务
    │
    ├── 1. 调用 PostgreSQL MCP → 查询昨日销售数据
    │
    ├── 2. 调用 PostgreSQL MCP → 查询昨日用户增长
    │
    ├── 3. AI 分析数据趋势,生成洞察
    │
    ├── 4. 生成 Markdown 报告 → 保存到 ~/reports/
    │
    ├── 5. 发送到飞书群(互动卡片格式)
    │
    └── 6. 写入 memory/:今日报告已生成

8.2 前置条件

确保你已经配好了(参考之前的文章):

bash 复制代码
# PostgreSQL MCP 已配置(参考 MCP 集成实战)
# 飞书频道已接入(参考多平台接入指南)
# Memory 系统已启用(参考 Memory 深度解析)

# 验证
openclaw doctor

8.3 创建 Skill:daily-sales-report

bash 复制代码
mkdir -p ~/.openclaw/workspace/skills/daily-sales-report
yaml 复制代码
---
name: daily-sales-report
description: Generate daily sales report from PostgreSQL database, analyze trends, and send to Feishu group. Use when asked to generate daily report, create sales summary, or analyze yesterday's sales data.
metadata: {"openclaw":{"emoji":"📊","requires":{"env":["PGHOST","FEISHU_WEBHOOK_URL"]}}}
---

# Daily Sales Report Generator

## Workflow

1. Determine the report date (default: yesterday)
2. Query PostgreSQL for sales data:

```sql
-- 昨日销售概况
SELECT
  COUNT(*) as order_count,
  SUM(amount) as total_revenue,
  AVG(amount) as avg_order_value,
  COUNT(DISTINCT customer_id) as unique_customers
FROM orders
WHERE created_at >= CURRENT_DATE - INTERVAL '1 day'
  AND created_at < CURRENT_DATE;
sql 复制代码
-- 各品类销售排行
SELECT
  p.category,
  COUNT(*) as orders,
  SUM(oi.quantity * oi.unit_price) as revenue
FROM order_items oi
JOIN products p ON oi.product_id = p.id
JOIN orders o ON oi.order_id = o.id
WHERE o.created_at >= CURRENT_DATE - INTERVAL '1 day'
  AND o.created_at < CURRENT_DATE
GROUP BY p.category
ORDER BY revenue DESC
LIMIT 10;
sql 复制代码
-- 与上周同日对比
SELECT
  'yesterday' as period,
  COUNT(*) as orders,
  SUM(amount) as revenue
FROM orders
WHERE created_at >= CURRENT_DATE - INTERVAL '1 day'
  AND created_at < CURRENT_DATE
UNION ALL
SELECT
  'last_week_same_day',
  COUNT(*),
  SUM(amount)
FROM orders
WHERE created_at >= CURRENT_DATE - INTERVAL '8 days'
  AND created_at < CURRENT_DATE - INTERVAL '7 days';
  1. Analyze the data:

    • Calculate week-over-week growth rate
    • Identify top-performing and underperforming categories
    • Flag any anomalies (revenue drop > 20%, order count spike > 50%)
  2. Generate report and save to ~/reports/daily-sales-{date}.md

  3. Send summary to Feishu webhook:

bash 复制代码
curl -s -X POST "$FEISHU_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d "{\"msg_type\":\"interactive\",\"card\":{\"header\":{\"title\":{\"tag\":\"plain_text\",\"content\":\"📊 每日销售报告 - {date}\"},\"template\":\"blue\"},\"elements\":[{\"tag\":\"div\",\"text\":{\"tag\":\"lark_md\",\"content\":\"REPORT_CONTENT_HERE\"}}]}}"
  1. Record in memory that today's report has been generated.

Rules

  • Never fabricate data. Only report actual query results.

  • If PostgreSQL is unreachable, report the connection failure instead.

  • If data seems anomalous (all zeros, negative values), flag it explicitly.

  • Keep the Feishu message under 2000 characters. Full report is in the file.

    8.4 配置定时任务

    jsonc 复制代码
    {
      "scheduler": {
        "enabled": true,
        "tasks": [
          {
            "id": "daily-sales-report",
            "cron": "0 9 * * 1-5",
            "timezone": "Asia/Shanghai",
            "agent": "personal",
            "message": "生成昨日销售报告(使用 daily-sales-report Skill)",
            "timeout": "10m",
            "onFailure": "notify"
          }
        ]
      }
    }

8.5 验证

bash 复制代码
# 手动触发测试(不等 Cron)
openclaw message --agent personal \
  "生成昨日销售报告(使用 daily-sales-report Skill)"

# 检查定时任务状态
openclaw scheduler list
# ID                   CRON           NEXT RUN           STATUS
# daily-sales-report   0 9 * * 1-5    2026-03-26 09:00   ✅ active

# 查看任务执行历史
openclaw scheduler history daily-sales-report
# 2026-03-25 09:00  ✅ completed (4m 23s)
# 2026-03-24 09:00  ✅ completed (3m 58s)
# 2026-03-21 09:00  ⚠️ partial (PostgreSQL timeout, fallback used)

9. 实战五:监控网站变更,自动推送到 Telegram

9.1 场景

你想监控竞品文档、政策法规页面或 API Changelog 的变更,一有更新就自动摘要并推送到手机。

9.2 创建 Skill:site-monitor

yaml 复制代码
---
name: site-monitor
description: Monitor web pages for changes, generate summaries of what changed, and send alerts via messaging platforms. Use when asked to monitor websites, track page changes, watch for updates, or set up change detection.
metadata: {"openclaw":{"emoji":"👁️","requires":{"bins":["curl","diff"]}}}
---

# Site Monitor

## Workflow

1. Read the target URL from the user's request
2. Fetch the current page content:

```bash
curl -sL "{URL}" | python3 -c "
import sys, html
from html.parser import HTMLParser
class TextExtractor(HTMLParser):
    def __init__(self):
        super().__init__()
        self.text = []
        self.skip = False
    def handle_starttag(self, tag, attrs):
        if tag in ('script', 'style', 'nav', 'footer'):
            self.skip = True
    def handle_endtag(self, tag):
        if tag in ('script', 'style', 'nav', 'footer'):
            self.skip = False
    def handle_data(self, data):
        if not self.skip:
            self.text.append(data.strip())
p = TextExtractor()
p.feed(sys.stdin.read())
print('\n'.join(t for t in p.text if t))
" > /tmp/site-monitor-current.txt
  1. Compare with the previous snapshot:
bash 复制代码
if [ -f ~/monitors/{DOMAIN}-last.txt ]; then
  diff ~/monitors/{DOMAIN}-last.txt /tmp/site-monitor-current.txt > /tmp/site-diff.txt
  CHANGED=$?
else
  CHANGED=2  # First run, no previous snapshot
fi
  1. If changes detected (CHANGED != 0):

    • Analyze the diff and generate a human-readable summary
    • Categorize: new content / removed content / modified content
    • Assess significance: minor (typo fixes) / major (new feature, policy change)
    • Send alert to the configured messaging platform
  2. Save current version as new snapshot:

bash 复制代码
mkdir -p ~/monitors
cp /tmp/site-monitor-current.txt ~/monitors/{DOMAIN}-last.txt
  1. If no changes: do nothing (silent success)

Rules

  • Only report actual changes, never fabricate differences

  • For first-run (no previous snapshot), just save and report "首次快照已保存"

  • Keep alert messages concise: what changed + significance + link

    9.3 定时任务配置

    jsonc 复制代码
    {
      "scheduler": {
        "tasks": [
          {
            "id": "monitor-api-docs",
            "cron": "0 */2 * * *",          // 每 2 小时
            "agent": "monitor",
            "message": "检查 https://docs.example.com/changelog 是否有更新(使用 site-monitor Skill)。如果有变更,摘要后发送到 Telegram。",
            "timeout": "5m"
          },
          {
            "id": "monitor-competitor",
            "cron": "0 8,20 * * *",          // 每天 08:00 和 20:00
            "agent": "monitor",
            "message": "检查 https://competitor.com/pricing 是否有更新(使用 site-monitor Skill)。如果定价有变化,立即通知我。",
            "timeout": "5m"
          }
        ]
      }
    }

10. 事件驱动:外部系统触发 Agent

除了定时触发,你还可以让外部系统通过 Webhook 或消息来触发 Agent 执行任务。

10.1 Webhook 触发

OpenClaw Gateway 可以暴露一个 Webhook 端点,接收外部系统的 POST 请求并路由到指定 Agent。

jsonc 复制代码
{
  "gateway": {
    "webhooks": {
      "enabled": true,
      "auth": {
        "mode": "token",
        "token": "${WEBHOOK_AUTH_TOKEN}"
      },
      "routes": [
        {
          "path": "/hook/deploy",
          "agent": "devops",
          "template": "收到部署通知:{payload.repository} 的 {payload.ref} 分支已部署到 {payload.environment}。请检查部署状态并运行冒烟测试。"
        },
        {
          "path": "/hook/alert",
          "agent": "devops",
          "template": "收到监控告警:{payload.alert_name} - {payload.message}。严重级别:{payload.severity}。请分析并建议处理方案。"
        }
      ]
    }
  }
}

10.2 GitHub Actions 集成

yaml 复制代码
# .github/workflows/deploy.yml
name: Deploy & Notify Agent
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy
        run: ./deploy.sh

      - name: Notify OpenClaw Agent
        if: always()
        run: |
          curl -s -X POST "https://your-gateway/hook/deploy" \
            -H "Authorization: Bearer ${{ secrets.WEBHOOK_AUTH_TOKEN }}" \
            -H "Content-Type: application/json" \
            -d '{
              "repository": "${{ github.repository }}",
              "ref": "${{ github.ref }}",
              "environment": "production",
              "status": "${{ job.status }}",
              "commit": "${{ github.sha }}"
            }'

10.3 文件监视触发

jsonc 复制代码
{
  "watchers": [
    {
      "path": "~/projects/myapp/logs/error.log",
      "event": "modify",
      "agent": "devops",
      "debounce": "30s",
      "message": "error.log 有新内容。读取最后 50 行,分析错误模式,如果有新类型的错误,通知我。"
    },
    {
      "path": "~/data/exports/",
      "event": "create",
      "agent": "personal",
      "message": "~/data/exports/ 下有新文件。检查文件格式,如果是 CSV,自动生成数据摘要。"
    }
  ]
}

11. Multi-MCP 编排:让多个工具协同工作

当你有多个 MCP 服务器时(参考我的 MCP 集成实战),自动化工作流的威力才真正爆发------你可以在一个任务中串联多个数据源和执行能力。

11.1 多 MCP 协作示例

复制代码
一个自动化工作流可能涉及的 MCP 调用链:

PostgreSQL MCP ──→ AI 分析 ──→ Notion MCP ──→ Slack/飞书
     │                │              │              │
  查询数据         生成洞察      创建页面        发送通知

Brave Search MCP ──→ AI 摘要 ──→ Filesystem MCP ──→ Git MCP
     │                  │              │                │
  搜索最新信息      总结关键点     保存到本地       提交到仓库

11.2 Multi-MCP 配置回顾

jsonc 复制代码
// ~/.openclaw/openclaw.json --- 完整的多 MCP 环境
{
  "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"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
    }
  }
}

11.3 Agent 如何选择 MCP 工具

Agent 的工具选择是基于 Skill 指令、上下文和工具描述的。你不需要显式编排"先调用 A 再调用 B"------你只需要在 Skill 中描述工作流步骤,Agent 会自动选择合适的工具。

但对于关键路径,Skill 中应该明确指定工具:

markdown 复制代码
## Workflow
1. 使用 PostgreSQL MCP 的 query 工具查询数据(不要用 exec + psql)
2. 分析结果
3. 使用 Filesystem MCP 的 write_file 工具保存报告
4. 使用 exec 工具调用 curl 发送飞书通知

12. 实战六:完整的"数字员工"工作流

把前面所有技术组合在一起,搭建一个完整的数字员工。

12.1 场景

你运营一个 SaaS 产品。你希望 OpenClaw Agent 每天自动完成以下工作:

复制代码
┌──────────────────────────────────────────────────────────┐
│           "数字运营助手" 每日工作流                        │
│                                                          │
│  ⏰ 08:30  数据采集                                      │
│  ├── PostgreSQL: 查询昨日注册/活跃/流失用户              │
│  ├── PostgreSQL: 查询昨日收入和退款                      │
│  └── Brave Search: 搜索品牌提及和竞品动态                │
│                                                          │
│  ⏰ 09:00  报告生成                                      │
│  ├── AI 分析数据趋势                                     │
│  ├── 生成 Markdown 报告 → ~/reports/                    │
│  ├── 发送摘要到飞书群(互动卡片)                        │
│  └── 记录到 Memory(memory/2026-03-25.md)              │
│                                                          │
│  ⏰ 每小时  健康监控                                      │
│  ├── PostgreSQL: 检查慢查询和连接数                      │
│  ├── 网站: 检查 /health 端点响应时间                     │
│  └── 异常时 → Telegram 实时告警                          │
│                                                          │
│  📡 实时  事件响应                                        │
│  ├── GitHub PR merged → 自动更新 Changelog               │
│  ├── error.log 有新错误 → 分析并建议修复                 │
│  └── 用户在飞书群提问 → 基于知识库回答                   │
│                                                          │
│  🪝 持续  Hooks                                          │
│  ├── afterResponse → 关键决策自动存档                    │
│  ├── onError → 自动重试 + 告警                           │
│  └── beforeToolCall → 拦截危险 SQL 操作                  │
└──────────────────────────────────────────────────────────┘

12.2 完整配置

jsonc 复制代码
// ~/.openclaw/openclaw.json --- "数字员工"完整配置
{
  // ===== 模型 =====
  "models": {
    "providers": {
      "anthropic": {
        "apiKey": "${ANTHROPIC_API_KEY}",
        "models": [{
          "id": "claude-sonnet-4-20250514",
          "reasoning": true,
          "contextWindow": 200000,
          "maxTokens": 8192
        }]
      }
    }
  },

  // ===== MCP 服务器 =====
  "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"]
    }
  },

  // ===== 频道 =====
  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "${TELEGRAM_BOT_TOKEN}",
      "dmPolicy": "pairing"
    },
    "feishu": {
      "enabled": true,
      "accounts": {
        "main": {
          "appId": "${FEISHU_APP_ID}",
          "appSecret": "${FEISHU_APP_SECRET}"
        }
      }
    }
  },

  // ===== Agent 配置 =====
  "agents": {
    "defaults": {
      "model": { "primary": "anthropic/claude-sonnet-4-20250514" },

      // 记忆
      "memorySearch": { "enabled": true },
      "compaction": {
        "memoryFlush": { "enabled": true }
      },

      // Hooks
      "hooks": {
        "afterResponse": {
          "enabled": true,
          "instruction": "如果本次对话包含技术决策、数据洞察或 TODO 项,简洁记录到 memory/ 今天的日志中。"
        },
        "onError": {
          "enabled": true,
          "instruction": "暂时性错误自动重试一次。持久性错误记录到 memory/errors.md 并通过 Telegram 通知。",
          "maxRetries": 1,
          "notifyScript": "~/.openclaw/hooks/error-notify.sh"
        },
        "beforeToolCall": {
          "enabled": true,
          "instruction": "拦截包含 DROP TABLE、DELETE FROM(无 WHERE)、TRUNCATE 的 SQL 操作。其他正常放行。",
          "tools": ["exec", "postgres"]
        }
      },

      // 安全
      "sandbox": { "mode": "non-main" }
    }
  },

  // ===== 定时任务 =====
  "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"
      }
    ]
  },

  // ===== 文件监视 =====
  "watchers": [
    {
      "path": "~/projects/myapp/logs/error.log",
      "event": "modify",
      "agent": "devops",
      "debounce": "60s",
      "message": "error.log 有新内容。读取最后 30 行,分析错误模式。如果是新类型错误,通过 Telegram 通知我。"
    }
  ],

  // ===== Webhooks =====
  "gateway": {
    "bind": "127.0.0.1",
    "webhooks": {
      "enabled": true,
      "auth": { "mode": "token", "token": "${WEBHOOK_AUTH_TOKEN}" },
      "routes": [
        {
          "path": "/hook/pr-merged",
          "agent": "personal",
          "template": "GitHub PR #{payload.number} 已合并到 {payload.base.ref}。标题:{payload.title}。请更新 CHANGELOG.md。"
        }
      ]
    }
  },

  // ===== 工具安全 =====
  "tools": {
    "exec": {
      "security": "allowlist",
      "allowlist": ["git *", "npm *", "curl *", "python3 *", "ls *", "cat *", "diff *"],
      "ask": "on-miss",
      "askFallback": "deny"
    }
  }
}

12.3 一周的运行效果

复制代码
周一 08:30  📊 数据采集完成 → data/daily-2026-03-23.json
周一 09:00  📄 日报生成 → 飞书群收到互动卡片
             "昨日注册 +234 (+12% WoW),收入 ¥45,200 (-3% WoW)"
周一 10:00  ⚠️ 健康检查告警 → Telegram
             "PostgreSQL 连接数达 85%(170/200)"
周一 14:30  🪝 afterResponse → 记录"决定升级 PostgreSQL 连接池到 300"
周一 16:00  📡 GitHub PR merged → 自动更新 CHANGELOG.md
周一 18:00  🪝 onError → Brave Search API 限流
             → 自动重试成功

周二 09:00  📄 日报生成(与周一的 Memory 连续)
             "注意:昨日讨论的 DB 连接池升级尚未执行"

... 周五 ...

周一 10:00  📄 周报自动生成
             → 整合本周 5 份日报 + Memory 中的决策记录
             → 飞书 + 保存到 ~/reports/weekly-2026-W13.md

13. 调试、监控与最佳实践

13.1 调试定时任务

bash 复制代码
# 查看定时任务列表和下次执行时间
openclaw scheduler list

# 手动触发(不等 Cron)
openclaw scheduler run daily-report

# 查看执行历史
openclaw scheduler history daily-report --last 10

# 查看特定执行的详细日志
openclaw scheduler log daily-report --run-id 2026-03-25-0900

13.2 调试 Hooks

bash 复制代码
# 查看 Hook 触发日志
openclaw logs --follow --filter hooks

# 测试 Hook 脚本
bash ~/.openclaw/hooks/error-notify.sh "timeout" "Connection refused" "postgres.query"
# → 检查飞书群是否收到通知

13.3 监控仪表盘

bash 复制代码
# 全局状态概览
openclaw status
# Gateway:     ✅ running (uptime: 14d 3h)
# Channels:    4 active (telegram, discord, feishu, whatsapp)
# MCP Servers: 3 healthy (postgres, brave-search, filesystem)
# Scheduler:   3 tasks (2 active, 1 completed today)
# Watchers:    1 active (error.log)
# Memory:      47 files indexed, last sync: 2 min ago

13.4 最佳实践

实践 说明
任务幂等 定时任务应该是幂等的------重复执行不会产生副作用。今天的报告生成两次应该覆盖而不是追加
超时保护 每个任务都设置 timeout。没有超时的任务可能永远运行下去
失败通知 关键任务设置 onFailure: "notify"。沉默的失败最可怕
渐进放权 新的自动化工作流先手动触发几天,确认无误后再开启 Cron
日志留存 所有定时任务的输出应保留日志,方便回溯问题
Hook 轻量 afterResponse Hook 不应该做重操作。必须异步的逻辑用后台脚本
任务依赖 有先后关系的任务使用 dependsOn,避免数据未就绪就开始分析
Memory 联动 自动化任务的结果写入 Memory,让后续的人工会话能感知到自动化任务做了什么

13.5 常见问题

问题 原因 解决方案
Cron 任务没触发 Gateway 未运行 / 时区错误 检查 openclaw gateway status;确认 timezone 配置
Hook 脚本没执行 脚本没有执行权限 chmod +x ~/.openclaw/hooks/*.sh
afterResponse 太慢 Hook 中做了同步的网络请求 nohup ... & 改为异步
定时任务重复执行 多个 Gateway 实例同时运行 `ps aux
Webhook 返回 401 Token 不匹配 检查 WEBHOOK_AUTH_TOKEN 是否一致
文件监视不触发 路径不存在 / 权限不足 确认路径和文件权限
任务超时 模型推理太慢 / MCP 服务器无响应 增加 timeout 或检查 MCP 连接

📋 速查卡

bash 复制代码
# ===== 定时任务 =====
openclaw scheduler list                  # 列出所有任务
openclaw scheduler run <task-id>         # 手动触发
openclaw scheduler history <task-id>     # 查看历史
openclaw scheduler enable/disable <id>   # 启用/禁用
openclaw scheduler log <id> --last       # 查看最近日志

# ===== 非交互消息 =====
openclaw message --agent <id> "指令"     # 发送非交互消息
openclaw message --agent <id> --file instructions.md  # 从文件读取

# ===== 监控 =====
openclaw status                          # 全局状态
openclaw logs --follow                   # 实时日志
openclaw logs --follow --filter hooks    # 仅 Hook 日志
openclaw logs --follow --filter scheduler # 仅定时任务日志

# ===== Webhook 测试 =====
curl -X POST http://localhost:18789/hook/deploy \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"repository":"myapp","ref":"main","status":"success"}'
复制代码
Hook 配置路径:
  agents.defaults.hooks.afterResponse     ← 回复后
  agents.defaults.hooks.onError           ← 出错时
  agents.defaults.hooks.beforeToolCall    ← 工具调用前
  agents.defaults.hooks.afterToolCall     ← 工具调用后
  agents.defaults.hooks.onSessionStart    ← 会话开始
  agents.defaults.hooks.onSessionEnd      ← 会话结束
  agents.defaults.hooks.onCompaction      ← 压缩前

定时任务配置路径:
  scheduler.enabled                       ← 总开关
  scheduler.tasks[].cron                  ← Cron 表达式
  scheduler.tasks[].timezone              ← 时区
  scheduler.tasks[].agent                 ← 目标 Agent
  scheduler.tasks[].message               ← 指令内容
  scheduler.tasks[].timeout               ← 超时
  scheduler.tasks[].dependsOn             ← 依赖

Webhook 配置路径:
  gateway.webhooks.enabled                ← 总开关
  gateway.webhooks.auth                   ← 认证
  gateway.webhooks.routes[]               ← 路由规则

文件监视配置路径:
  watchers[].path                         ← 监视路径
  watchers[].event                        ← 事件类型
  watchers[].debounce                     ← 防抖
  watchers[].agent                        ← 目标 Agent
  watchers[].message                      ← 指令

📚 参考资料


如果觉得有帮助,欢迎 点赞 👍 收藏 ⭐ 关注 🔔,有问题评论区见!

相关推荐
lbb 小魔仙2 小时前
Docker容器化实战:从入门到精通,附完整实战案例
运维·docker·容器
by————组态2 小时前
Ricon组态系统:物联网时代的连接桥梁
运维·物联网·数学建模·组态·组态软件
盼小辉丶2 小时前
PyTorch实战(38)——深度学习模型可解释性
人工智能·pytorch·深度学习
你们补药再卷啦2 小时前
AgentSkills(2/4)笔记
人工智能
温九味闻醉2 小时前
Meta | HSTU:生成式推荐工业级方案
人工智能·深度学习·机器学习
迈巴赫车主2 小时前
大数据:Hadoop(HDFS)
大数据·hadoop·hdfs
Fabarta技术团队2 小时前
北邮院企工作坊 | 枫清科技解析Fabarta龙虾技能(skill)开发实践——从使用AI到共创AI
人工智能·科技
hf2000122 小时前
零成本迁移,原地加速,成本降低60%:火花思维基于云器Lakehouse升级实践
大数据·分布式·spark·lakehouse
Rubin智造社2 小时前
OpenClaw实操指南 04|主流AI编程模型权威对比:Claude Code/Codex/Gemini+国产,你的模型选对了吗?
人工智能·ai编程·openclaw·小龙虾