推荐教程:AI 编程 Agent 实战方法:从需求到测试的可靠工作流

AI教程21小时前更新 程序员阿超
287 0 0

一、背景:Agent 写代码,为什么总是”看着很美、合入很痛”

AI 编程 Agent(Claude Code、Codex、Cursor Agent、Gemini CLI 等)已经能自主完成”读仓库—改多文件—跑测试—修 bug”的闭环。但大量团队的真实体验是:演示时惊艳,合入时心惊。常见症状有四个:第一,Agent 一次改了十几个文件,diff 大到没人敢 review,只能含泪合入;第二,需求只讲了一半,Agent 把剩下的一半”脑补”完了,方向跑偏;第三,没有测试兜底,Agent 修好一个 bug、引入两个新 bug;第四,换个会话一切重来,上次的约定、踩过的坑全部失忆。

问题的根不在模型能力,而在工作方法。Towards Data Science 上那篇《How to Work with AI Coding Agents》点破了关键:把 Agent 当作”能力很强但缺乏上下文、需要被管理的初级工程师”,人承担架构师 + 验收者的角色,用可靠的流程把 Agent 的产出约束在可控范围内。本文把这个思想展开成一套从需求到测试的完整实战工作流,每一步都有可复制的话术模板、文件模板和代码示例。

二、原理:人与 Agent 的责任边界

2.1 Agent 的能力模型

理解 Agent 的三强三弱,才能分好工。三强:阅读速度极强(几分钟扫完数万行仓库)、样板代码生成极强(CRUD、测试脚手架、迁移脚本)、不知疲倦(可以连续跑几十轮”改—测—修”循环)。三弱:业务上下文弱(不知道你们为什么这样设计)、长期记忆弱(超长会话后遗忘早期约定)、自我纠错弱(倾向于证明自己是对的,而不是发现自己错了)。

结论:凡是依赖”判断”的事(需求取舍、架构决策、最终验收)必须人做;凡是依赖”执行”的事(搜代码、写样板、跑测试、修 lint)放心交给 Agent。流程设计的本质,就是把这两类事 cleanly 分开。

2.2 可靠性的三个支柱

第一支柱是书面契约:需求、约束、验收标准全部落成文字(spec、AGENTS.md、测试),而不是口头erse。文字是 Agent 唯一可靠的记忆载体。第二支柱是小批量流动:每次只让 Agent 做一小步,每步都可 review、可回滚,风险敞口永远有限。第三支柱是机器验收:用测试、类型检查、lint 作为客观裁判,而不是让 Agent 自己宣布”完成了”。三者缺一不可:没契约会跑偏,没小批量会爆雷,没机器验收会自欺。

2.3 成本账:为什么”慢即是快”

很多人觉得写 spec、拆任务、逐块验收太慢,不如直接让 Agent”全自动搞完”。实测数据恰恰相反:一次 800 行的”全自动”提交,review + 返工经常花掉半天;而 8 次 100 行的小步提交,每次 review 十分钟,总耗时反而更少。因为大 diff 的 review 质量极低——人看 800 行 diff 时基本在”扫”,bug 漏网率极高。小步提交的 review 是”读”,能真正发现问题。流程的前置成本,都会在返工环节数倍赚回来。

三、环境准备

3.1 选型与安装

任选其一即可,本文话术对三者通用:

# Claude Code(终端 Agent)
npm i -g @anthropic-ai/claude-code && claude --version
# 或 OpenAI Codex CLI
npm i -g @openai/codex && codex --version
# 或 Cursor / Gemini CLI,按各自文档安装

3.2 仓库脚手架

mkdir agent-workflow-demo && cd agent-workflow-demo
git init && python -m venv .venv && source .venv/bin/activate
pip install pytest ruff mypy
mkdir -p specs src tests docs .agent

3.3 三份契约文件

AGENTS.md(仓库级约束,Agent 每次开工前必读):

# AGENTS.md
- 语言 Python 3.11;风格 ruff(行宽100);类型注解 mypy --strict
- 测试 pytest -q;新功能必须带测试;覆盖率 ≥80%
- 禁止:新增第三方依赖(spec 特批除外)、提交密钥、修改 migrations 以外的 DB schema
- 工作方式:一次只做一个任务;每步结束给出 diff 摘要 + 测试结果;等我确认再继续

