前言:关于写日报这件事
刚入职新公司,还没领略到技术栈的深奥,先被"日报文化"给教育了。
每天下午一下班,微信群里的行政小姐姐就开始复读机模式:"@所有人,今天的日报还没交的抓紧了哈!" 到了 7 点,如果还没交,你的名字就会出现在那个"未提交名单"里,就像小时候没写作业被老师点名。
最离谱的是,每次写日报都要坐在工位上对着屏幕发呆十分钟: "我今天到底干了啥?" "修了一个 Bug,但这 Bug 叫啥来着?"
这种回过头翻 Git 记录、翻 Chrome 历史记录、翻笔记软件的行为,简直是对程序员脑细胞的二次谋杀。作为一个推崇"自动化一切"的懒人,我决定:我命由我不由天,日报得靠 AI 填。
于是,我参考了 OpenClaw 的思路,基于 Vercel AI SDK 手搓了一个"日报生成神器"------Damn Reports

效果展示
先看成品,这就是我用来"偷懒"的秘密武器:


核心原理:Agent 的工具循环调用
要实现这样一个能"自动干活"的 AI Agent,手搓还是有点难度,所以我们要站在巨人的肩膀上,使用 Vercel AI SDK 来实现。
以前我们写 AI,通常是简单的 Chat:输入 -> 输出。但要让 AI 能读取你的文件、查你的数据库、甚至帮你提交 HTTP 请求,就需要 Tool Use(工具调用)。
AgentToolLoop
在 ai SDK 中,有一个核心概念叫 ToolLoopAgent。它的逻辑可以用下面这个闭环来描述:
- LLM 思考:用户说"你今天都做了什么",AI 发现自己不知道我今天干了啥。
- 调用工具 :AI 决定调用
read_file工具去读我的memory/2026-03-11.md。 - 获取结果:程序执行文件读取,把内容丢回给 AI。
- 再次思考:AI 拿到了内容,发现信息够了,开始组织语言生成结果,不够则在调用工具。
- 输出结果:最终把日报呈现在我面前。
自己处理会非常麻烦,你要自己处理循环调用,而使用 vercel ai sdk,则只需要几行代码:
typescript
// src/store/modules/llm/store.ts
import { ToolLoopAgent } from 'ai'
import * as tools from '@/tools'
const agent = new ToolLoopAgent({
model: createModel(),
instructions: [/* 系统提示词 */],
// 注入所有的工具
tools
})
const stream = await agent.stream({
messages: userMessages,
})
let result = ''
for await (const part of stream.textStream) {
result += part
}
console.log(result)
其原理就是将复杂的 Loop 循环抽象为简单的调用逻辑:

