人类设计系统,AI 写代码:一个五人团队不再接受人类提交的 PR
Humans Architect The System, AI Writes The Code
Tessl 的 Paul Stack 分享其团队自 1 月底起不再手写任何代码,所有实现由智能体完成,人类提交的 pull request 一律不合并,外部贡献只接受 issue、设计提案和问题证据。
作者以五个月不写代码的团队实践,给出把约定变成约束、用门禁替代信任模型的具体做法。
自一月底以来,我在工作中没有写过一行代码。这并不是在断言每个团队明天都应该如此。这就是我们的工作方式,而它已经改变了我把时间花在什么地方。
我在演讲《人类架构系统,AI 编写代码》中想要区分的,是编写代码与构建编写代码的机器之间的区别。在 AI 时代,这一区分至关重要。人们把这称为软件工厂、黑暗工厂、智能体工作流,或者别的什么。真正有用的部分其实更简单:人类需要设计出将意图转化为可靠软件的流程。
在 System Initiative,以及我们从这项工作中拆分出来的新公司里,这一点变得非常具体。我们花了数年时间构建一个架构精美的 Rust 系统。一月底,我们把代码扔掉了,因为产品本身需要为 AI 原生世界重新思考。我们五个人留了下来,从一块 Miro 白板开始,从一开始就围绕智能体重建了我们的工作方式。
这就是我想要分享的故事。不是建议每个人都禁止自己敲代码,而是一个具体的例子,说明当你认真对待这个想法时会发生什么变化。
把这次演讲用作智能体上下文
Tessl 把我的 AI DevCon 演讲变成了一个可供你的智能体用作上下文的技能。你也可以观看完整录像。