specs/spec.mdspecs/tasks.md 后面实战中生成。.agent/memory.md 记录跨会话约定(喜欢的库、踩过的坑),每次会话开始让 Agent 先读它。

四、分步实战:从需求到测试的完整闭环

贯穿例子:给内部订单系统加”按客户导出对账单 CSV”功能。需求来源是一句话:”财务每月要对账,能不能一键导出某客户某月的账单?”

步骤 1:需求澄清——把一句话变成规格

为什么必须做:一句话需求丢给 Agent,它会脑补计费口径、时区、金额精度,十次有九次脑补错。需求澄清的目标是消灭”合理但错误”的假设。

话术模板(直接复制可用):

你是资深业务分析师。先读 AGENTS.md 和 src/ 订单相关代码,
然后针对这个需求向我提问,把所有模糊点挖出来,一次问完:
"给订单系统加按客户导出月度对账单 CSV"。
要求:问题按"计费口径 / 时间边界 / 金额精度 / 异常场景 / 性能"分类,
每个问题给你的推荐选项。等我答复后再写 specs/spec.md,不要提前写代码。

本例问出的关键问题(真实项目中这类问题通常有 10~20 个):

  • 退款单是否计入?(答:计入,单独一列负金额)
  • 月边界按 UTC 还是本地时区?(答:按公司时区 Asia/Shanghai)
  • 金额精度:分还是元?(答:元,保留 2 位小数)
  • 无订单月份导出什么?(答:只有表头的空文件 + 警告)
  • 数据量上限?(答:单客户单月最多约 50 万行,必须流式写)

spec.md 落稿模板

# spec:月度对账单导出

## 1. 目标与非目标
- 目标:按客户+月份导出对账单 CSV,50万行 < 30s
- 非目标:PDF 格式、自动邮件发送、多客户批量导出

## 2. 接口
- CLI:`billing export --customer C123 --month 2026-08 [--out bill.csv]`
- 库函数:`export_statement(customer_id, year_month) -> Iterator[Row]`
- 错误码:参数非法 exit 2;客户不存在 exit 3

## 3. 口径(核心!)
- 含退款单(amount 为负);月边界 Asia/Shanghai;金额元/2位小数
- 排序:按下单时间升序;列顺序:order_id, created_at, amount, status

## 4. 边界矩阵
| 场景 | 行为 |
| 无订单月份 | 仅表头 + stderr 警告 |
| 非法月份格式 | exit 2 + 用法提示 |
| 客户不存在 | exit 3 + 错误信息 |

## 5. 验收标准
- A1 口径单测全过;A2 50万行性能达标;A3 CLI 端到端覆盖边界矩阵

自检清单:spec 有没有”验收标准”节?每个验收项能不能翻译成测试用例?如果不能,spec 还不够具体。

步骤 2:架构踩点——让 Agent 先画地图再施工

为什么必须做:直接让 Agent 写代码,它可能在错误的分层上实现(比如把 SQL 拼在 CLI 层)。先让它输出”实现方案”,人确认后再动手,纠偏成本差一个数量级。

根据 specs/spec.md,阅读 src/ 相关模块,输出实现方案(只写文档不写代码):
1) 改哪几个文件、每个文件改什么;2) 复用哪个现有函数;
3) 流式导出的技术选型(生成器/分块查询);4) 风险点。
控制在 300 字内。等我回复"开工"再实现。

本例中 Agent 发现 src/orders.py 已有 iter_orders(customer, start, end) 生成器可复用——这个发现省掉了重复造轮子。如果人直接让它写,它大概率会另起炉灶再写一套查询。

步骤 3:任务拆分——切到 15 分钟粒度

把 spec 拆成 specs/tasks.md,要求:
- 每个任务 ≤15 分钟、有明确验收(引用 A 编号)、标注依赖;
- K1 必须是测试脚手架 + fixture;性能任务单独列最后。
# tasks
- [ ] K1 脚手架:tests/test_statement.py + 万行 fixture 生成器
- [ ] K2 口径函数 export_statement()(验收 A1)
- [ ] K3 CSV 序列化与 CLI 接线(验收 A3)
- [ ] K4 边界矩阵用例补齐(验收 A3)
- [ ] K5 50万行性能优化 + bench.py(验收 A2)

