一、什么是"工作流"
回到第六章:"让 OpenClaw 帮我整理桌面"——你说一句它做一次。这是任务。
工作流(Workflow)就是把一个任务变成长期、自动、按规则触发的"自动化任务":
任务(一次性) 工作流(长期)
──────────── ────────────────────────
你说一句它做一次 你定一次它每周日 22:00 自动跑
或:邮件一来自动归档
或:监控股价,跌破 X 自动通知你
OpenClaw 把这个能力做得非常简单:所有工作流就是一份 YAML 配置文件,存在 ~/.openclaw/workflows/ 目录下。OpenClaw 自带一个调度器,开机自启就开始守着这些工作流。
二、工作流的三大触发器
任何工作流都得有"什么时候跑"的开关。OpenClaw 支持三类:
1. 时间触发器(cron)
最常用,符合 Linux cron 表达式。
schedule: "0 8 * * *" # 每天早 8 点
schedule: "*/30 * * * *" # 每 30 分钟
schedule: "0 9 * * 1-5" # 工作日早 9 点
schedule: "0 17 * * 5" # 每周五 17:00
schedule: "0 22 1 * *" # 每月 1 号晚 10 点
不会写 cron?去 crontab.guru 在线生成,超级直观。
关于"秒级触发":标准 cron 是 5 段(分时日月周),最小粒度 1 分钟。OpenClaw 额外支持 6 段写法,首位是秒,例如
*/30 * * * * *表示每 30 秒。秒级触发只在"抢票、价格瞬变监控"这类极端场景才用,会显著增加 API 调用量与成本,请谨慎。
2. 事件触发器
监听本地或外部事件,一旦发生就跑。
trigger:
type: file_changed
path: ~/Desktop/截图/
pattern: "*.png"
trigger:
type: email_received
account: gmail
filter:
from: "billing@aws.com"
trigger:
type: webhook
path: /flow/jira-issue-created
trigger:
type: rss
url: https://news.ycombinator.com/rss
match: "OpenClaw"
3. 关键词触发器
在你的 IM、邮件、笔记里说一句"暗号"就触发。
trigger:
type: keyword
channels: [wechat, telegram]
pattern: "^/早报$"
之后你在微信发"/早报",OpenClaw 立刻跑,把今天的早报推回给你。
三、工作流的 5 段编排
一个完整的工作流文件长这样:
# ~/.openclaw/workflows/morning-brief.yaml
# 1. 元信息
name: 个人早报
description: 每天早 8:00 给我推送一份个性化早报
version: 1.0.0
author: cassius
enabled: true
# 2. 触发器
schedule: "0 8 * * *"
# 3. 上下文 / 变量
context:
user_name: Cassius
city: 杭州
email_account: cassius@gmail.com
push_target: wechat:文件传输助手
# 4. 步骤编排
steps:
- name: 抓天气
skill: weather-cn
args: { city: "{{city}}" }
output: weather
- name: 抓邮件简报
skill: gmail-assistant
args: { account: "{{email_account}}", since: "24h" }
output: emails
- name: 抓微信关键消息
skill: wechat-bridge
args: { since: "24h", filter: "@me OR 重要" }
output: wechat_msgs
- name: 抓今日日程
skill: calendar-sync
args: { date: today }
output: calendar
- name: 抓行业新闻
skill: rss-watcher
args:
sources:
- https://36kr.com/feed
- https://news.ycombinator.com/rss
output: news
- name: 汇总成早报
prompt: ./prompts/morning-brief.md
inputs:
weather: "{{weather}}"
emails: "{{emails}}"
wechat_msgs: "{{wechat_msgs}}"
calendar: "{{calendar}}"
news: "{{news}}"
model: deepseek/deepseek-chat
output: brief
- name: 推送到微信
skill: notify-bridge
args:
target: "{{push_target}}"
content: "{{brief}}"
tts: true # 同时生成语音
# 5. 失败处理
on_failure:
retry: 1
notify: cassius@gmail.com
fallback: skip
跑这条命令把工作流注册:
openclaw workflow add ~/.openclaw/workflows/morning-brief.yaml
立即手动跑一次验证:
openclaw workflow run morning-brief
每天早 8:00 会自动跑,结果推到微信"文件传输助手"。
四、实战:你的"个人早报"完整搭建
我们把上面的早报工作流补全,给你一个今天就能复制粘贴用的版本。
第 1 步:建提示词文件
~/.openclaw/prompts/morning-brief.md:
<role>
你是 Cassius 的私人早报编辑,文风克制、信息密度高,像一个负责任的老师傅。
</role>
<task>
基于 <inputs> 中的素材,写一份今早 8:00 的个性化早报。
</task>
<inputs>
天气:{{weather}}
邮件:{{emails}}
微信:{{wechat_msgs}}
日历:{{calendar}}
新闻:{{news}}
</inputs>
<constraint>
- 全程中文;
- 总长度 < 400 字;
- 最重要的最先讲;
- 没有"早安"、"祝你愉快"这类客套;
- 数字和时间要精确;
- 没有发生的事不要编。
</constraint>
<format>
{{date}} 早报|{{user_name}}
【天气】(一行)
【今日日程】(按时间排,最多 5 条)
【今日要事】(必须今日处理的,最多 3 条;分别给"建议处理时间")
【值得回的微信】(最多 3 条)
【值得读的新闻】(一句话总结 + 链接,最多 3 条)
【一句话提醒】(任意软性提醒,例如"今天是你妈生日"或"该健身了")
</format>
第 2 步:注册工作流
把第三节的 morning-brief.yaml 保存好,然后:
openclaw workflow add ~/.openclaw/workflows/morning-brief.yaml
openclaw workflow enable morning-brief
openclaw workflow list
第 3 步:测试
openclaw workflow run morning-brief --dry-run # 干跑,不真的推送
openclaw workflow run morning-brief # 真的跑一次
第 4 步:调优
第一次出来的早报你大概率会觉得"哪里不太对",例如:
- 微信关键消息抓得太多 → 把 filter 收紧
- 新闻太杂 → 把 RSS 源精简
- 早报太啰嗦 → 在 prompt 里把"< 400 字"改成"< 250 字"
- 推送时间不对 → 改 cron 表达式
每天调一点点,一周内你会得到一份"完全适合你"的早报。
五、工作流的常用命令
# 添加工作流
openclaw workflow add <yaml-path>
# 列出
openclaw workflow list
# 启用 / 禁用
openclaw workflow enable <name>
openclaw workflow disable <name>
# 立刻跑一次
openclaw workflow run <name>
# 干跑(不发送、不写文件、只看会怎么干)
openclaw workflow run <name> --dry-run
# 看历史运行
openclaw workflow history <name> --limit 10
# 看一次具体运行的日志
openclaw workflow logs <run-id>
# 删除
openclaw workflow remove <name>
# 重载(改完 yaml 不重启)
openclaw workflow reload <name>
六、11 个开箱即用的工作流模板
下面 11 个模板拿过去改两个字段就能跑。完整 YAML 太长,这里给"核心结构",完整文件请访问本书附录 D 或 GitHub。
模板 1:个人早报(已讲)
每天早 8:00 推送早报。
模板 2:周报自动起草
name: weekly-report-draft
schedule: "0 17 * * 5"
steps:
- { skill: git-summary, args: { repos: ["~/Code"] }, output: git_log }
- { skill: gmail-assistant, args: { folder: "Sent", since: "7d" }, output: sent }
- { skill: feishu-bridge, args: { groups: ["产品组"], since: "7d", author: me }, output: chats }
- { skill: calendar-sync, args: { since: "7d" }, output: cal }
- prompt: ./prompts/weekly-report.md
inputs: { git: "{{git_log}}", emails: "{{sent}}", chats: "{{chats}}", cal: "{{cal}}" }
output_file: ~/Documents/周报/{{week_end}}-初稿.md
on_complete:
- notify: { target: wechat, content: "你的周报初稿已生成" }
模板 3:每日邮件简报
name: email-brief
schedule: "30 8 * * *"
steps:
- { skill: gmail-assistant, args: { folder: Inbox, since: 24h }, output: mails }
- prompt: ./prompts/email-brief.md
inputs: { mails: "{{mails}}" }
output: brief
- { skill: notify-bridge, args: { target: "wechat:文件传输助手", content: "{{brief}}" } }
模板 4:竞品监控周报
name: competitor-watch
schedule: "0 9 * * 1"
context:
targets:
- { name: A, urls: ["https://a.com/pricing", "https://a.com/blog"] }
- { name: B, urls: ["https://b.com/release-notes"] }
steps:
- { skill: browser-pilot, args: { snapshot: "{{targets}}", store_to: ~/.cache/competitor/this-week } }
- { skill: diff-tool, args: { old: ~/.cache/competitor/last-week, new: ~/.cache/competitor/this-week }, output: diff }
- prompt: ./prompts/competitor-diff.md
inputs: { diff: "{{diff}}" }
output_file: ~/Documents/竞品监控/{{week}}.md
- { shell: "mv ~/.cache/competitor/this-week ~/.cache/competitor/last-week" }
模板 5:演唱会票/球鞋监控
name: ticket-watch-jay-shanghai
schedule: "*/60 * * * * *" # 6 段语法,首位是秒:每 60 秒一次
context:
url: https://detail.damai.cn/item.htm?id=xxxx
steps:
- { skill: browser-pilot, args: { open: "{{url}}", screenshot_to: /tmp/ticket.png } }
- { skill: vision, args: { image: /tmp/ticket.png, prompt: "页面上'立即购买'按钮是不是可点击的(不是灰色'即将开售'或'已售罄')?只回答 YES 或 NO" }, output: clickable }
- if: "{{clickable == 'YES'}}"
then:
- { skill: notify-bridge, args: { target: ios_push, content: "[抢票提醒] 周杰伦上海站票放出来了!" } }
- { skill: workflow_disable, args: { name: ticket-watch-jay-shanghai } }
模板 6:新文件夹自动整理
name: download-tidy-on-arrival
trigger:
type: file_changed
path: ~/Downloads/
debounce: 60s
steps:
- prompt: |
文件夹 ~/Downloads 有新文件。请按"图片/视频/文档/压缩包/安装包/其他"分类。
新文件清单:{{event.files}}
执行前先告诉我打算移到哪里(dry-run)。
模板 7:照片自动备份与压缩
name: photos-backup
schedule: "0 3 * * *"
steps:
- { skill: image-magic, args: { src: ~/Pictures/Camera, dest: ~/Pictures/Compressed, quality: 85, max_size: 2000 } }
- { skill: rclone, args: { src: ~/Pictures/Compressed, dest: "onedrive:photos", incremental: true } }
- { skill: notify-bridge, args: { target: wechat, content: "昨夜共备份 {{count}} 张照片" } }
模板 8:每月账单分析
name: monthly-bill
schedule: "0 10 1 * *"
steps:
- prompt: ./prompts/bill-analysis.md
inputs:
csv_dir: ~/Desktop/账单/{{last_month}}
output_file: ~/Documents/财务/{{last_month}}-体检报告.md
- { skill: notion-bridge, args: { db: "财务", title: "{{last_month}} 月度报告", file: ~/Documents/财务/{{last_month}}-体检报告.md } }
模板 9:客户反馈自动归类
name: feedback-classifier
trigger:
type: file_changed
path: ~/Inbox/客户反馈/
pattern: "*.csv"
steps:
- prompt: ./prompts/feedback-classify.md
inputs: { csv: "{{event.path}}" }
output_file: "{{event.path}}.classified.xlsx"
- { skill: notify-bridge, args: { target: feishu_group, content: "客户反馈已分类,{{event.path}}.classified.xlsx" } }
模板 10:日报数据看板
name: daily-dashboard
schedule: "0 9 * * *"
steps:
- { skill: db-query, args: { sql: "SELECT ... FROM ... WHERE date=yesterday" }, output: rows }
- { skill: chart-render, args: { rows: "{{rows}}", type: line, save_to: /tmp/dashboard.png } }
- prompt: ./prompts/daily-dashboard.md
inputs: { rows: "{{rows}}" }
output: comment
- { skill: email-sender, args: { to: boss@xyz.com, subject: "{{date}} 业务日报", body: "{{comment}}", attachments: ["/tmp/dashboard.png"] } }
模板 11:求职跟踪
name: job-hunt-loop
schedule: "0 9 * * *"
steps:
- { skill: jobs-aggregator, args: { keywords: ["高级产品经理", "产品总监"], cities: [杭州,上海,深圳], min_salary: 500000 }, output: jobs }
- prompt: ./prompts/job-screen.md
inputs: { jobs: "{{jobs}}", profile: "@~/.openclaw/projects/job-hunt/CONTEXT.md" }
output: filtered
- { skill: notion-bridge, args: { db: "求职跟踪", upsert: "{{filtered}}" } }
- { skill: gmail-assistant, args: { folder: "Inbox", filter: "from:hr OR from:招聘", since: 24h }, output: hr_replies }
- prompt: ./prompts/job-update.md
inputs: { replies: "{{hr_replies}}" }
完整 YAML 参考 附录 D 资源与社区链接 中的"工作流模板仓库"。
七、工作流的最佳实践
1. 先 dry-run 再上线
任何会动数据 / 发消息 / 花钱的工作流,第一次都用 --dry-run 跑。
2. 加"人工兜底"
高风险步骤(自动发邮件、自动下单、自动删除)一律先生成草稿、推给你,让你确认后才真的发。
- name: 起草回复
prompt: ./prompts/email-reply.md
output: draft
- name: 推送审批
skill: approval-flow
args:
target: wechat
message: "草稿如下:{{draft}}\n回复 OK 自动发送,回复 NO 取消"
on_approve:
- { skill: gmail-assistant, args: { send: "{{draft}}" } }
3. 写清楚日志
每一步加 output: 字段,方便事后排查。
4. 控制频率
schedule: "*/1 * * * *" 这种每分钟跑的工作流要慎用,烧钱、容易被外部 API 限流。
5. 错误时给自己留个口
on_failure:
retry: 1
notify: cassius@gmail.com
fallback: skip
不要让一个工作流挂了你都不知道。
八、监控你的工作流
# 看看哪些工作流跑得健康
openclaw workflow status
# 输出示例
NAME LAST RUN STATUS NEXT RUN
morning-brief 2026-04-19 08:00:13 SUCCESS 2026-04-20 08:00
weekly-report-draft 2026-04-19 17:00:08 SUCCESS 2026-04-26 17:00
ticket-watch 2026-04-19 14:23:00 RUNNING *
photos-backup 2026-04-19 03:00:00 SUCCESS 2026-04-20 03:00
# 看本月所有工作流的执行次数和成本
openclaw workflow stats --since "2026-04-01"
九、本章你应该完成的
- 建立你的第一个工作流:个人早报
- 至少把工作流跑过 3 次(手动 + 自动各一次)
- 给至少 1 个工作流加上"失败时通知"
- 试着改 1 个模板成你自己的版本
本章一图回顾
触发器 编排 输出
┌──────────────┐ ┌────────────────────┐ ┌────────────┐
│ 时间 (cron) │ │ 抓数据 (skills) │ │ 写文件 │
│ 事件 │ → │ 调模型 (prompt) │ → │ 发消息 │
│ 关键词 │ │ 存结果 (output) │ │ 调 API │
│ Webhook │ │ 分支 / 重试 │ │ 生成报告 │
└──────────────┘ └────────────────────┘ └────────────┘
下章预告
工作流让"一个 OpenClaw"24 小时上班。但有时候任务太复杂,一个 OpenClaw 忙不过来——这时你需要一个 AI 团队。下一章 第九章 子代理与 AI 团队,我们让"一个老板 + 多个员工"的协作模式真正跑起来,并教你如何用便宜模型组团做事,把成本压到极限。