代理式工程模式:三个提示词让AI写出靠谱代码

一、这篇文章讲什么

2026 年 2 月,Django 联合创始人 Simon Willison 在 GitHub 上发布了一个项目——Agentic Engineering Patterns(代理式工程模式)。

这个项目要解决的问题很具体:我们都在用 Claude Code、Codex 这类编码代理写代码了,但怎么才能让代理写出来的代码靠谱

Simon 给出了三个极短的提示词,分别对应三种场景。本文把它们拆开讲清楚,给出可以直接复制使用的模板。


二、一个前提:写代码变便宜了,好代码仍然贵

在讲具体模式之前,先说一个核心判断。

过去,写几百行干净代码可能要花一整天。所以我们的很多习惯——前期设计、排期、对每个改动做成本收益分析——都是围绕“编码时间稀缺”建立的。

编码代理把“敲代码”这件事的成本压到接近零。但这只是故事的一半。

Simon 列了一份“好代码”的清单:

  • 能工作(功能正确,没有明显 bug)
  • 能被证明能工作(有测试、有可复现步骤)
  • 解决的是正确的问题(需求本身没跑偏)
  • 异常和边界条件有处理
  • 足够简单,只做需要做的事
  • 有测试保护
  • 文档和代码同步
  • 为未来变化留余地,但不过度设计

结论:代理能帮你做大部分,但你仍然要为最终质量负责

下面是三个具体的做法。


三、模式一:First run the tests

3.1 是什么

每次让代理进入一个已有项目的新会话,第一句话就说:

1
First run the tests

就这四个词。

3.2 为什么有效

这四个词同时做了三件事:

第一,让代理发现测试套件。 它会自己去找怎么运行测试(pytestnpm testgo test ./...),找的过程本身就是在熟悉项目。

第二,建立项目基线。 测试框架会显示测试数量和结果。代理因此知道项目有多大、质量如何、哪些地方有问题。

第三,切换心智模式。 跑过一次测试后,代理在后续的改动中更倾向于自觉回归测试。

Simon 有一句很实在的判断:如果 AI 生成的代码从未被执行过,它部署后能工作几乎只能靠运气。

3.3 不同技术栈的写法

Python(uv + pytest):

1
Run "uv run pytest"

Simon 自己用 pyproject.toml 的 dependency groups 管理 dev 依赖,让 uv run pytest 成为拿到仓库就能跑的默认体验。

Node/TypeScript:

1
2
First run the tests. Try: npm test.
If that fails, inspect package.json scripts and run the correct one.

Go:

1
First run the tests. Run: go test ./...

Rust:

1
First run the tests. Run: cargo test

有 Makefile 的项目:

1
2
First run the tests. Run: make test.
If unknown, list targets first.

3.4 常见坑

  1. 只看测试输出,不让代理解释失败原因。 很多失败是环境问题。建议要求代理每次修复都写清楚“为什么失败——怎么改——影响面”。

  2. 允许代理跳过测试。 如果代理说“我无法运行测试,但我认为改动没问题”,把它拉回来。要么修环境,要么缩小改动范围。

  3. 项目本身没有测试。 这种情况下,把 First run the tests 换成“先搭最小测试骨架”,然后进入下一个模式。


四、模式二:Use red/green TDD

4.1 是什么

当你要让代理做任何行为变更——新功能、修 bug、重构——开头加一句:

1
Use red/green TDD

代理会自动进入测试驱动开发模式:先写测试,确认失败(红),再写实现让它通过(绿)。

4.2 为什么对代理特别有效

代理有两个常见问题:

  • 写出“看起来对但实际不能跑”的代码
  • 写出“不必要的、没人用的”代码

TDD 同时压制了这两个问题。Test-first 迫使代理先把需求变成可失败的断言,再写最小实现。正确性和范围都被约束了。

4.3 四步节奏

一个完整的红/绿循环:

  1. 澄清行为:把需求写成输入/输出/边界/错误。
  2. 写测试(红):新增测试用例,运行,确认失败。
  3. 写实现(绿):写最小代码让测试通过。
  4. 重构与回归:整理代码,全量测试仍通过。

其中第 2 步特别重要:一定要确认测试会失败。 如果你写了一个“本来就会过”的测试,等于什么也没验证。

4.4 可直接使用的提示模板

1
2
3
4
5
6
7
8
We are going to implement <feature>.
Use red/green TDD.

1) Add/modify tests first.
2) Run the tests and confirm they fail for the right reason (red).
3) Implement the minimal code to make them pass (green).
4) Run the full test suite again.
5) If you refactor, keep tests green after each step.

<feature> 换成你的具体需求就行。