我为什么停止写代码?
诚实的答案是,我早已不再热爱逐行编写代码了。
我描述过的其中一个时刻,是坐在一通电话会议上,人们正在讨论 NATS 队列的命名约定。电话上的人非常在意把它做对。我理解为什么。这些细节在系统中很重要。但对我来说,那不再是我想要投入大部分精力的工作。
我现在关心的是架构、设计、约束、不变量,以及产品随时间推移的一致性。如果智能体能承担更多实现工作,那么人类的工作就会上升一个层次。问题就变成了:这个系统必须意味着什么,它应该如何表现,什么绝不能违反,以及我们如何让这些期望变得可执行?
这就是为什么我说感觉无法规模化。一行提示词也许能让你在小任务上有所进展。它甚至可能让人印象深刻。但如果没有关于系统应该变成什么样的明确想法,输出就无法保持一致。你可以消耗大量 token,最终仍然得到一个没有架构脊梁的产品。
我们不接受人类编写的拉取请求
我们的规则很直白:每一行代码都由智能体编写。
这不是偏好或指导方针。如果有人提交了人类编写的拉取请求,我们不会合并它。原因不是人类编写的代码不好。原因是我们试图保护正在构建的系统的完整性。如果系统依赖于智能体产出实现,那么流程、约束、检查和反馈循环就必须围绕这一事实来设计。
同样的规则也影响开源贡献。我们不接受包含代码的外部拉取请求。我们确实接受问题、功能请求、想法、设计提案,以及证明某处有问题的证据。这听起来可能很苛刻,但在 AI 生成代码的世界里,开源维护者已经在应对大量看似合理的补丁。有些有帮助。有些很草率。有些可能是供应链攻击。
如果我无法可靠地区分一个由 agent 生成的良好贡献和一个恶意贡献,那么我就不希望代码路径中存在这样的攻击面。贡献的方式是帮助我们改进产品和对工作的规范。然后 agent 可以在我们控制的流程内实现它。
流程是一个状态机
这个系统的重要部分不是 agent 编写代码。重要的是围绕这项工作的生命周期。
我们的流程从一个 issue 或功能请求开始。该 issue 会被分诊和分类。然后系统生成一个计划。该计划会经过一个对抗性审查循环。一个 agent 提出计划,另一个 agent 对它提出质疑,寻找安全问题、架构漏洞、缺失的需求,以及计划与系统约束不匹配的地方。
这个循环是有边界的。我们允许最多五轮。如果 agent 们无法达成一致,就由人类来仲裁。人类不会被丢进一团模糊的混乱中。分歧会被捕获为结构化数据,这样我们就可以询问 agent 们在哪些方面达成一致、在哪些方面存在分歧,以及计划为何被阻塞。
一旦计划足够好,实现就开始了。如果是 bug,系统会尝试复现并验证它。如果是功能,路径会继续进入 pull request。从那里开始,工作会经过审查关卡、UAT、发布,并通知回提出请求的人。
这不是一堆 shell 脚本。它是一个技能内部的状态机,由 CLI 支撑。这使它可维护且可扩展。agent 不只是即兴发挥。它是在一个设计好的工作流中推进。
CLAUDE.md 是可执行契约
对我们来说,CLAUDE.md 是重心。它不是被动文档。它是与 agent 之间的可执行契约。
该文件包含我们代码库中重要的约束。TypeScript 必须是严格模式。我们不使用 any。我们使用命名导出。文件带有正确的 AGPL 版权。我们不会发出 promise 后就不管。端点返回 JSON。实现细节不会泄漏到公共接口中。
这些看起来可能像编码标准,但在 agentic 工作流中,它们变得重要得多。它们是 agent 在行动之前读取的规则。如果它们含糊、过时或不完整,系统就会表现不一致。如果它们精确且得到维护,就能让团队改进生成器,而不是反复手工修复输出。
最后一行也很重要。如果 agent 遇到一个不明显、会绊倒未来会话的问题,它应该记录下来并提出更新。这就是系统从失败中学习的方式。一个错误应该变成更好的约束,而不只是一次性的修正。
测试和关卡承载信任
这个工作流中的信任不是来自信任模型。它来自信任关卡。
我们运行单元测试、集成测试、契约测试、属性测试和架构测试。在构建出二进制文件后,我们会把它发布到另一个仓库,并作为用户运行它。该用户验收测试是一个发布关卡。一个已合并的 pull request 并不自动意味着代码到达了最终用户。
我们还运行对抗性测试。系统会尝试注入输入、杀死进程、删除数据,以及做真实用户和损坏环境会做的那些事情。失败会被反馈回流程中。
我们的 CI 有五道合并门禁:代码审查、对抗性审查、用户体验审查、CI 安全审查和技能检查。技能检查之所以重要,是因为我们的产品设计为由 agent 驱动。如果技能的内容、格式、触发条件或 agent 体验出现退化,那就是真正的产品退化。
当每一道门禁都通过时,pull request 可以自行合并。这一点之所以可信,仅仅是因为发布路径仍然受到证据的约束。
这些数字是循环的结果
我展示这些数字,并不是为了证明每个人都应该完全照搬我们。它们是为了展示一个有边界的流程能够实现什么。
在过去 30 天里,共开启了 295 个 issue。我们发布了其中 217 个,并将 81 个作为重复项或我们不会做的事情关闭。分诊的中位时间为 4.6 个实际小时。从分诊到发布,包括各道门禁,中位时间为 1.6 个实际小时。
公司里有五个人。我们每个人都有一个 Claude Max Pro 订阅,我们在 CI 审查流程上每月花费大约 $1,500 到 $2,000,这种工作方式每月总共花费约 $3,000。对我们来说,这与我们过去构建软件的方式相比,成本结构截然不同。
但瓶颈并没有消失。在问答环节中,我说现在的瓶颈是决定要构建什么。如果我能启动十个 agent,却把它们指向错误的功能,我就能制造出一团非常快速的混乱。人的工作变成了意图、产品判断和架构。
从一个约束开始
如果你想尝试这种模式,不要把一个 agent 指向整个组织然后指望一切顺利。
从把约定变成约束开始。写下你的代码仓库所假定但从未言明的东西。把一条似乎只有组织中某一个人知道的知识编码下来。运行一个从 issue 到计划、到审查、到实现、到验证的完整工作流。然后看看它在哪里出问题,并添加下一个约束。
这就是最小可用的循环。重点不是第一天就构建出我们的整个流程。重点是不要再把 agent 的失败当作孤立事件,而是开始改进导致这些失败的系统。
我在演讲结尾提出了一个观点:意图是新的架构。我认为这就是人类角色正在转向的方向。只有当人类把系统的意图表达得足够明确,使其能够被执行、审查、测试和改进时,agent 才能编写更多的代码。
这一论点的完整版本在 AI DevCon London 上进行了展示。想深入了解,请观看完整录像。
来源:Tessl Blog · tessl.io