一篇没过关的草稿:把博客工作流写成编程 agent 能遵循的规则
这篇笔记的存在,是为了记录一篇没过关的草稿。
原稿试图解释我为编程 agent 建立的博客工作流:仓库内技能、写明的约定、把 Git 工作交给简单模型、同一轮必须补齐时间线条目的规则,以及更好的工作流工具带来的复利效应。这些都没有错,事实上,其中不少内容很有用。
但它没有达到我对正式文章的标准。
问题不在正确性,而在重心。它过于关注运作机制,却没有充分聚焦我真正想写的更深层主题:创作速度的加快,以及我内心所知与对外交付之间不断缩短的距离。
因此,我把它留在 notes/ 中,记录一个具体、或许也有帮助,却仍不是那篇真正文章的东西。我真正想写的版本是《创作正在加速》。这个区别对我很重要。AI 能快速帮助生成草稿,但什么值得作为正式文章发布,仍由人的标准决定。
下面是当时的草稿。
过去一周,我同时在做两件事:为 11ty-subspace-builder 交付功能,以及构建让这些功能的写作更快、更一致的工作流工具。
结果是在这个仓库的 .claude/skills/ 中形成了一套小小的本地技能系统。它们把我反复经历的编辑循环写成了规则:写时间线条目、发布文章、发布版本。
为什么用技能?
编程 agent 支持仓库内技能:用 Markdown 文件描述可重复的工作流,并在对话中通过斜杠命令调用。当我输入 /timeline-entry 或 /release,agent 就读取技能文件,遵循其中的流程,包括文件命名、front matter 约定、正文风格和链接对象。
没有这些文件时,agent 通常会自己阅读仓库、摸清规则,这其实很聪明。但摸索会消耗 token。agent 探索代码库,推断时间线条目需要带引号的 YAML 日期,标题需要 blog: 前缀,或正文必须链接版本标签而不是原始提交,这些事做得没错,只是每个会话都重新来一遍,缓慢又昂贵。
写好的技能省去了这条弯路。规范直接写明,不用再从示例里推导隐含规则。agent 一开始就知道方向,而不是先探索。
我写了哪些技能
/timeline-entry
第一个是时间线条目技能,在 4 月 14 日发布时间线页面后不久写成。时间线是一份船长日志:条目带有 shipped、published、wip、idea 或 thinking 标签,每条都有日期、时间和一小段第一人称文字。
规则出乎意料地具体。其中最重要的是 YAML 引号:date 和 time 必须始终是带引号的字符串("2026-04-12",而不是 2026-04-12)。没有引号、看起来像 ISO 日期的值,在 Eleventy 集合排序前就会被解析成 JavaScript Date 对象,悄悄破坏同一天内的顺序。我在《AI 的边界,以及人类擅长的地方》里写过这个确切的 bug。
技能还规定,时间戳应来自 git 提交,而不是我随手填进文件的值。提交时间才是依据。标题前缀必须遵循仓库现有约定。正文必须链接实际发布的内容:文章 URL、GitHub release 标签,或提交。
把这些都写下来后,我终于不用每次会话都重新解释 YAML 引号规则。技能会把它传下去。
/release
发布技能位于 11ty-subspace-builder 仓库,而不是这里。发布版本有一套固定程序:更新 package.json 和 package-lock.json 中的两个版本字段,提交 chore: release vX.Y.Z,推送,再创建 GitHub release,使用正确的标题格式、简短更新日志和对比上一标签的链接。
步骤多到足以漏掉一个。现在,技能描述了完整流程。agent 验证版本更新、格式化提交信息,并生成带正确对比 URL 的发布正文。
由于这个过程纯粹是机械性的,也很适合使用最便宜的可用模型。正如我在《合理使用 AI Token》里所写,这类常规操作不需要重度推理,codex --profile simple 就够了。
/frontmatter-editing 和 /post-and-note-workflow
这两个技能晚一天出现,因为我发现每次新建文章或笔记,仍然要重新解释 front matter 约定。frontmatter-editing 会指向各内容类型的参考文档:posts/ 有一个模板,notes/ 有另一个,timeline/ 则有自己的规则。技能只读取当前任务相关的内容,而不是用一份长文件包揽三种类型。
post-and-note-workflow 则明确了一条我总得手动督促的规则:每次发布文章或笔记,都必须在同一轮交付对应的时间线条目。不能留到后续,也不是可选的下一步,就是同一轮。把它写成技能中的硬约束,agent 就会把它当作要求,而不是建议。
实际用起来是什么感觉
典型的一次发布是这样的:两个 tmux 窗格,两个 agent 同时运行。
- 窗格 1,Subspace 仓库: 我让 agent 提交、推送并发布版本。它遵循
/release技能,更新版本号,创建 GitHub release。整个过程用--profile simple就够了。 - 窗格 2,博客仓库: 同时,我让另一个 agent 写时间线条目。我只需贴上版本 URL:“为
https://github.com/TheClooneyCollection/11ty-subspace-builder/releases/tag/v1.25.0中的主题模式控制和延迟预览写一条shipped时间线记录。” agent 阅读发布说明,推断细节,起草条目。我确认后就完成了。
两个 agent 并行工作。版本上线时,时间线条目已经写好。
我现在很少手动提交了。暂存、提交、推送这些常规 git 操作足够机械,--profile simple 能顺利处理。我遵循的经验原则,也正是《合理使用 AI Token》里的原则:让模型匹配任务复杂度。
但有一条明确界线。涉及重写 git 历史的工作仍交给人,至少也要用 --profile complex。变基、修改已发布提交、理清损坏的合并,这些都需要判断历史应当是什么样,出错代价很高。简单 git 操作已是解决好的问题,历史手术还不是。
阻力的减少是真实的。过去要先交代一轮背景,现在直接从共同基础开始。技能本身就是上下文。
技能受版本控制,也让人很满足。新增标题前缀或改变约定时,只需更新一次技能文件。改动会自动传递到之后的每个会话,无论与哪个 agent 合作。这与把工程决策放进 ADR 或 CLAUDE.md,而不是 Slack 聊天串,是同一个道理:规则应该放在会被找到的地方。
再往上一层
这轮开发有趣的地方在于,我用编程 agent,构建了帮助编程 agent 更有效工作的工具。
技能是协作写成的:我描述约定,agent 起草技能文件,我再完善。发现模糊之处后,几条规则经过迭代变得更清晰。YAML 引号规则就是好例子。最初只写“给日期和时间加引号”,后来补上原因:“没有引号的 YAML 日期会在 Eleventy 集合排序前被解析为 JavaScript Date 对象,可能破坏同一天内的排序。”
多出来的这句话,让规则从需要遵循的东西,变成可以理解的东西。理解之后,就不会再随意破坏它;遇到新边界情况,也能自行判断,不必回头查技能文件。
这是更持久的 AI 工作流工具形态:不只有指令,还有解释。既给出规则,也说明它为何存在。
一个不断累积的循环
这种工作具有复利效应。更好的工作流工具,让每篇新内容的产出成本更低;成本更低,内容就更多;内容更多,就能发现工具里更多缺口;于是工具继续变好。
我不知道这个循环会在哪里结束。但此刻,它恰好是我想身处其中的那种问题。