步骤 4:TDD 实现——红绿小循环

每个任务固定三句话派工,做到极致的”一次一件事”:

只做 K1(测试脚手架),不写实现。测试引用 A1 口径。
完成后运行 pytest -q,把结果贴出来,等我确认。
# tests/test_statement.py(K1 产出)
from decimal import Decimal
from billing import export_statement

def test_refund_as_negative(sample_orders):
    rows = list(export_statement("C123", "2026-08"))
    refunds = [r for r in rows if r["status"] == "refunded"]
    assert refunds and all(r["amount"] < 0 for r in refunds)

def test_empty_month_warns(sample_orders, capsys):
    rows = list(export_statement("C123", "2020-01"))
    assert rows == []
    assert "警告" in capsys.readouterr().err

def test_sorted_and_rounded(sample_orders):
    rows = list(export_statement("C123", "2026-08"))
    ts = [r["created_at"] for r in rows]
    assert ts == sorted(ts)
    assert all(Decimal(str(r["amount"])).as_tuple().exponent >= -2 for r in rows)

红灯确认后再派实现任务:

只做 K2(export_statement 实现),要求:
1) 复用 iter_orders;2) 不碰 CLI;3) 跑通测试后附 ruff + mypy 结果。
# src/billing.py(K2 产出节选)
from collections.abc import Iterator
from decimal import Decimal, ROUND_HALF_UP
from zoneinfo import ZoneInfo

TZ = ZoneInfo("Asia/Shanghai")

def export_statement(customer_id: str, year_month: str) -> Iterator[dict]:
    """按客户+月份流式产出对账单行,金额元/2位小数,退款为负。"""
    start, end = _month_range(year_month, TZ)
    found = False
    for o in iter_orders(customer_id, start, end):
        found = True
        amt = (Decimal(o["amount_cents"]) / 100).quantize(
            Decimal("0.01"), rounding=ROUND_HALF_UP)
        if o["status"] == "refunded":
            amt = -amt
        yield {"order_id": o["id"], "created_at": o["created_at"],
               "amount": float(amt), "status": o["status"]}
    if not found:
        import sys
        print(f"警告:{customer_id} 在 {year_month} 无订单", file=sys.stderr)

步骤 5:逐块 review——人的核心价值所在

每块完成后强制 Agent 输出结构化报告:

K2 完成。请输出:1) diff 摘要(每个文件改了什么、为什么);
2) 风险自评;3) pytest/ruff/mypy 结果全文。不要开始 K3。

人的 review 清单(打印贴显示器旁):

  1. 接口与 spec 口径是否逐字一致(时区?精度?排序?)
  2. 有无引入 spec 之外的依赖或文件
  3. 边界用例是否真覆盖(空月份?非法输入?)
  4. 复杂度是否失控(函数超 50 行就要求拆)
  5. 有无硬编码魔法数字(时区、精度必须走常量)

通过就 git commit,不通过就精确指出文件行号打回。提交信息建议带任务号:feat(billing): K2 口径函数与退款负金额

步骤 6:集成与回归——把散件拼成整机

K3/K4 做 CLI 接线与边界补齐:

做 K3,要求:1) argparse 参数 --customer/--month/--out;
2) 非法月份 exit 2、客户不存在 exit 3;3) 端到端测试覆盖边界矩阵全部 4 行。
# 端到端测试节选
def test_cli_bad_month(tmp_path):
    p = subprocess.run(["billing", "export", "--customer", "C123",
                        "--month", "2026-13"], capture_output=True, text=True)
    assert p.returncode == 2

步骤 7:性能验收——先量化再优化

# bench.py(K5)
import time
from billing import export_statement
from tests.conftest import make_half_million

make_half_million()
t0 = time.time()
n = sum(1 for _ in export_statement("BIG", "2026-08"))
cost = time.time() - t0
print(f"rows={n} cost={cost:.1f}s")
assert cost < 30, "性能不达标"
跑 bench.py。若超标,只允许做"分块查询/减少 ORM 开销/流式写文件"三类优化,
不准改口径。优化前后各跑 3 次取中位数对比。

步骤 8:文档与记忆沉淀——让下次更快

收尾:1) 更新 README 的导出用法;2) 写 CHANGELOG 条目;
3) 把本次踩过的坑追加到 .agent/memory.md(每条 ≤30 字)。

