几周前我在测试一个技术方案设计节点。
这是 agentic workflow 里最上游的一环:输入产品文档和设计稿,输出技术方案,下游的代码生成节点照着方案写代码。我一开始跑出了一个质量不怎么样的技术方案,然后就开始沉迷于调试 workflow——改 prompt、调 stage 配置、折腾门禁脚本。我想着 workflow 调好了,方案自然就好了。
但 workflow 一直没调好。我陷在那个循环里出不来。
下游负责代码生成的同学等不及了。他拿到的技术方案质量很差,没办法,就自己通过多轮对话,额外补充了一堆信息进去,好歹先把代码生成跑通了,提交了一些基础框架代码,已经合入了主干。等我想再跑一次 workflow 看看效果的时候,这些代码就在仓库里。agent 做技术方案的第一步是梳理现状——它读了这些代码,然后基于这些代码输出了技术方案。
某种程度上,它是先看了答案再回答问题的。
你说这不对吗?从单纯测试节点的角度看,确实不对——我没法判断方案质量好是因为 workflow 调得好,还是因为答案已经写在代码里了。但从实际生产的角度看,这再正常不过了。大部分需求都不是从零开始,而是在已有代码基础上继续迭代。技术方案本来就该参考现有代码、架构、模式。
这里有一个更深的洞察。我一开始觉得 Plan 和 Code 是线性的上下游关系——先有方案,后有代码。但实际上,在 repo-first 模式下,这个依赖是双向的:已有代码影响方案设计,方案设计指导新代码。这不是 bug,这是现实。
仓库不是空画布
这件事让我重新理解了什么是"知识库"。
我们之前有一个反复纠结的问题:agent 需要的知识应该放在哪?外部 RAG 服务?ARCHITECTURE.md、DESIGN.md 这类项目文档?还是 skill 的内部指令?后来我渐渐觉得,很多东西根本不需要单独写成文档。目录结构、文件名、代码、注释——这些已经包含了大量信息。随着仓库不断迭代,这些知识也在积累。你可能不需要额外补充什么,它们已经够了,或者基本够用了。
从零搭建项目既简单又困难。简单在没有历史债,轻装上路;困难在可发挥空间太大,你什么都得考虑。但后续加入的开发者,在做技术方案时,难度已经大幅下降了——因为可以参考现有方案,仿照着写。这不是偷懒,这是被鼓励的行为:它让项目的架构保持统一。直到某天达到临界点,触发重构——那是后话了。
Vercel 的 v0 工具在 2026 年初做了一次重建,从 sandbox-first 转向了 repo-first。他们的 CPO 说了一句很直白的话:90% 的工作是对已有代码库做修改,不是从零构建。v0 的第一个版本有四百万用户,产出了无数原型,但大部分是废弃的——不是因为代码质量差,而是因为代码不在生产环境里。重建后的 v0 直接从 GitHub 仓库读取代码,生成的代码走标准 PR 流程。
这个转向不是功能升级,而是范畴切换。sandbox 工具产出的是 prototype——看起来像但架构不对。repo-first 工具才能产出 scaffold——能直接进入开发的代码。区别不在模型质量,而在输入约束:仓库本身就是架构约束。
一起长大
但这里有一个容易被忽略的东西。v0 的转向说明的是仓库的价值,没说仓库是怎么变有价值的。
回到我最开始的那个场景。我调了几轮 workflow,下游同学等不及了,自己先跑通了代码,合入了主干。这对我的测试造成了干扰,但从另一个角度看,他的代码让仓库变厚了一点。目录结构多了一些,代码模式多了一些,agent 有了更多东西可以读。
我之前所在团队的迭代策略是这样的:先各自生成节点自己的 workflow,然后从最上游开始,完整跑一遍。不管产出有多烂,这就是第一版代码。然后大家人工半自动地把它修正成最终符合预期的样子。过程中记录下补充了什么信息、出现了什么问题,结束后做一次复盘。
复盘问两类问题。一种是"缺了什么":某个东西没做好,因为上游节点没有提供足够的信息——那就给上游提要求,做加法。另一种是"多了什么":上游说了,但下游没用上,或者用了反而搞混了——说明 context 太大了,节点可能需要拆分,做减法。
这个循环很自然,但它隐含了一个假设:workflow 是唯一在优化的东西。实际上不是的。每一轮下来,改的不只是 workflow,还包括仓库里的代码。第一轮的代码(不管多烂)被修正、合入之后,第二轮的 agent 面对的是一个更厚的仓库。它的产出变好,不仅仅因为 workflow 改了,也因为仓库有了更多信息。
workflow 和代码是共生的。
从零搭建一个完善的 workflow 之所以难,是因为你面对的是空仓库。为了让 agent 产出像样的东西,workflow 几乎得把所有架构知识都编码进去——哪个模块放哪、用什么状态管理、API 怎么设计、错误怎么处理。这些东西在成熟项目里是在代码里的,你不需要告诉 agent,它自己读。但在空仓库里,代码没有,你只能往 workflow 里塞。
这不是 workflow 的问题,是仓库太薄的问题。
反过来想:与其执着于造一个在空仓库上也能完美产出的 workflow,不如先跑出第一版代码,合入,让仓库变厚一点。第二版的 agent 就有东西可读了。第三版更多。每一轮,workflow 可以变薄一点,因为有些信息不需要 workflow 重复告诉了——代码已经说了。
这个方向是反直觉的。搭 workflow 的人天然会把 workflow 当成自变量,把输出质量当成因变量。但实际上,仓库也是自变量,而且可能是更强的那个自变量。Workflow 是杠杆,但支点是仓库。空仓库上再长的杠杆也撬不动什么。
这也是为什么那些"先搭完美 workflow 再开始干活"的计划总是落空。完美的 workflow 需要完美的仓库作为输入,完美的仓库需要完美的 workflow 来生成——这是鸡生蛋。打破循环的方式不是找到最完美的初始 workflow,而是接受第一版就是烂的,靠人工修到可接受,然后让仓库和 workflow 互相推着往前走。
Vercel 做 v0 的时候说的那句话——90% 是对已有代码的修改——其实还有后半句没说:剩下的 10% 从零构建,靠的是第一版的人先把最初始的仓库填出来。那 10% 不能自动化,不是因为技术做不到,而是因为自动化需要输入,而输入还不存在。
注释是决策痕迹
写到这儿,我临时想起一个相关的点。前面一直在说仓库本身包含信息,但有一个很容易被忽略的细分值得单独拎出来:注释。这个想法不是主线论证的一部分,但写的过程中一直冒出来,觉得挺有意思,就放在这儿。
关于注释有没有必要,讨论了几十年。有人说注释是代码表达力不够的补丁,Clean Code 学派认为应该尽量避免。有人说注释不可替代,因为它记录的东西代码没法表达。
我觉得两边都没说错,但需要区分两个东西:结果和决策过程。
代码是结果。它说做了什么,通过命名和结构能表达怎么做。但代码没法说为什么选了这个方案而不是别的方案,考虑了哪些边界条件,接受哪些已知限制。这些是决策痕迹——在最终代码中被压缩掉的过程信息。
举个实际的例子。你发现某个按钮在 Safari 里偏移了 3 个像素,查了半天发现是 Safari 对 inline-block 的 baseline 计算和其他浏览器不一致。你试了几个方案,最后加了一行 vertical-align: -3px,问题解决了。代码本身只能告诉后来者这里偏移了 3 像素,但没法说为什么。几个月后有人重构样式,看到这个 magic number,觉得不干净,删了。Safari 又歪了。
这时候需要在旁边写一行注释:Safari 17 对 inline-block 元素的 baseline 计算与 Chrome/Firefox 不一致,-3px 是用来补偿这个偏差的。测试覆盖:Safari 17.4、iOS Safari。这就是决策痕迹。不是"这行代码在做什么"——代码已经说了。是"这个决策当时是怎么做出的、为什么必须是这个值、什么情况下可以重新评估"。
这个原则到处都适用。一个奇怪的默认值、一处刻意的冗余查询、一段故意没抽象的函数——每一项都可能是时间线上的决策节点,丢了理由就丢了上下文。
修 bug 的时候,最危险的操作不是改错了代码,而是在不理解为什么这行代码这么写的情况下去改它。git log 偶尔能帮你恢复这个信息,但前提是当时的 commit message 记录了——大部分时候它没记录。一个在决策点旁边写的注释,比几年后隔着几百个 commit 翻出来的 message 可靠得多。
这意味着代码注释和 agent handoff 里的 rationale 字段是同一个东西,只是对象不同。agent 之间的交接需要记录决策理由,人类之间的交接也需要。代码是长期交接的介质,注释就是长期交接的决策痕迹。
从右往左推
如果仓库本身就是知识库,那我们应该怎么摆放信息?
我画了一个梯度。
最左边是目录结构和文件名。它们的信息密度最高,维护成本为零——模块边界、功能分区都写在这里,而且你想不维护也不行,编译逼着你维护。
往右是代码本身。接口契约、逻辑、约束,都在这里。密度高,维护成本零——改代码本来就是你的工作。
再往右是注释。决策理由、边界条件、已知缺口。密度中等,维护成本低——只有决策变了才需要改。
再往右是 ARCHITECTURE.md、DESIGN.md 这类项目级文档。跨模块的设计意图、整体权衡。密度低,维护成本中等。
最右边是 skill——项目无关的方法论、流程约束。密度最低,维护成本不低。
每一层应该只包含左边那一层无法表达的东西。目录结构不需要一份说明模块布局的文档——目录本身就是布局。代码不需要一份罗列 API 签名的文档——代码本身就是目录。这些项目级文档只需要覆盖从代码里读不出来的东西。skill 应该尽量薄,只包含通用方法,不包含项目特定的架构信息。
这解释了为什么很多知识库工程推不动:它们要求人额外维护一套独立于代码的知识体系,而那套体系一定会过时。过时的东西,agent 读了反而有害。
优化的方向应该是从右往左:把知识从 skill 推到项目文档,从项目文档推到注释,从注释推到代码。代码是最终的知识存储,维护成本最低,存活时间最长。workflow 的目标不是替代码记住所有东西,而是把知识推向代码,让 workflow 变薄。
这听上去有点抽象。落到日常操作上,大概是这样。
那到底怎么办
如果你在搭 agentic workflow,下面几条可能有用。
第一,别追求从零产出完美结果的 workflow。做不到的——一个空仓库给 agent 的信息太少,workflow 得编码所有架构知识才能补上这个缺口,这样的 workflow 会肥到无法维护。第一版允许产出平庸,人工修正,合入仓库。这就是 baseline。
第二,每次迭代之后,不只复盘 workflow 哪里该加减,也问一句:有哪些信息明明应该在代码里,结果跑到了 workflow 的 prompt 里?把它们移到代码里去。下次 agent 读到代码的时候,就不需要 workflow 重复告诉它了。
第三,认真对待目录结构和命名。它们是信息密度最高、维护成本最低的知识层。一个 agent 看到 src/features/auth/ 比看到某份项目文档里写"认证模块在 src/features/auth/"有用得多——前者是代码事实,后者是文档描述,后者可以过时,前者不能。
第四,写"为什么"注释,别写"是什么"注释。agent 读代码和人类读代码一样,需要决策理由。这不需要很多,只有在决策不显然的时候才需要。但一旦写了,未来读这行代码的人(或 agent)就不用猜了。
一句话:仓库和工作流是一起长大的。别追求那个能凭空产出完美代码的 workflow,先跑出第一版不完美的代码,让仓库厚起来,workflow 自然就变薄了。
我现在还没搞明白的一些事
一个问题是,这个梯度框架对"设计文档"这类东西的定位。技术方案文档是放在仓库里还是放在 workflow 的产物目录里?它似乎在代码和项目级文档之间占据了一个奇怪的位置——它是生成出来的,不属于原始代码,但生成完之后就成了下游节点的事实输入。会不会存在一种中间形态,设计文档的某些部分应该直接"编译"进代码(比如作为注释),而不是作为独立文档永远存在?
另一个是,如果仓库厚到一定程度了,workflow 能不能薄到消失?不是所有的 workflow,而是某些特定 stage。比如 Code stage,当仓库里的代码模式足够丰富、agent 只需要"照着写"就能产出架构正确的代码,Code stage 的 workflow 指令是不是可以压缩到几行?如果把 skill 推到极限,让它只包含"读代码→仿写→跑测试",那它还算 workflow 吗,还是说它退化成了一个薄 wrapper,本质上是 agent 在靠仓库自导航?
还有一个和人的因素有关的。我观察到很多工程师对注释有抵触——不是因为注释没用,而是因为以前被要求写的那种注释(解释一段代码做什么)确实没用。他们没体验过"为什么"注释带来的好处。如果团队没有养成写决策理由注释的习惯,仓库对 agent 的可用性会打折。但这个习惯怎么培养,目前没有好的答案。它不是工具问题,是文化问题。
参考文献
- Vercel v0 rebuild (Feb 2026). Tom Occhino on the pivot from sandbox-first to repo-first generation. 提供了"90% 是对已有代码的修改"这个关键数据点。
- GitHub Blog (Oct 2025). How to Build Reliable AI Workflows with Agentic Primitives and Context Engineering. 提出了 context engineering 三层框架,包括 session splitting 防止上下文污染。
- The Rice Stack (2025). Building AI-First Codebases. 结构化 AI-first 仓库的实践方案,显式指出已有代码架构约束 agent 行为。
- Jeff Atwood (2006). Code Tells You How, Comments Tell You Why. Coding Horror. 引述 Jef Raskin,提供了"注释解释 why"的经典表述。
- Steve McConnell. Code Complete (2nd ed.). Section 32.3 on commenting techniques. 软件工程领域关于注释目的的经典论述。
- Martin Fowler. CodeAsDocumentation. martinfowler.com. 论证代码是唯一足够详细和精确的文档形式。
- Michael Nygard (2011). Documenting Architecture Decisions. cognitect.com. ADR 的起源,主张架构决策记录应与代码存放于版本控制中。
- BoringDocs (2025). The Hidden Cost of Documentation Drift. 量化了文档-代码分叉的经济成本,中型团队每年 $100K-$150K。