4.5 常见坑

  1. 代理跳过红阶段。 直接写实现再补测试。这样测试变成“验证已写代码”而不是“定义目标行为”。可以硬性要求:先展示测试 diff,再写实现。

  2. 测试太宽松。 只断言“返回值非空”,或者 mock 太多导致不接触真实逻辑。你需要像 code review 一样 review 测试质量。

  3. 一次改太多。 代理喜欢“顺便把 XX 也做了”。在 TDD 下明确:每次只引入一个可验证的行为变化。


五、模式三:Linear walkthroughs(线性走查)

5.1 是什么

当你需要理解一个代码库——可能是别人的、可能是你自己 vibe coded 出来的——让代理生成一份结构化的逐模块讲解文档。

5.2 为什么需要这个

Simon 自己就遇到了这个场景:他用 Claude Code 做了一个 SwiftUI 幻灯片应用 Present,发到 GitHub 后发现自己不懂它怎么工作。

他的做法是开一个新会话,让 Claude Code 先读 repo,再做线性走查。

5.3 关键约束:防止幻觉

这里最重要的技术决策:

代码片段必须来自命令输出(sed/grep/cat),不允许代理手工复制粘贴代码。

为什么?因为模型在“复述代码”时非常容易出现微妙偏差——改了变量名、漏了参数、调换了顺序。讲解文档里如果有这种错误,读者会建立错误的理解。

用命令输出插入代码片段,就把“解释”变成了“解释 + 证据链”。

5.4 可直接使用的提示模板

1
2
3
4
5
6
7
8
9
Read the repository source code and plan a linear walkthrough
that explains how it works.

Rules:
1) Use shell commands (sed/grep/cat/rg) to extract real code snippets.
Do NOT manually retype code.
2) Cover file by file or module by module:
what it does, key types/functions, data flow.
3) End with "How to verify": commands to build, run, and test.

如果你的项目装了 Showboat(Simon 自己写的工具),可以用它来生成可执行的 walkthrough 文档:

1
2
3
Run "uvx showboat --help" and use that tool to create walkthrough.md.
Use "showboat note" for commentary.
Use "showboat exec" to run shell commands that extract code snippets.

5.5 适用场景

  • 入职新项目:让代理生成系统结构 + 关键模块 + 入口 + 测试说明。
  • Vibe coded 项目需要维护:先理解再改。
  • 事故复盘:根据日志和代码,生成故障路径走查文档。
  • 重构前评估:输出耦合点、隐式假设、测试覆盖缺口。

六、三个模式怎么组合使用

6.1 接手陌生代码库

1
2
3
步骤 1:线性走查(理解)
步骤 2:First run the tests(建立基线)
步骤 3:用 red/green TDD 做一个小改动(验证理解)

先有理解,再有基线,再有可验证的实操经验。

6.2 修 bug

1
2
3
4
步骤 1:Use red/green TDD
步骤 2:第一步必须是"复现 bug 并写成失败测试"
步骤 3:写最小修复让测试通过
步骤 4:全量回归

本质就是把代理变成一个“测试驱动的补丁生成器”。

6.3 重构

1
2
3
4
步骤 1:First run the tests(确认当前绿)
步骤 2:补充/加固关键行为的测试
步骤 3:让代理按小步重构,每一步跑测试
步骤 4:如果任何一步测试变红,立刻回滚这一步

重构真正昂贵的不是“改动本身”,而是“确信没改坏”。


七、落地清单

把上面的内容压缩成可以直接贴到团队文档里的清单。

会话开局

  • 一句话说清本次目标
  • 说清约束(不改哪些模块、兼容性、性能边界)
  • 执行 First run the tests
  • 代理解释了测试怎么跑、跑了多少、失败原因

代码变更

  • 用 Use red/green TDD 开头
  • 红阶段:新测试确实失败,失败原因与需求一致
  • 绿阶段:最小实现通过
  • 全量测试通过
  • 文档/注释是否需要同步

代码理解

  • 代理先输出走查计划(目录结构、入口、关键模块)
  • 代码片段来自命令输出,不是手动复制
  • 文档包含:如何运行、如何测试、关键数据流

PR 审阅(“好代码”检查)

  • 代码真的跑过了吗?
  • 怎么知道它能工作?(测试/证据在哪?)
  • 解决的是正确的问题吗?
  • 异常和边界条件怎么处理的?
  • 是否足够简单?有没有不必要的额外改动?
  • 测试覆盖了新增行为吗?
  • 文档同步了吗?

八、总结

Simon Willison 这个项目的核心思路用三句话就能说清:

  1. 写代码便宜了,但好代码仍然贵。
  2. 用极短的提示词触发完整的工程纪律——“First run the tests”“Use red/green TDD”“Linear walkthrough”。
  3. 你的价值不在于写代码,而在于定义问题、建立证据、守住质量。

这三个提示词你今天就可以开始用。不需要任何配置,不需要任何工具链改造。打开你的编码代理,把它们打进去,然后观察代理的行为变化。

(完)