.agent/memory.md 示例:

- 订单金额库里是"分",展示层一律转"元"
- 月边界用 Asia/Shanghai,别用 UTC
- 大批量导出必须流式,禁止先攒 list

下次新会话第一句话就是:”先读 AGENTS.md 和 .agent/memory.md,再开始。”记忆不再失忆。

五、六类常见坑与对策

坑 1:需求只说一半就开工

症状:Agent 脑补口径,做完发现计费逻辑全错,整块返工。对策:spec 没有”口径”节和”验收标准”节,不许进入实现。宁可在提问环节多花 20 分钟,不在返工环节花 2 小时。

坑 2:任务块太大导致 review 瘫痪

症状:一次 800 行 diff,人根本看不动,只能”感觉没问题”就合入。对策:15 分钟粒度是铁律,超了就继续拆。大 diff 合入后出 bug,定位成本是小步提交的数倍。

坑 3:让 Agent 同时做两件事

症状:”顺手把 K3 K4 一起做了吧”——结果 K3 的 bug 藏在 K4 的代码里,互相掩盖。对策:一次只派一个任务号,完成、验收、提交后再派下一个。并行只适用于无依赖的纯研究任务。

坑 4:测试后补等于没测

症状:先实现后补测试,测试只是给现有行为”背书”,边界 bug 全漏。对策:测试文件提交时间必须早于实现;CI 校验覆盖率门槛;从 K1 开始就是红灯先行。

坑 5:上下文污染与记忆漂移

症状:长会话后期 Agent 开始违背早期约定(又用了 UTC、又攒了 list)。对策:任务拆小自然缩短会话;新开会话只喂”AGENTS.md + spec + 当前任务 + memory.md”,不喂整段历史;关键约束写进 lint 规则(如禁用 datetime.utcnow)比写进提示词更可靠。

坑 6:把最终验收外包给 Agent

症状:Agent 说”全部完成,已自测通过”,人看一眼就合入,上线翻车。对策:验收标准必须是机器可执行的(pytest/ruff/mypy/bench),人只认命令输出不认 Agent 的总结。Agent 的”完成了”只是开工信号,不是完工证明。

六、总结:可靠工作流一页纸

  1. 契约先行:AGENTS.md(约束)+ spec.md(口径与验收)+ memory.md(经验),全部落字。
  2. 方案踩点:先让 Agent 输出实现方案,人确认分层与复用后再开工。
  3. 小步流动:15 分钟任务粒度,一次一件事,每步提交。
  4. 测试驱动:红灯先行,覆盖率门禁,边界矩阵全覆盖。
  5. 机器验收:pytest/ruff/mypy/bench 的输出才是完工证明。
  6. 记忆沉淀:每轮把坑写进 memory.md 和 lint 规则,下次不再交学费。

按这套流程跑两到三个需求,你会发现 Agent 从”惊喜制造机”变成”稳定产能”:一次通过率上升、返工消失、新人接手也能照单执行。而沉淀下来的 spec、测试与 memory,正是团队最值钱的工程资产。 点击阅读原文

参考资料:Towards Data Science《How to Work with AI Coding Agents》(1行)。 点击阅读原文

七、附录:并行研究任务与多 Agent 分工

除了一次一件事的主线实现,还有一类适合并行的纯研究任务:让两个 Agent 同时调研不同技术选型,各自输出方案文档,最后由人拍板。这种”竞争式调研”能显著拓宽方案空间,前提是任务只读不写代码,避免互相污染。输出模板强制统一:方案描述、改动文件清单、风险点、估算工作量四节,格式一致才好横向对比。多 Agent 分工的另一形态是审查员模式:一个 Agent 写实现,另一个只做审查输出问题清单,写者根据清单修改。审查员与写者用不同模型或不同 temperature,能发现更多单视角遗漏。但注意审查员只能提问题不能直接改代码,改代码的权力始终在主线任务手里,避免多头写入导致冲突。并行虽好,主线实现永远串行,这是可靠性的底线,任何时候都不要为了赶时间把有依赖的两个实现任务并行派出去,并行省下的半小时,抵不上一次合并冲突事故。

© 版权声明

相关文章

暂无评论

暂无评论...