Vibe Coding 从乱序到有序,不能只靠 Agent

通过近几个月内使用 Codex 和 Zcode 进行我的业余 APP 项目的开发,大模型在编码方面的能力之强,确实让我这个古法编程了十几年的软件工程师觉得叹为观止。很多我以前的想法都通过 Codex,通过 Zcode 变成了一个个产品,这种感觉让我找回了对编程开发的热情。「没办法,被大厂厚重的流程折磨得够呛」。
高度智能、快速交付、Computer Use,三大法宝完虐古法编程
一是大模型的丰富知识和高度智能。不管我要开发 iOS,MacOS,node-js,chrome 插件,FCP 插件,它都游刃有余。
二是大模型的极快的交付效率。在识别我的意图后,它可以立马给我输出一个成品,我在使用过程中发现有 bug,跟它交流一下,然后修复版本「嗖」一下就出来了。
三是 Computer-Use。第一次使用 Codex 的 Computer-Use 的时候,我惊呆了,它竟然可以通过操作剪映的字幕动画库,观察,然后编写 FCP 插件来实现类似的动画效果。这一切全自动。当然,第一版编写出来的效果差强人意,但如果让我自己去做这个事情,最起码半个月的工作量,而且几乎做不到大模型第一版的水平。
大模型就相当于一个知识丰富,永不疲劳,响应快速的工程师助手,可以很有效地和我形成互补。我提出想法,它会和我一轮轮讨论,最后形成方案,并很快给我输出一个产品。这种爽感,让我很难想象以前那种手敲代码的日子是怎么过的了。
随之而来的乱序,让我开始思考 VibeCoding 背后的三个隐性问题
随着对产品的逐步迭代的过程中,我发现了这种人+Agent 协作开发模式反而让我陷入了乱序中。
很多时候一天下来,我的时间全花在三件事上:回忆"优化构建脚本"这个需求是什么时候、在哪句话里交代过的;核对那句"已完成"到底算不算完成;拍板那些 Agent 不敢做、也不该让它做的决定。
我从一个用创意构建一切的开发工程师,变成了一个用眼睛盯着一切的项目经理。热情在逐步消去。
深思之后,我总结应该是以下三个原因:
一:状态不可见。 需求散落在会话中。哪个需求是谁提的、做到哪一步了、当时为什么这么定——对话一关,上下文就蒸发了,下次要么靠脑子记,要么翻会话记录考古。Agent 不缺执行力,缺的是针对执行力的管理。
二:质量不可控。 Agent 说"完成"和你敢不敢信,是两回事。在提示词里写"必须先跑测试"、在 skill 里写"不要自动 push",这些都属于劝告——模型大概率遵从,但没有任何机制保证。遵从是概率的,验证就得是全量的:每一句"已完成"背后都是一次人工验收——测试真跑了吗?边界条件处理了吗?有没有顺手改坏别的东西?AI 的产出速度翻几倍,验证成本就跟着翻几倍,而负责验证的人始终只有你。人成了整条流水线上唯一的硬约束,自然就成了质量不可控最大的瓶颈。
三:决策不可管。 Agent 干活时一定会撞上需要人拍板的时刻。每个需求或 bug 的方案决策散落在会话中,要么卡在那等待你的输入,要么先做了,等人工验证时再说。久而久之,每一个决策都不可考究了。
这三个问题和 Agent 数量无关,开一个会话也照样收;但当你想像管理一个开发团队那样,让多个 Agent 并行干活,这些问题会被同步放大。
有意思的是,这些问题人类开发团队早就遇到过,名字分别叫分工、边界、交接、验证、追溯。人类团队的答案是 Jira 、Git Flow 、code review。
那现在"人 + Agent"的Vibe Coding 时代,有对应的答案么?当然你可以让 Agent 们自己去记录,自己搞,你有需要再问它搞到哪了。但这种方案对于我来说是不可接受的,根本原因就是每一次跟 Agent 的对话,都是一笔开销,这笔钱应该是花在让它帮我做创造性工作,而不是一轮轮的状态确认等确定性工作。何况每一次对话,Agent 都要思考一番,如果说我让它帮我创建一个bug 单,它还要长篇大论输出一番,这种体验对我也是不可接受的。
因此我作为一个喜欢造轮子的软件工程师,开发了 「Agent Team Board」(简称 ATB),尝试为这上面问题提供综合性的解决方案。ATB 已经开源,大家有兴趣可以去围观试用。
ATB 把需求看板内嵌进 Git 仓库
ATB 不是又一个"让 Agent 自主开发"的框架——恰恰相反,它从第一天就假定 Agent 不能自主。它做的事情是:把需求管理看板内嵌进 Git 仓库,用明确的状态机和执行规范,让 Agent 在人工把关下像真正的开发团队一样协作。
我的一个核心设计决策是:所有需求的内容都用文件表示,随代码一起提交进 Git 。 没有外部数据库,没有云端服务,没有需要额外维护的看板页面——仅在你的业务项目里多一个目录而已。
这样设计的好处是可以和业务代码共享同一套 Git 平台,而且全文本架构对人和 Agent 都非常友好,Git 的历史版本管理机制也足够强大。但未来也可以预期到数据量大后,查询性能会首先成为瓶颈,到时再考虑索引机制。
人机边界不靠提示词,靠强制的硬约束
ATB 用一条简单的状态流转线来明确"什么事 Agent 能做,什么事人来做":
submitted → accepted → planned → in-progress → done
↑ ↑ ↑
└── 人工接受 ──────────────┴── 人工确认 ──┘
Agent 认领
这条线的关键不是状态多,而是每个状态的流转权限被严格限定:
| 流转 |
操作者 |
说明 |
| → submitted |
任何人 / Agent |
有人(或 Agent )提出了一个需求 |
| submitted → accepted |
人 |
人工判断这个需求值得做 |
| accepted → planned |
人 |
人工确认技术方案和测试用例就绪 |
| planned → in-progress |
Agent |
Agent 认领并开始实施 |
| in-progress → done |
人 |
人工确认实施完成并通过验收 |
Agent 不能代替人做任何一个关键决策:不能接受需求、不能确认完成、不能越过 planned 状态直接开干、不能在卡住的时候自己做取舍。
这不是不信任 Agent ——这是明确分工。 Agent 擅长执行明确的指令,人擅长定义什么指令值得被执行。把这两件事混在一起,才是大多数"Agent 自己把项目改坏了"故事的根因。
ATB 同时提供了钩子脚本,能够限制 Agent 对某些文件和指令的执行,确保 Agent 不会自己去接收或确认需求已完成。整个流程在工具层堵死了,这比在提示词里面写一百遍「禁止修改需求状态」可靠得多。
让需求成为上下文隔离单元,杜绝上下文污染和膨胀
一个主会话(调度者)可以一次性把多个 planned 状态的需求批量派发出去,每个子 Agent ( worker )领取其中一项,独立完成。每个子 Agent 只会按需加载所领取的需求的文档进行分析或开发,完成后不会把上下文传递回主会话或交给下一个子 Agent。
需求是天然的上下文隔离的载体,正如人类团队开发项目一样,在这一点上是殊途同归了。
至于说是否能真的杜绝上下文污染和膨胀,我只能说从原理上应该是可行的,但是没有做 AB 测试,目前看效果也还稳定,没有出现突然降智的情况,在 Agent 中显示的上下文窗口的占用也一直是比较低的水平。
让AI串行还是并行,这是个问题
我知道很多人都喜欢让多个 Agent 同时开发多个需求,认为这会提升效率,毕竟人类开发团队也都是这么做的。
但我认为 AI 时代,需要分开来看
- 需求分析阶段,确实可以并行,因为这时候的产出是需求文档,不同 Agent 产出是不同的需求文档,彼此之间不会有冲突需要合并,所以可以大胆并行。
- 需求实施阶段,不建议并行。原因很简单: AI Agent 写代码的质量还没稳定到可以放心让两个 Agent 同时改同一个代码库。文件冲突、依赖顺序问题、接口不一致——这些在人类团队里都需要认真协调的事,对 Agent 来说只会更难。
- 需求验证阶段和分析阶段类似,也是可以大胆并行的。
所以 ATB 用一个 impl 互斥锁 来保护执行阶段。调度者可以把多个 worker 排好队,但实际只有一个在跑,其他 worker 在 $ATB batch next 时会被阻塞,等前一个完成、互斥锁释放后才继续。这不是"不能并行",而是"保守地并行"——批量派发保留了清晰的分工和任务列表,但执行时串行以保证安全。
希望后面大模型的发展会让我打消这个顾虑和限制。毕竟,「又快又好,谁不喜欢呢?」
让 TDD 成为强制约束,而不是建议
每个 worker 的执行规范里有一段刚性流程:
- TDD 实施:
test-cases.md 补用例跑红 → 实现 → 跑绿 → 重构。新问题按 /bug 登记。
修 Bug 必须归因引入来源( REQ-/BUG- 编号)。
这不是"建议你先写测试"。 worker-spec.md 里写的是执行命令序列:先跑 atb claim 认领,然后必须读 test-cases.md,然后红绿重构,然后 atb report 上报覆盖率和框架,最后 atb run receipt 回执。
如果 Agent 跳过了测试?那它根本走不通上报流程—— report 命令需要 --coverage 和 --framework 参数,没有实际跑过测试的 Agent 拿不到这些。
把约束从"劝告"下沉到"走不通"。report 缺参数就交不了差,流程在工具层堵死了"没跑测试"这条路
人工介入全过程可视,可追踪
任何 Agent 在执行中都可能遇到需要人工拍板的问题。过去这个时刻, Agent 要么自己拍了(然后可能拍错),要么卡死在那里等待人类去捞起。
ATB 给了 Agent 第三条路:
$ATB hold declare <ID> \
--question "这里用 SQLite 还是 PostgreSQL?" \
--reason "需求文档没指定,影响后续部署" \
--run <runId> --by <agentId>
声明发出后,本轮执行以 blocked 回执收尾,条目本身保持 in-progress,进入看板的「待人工确认」聚合区(atb hold list 可查等待时长与未答计数),问题与决策留痕写入 runtime/holds/decisions/<ID>.md。待决期间,该条目会拒绝新的认领——防止第二个实施者插手。
人工在看板上补充决策(hold answer,仅限人工,支持存草稿),决策齐备后一次操作复工(hold resume),条目经专用通路回到 planned 队列等待重新取单;也可以越过未答项直接确认完成,或者作废这单阻塞(hold cancel)。
关键点:声明与决策全程留痕——谁问的、等了多久、人为什么这么答,都有账可查。以后再遇到类似问题,新的 Agent 可以直接读到当时为什么做了这个选择,而不是从头再纠结一遍。
结语:约束要下沉为门禁,不能停在建议
当前 AI Agent 的主流叙事要么是"让 Agent 自主完成一切",要么是"Agent 就是个辅助工具,人手一个自己玩"。 ATB 试图走中间那条路:用最小的工程开销,让多个 Agent 像一个有序的开发团队一样协作,同时保持人类对关键决策的完全控制。
开篇那三个问题的本质是:提示词层面的遵从永远是概率的,所以一切只停留在"劝告"层面的质量保证,最终都会折算成人的验证时间。 ATB 的做法是把约束逐层下沉——没跑测试, report 交不上去;互斥锁没释放,第二个 worker 进不来;状态没到, Agent 推不动任何人工节点。真正不可绕过的闸门,物理上只属于人。
它解决的不是一个技术难题,而是一个协作难题。 VibeCoding 的项目开发,需要的不是更聪明的提示词,而是更清晰的规则、更明确的人 Agent 边界、以及一个能随代码一起走的「项目记忆」。