接下来,就是让 AI 拥有一些基础的能力,比如读取与写入文件。
typescript
// src/tools/file.ts
export const read = tool({
description: '读取文件内容',
inputSchema: z.object({
path: z.string().describe('文件路径'),
}),
execute: async ({ path }) => {
const data = await fs.readFile(path)
return decoder.decode(data)
},
})
export const write = tool({
description: '创建或覆盖文件',
inputSchema: z.object({
path: z.string().describe('文件路径'),
content: z.string().describe('文件内容'),
}),
execute: async ({ path, content }) => {
await fs.writeFile(path, encoder.encode(content))
return `Successfully written to ${path}`
},
})
有了这两个工具,AI 就可以在目录里翻箱倒柜了。
当然,实际上你可能还得约束 AI 的读写范围之类的。
一个完整的 Agent,除了上面最基础的读写外,通常还会有更多的内置工具,比如 openclaw 内置的工具就将近有 20 个,而我们的使用场景就比较简单,所以就只做了以下的 tool:
md
- apply_patch: 应用多文件补丁
- ls: 列出文件夹
- date: 获取当前日期
- edit: 对文件进行精确编辑
- read: 读取文件内容
- exec: 执行命令
- exec_tool: 执行指定 tool.json 中的工具(获取数据源的工具)
- skill: 加载指定的 Skill,并返回其内容和相关文件列表
- get_settings: 获取应用的配置
- set_settings: 设置应用的配置
- ...
让 AI 直接帮我配置工具和数据
目前 Damn Reports 只支持了两个数据源工具,但这样肯定不能满足所有场景,而我又不可能到每一个平台都把这些 API 接一遍,所以我将这个能力,也交给了 AI。
在 Damn Reports 里,所有的数据源工具跟数据源都是通过 json 文件来管理的,而让 AI 能帮我处理这些文件,这个时候,我们就需要通过 skill 来加载对应的技能了。
可能有人想问,为什么不直接在写个 read_soruce、edit_source、add_source 的工具呢?这时候就要说到 tool 其实并不是越多越好的,这会大大增加 AI 的认知负担,而且也会让 AI 的回答变得不那么准确,因为每一次对话,你都把完整的工具链塞给 AI。
而 skill 则不同,他更像是一本操作指南,只有 AI 需要的工具,才会被加载进来,这里就拿 agent-browser 技能为例:
一般来说,skills 的文件结构如下:
md
skills/
└── agent-browser/
├── SKILL.md
├── README.md
├── references/
│ ├── authentication.md
│ ├── commands.md
│ └── ...
└── tools/
└── agent-browser.json
└── ...
而入口,就只有标题、描述、每个功能导航的链接。
md
---
name: agent-browser
description: "..."
allowed-tools: Bash(agent-browser:*)
---
1. xxx (./references/authentication.md)
2. xxx (./references/commands.md)
3. xxx (./references/...)
这样 AI 就会自己思考将要做的事情,需要用到哪些功能,然后就会自动去对应的文件里找答案。
比如我要增加一个新的数据源工具,我不需要去改代码。我直接对 AI 说:
"帮我配置一个新的数据源工具,用来获取 xxx 的数据"
可能会有人搞混,tool.json 是用来获取数据源的工具,跟 AI tool 其实不是一个东西,其实 openclaw 也有一个 TOOL.md,其本身也跟 AI tool 不是一个东西,这些都是用户跟 AI 自定义的一些工具集。
AI 会执行以下链式反应:
- 加载
tool技能,这里会有tool.json的数据结构、更改规则。 - 读取
tool.json。 - 调用
edit工具修改 JSON 结构,插入新的配置。 - 调用
exec_tool验证,确认修改成功。
这种 "用 AI 配置" 的流程,其实就跟 openclaw 差不多,但这种模式比较依赖大模型是否足够聪明。
提示词注入是根本
和 OpenClaw 一样,整个 Agent 的行为逻辑是由一组 Markdown 文件定义的:
AGENTS.md:定义了 AI 的身份(日报助手)和行为准则、可用的 skill 列表。MEMORY.md:存放长期记忆,比如我的项目背景、常用术语。IDENTITY.md:告诉 AI 我是谁。
通过在每次对话开始前注入这些上下文,AI 瞬间就从一个"通用的聊天机器人"变成了"最懂我的私人助理"。
终极形态:自动提交与定时任务
日报生成了,难道还要我每天到软件里,手动生成,手动复制粘贴到公司后台? 不可能!
所以我支持了定时任务,每天下班前准时生成日报,但这还不够,我直接让 AI 帮我写了两个定时任务,用来提交到公司后台。
由于 cron 也是使用 json 文件来管理的,我们只需要写好 cron 技能就可以直接跟 AI 对话去帮我写定时任务啦,我就让 AI 帮我写了两个定时任务。
- 获取公司 OA 的 Token:每天下午 5.30 点自动获取公司 OA 的 Token。
- 自动提交:询问我是否要提交日报,如果回答是,则调用脚本提交日报。
json
// tauri/workspace/cron.json
{
"jobs": [
{
"name": "Auto Submit Report",
"cron": "0 18 * * 1-5",
....
}
]
}
从此,下班后的微信群催促对我来说,不过是划过屏幕的一条无意义通知罢了。
一些思考
其实手搓这个工具,除了想解决自己的"日报焦虑",更多的是对目前 AI Agent 的探索,以缓解我对层出不穷的 Agent 工具的焦虑,直到我把整个项目做完,我也有了一些自己的理解。
其实 AI Agent 的底层模式其实并没有发生翻天覆地的变化。像是我们常用的 Cursor、Trae 这些 AI IDE,其实早就是按照这种设计思路在跑了:感知环境(读代码、查终端) -> 决策(思考怎么改) -> 执行动作(改代码、跑命令)。但这终究还是给程序员准备的"工具",普通人很难去接触到这种工具。
我想了想 OpenClaw 为什么能这么火,可能正是因为它把这种高度自动化的模式真正"搬"到了普通大众面前。它不仅仅是一个聊天框,更像是一个拥有"心脏"和"记忆"的数字生命。
如果你对这个项目感兴趣,欢迎去 GitHub 关注。 觉得有用的同学,点个 Star 支持一下吧!💪