当 Claude Code 在 2025 年 12 月底突然爆红时,大量软件开发者迅速转向把编码代理(coding agents)纳入自己的主要开发工作流。
“vibe coding”一词的创造者 Andrej Karpathy 在 2026 年 3 月的 No Priors 播客中表示:
我觉得我大概从 12 月以后就没再敲过哪怕一行代码了,基本上就是这样,这是个极其巨大的变化。我觉得普通人其实并没有意识到这件事已经发生了,或者说它有多么戏剧性。
我信他。很多人说这只是营销或炒作,但作为一个自去年以来也一行代码都没写过的人,我觉得他说的是实话。至于这到底是好是坏,要看你从什么角度看,但毫无疑问,我们已经进入了软件工程的一个新时代。
尽管代理被迅速采用,但从业者以及旁观者心里的普遍焦虑也在增长:这场席卷一切的“糊代码”浪潮会有结束的一天吗?我们是在为了便利而把自己一点点毁掉吗?我们该怎么阻止这一切?
UML 的共同创造者 Grady Booch 其实认为,我们正处在软件工程的第三个黄金时代:
Booch 很谨慎地指出,这第三个时代并不是由 AI 开启的,只是被 AI 加速了。但他也把 AI 编码代理比作 Grace Hopper 时代编译器的出现,而这才是这里真正重要的类比。编译器抽象掉了机器;代理抽象掉了代码本身。
现在,我们第一次能够直接从意图生成代码。过去之所以有模型驱动开发(model-driven development,MDD)失败,很大程度上就是因为我们做不到这一点。(你可以怎么看 UML 都行,但也许现在是时候考虑以某种形式把 MDD 拉回来了。)
从实践上说,当我们沿着抽象层级向“意图”上移时,我们会失去很多让代码工作变得可靠的工具和方法。如果我们能适应这种变化,我相信它不仅可能加快开发速度,还可能大幅提升软件方案的质量。
但就目前而言,我们还困在 vibe coding 的赌场里。现在几乎人人都在像世界末日一样疯狂产出代码,拉动把手,祈祷好运。
Vibe coding 几乎普遍被描述为两点:(a)会损害对解决方案和架构的个人理解;(b)由于提示词过于模糊、自然语言接口存在信息损失,以及代码生成本身具有非确定性,因此不可靠。
当你在做 vibe coding 时:
这就是那种黑箱效应:它会慢慢吞噬你的工作流,让你作为软件工程师变得越来越不严谨,直到最后你开始盲目提交 commit,把生产环境搞挂。
即便你不会以这种方式滥用编码代理,而是更愿意手动编程,也很难否认这大概就是整个软件工程的大趋势。我们能看到有多少工程师正在把编码代理纳入核心工作流,也能看到有多少 100x 开发者已经开始试图和它们一起构建自动化循环,仿佛控制与决策只是阻碍真正目标的干扰项:tokenmaxxing。
无论如何,归根结底都是信任问题;你无法信任自己对代码库的理解,也无法信任代理真的做了你想让它做的事。
我们都明白这很糟,但潜在的解决方案呢?围绕这个话题有很多讨论,但我认为到目前为止提出的方案都远谈不上有说服力。
首先,我们得先达成共识:我们到底想解决什么。我们的目标是尽可能减少对编码代理输出的信任需求。
为此,我们希望:
而现有方案没有一个能充分满足这三点。它们大多依赖于某种提示词工程,或者干脆就是提示词工程本身,而这和意图提炼(#1)不是一回事。
我和很多工程师聊过,他们通常会这样讲:
嗯,我会用 markdown 规格说明,然后协调一个代理流水线去审查它们,把它们实现成代码,再去管理和更新它们;它还会检查一致性,对照现有代码库,标记任何冲突的地方,然后交给实现;等做完之后再回头更新 spec,这样文档和代码就永远不会漂移,所以说到底 markdown 就是唯一真相源,其他一切都只是围着它同步运转……
当我听得眼神开始放空时,脑子里会不停冒出这些问题:
这里会衍生出很多问题,而答案通常都极其含糊——到这一步,这看起来就只是个人工作流优化,对可验证的结果没有任何影响。他们自己觉得这样很“严谨”,也就仅此而已。
Addy Osmani 在 2026 年 2 月写的文章 “How to Write a Good Spec for AI Agents” 很好地体现了这一点。
它并不算空泛,恰恰相反,它很密:五条原则、一个六段式格式、对 2500 个配置文件的研究、提到你听过的所有工具。看起来像一套系统。然后你会发现,整篇文章其实只是在代理场景下讲提示词工程。
我们不能严肃地把这叫作规格驱动开发,因为这个 spec 并不是“唯一真相源”,而只是一个引导性提示词。既没有强制机制,甚至连简单的对齐机制都没有,除了去问代理“代码是否符合 spec?”——而 AI 可以随便怎么理解这个问题,因为根本没有共享语法!
从根本上说,Markdown 规格说明并没有解决我们对代理的不信任,而且管理起来真的很烦。它们必须变得清晰结构化,并被放进一个更大的系统中,才会有用。
这些本质上就是你按任务有条件注入的上下文/指令。虽然它们可能有用,但它们仍然完全依赖代理去遵循,而这在我们的需求下和 markdown spec 的失败方式一模一样——尽管它们实现起来没那么麻烦。
有趣的是,它们往往也很啰嗦、很累赘,比如 gstack 的这个巨大的 “QA” 技能。
我几乎可以肯定,对大多数代理来说,提示“find and fix bugs plz”也能把事情做得一样好(甚至更好?)。
技能充其量只是提示词工程的补充。
Spec Kit 是一组 markdown 模板目录,由一个 CLI 放进你的项目里。你需要按顺序运行六个命令:specify → clarify → plan → tasks → analyze → implement。
在幕后,代理会被引导着按照模板定义所有内容,然后把这些产物保留下来,作为后续提示词的上下文。
这几乎算是一个开端,因为它试图给 vibe coding 套上一点流程,并松散地定义了一个让编码代理遵循的结构。关键词是“松散”,而问题在于,是开发者在驱动整个流程——六个命令代替原本的一个——但你仍然看不到任何真正发生的东西。
OpenSpec 则是同一思路的轻量版本:用 explore → propose → apply → archive 代替六命令流水线,用普通 markdown 的 WHEN/THEN 场景代替 Kiro 的 EARS。它做了同样的押注,也以同样的方式失败:你在驱动流程,代理给自己的作业打分,但没有任何机械化检查去对比 spec 和代码。
这类项目有很多个,基本上都一样。
通过 hooks 引导代理使用带有 EARS 需求的 markdown 规格说明,试图把功能开发系统化。
如果你不知道 EARS(Easy Approach to Requirements Syntax,需求语法简明法)是什么,下面有两个例子,展示自然语言需求和 EARS 需求的区别:
| 自然语言 | EARS |
|---|---|
| 为了安全起见,如果用户长时间不活动,应该把他们登出。 | WHEN a user session has been inactive for 15 minutes, the system SHALL terminate the session and redirect the user to the login page. |
| 处理失败支付时要优雅一点。 | IF a payment attempt fails, THEN the system SHALL preserve the cart contents and display the reason for the failure. |
这里使用 EARS 很有意思,因为它通过比纯散文更结构化的方式来表述需求,对代理和开发者都有帮助。当你在处理意图时,使用无结构的散文会很快让你眼花缭乱;它根本没法像扫代码那样去扫读。EARS 能帮上这个忙。
实现 hooks 也是个不错的方向,它强制代理对触发器作出反应,并显式遵循其流程步骤。虽然不是确定性的,但它是有结构的。
可惜的是,Kiro 有两个致命问题:
一个测试的名称就是对意图的描述;是必须由代码满足的业务或流程需求,用自然语言写成。测试本身则是锚定到真实代码上的一个锚点,它希望能够证明代码与该意图一致。从这个意义上说,更高层级的测试甚至可以充当功能依赖图。
终于有了一点确定性强制执行的影子。这确实有帮助!
不过,开发者通常会让代理去写测试,因为这样更省事,但这又把我们想解决的那些问题重新引了回来。
另一种办法是手动写测试,但那样你就必须知道代码是怎么实现的——而且你还得写代码;如果我们讨论的是把代码本身抽象掉,那我认为这就是个问题。我并不是说自己写测试不对,但这篇文章具体讨论的是如何修复 vibe coding。作为编码代理的爱用者,我们更希望尽可能停留在“意图”层,而不是“实现”层。
顺带一提: 下文还会提到的 CodeSpeak 最近就遇到了这个确切问题:最初的理论是开发者会手动编写 spec 文件,但大多数 alpha 测试者反而让自己的代理去做这件事。于是他们后来转向从自然语言提示词中自动提取结构化意图。
所以,我们还得绕回来:TDD 只能解决其中一部分问题,但前提是我们能够约束代理如何写测试,或者以确定性方式生成测试。
前面这些方案之所以不足,是因为它们没有解决核心问题:信任。
没错,它们确实试图让代理更贴合我们的意图。它们试图给代理一套操作流程。它们甚至也有一些关于保留变更历史、或者收紧执行框架(如 hooks)的基本思路。
但它本质上仍然只是一个提示词接口——再加上一些仪式化流程来充当纪律——让你读散文或读代码。它们没有把你正在做的事情完整地展示出来。它们没有强制代理去实现你定义的东西,甚至连代理自己声称实现了什么也没有强制核验。它们没有提供一个开发者和代理都认可的共享表面层。
而且,解决这个问题真的很难。值得注意的是,Tessl——一家因“规格驱动开发”承诺而融资 1.25 亿美元的公司——如今已经悄悄从向开发者出售 SDD 转向了“skills 是新的代码”。哎哟?
幸运的是,这个领域还很年轻,而且仍在积极试验中,已经有少数方法开始收敛到一些真正可用的方向上。
下面这两个项目(免责声明:其中一个是我自己的),我认为是最朝着正确方向前进的。
顺便说一句,据我所知,真正聚焦信任问题的项目只有这两个;如果还有别的,我也很想了解。
由 Kotlin 的创建者 Andrey Breslav 发起。
CodeSpeak 的押注是:信任可以被编译掉。你编写简洁的 markdown 规格说明,把它们组织成可以互相导入的模块,然后用 codespeak build 把它们编译成可运行的代码——Python、Go 或 TypeScript,基本不需要你去审阅。这个工具链非常认真地对待“编译器”这个定位:构建前会先验证 spec 的一致性,构建后会运行测试,而 codespeak takeover 甚至可以从现有代码库反向生成 spec。
在我前面提到的那个转向之后,他们也在上层继续做需求层:把你和代理的对话提炼成结构化需求,映射到实现这些需求的代码文件上,并在变更偏离时标记漂移。同时,他们也还在努力把 spec 语言本身形式化,目标是让构建过程具有确定性,或者至少接近确定性。
过去六个月里,我一直在做这个工具,并不断迭代它,以贴合我自己的开发工作流。
Scryer 的押注方向相反:代理本身的信任不可约减,所以应该尽可能降低这部分信任的成本。它是面向编码代理的模型驱动开发。你和你的代理共享一个系统模型:一个 C4 风格的层级结构,其中每个节点都用简短、与语言无关的声明说明自己的职责,并映射到实现这些职责的源码行以及证明这些职责的测试。代理通过 MCP 读写这个模型;你则把它当作 wiki 页面和图表来浏览,而不是去读代码。
模型先行,代码跟随。你计划一次变更时,计划会以类似 git diff 的形式显示在整个模型上。这就是你的影响范围。其下则是一个确定性的可观测层,报告已构建内容与计划内容的差异、哪些声明已被锚定且有测试支撑,以及自上次对账以来代码相对模型发生了哪些漂移。
现代软件开发在很大程度上就是一遍又一遍重做同样的模式,使用标准解决方案,并进行算法的混搭。这正是 LLM 擅长的事情——它们在这方面比我们做得更好,老实说,我们为什么还要手工做这些事?它只会带来倦怠和虚无主义。
手写代码永远会存在于定制化、全新且复杂的工作中。希望很多开发者能慢慢重新找回对编程的热爱——当他们能把这份热爱用在真正让自己感兴趣、真正有挑战的问题上时;而对其他一切,我们都应该尽量让编码代理变得尽可能可靠。
也许我们会继续作为代理的“飞行员”;也许不久之后自主代理就会承担大部分工作。无论哪种情况,它们都需要一份 spec——而那些披着流程外衣的提示词仪式并不够。我们需要跨过当前这一堆半成品方案,走向真正为此构建的工具:把意图作为一等公民的工件,并与代码进行校验。
我们回不到没有编码代理和 vibe coding 的世界了,但我们可以把这台老虎机调好,然后离开赌场。