1. 周五下午五点的周报焦虑OpenClaw 能接住多少周五下午五点日历提醒弹出来「提交周报」你打开空白文档脑子里只剩一句「这周干了啥」。翻 Git 提交记录、翻会议纪要、翻聊天记录凑出一份自己都不想看的流水账。这个场景我太熟了所以这次直接动手把 OpenClaw 接上 AI做一条从 Git 日志到成稿周报的自动化链路。OpenClaw 是一个可编排的自动化 Agent 运行框架你可以把它理解成一个「能读文件、能跑脚本、能调模型」的调度中枢。它本身不替你写周报但它能把「收集原始素材 → 调用模型生成 → 落盘输出」这三步串成一条可重复执行的流水线。适合谁适合每周要交周报、又不想把时间花在「回忆和排版」上的开发者、测试、产品同学。这篇会交付一份可复制的config.toml骨架、一个周报生成脚本、一次端到端验证动作你照着跑就能出第一份 AI 周报。核心检索词先摆出来OpenClaw 周报自动化、config.toml 配置、AI 生成周报代码。这三个词贯穿全文你搜到的其他教程如果只讲概念不讲配置可以直接跳过。2. 前置准备TaoToken 接入与 OpenClaw 环境2.1 为什么周报生成要接 TaoToken周报生成脚本最后一步是调模型把结构化数据转成自然语言。这一步需要一个稳定的模型 API 入口。TaoToken 提供统一的模型调用地址你不需要在脚本里硬编码多家厂商的 key换模型只改一个配置项。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 注意 API 地址不带 UTM 参数配置时别写错。2.2 拿 Key 与确认模型登录后进控制台在 API Keys 页面创建一个新 key复制保存。这个 key 只显示一次丢了就重建。创建入口https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。拿到 key 后建议先去模型对话页面确认你要用的模型能正常响应避免脚本跑一半报 401。模型对话入口https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 。2.3 环境要求Node.js 需要 18 及以上OpenClaw 的脚本执行依赖它。Python 可选如果你后续要解析 Excel 或 PDF 会议纪要再装。Git 必须可用因为周报素材主要来自git log。检查命令node --version # 期望 18 git --version # 期望 2.302.4 项目目录结构在本地建一个独立目录别混在业务仓库里避免误提交mkdir -p ~/workspace/openclaw-weekly cd ~/workspace/openclaw-weekly mkdir -p scripts templates data output touch scripts/collect-git.js scripts/generate-report.js touch templates/report-template.md config.toml .env目录职责scripts放采集和生成脚本templates放周报模板data放中间产物output放最终周报config.toml是 OpenClaw 的编排配置。3. 可复制配置config.toml 骨架与脚本代码3.1 config.toml 完整骨架OpenClaw 的config.toml决定「什么时候跑、跑什么、用什么模型」。下面这份是周报场景的最小可用配置字段含义我写在注释里# OpenClaw 周报自动化配置 [agent] name weekly-report-agent description 从 Git 日志生成周报初稿 # 模型接入指向 TaoToken 统一入口 [model] provider openai-compatible base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY # 从环境变量读取不写死在文件里 model claude-sonnet-4-20250514 max_tokens 4096 temperature 0.3 # 周报要稳温度调低 # 任务编排先采集再生成 [[tasks]] name collect type shell command node scripts/collect-git.js output data/git-log.json [[tasks]] name generate type shell command node scripts/generate-report.js depends_on [collect] output output/weekly-report.md # 定时触发每周五 17:00 [schedule] cron 0 17 * * 5 timezone Asia/Shanghai注意api_key_env这一行它让脚本从环境变量读 key而不是把 key 写进config.toml。这是基本安全习惯别偷懒。3.2 环境变量文件.env内容TAOTOKEN_API_KEY你的key GIT_REPO_PATH/path/to/your/project OUTPUT_DIR./output.env要加进.gitignore别提交。3.3 Git 日志采集脚本scripts/collect-git.js负责把最近 7 天的提交拉出来按类型分类输出 JSON#!/usr/bin/env node const { execSync } require(child_process); const fs require(fs); const path require(path); const repoPath process.env.GIT_REPO_PATH || .; const days 7; function collectCommits() { const since new Date(Date.now() - days * 86400000) .toISOString().slice(0, 10); const cmd git -C ${repoPath} log --since${since} --prettyformat:%h|%an|%ad|%s --dateshort; try { const out execSync(cmd, { encoding: utf-8 }); if (!out.trim()) return []; return out.split(\n).map(line { const [hash, author, date, message] line.split(|); return { hash, author, date, message }; }); } catch (e) { console.error(Git 读取失败:, e.message); return []; } } function classify(commits) { const buckets { feature: [], fix: [], refactor: [], docs: [], other: [] }; commits.forEach(c { const m c.message.toLowerCase(); if (m.startsWith(feat)) buckets.feature.push(c); else if (m.startsWith(fix)) buckets.fix.push(c); else if (m.startsWith(refactor)) buckets.refactor.push(c); else if (m.startsWith(docs)) buckets.docs.push(c); else buckets.other.push(c); }); return buckets; } const commits collectCommits(); const result { total: commits.length, buckets: classify(commits) }; fs.mkdirSync(data, { recursive: true }); fs.writeFileSync(data/git-log.json, JSON.stringify(result, null, 2)); console.log(采集完成共 ${commits.length} 条提交);跑一下确认能出数据node scripts/collect-git.js cat data/git-log.json3.4 AI 周报生成脚本scripts/generate-report.js读取上一步的 JSON拼 prompt调 TaoToken落盘#!/usr/bin/env node const fs require(fs); const path require(path); const API_URL https://taotoken.net/api/v1/chat/completions; const API_KEY process.env.TAOTOKEN_API_KEY; async function callModel(prompt) { const res await fetch(API_URL, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${API_KEY} }, body: JSON.stringify({ model: claude-sonnet-4-20250514, messages: [ { role: system, content: 你是周报助手输出 Markdown结构清晰不编造数据。 }, { role: user, content: prompt } ], temperature: 0.3 }) }); if (!res.ok) throw new Error(API ${res.status}: ${await res.text()}); const data await res.json(); return data.choices[0].message.content; } function buildPrompt(gitData) { const b gitData.buckets; const fmt arr arr.map(c - ${c.message} (${c.hash})).join(\n) || - 无; return 根据以下 Git 提交记录生成周报初稿。 本周提交总数${gitData.total} 新功能 ${fmt(b.feature)} Bug 修复 ${fmt(b.fix)} 重构 ${fmt(b.refactor)} 文档 ${fmt(b.docs)} 其他 ${fmt(b.other)} 要求 1. 按「本周完成 / 问题与思考 / 下周计划」三段输出 2. 本周完成部分按功能、修复、其他分组 3. 问题与思考和下周计划留占位符标注需人工补充 4. 不要编造未在提交中出现的功能; } async function main() { const raw fs.readFileSync(data/git-log.json, utf-8); const gitData JSON.parse(raw); const prompt buildPrompt(gitData); const report await callModel(prompt); fs.mkdirSync(output, { recursive: true }); const file path.join(output, weekly-${new Date().toISOString().slice(0, 10)}.md); fs.writeFileSync(file, report, utf-8); console.log(周报已生成${file}); } main().catch(e { console.error(e.message); process.exit(1); });4. 端到端验证跑一次看结果4.1 设置环境变量并执行export $(cat .env | xargs) node scripts/collect-git.js node scripts/generate-report.js4.2 预期输出output/weekly-2025-XX-XX.md里应该出现类似结构## 本周完成 ### 新功能 - 完成用户登录模块 (a1b2c3d) - 新增订单查询接口 (m0n1o2p) ### Bug 修复 - 修复 token 过期问题 (e4f5g6h) ## 问题与思考 待补充 ## 下周计划 待补充4.3 用 OpenClaw 编排执行如果你已经装好 OpenClaw CLI直接openclaw run --config config.toml它会按[[tasks]]顺序先跑采集再跑生成。看到周报已生成就说明链路通了。想手动触发模型对话验证 key 是否有效可以去 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 发一条测试消息。5. 本篇常见错排查5.1 401 Unauthorized九成是TAOTOKEN_API_KEY没导出。检查echo $TAOTOKEN_API_KEY是否有值。如果.env里写了但没export脚本读不到。另一个可能是 key 复制时带了空格重新去 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 复制一次。5.2 Git 读取为空GIT_REPO_PATH指向的目录不是 Git 仓库或者最近 7 天确实没提交。先用git -C $GIT_REPO_PATH log --oneline -5确认。如果仓库在子目录路径要写对。5.3 模型返回内容被截断max_tokens设太小。周报如果提交多4096 可能不够调到 8192。同时检查temperature设太高会导致输出发散周报场景 0.2 到 0.4 之间比较稳。5.4 config.toml 解析报错TOML 对缩进和引号敏感。base_url必须带引号cron表达式用双引号。如果报expected key检查是不是用了 Tab 缩进统一用空格。5.5 脚本找不到模块collect-git.js和generate-report.js用的是 Node 内置模块不需要npm install。如果你加了dayjs之类的依赖记得在项目根目录npm init -y npm install dayjs。6. 长期编码与 Agent 场景的延伸周报只是 OpenClaw 的一个入口场景。同样的config.toml结构你可以把collect任务换成拉 Jira 任务、拉会议纪要、拉代码评审记录generate任务换成生成项目周报、迭代总结、风险预警。如果你打算把这类自动化长期跑在编码流程里比如让 Agent 每天自动整理提交、生成 changelog、甚至辅助 code review可以了解 Coding Plan 的接入方式https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有完整的 API 参数和错误码说明排障时对着查比猜快。我自己的习惯是每周五 16:50 让 OpenClaw 先跑一遍采集和生成17:00 收到草稿后只补「问题与思考」和「下周计划」两段十分钟内交掉。模板放在templates/report-template.md改样式不用动脚本。先跑通再迭代别一上来就追求完美模板。