1. 这个自动化日报是怎么来的
先交代一下背景。我每天早上的固定动作是:打开手机刷一遍 AI 圈的消息,看看各家大模型又发了什么新版本、有没有开源项目值得关注、哪些产品的政策变了。但说实话,这个习惯坚持了不到两周就断了好几次——不是不想看,是信息源太散:技术博客、公众号、推特、GitHub Trending、还有几个微信群,想全部刷完起码半小时,刷完还不一定能抓住重点。
后来我换了个思路:与其我每天早上主动去翻,不如让工具把信息整理好,直接送到我眼前。于是就有了这个项目——用 WorkBuddy 搭了一个定时任务,每天上午十点半自动抓取并整合 AI 领域的核心动态,生成一份结构化的日报,然后通过微信机器人推送到我的企业微信群里。整个流程跑通之后,我只需要在十点半看一眼手机,就能用五分钟掌握当天值得关注的 AI 信息。
这个方案适合谁?第一类是每天需要跟踪 AI 动态但时间碎片化的从业者;第二类是已经在用 WorkBuddy 但没把它用到定时任务场景里的同学;第三类是单纯想学“让机器定时把消息送到你手上”这套玩法的朋友。技术栈不复杂,核心就三件事:定时触发、内容生成、消息推送。
2. 整体设计思路:为什么是 WorkBuddy 而不是纯脚本
决定动手之后,第一个问题是:这个定时任务怎么承载?
最简单的方案是写一个 Python 脚本扔在服务器上,用 crontab 定时跑。这个方案我熟,十分钟就能搞定,但我还是选择了以 WorkBuddy 为主体来做编排,主要原因有三个。
第一,WorkBuddy 本身就是一个面向工作场景的 AI 智能体平台,它擅长的是把任务拆解成 Agent 和 Skill,再组合成完整流程。对我这个需求来说,用 WorkBuddy 把“信息采集—内容生成—消息推送”串成一条工作流,后续要调整日报的主题、格式、推送时间,改起来比改脚本灵活得多。
第二,题目里说的“设了个闹钟”,本质上是给 WorkBuddy 配置一个定时触发规则。WorkBuddy 支持按时间点或周期触发工作流,这就相当于内置了一个 cron,不需要我再单独维护一套调度系统。当然,实测下来它依赖运行环境常驻,如果你用个人电脑,得保证机器不关机;如果你想彻底托管,后面我会讲怎么搭配轻量服务器或者云函数来兜底。
第三,日报里的内容分析环节,靠的就是大模型。WorkBuddy 本身集成了模型调用能力,但我在实践里更倾向于把生成逻辑写在调度脚本里,让 WorkBuddy 负责业务流程编排、脚本负责拉数据和调模型,最后统一把结果推到微信。各司其职,出了问题也好排查。
整个流程串起来是这样的:定时触发器到点唤起 WorkBuddy 的日报工作流,工作流里的信息采集 Skill 负责抓取和筛选指定信息源,接着调用大模型对抓取结果做归纳和排版,最后推送模块把生成的 Markdown 文本通过企业微信群机器人 webhook 发出来。架构不复杂,但每一个环节都有值得展开的细节。
3. 三大核心环节的拆解与实操
3.1 定时触发:时间配置和兜底策略
定时触发是整个流程的起点。WorkBuddy 里创建定时任务的方式和设置闹钟类似,你可以指定具体时刻,也可以指定周期,比如每个工作日十点半。我配置的是每天上午十点半,因为我看日报的习惯固定在上午,而且十点半这个时间点能覆盖当天的早间新闻和前一晚的海外动态。
需要注意两个细节。第一是时区问题。如果 WorkBuddy 运行的机器不在本地时区,或者你用了云服务器,一定要确认系统时间和你的预期一致。我最初一次没推送,排查了半天,发现是服务器默认 UTC 时间,十点半实际上是北京时间十八点半。解决方案很简单,在系统环境里设置TZ=Asia/Shanghai,或者在 WorkBuddy 的调度配置里明确时区。
第二是兜底策略。任何单一定时方案都有失手的可能性:电脑休眠、网络断连、平台临时故障。我的做法是设置了两层保障:WorkBuddy 的定时触发是主方案,同时在一个轻量服务器上放了一个 cron 表达式作为备份,两者指向同一个执行脚本,脚本内部做了幂等处理(用日期做去重),这样即使两边同时触发,也不会推送两份重复内容。
先看主方案的配置。在 WorkBuddy 的自动化面板里新建一个定时任务,关键字段这样填:
- 任务名称:AI 早报生成与推送
- 触发规则:每天 10:30
- 执行内容:调用日报工作流
- 失败重试:开启,间隔五分钟,最多三次
备份方案用常见的 cron 表达式就够了,一句命令就能注册:
30 10 * * * cd /path/to/ai-daily-news && python3 run_daily.py >> logs/cron.log 2>&1这个表达式的意思是每天十点三十分执行一次脚本,并把标准输出和错误输出追加到日志文件里,方便事后排查。
3.2 日报内容生成:信息源筛选与提示词设计
日报的核心价值在内容,而内容的质量取决于两样东西:信息源好不好、提示词写得准不准。
信息源方面,我没有追求大而全。一开始我列了二十多个网站和 RSS,后来发现抓取量太大,大模型在整理时反而容易丢失重点。经过几轮调整,我把信息源收敛为四类:
- 主流 AI 媒体的当日要闻(通过 RSS 获取)
- GitHub 上 AI 相关仓库的 Trending(通过 GitHub API 获取,按 star 增速排序)
- 几个重点大模型厂商的官方公告页
- 我所在几个技术社群的精选讨论话题
每个信息源对应 WorkBuddy 里的一个采集 Skill。采集 Skill 的本质是一个可复用的抓取任务,里面定义了入口 URL、抓取规则、超时时间和解析方式。RSS 用标准库解析就行,GitHub 直接调接口,社群的讨论话题我做了一个简单的关键词过滤,避免什么内容都往里塞。
信息抓回来之后,生成环节交给大模型。我用的提示词经过了好几版迭代,最终版本大概长这样:
你是一名 AI 行业编辑。请根据以下信息源摘要,生成一份今日 AI 日报。 要求: 1. 按“模型与产品动态 / 开源项目 / 业界观点 / 值得关注”四个板块组织 2. 每条内容控制在 60 字以内,保留关键数据与结论 3. 优先保留与模型发布、性能评测、开源许可变化、重要合作相关的内容 4. 如果某条信息无法确认来源,标注“来源待核实” 5. 日报末尾附上 2 条你个人觉得有潜力的趋势判断这里有一个很重要的经验:提示词里一定要写“来源待核实”的兜底规则。大模型在生成日报时偶尔会自己脑补一些看起来合理但实际不存在的信息,明确告诉它标注来源,能有效减少你拿着假新闻当真的情况。
3.3 微信推送:企业微信群机器人的完整接入
推送环节,我选的是企业微信群机器人。原因很简单:它给了一个 webhook 地址,你用 HTTP POST 往这个地址发 JSON,消息就会出现在群里,不需要开发公众号、不需要申请模板消息、更不需要个人微信号的自动化(那个方案风险太高,不建议碰)。
在企微群里添加机器人的路径是:群设置 → 群机器人 → 添加机器人。添加后会得到一个 webhook URL,格式类似:
https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的密钥推送的核心代码很短,Python 里用 requests 就能完成。我封装了一个推送函数,支持 text 和 markdown 两种消息类型:
import requests import json WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的密钥" def push_markdown(content: str) -> bool: headers = {"Content-Type": "application/json"} payload = { "msgtype": "markdown", "markdown": { "content": content } } resp = requests.post(WEBHOOK_URL, headers=headers, data=json.dumps(payload), timeout=10) result = resp.json() if result.get("errcode") == 0: return True else: print(f"推送失败: {result}") return False企业微信群机器人对 markdown 的支持有限,支持标题、加粗、引用、链接这些基础语法,但表格和图片不行。所以我在生成日报时就让大模型输出纯 markdown 文本,板块标题用二级标题,核心信息用加粗和链接,这样在手机上的阅读体验已经很清爽了。
4. 完整工作流配置与脚本实现
4.1 WorkBuddy 工作流配置要点
回到 WorkBuddy 侧,我把整个流程配置成一个名为ai_daily_report的工作流。工作流包含三个节点:采集节点、生成节点、推送节点。
采集节点的配置比较繁琐,值得说的是如何设置超时和重试。RSS 源偶尔会超时,GitHub API 偶尔会限流,所以我给每个采集 Skill 都单独设置了超时阈值(默认 15 秒)和重试次数(默认 2 次)。如果某个源连续失败,就跳过它,不阻塞整个工作流——日报里有三四个板块也够看,没必要因为一个源挂了就不推送。
生成节点调用大模型接口。这里需要准备 API Key,放到 WorkBuddy 的密钥管理里,不要在脚本中明文写死。我在调用时设置了一个重要参数:temperature=0.3。温度越低,输出越稳定、越忠实于原文,这种摘要任务不需要创造力,稳比炫重要。
推送节点就是调用前面写的push_markdown函数。节点之间通过变量传递数据:采集节点输出原始文本列表,生成节点的输入是这些文本+提示词,输出是格式化日报,推送节点拿到日报后直接 POST 到 webhook。
WorkBuddy 界面配置时的节点参数大致是:
- 采集节点:信息源列表、抓取频率、超时、重试
- 生成节点:API Key、模型名称、temperature、最大输出长度
- 推送节点:webhook 地址、消息类型、失败处理方式
如果你更习惯代码的方式,WorkBuddy 也支持把 Skill 导出为描述文件。我建议还是先在界面上跑通一次,再考虑版本化管理。
4.2 调度脚本的完整实现
为了让你能直接参考,我放一版适合部署到轻量服务器的独立调度脚本。这个脚本不依赖 WorkBuddy 也能跑,核心逻辑是:抓 RSS → 抓 GitHub Trending → 调大模型生成日报 → 推送微信。
import feedparser import requests import json from datetime import datetime # ---------- 配置区 ---------- DEEPSEEK_API_KEY = "your-api-key" MODEL_NAME = "deepseek-chat" WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=your-key" RSS_SOURCES = [ "https://example.com/rss/ai-news.xml", ] GITHUB_TRENDING_URL = "https://api.github.com/search/repositories?q=topic:ai&sort=stars&order=desc&per_page=5" # ---------- 信息采集 ---------- def fetch_rss_news(): items = [] for url in RSS_SOURCES: try: feed = feedparser.parse(url) for entry in feed.entries[:5]: items.append(f"- {entry.title}:{entry.get('summary', '')[:80]}") except Exception as e: print(f"RSS 抓取失败 {url}: {e}") return "\n".join(items) def fetch_github_trending(): try: resp = requests.get(GITHUB_TRENDING_URL, timeout=10) resp.raise_for_status() data = resp.json() lines = [] for repo in data["items"][:5]: lines.append(f"- {repo['full_name']} ★{repo['stargazers_count']}:{repo['description'][:60] if repo.get('description') else '无描述'}") return "\n".join(lines) except Exception as e: print(f"GitHub 抓取失败: {e}") return "" # ---------- 日报生成 ---------- def generate_daily_report(rss_content, github_content): prompt = f"""你是一名 AI 行业编辑。请根据以下信息生成今日 AI 日报。 按“模型与产品动态 / 开源项目 / 业界观点”三个板块组织,每条不超过 60 字,保留关键数据。 RSS 摘要: {rss_content} GitHub Trending: {github_content} """ headers = {"Authorization": f"Bearer {DEEPSEEK_API_KEY}"} payload = { "model": MODEL_NAME, "messages": [{"role": "user", "content": prompt}], "temperature": 0.3, } resp = requests.post( "https://api.deepseek.com/chat/completions", headers=headers, json=payload, timeout=60, ) resp.raise_for_status() return resp.json()["choices"][0]["message"]["content"] # ---------- 微信推送 ---------- def push_markdown(content: str) -> bool: headers = {"Content-Type": "application/json"} payload = {"msgtype": "markdown", "markdown": {"content": content}} resp = requests.post(WEBHOOK_URL, headers=headers, data=json.dumps(payload), timeout=10) return resp.json().get("errcode") == 0 # ---------- 主流程 ---------- if __name__ == "__main__": today = datetime.now().strftime("%Y-%m-%d") rss = fetch_rss_news() github = fetch_github_trending() report = generate_daily_report(rss, github) full_content = f"## AI 早报 {today}\n\n{report}" ok = push_markdown(full_content) print(f"推送{'成功' if ok else '失败'} at {datetime.now()}")这段代码可以直接保存为run_daily.py,配合前面的 cron 表达式就能跑。需要注意requests和feedparser需要安装,一条命令搞定:pip install requests feedparser。
如果你用的是 WorkBuddy 内置调度而不是服务器 cron,其实原理一样:WorkBuddy 到点唤起工作流,工作流里执行等价逻辑。脚本独立出来还有一个好处,就是出了问题你可以脱离 WorkBuddy 单独测某一段,定位更快。
4.3 一次完整的测试与上线流程
我把整个上线过程拆成几个步骤,你可以照着走。
第一步:验证各模块独立可用。先单独跑fetch_rss_news()和fetch_github_trending(),确认能拿到数据。如果某段返回空,先看是不是网络或 API Key 的问题,不要急着联调。
第二步:验证大模型生成。把抓到的内容复制到模型对话里试生成,看格式是否符合预期。我在这一步调整过几轮提示词,主要是控制长度和防止它编造来源。
第三步:验证推送。生成一段测试 markdown,调用push_markdown(),确认企业微信群能收到消息。这里注意 webhook 的 key 是敏感信息,推到公开仓库前务必脱敏。
第四步:联调触发链路。先在 WorkBuddy 里手动触发一次工作流,确认整个链路通了,再配置定时规则。定时规则配置完成后,可以把时间临时改成两分钟后的一个时间点,快速验证是否能自动触发,验证完再改回十点半。
第五步:切换正式时间并观察三天。前三天我会在十点四十五分左右看一眼群里有没有日报,连续三天正常,这个项目才算真正稳定。
5. 常见问题与排查技巧实录
5.1 定时任务没有触发
最常见的原因有三个:电脑休眠、时区错乱、WorkBuddy 进程未常驻。
排查思路按顺序来。先看 WorkBuddy 的自动化日志里有没有当天的执行记录,如果没有,说明调度本身没起来。再确认运行环境的时区是否符合预期,执行date命令看一眼当前系统时间。最后检查机器是否在预定时间处于休眠状态,如果是个人电脑,可以在系统设置里临时关闭休眠,或者干脆把脚本迁到云服务器上。
我自己的经历是第一次部署在办公室电脑上,结果国庆假期回来发现断更了四天——电脑被断电。之后我把备份 cron 迁到了一台常开的轻量服务器上,这个坑就再也没踩过。
5.2 企业微信推送失败
企微 webhook 返回错误时,常见情况分两类:
一类是返回errcode: 93000,意思是 webhook 地址不正确或者机器人被移出了群。解决办法是重新添加机器人,拿新的 key。
另一类是请求超时或errcode: 45009,触发限流了。企业微信群机器人对频率有限制,同一机器人每分钟最多 20 条,我每天只推一条,基本不会触到这个限制。但如果你是手动测试时点了很多次,会短暂触发限流,等一分钟再试就行。
还有一个容易忽略的点:webhook 地址里的 key 是拼接在 URL 后面的,如果复制的时候带了额外的空格或换行,请求会被判非法。用编程方式配置时记得先strip()一下。
5.3 日报内容质量不稳定
内容质量忽高忽低,通常是大模型的提示词问题,不是信息源问题。
如果你发现生成的日报里经常出现重复信息、信息来源不明、或者每个板块内容长短不一,我建议按这几个方向优化:
- 在提示词中明确字数范围。不要只说“短一点”,要说“每条不超过 60 字”。
- 给大模型提供原文标题和链接。RSS 摘要往往不完整,如果只给它摘要文本,它容易把摘要里不完整的信息当成完整事实。
- 分阶段生成。先让模型提取要点,再把要点交给它排版。一次给太多信息,模型容易顾此失彼。
我在最终版本里用了一个偷懒但有效的做法:让 WorkBuddy 的生成 Skill 先输出一份“要点草稿”,然后我再加一条指令“请将草稿整合为正式日报”,相当于让模型自己审校一遍。实测下来内容连贯性好了很多。
5.4 推送内容在微信里显示异常
企业微信群机器人的 markdown 和你在编辑器里看到的 markdown 不太一样。它不支持表格、不支持图片语法、不支持嵌套列表。如果你发现部分内容在微信里变成了纯文本或者格式乱了,多半是用了不兼容的语法。
我的日报模板最终只用了四种语法:标题(##)、加粗(**)、链接([文字](url))、换行(\n)。不要用什么表格、代码块、引用块,兼容性都一般。
6. 这个方案还能怎么扩展
日报推通了以后,我发现这套“定时触发 + AI 生成 + 微信推送”的骨架完全可以复用,换一下信息源和提示词,就能输出完全不同的内容。
我已经用同一套架构做了几件事:每天早上八点半推送一份产品数据摘要,内容来自内部数据看板的 API;每周五下午推送一份开源项目周报,聚合本周 star 增长最快的 10 个仓库;还有一个股票自选池的早盘提醒,用的是相同的工作流,改了个提示词风格。
扩展的时候有一个建议:把采集、生成、推送三个环节彻底解耦。现在我的采集节点和生成节点都支持独立调用,换信息源不用碰推送代码,换提示词不用动采集任务。这样做的好处是,每次新需求基本上只需要新增一个采集 Skill 和一套提示词,剩下的基础设施全部复用。
如果你之前没怎么用过 WorkBuddy 的定时能力,我的经验是从一个“一天的日报推送”开始跑通,不要上来就搞复杂的多源多平台任务。先让链路转起来,再逐步加信息源、加格式、加触发频率。这套流程跑顺之后,你可能会和我一样,慢慢开始把所有重复的信息处理工作都交给它。