1. 为什么我要做 AI 定时资讯推送助手
每天早上的固定动作是这样的:打开三四个 AI 资讯站点,快速扫标题,挑出值得看的,复制链接,整理成一段话,再发到团队群里。整套流程走下来差不多二十分钟,而且全是重复劳动。更麻烦的是,有时候忙起来忘了发,团队里就有人来问今天怎么没有早报。
我想要的其实很简单:每天早上八点,系统自动把当天 AI 圈的热点抓下来,去重、生成摘要,然后推送到飞书。我不需要打开任何网页,也不需要手动复制粘贴。这就是所谓的“主动交付式 AI”——不是我问它答,而是它按我定的规则,到点把结果送到我面前。
OpenClaw 正好适合干这件事。它本身是一个支持多模型接入的本地 AI 工作流工具,能通过 YAML 配置定义抓取任务、推送任务和调度规则,不用写大量代码就能把整条链路串起来。配合飞书机器人的 Webhook 和 TaoToken 统一 Key 调用模型生成摘要,整套系统可以做到零人工干预。
这篇文章面向的是需要每日自动汇总 AI 资讯的开发者,尤其是那些已经用过 OpenClaw 但还没把它用在定时任务上的朋友。我会把 YAML 调度配置、飞书 Webhook 接入步骤、以及通过 TaoToken 调用模型生成摘要的验证动作全部拆开讲,每一步都可以直接复制去用。如果你还没装 OpenClaw,建议先看之前的安装教程,把基础环境跑通再回来跟这篇。
整条链路的核心检索词是 OpenClaw 定时调度 + 飞书 API 推送 + AI 资讯摘要生成,下面按实际搭建顺序展开。
2. TaoToken 前置准备与 OpenClaw 模型接入配置
在开始写 YAML 之前,需要先把模型调用这条链路打通。OpenClaw 本身不绑定特定模型供应商,它通过 OpenAI 兼容接口调用模型。我用 TaoToken 作为统一入口,原因是它一个 Key 可以切换多个模型,不用在配置文件里维护多套鉴权信息。
2.1 获取 TaoToken API Key
打开 TaoToken 控制台,进入 API Keys 页面创建一个新 Key。创建时注意权限范围,如果你只是用来生成摘要,选默认的对话权限就够了,不需要开太多。创建完成后把 Key 复制下来,后面配置里要用。
控制台地址:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=console
API Keys 页面:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api-keys
Key 的格式一般是 sk- 开头的一串字符。拿到之后不要直接写在代码里,放到环境变量或者 OpenClaw 的 secrets 配置里。
2.2 OpenClaw 中配置模型供应商
OpenClaw 的模型配置通常放在~/.openclaw/config.yaml或者项目目录下的openclaw.yaml里。我习惯放在项目目录,方便跟抓取配置一起管理。模型供应商部分这样写:
model_providers: - name: "taotoken" type: "openai_compatible" base_url: "https://taotoken.net/api" api_key: "${TAOTOKEN_API_KEY}" models: - id: "claude-sonnet-4-20250514" alias: "summary-model" max_tokens: 2048 temperature: 0.3这里有几个点要注意。base_url填https://taotoken.net/api,不要加多余的路径。api_key用环境变量引用,避免明文写在配置文件里。alias是给模型起的别名,后面在任务配置里用别名引用,这样换模型的时候只改这一处。
环境变量在 shell 里这样设置:
export TAOTOKEN_API_KEY="sk-你的实际Key"如果是 macOS 用 LaunchAgent 调度,环境变量要写在 plist 的EnvironmentVariables里,否则调度启动时读不到。
2.3 验证模型连通性
配置写完后先别急着跑抓取任务,单独验证一下模型能不能调通。OpenClaw 一般提供openclaw model test之类的命令,或者你可以直接用 curl 测:
curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "用一句话说明什么是AI早报"}], "max_tokens": 100 }'如果返回里有choices数组并且 content 字段有内容,说明模型链路通了。如果返回 401,检查 Key 是否复制完整、环境变量是否生效。如果返回 model not found,检查模型 ID 是否拼写正确。
这一步看起来简单,但后面所有摘要生成都依赖它,所以务必先确认通过再往下走。
3. 可复制的 YAML 调度配置与飞书 Webhook 接入
这一节是整篇文章的核心,配置写对了,后面基本就是等它自己跑。我把配置拆成三块:抓取任务、推送任务、调度规则。每一块都可以单独调整,互不影响。
3.1 抓取任务配置
抓取任务定义“从哪里抓、抓多少”。我的配置如下:
fetch_jobs: - id: "morning_ai" sources: - name: "36kr" enabled: true url: "https://36kr.com" selector: "article" - name: "qbitai" enabled: true url: "https://www.qbitai.com" selector: "article" - name: "xinzhiyuan" enabled: true url: "https://www.xinzhiyuan.com" selector: "article" collect_count: 20 timeout_seconds: 30 fallback_on_error: truecollect_count我设成 20,之前试过 50,结果抓取超时,后来降到 20 刚好。fallback_on_error设成 true,意思是某个站点挂了就跳过,不影响其他站点。这个参数很关键,我第一次上线时没开,结果量子位那天访问慢,整个任务直接失败,早报没推出去。
3.2 推送任务配置
推送任务定义“推什么、推到哪、什么时候推”:
push_jobs: - id: "push_morning_ai" fetch_job_id: "morning_ai" schedule: - time: "08:00" frequency: unit: "day" value: 1 features: content_blocks: - "headline" - "topic" - "top10" link_count: 10 channels: - type: "feishu_webhook" webhook_url: "${FEISHU_WEBHOOK_URL}" msg_type: "interactive" - type: "feishu_api" app_id: "${FEISHU_APP_ID}" app_secret: "${FEISHU_APP_SECRET}" receive_id: "${FEISHU_RECEIVE_ID}" fallback: true summary: model_alias: "summary-model" max_length: 500 style: "bullet_points"content_blocks里 headline 是要闻,topic 是选题建议,top10 是热点链接。link_count控制推几条链接,我设 10,太多没人看。channels里配了两个渠道,Webhook 为主,飞书 API 为备用,fallback: true表示 Webhook 失败时自动切到 API。
3.3 飞书 Webhook 接入步骤
飞书机器人 Webhook 的获取路径:打开飞书,进入目标群组,点设置,找到群机器人,添加自定义机器人。添加时给它起个名字,比如“AI早报”,然后复制生成的 Webhook 地址。地址格式类似https://open.feishu.cn/open-apis/bot/v2/hook/xxxxx。
拿到之后设成环境变量:
export FEISHU_WEBHOOK_URL="https://open.feishu.cn/open-apis/bot/v2/hook/你的实际地址"如果你要用飞书 API 作为备用渠道,还需要在飞书开放平台创建应用,拿到 app_id 和 app_secret,并开通im:message权限。接收者 ID 可以是用户 ID 或群 ID,根据你的推送目标填。
3.4 调度规则配置
调度我用 LaunchAgent(macOS),配置文件放在~/Library/LaunchAgents/com.openclaw.morningai.plist:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.openclaw.morningai</string> <key>ProgramArguments</key> <array> <string>/usr/local/bin/openclaw</string> <string>run</string> <string>--config</string> <string>/Users/你的用户名/openclaw/morning-ai.yaml</string> </array> <key>StartCalendarInterval</key> <dict> <key>Hour</key> <integer>7</integer> <key>Minute</key> <integer>55</integer> </dict> <key>EnvironmentVariables</key> <dict> <key>TAOTOKEN_API_KEY</key> <string>sk-你的实际Key</string> <key>FEISHU_WEBHOOK_URL</key> <string>https://open.feishu.cn/open-apis/bot/v2/hook/你的实际地址</string> </dict> <key>StandardOutPath</key> <string>/Users/你的用户名/openclaw/logs/morningai.log</string> <key>StandardErrorPath</key> <string>/Users/你的用户名/openclaw/logs/morningai.err</string> </dict> </plist>注意调度时间设成 7:55,比推送时间 8:00 早 5 分钟,给抓取和摘要生成留出缓冲。脚本路径写绝对路径,日志也放固定目录,方便排查。
加载调度:
launchctl load ~/Library/LaunchAgents/com.openclaw.morningai.plist加载后可以用launchctl list | grep openclaw确认是否生效。
4. 验证请求与成功结果确认
配置写完,先手动跑一次,确认整条链路能通,再交给调度。
4.1 手动触发一次完整流程
openclaw run --config /Users/你的用户名/openclaw/morning-ai.yaml --once--once表示只跑一次,不进入常驻模式。跑的时候观察终端输出,正常流程会依次打印:开始抓取、抓取到 N 条、去重后剩 M 条、调用模型生成摘要、推送飞书、推送成功。
如果中间某一步卡住,日志里会有对应记录。我建议第一次跑的时候把日志级别调到 debug:
openclaw run --config /Users/你的用户名/openclaw/morning-ai.yaml --once --log-level debug4.2 检查飞书是否收到消息
跑完后打开飞书,看目标群组或私聊里有没有收到消息。正常的话会看到一条卡片消息,包含要闻摘要、选题建议和 Top10 链接。如果没收到,先检查 Webhook 地址是否正确,再检查飞书机器人是否被移出群组。
4.3 验证摘要生成质量
摘要部分由 TaoToken 调用的模型生成。你可以打开日志,找到模型返回的原始内容,看看摘要是否抓住了关键信息。如果摘要太长或太短,调整summary.max_length参数。如果风格不对,调整summary.style,支持bullet_points、paragraph、mixed三种。
我实测下来,bullet_points最适合早报场景,每条一行,扫一眼就能看完。
4.4 确认调度生效
手动跑通后,等第二天早上看调度是否自动触发。检查日志文件:
tail -f /Users/你的用户名/openclaw/logs/morningai.log如果 7:55 左右看到新的日志输出,说明调度生效。如果没动静,检查 LaunchAgent 是否加载成功,以及 plist 里的路径是否正确。
5. 本篇常见错误排查
搭建过程中我踩过不少坑,这里把最常见的几个列出来,对照排查能省很多时间。
5.1 401 Unauthorized
报错信息:{"error":{"message":"Invalid API key","type":"invalid_request_error"}}
原因通常是 Key 没设对。检查三处:环境变量是否 export 成功、plist 里是否写了 Key、Key 是否复制完整。如果是 LaunchAgent 调度时报 401,多半是 plist 里没写EnvironmentVariables,因为调度启动时不会继承 shell 的环境变量。
5.2 local proxy failed
报错信息:local proxy failed: connection refused
这个一般出现在模型调用环节,说明 OpenClaw 尝试走本地代理但没连上。检查model_providers里的base_url是否写成了https://taotoken.net/api,不要加/v1后缀,OpenClaw 会自动拼接。如果之前配过其他代理,把相关环境变量清掉。
5.3 reading choices 报错
报错信息:error reading choices: unexpected end of JSON input
这是模型返回内容为空导致的。常见原因是max_tokens设得太小,模型还没输出完就被截断。把max_tokens调到 2048 以上。另一个原因是输入内容太长,超过了模型上下文限制,可以在抓取配置里减少collect_count,或者让摘要任务只处理前 N 条。
5.4 OAuth 相关报错
报错信息:OAuth token expired或invalid_grant
如果你用的是飞书 API 渠道,token 过期会报这个。飞书的 tenant_access_token 有效期一般两小时,OpenClaw 会自动刷新,但如果 app_secret 填错了,刷新会失败。检查app_id和app_secret是否匹配,以及应用是否开通了im:message权限。
5.5 推送成功但内容为空
飞书收到消息了,但摘要部分是空的。这种情况多半是模型调用失败但没抛异常,OpenClaw 用了空内容继续推送。检查日志里模型调用那一段,看是否有超时或返回空。可以在summary配置里加retry_on_empty: true,让它在空内容时重试。
5.6 调度不触发
LaunchAgent 加载了但到点没跑。先看launchctl list | grep openclaw的输出,如果第二列是非零数字,说明上次运行报错了。再看日志文件是否有新内容。常见原因是 plist 里的ProgramArguments路径写错,或者openclaw不在/usr/local/bin下。用which openclaw确认实际路径。
6. 长期运行与 CTA
这套系统跑起来之后,基本不需要每天管。但我建议每周花五分钟看一眼日志,确认没有连续失败。如果某个数据源经常超时,可以在sources里把它enabled设成 false,换一个更稳定的源。
如果你想把摘要模型换成更便宜的,或者想同时推送到多个渠道,只需要改 YAML 里的对应字段,不用动代码。这就是配置驱动的价值。
模型调用统一走 TaoToken,一个 Key 管理所有模型,换模型只改model_alias对应的 ID。如果你还没创建 Key,可以从这里进:
API Keys:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api-keys
接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc
想先试试模型对话效果,可以打开:
模型对话:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=chat
如果你打算把这套逻辑扩展到更多定时任务,比如竞品动态监控、周报自动生成,可以考虑 Coding Plan,长期跑 Agent 类任务更划算:
Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=coding-plan
整套配置我放在项目目录里,跟抓取规则、推送规则、调度 plist 一起版本管理。每次调整都留个 commit,出问题能快速回滚。这是我从第一次上线失败里学到的:配置也要有版本,不然改乱了都不知道哪版是能跑的。