3 个 AI Agent,1 个空目录,2 小时 49 分钟,跑完一个 Todo Demo 的开发、测试和收尾。它不是生产项目,而是一次观察 Agent Teams 协作边界的实验。
一、起因
我想做个小实验:用 FastAPI + React 搭一个 Todo Demo,不追求业务复杂度,只看 Agent Teams 能不能把前后端、QA 和收尾流程串起来。
按以前的习惯,这类 demo 我会自己撸后端、写前端、再补测试。工程量不大,但流程很完整,刚好适合做一次受控观察。
这次我想试试 Claude Code 的 Agent Teams:能不能让几个 Agent 分角色协作,跑完一个小型样例项目?
结论是:能跑通,也暴露了不少边界。
二、实验过程:从空目录到 Todo Demo
2.1 环境准备
Agent Teams 目前还是 Claude Code 的实验特性,需要 Claude Code v2.1.32+。建议先用claude --version查 CLI 版本;启动会话后,也可以用/status看当前会话状态。
开启方式二选一:
// ~/.claude/settings.json{"env":{"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS":"1"}}exportCLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1终端建议用 iTerm2(macOS)或 tmux。Agent Teams 支持 Split Panes 分屏模式,能同时看到所有 Agent 的工作状态。不过本次实验用的是"进程内"模式,所有 teammate 在一个会话里按时间线展示。
teammateMode默认是auto,Claude Code 会根据运行环境自己选分屏还是进程内。
2.2 下达指挥官指令
这一步最关键。Prompt 写得含糊,团队跑得就含糊。
空目录下启动 Claude Code,输入:
🎯 项目:Todo List 应用 技术栈 - 后端:Python3.11+ / FastAPI / SQLite(使用 SQLAlchemy 或 sqlite3) - 前端:React18+ / Vite / TailwindCSS - 测试框架:pytest + httpx + 其他专项工具 🧩 API 接口定义(契约) 在动手写代码之前,我们先把前后端共同遵守的 API 契约定清楚。 Base URL:http://localhost:8000/api/v1|方法|路径|描述|请求体|响应||------|------|------|--------|------||GET|/todos|获取所有待办|-|[{id, title, completed, created_at}]||POST|/todos|创建待办|{"title":"..."}|{id, title, completed, created_at}||PUT|/todos/{id}|更新待办|{"title":"...","completed":true}|{id, title, completed, created_at}||DELETE|/todos/{id}|删除待办|-|{"message":"deleted"}|通用约定: - 请求/响应均为 JSON - 状态码规范:200(成功)、201(创建)、404(未找到)、422(校验失败) - 字段:id int, title str, completed bool, created_at datetime(iso8601)👥 Agent Team 及详细任务1. Backend Dev(后端开发) 职责:根据 API 定义实现后端逻辑与数据库。 核心任务: - 使用 FastAPI 搭建项目结构(main.py, models.py, schemas.py, database.py) - 使用 SQLAlchemy + SQLite 定义 Todo 模型 - 实现完整的 CRUD 路由,严格遵循契约 - 添加输入校验(Pydantic models) - 提供 CORS 配置以便前端调用 - 编写 requirements.txt - 提供数据库初始化脚本(自动建表) 交付物:可独立运行的后端服务,运行命令 uvicorn main:app--reload2. Frontend Dev(前端开发) 职责:基于 API 契约实现用户界面。 核心任务: - 使用 Vite + React + TailwindCSS 初始化项目 - 实现 Todo 组件:列表展示、添加输入框、完成/未完成切换、删除按钮 - 编写 API 调用层,封装 fetch/axios 请求所有端点 - 适配后端响应格式,展示 title, completed, created_at - 错误处理(请求失败时给出友好提示) - 响应式设计,保证移动端基本可用 交付物:可独立运行的前端服务,开发时配置 proxy 到后端8000端口3. QA Engineer(全面质量保障) QA 工作细化为以下十个维度,每个维度都有明确工具和产出要求。3.1代码审查(Code Review) - 代码风格:使用 black 和 isort 检查后端代码格式;前端使用 ESLint + Prettier - 类型检查:后端用 mypy 对 FastAPI 代码进行静态类型检查 - 覆盖率:用 coverage.py 收集后端覆盖率,目标>80% - 构建验证:验证后端能否成功启动,前端能否成功npmrun build3.2单元测试 - 后端:使用 pytest 对 Pydantic schemas、数据库模型操作、工具函数进行单元测试 - 前端:使用 Vitest + React Testing Library 对 Todo 组件进行单元测试3.3集成测试 - 后端:使用 pytest + httpx(或 TestClient)对每个 API 端点进行真实数据库(内存 SQLite)的 CRUD 测试 - 必须覆盖:创建/查询/更新/删除的正常路径、404 处理、请求体校验失败3.4契约测试 - 针对 API 定义写契约测试,验证响应 JSON schema、字段类型、缺失字段时的错误处理等 - 可以在集成测试基础上额外用 jsonschema 库校验响应结构3.5性能测试 - 使用 Locust 编写性能脚本,模拟10个用户并发创建和查询 Todo - 设定基线:平均响应<50ms,无异常失败3.6安全测试 - 静态扫描:使用 bandit 扫描后端代码,检查 SQL 注入、硬编码密钥等 - 依赖漏洞:pip-audit 检查后端依赖;前端npmaudit - 手动检查:确认 CORS 配置安全,输入输出转义3.7系统测试(端到端业务流程验证) - 使用 Playwright 编写 E2E 测试脚本,模拟真实用户操作: 打开页面 → 添加 Todo → 勾选完成 → 删除 Todo → 列表恢复为空3.8验收测试 - 基于用户故事编写验收用例 - 可以是手动测试清单,也可以用 BDD 框架自动化3.9数据整理 - 验证数据库初始状态、数据一致性 - 检查删除操作是否真的移除了记录,更新后时间戳是否变化3.10测试报告汇总 - 收集所有测试结果 - 给出质量结论:"所有测试通过,符合本次实验验收标准"或发现问题清单 ⚙️ 并行开发流程1. Team Lead 输出 API 契约后,Backend Dev 和 Frontend Dev 立即开始并行工作2. QA Engineer 在开发开始前先编写集成测试/契约测试用例和性能测试脚本框架3. 后端完成后,QA 立即执行代码审查、单元测试、集成测试、契约测试、安全扫描4. 前端完成后,QA 执行前端构建验证、E2E 系统测试、验收测试5. 所有测试数据汇总,生成最终测试报告 📦 交付清单 后端代码仓库(含所有测试) - 前端代码仓库(含必要的测试) - 测试脚本、配置文件(locustfile, playwright 脚本等) - 测试报告 TEST_REPORT.md(或 Allure 报告) - 启动说明 README.md 作为 Team Lead,现在请各角色开始认领自己的任务,严格按照契约开发。 QA Engineer 请密切跟踪每项质量检查点,汇总时直接向我汇报。按回车。然后等几秒,三个 Agent 就跑起来了。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
这个 Prompt 为什么管用?三个原因:
第一,API 接口表直接写在 Prompt 里,Team Lead 据此生成API_CONTRACT.md作为唯一真实数据源,三个 Agent 不需要猜接口长什么样。
第二,角色任务具体到了交付物。"可独立运行的后端服务,运行命令uvicorn main:app --reload"比"写个后端"清楚得多,Agent 知道什么算做完。
第三,QA 被当成了和开发对等的独立角色,十个维度逐条列出来,而不是"顺便帮我测测"。
三、团队组建
Claude Code 收到指令后做了两件事。
第一步,输出API_CONTRACT.md,覆盖 Base URL、请求/响应结构、状态码、CORS 配置。文件开头写明:
这是项目的唯一真实数据源。Backend Dev、Frontend Dev、QA Engineer 都必须严格按照本文档对接。任何变更必须由 Team Lead 同意并更新本文档。
第二步,三个 Agent 同时在后台启动:
3background agents launched(↓ to manage)├ @backend-dev ├ @frontend-dev └ @qa-engineer| 角色 | Agent ID | 任务 |
|---|---|---|
| Backend Dev | backend-dev@todo-app-team | 实现 FastAPI 后端(Task #1) |
| Frontend Dev | frontend-dev@todo-app-team | 实现 React 前端(Task #2) |
| QA Engineer | qa-engineer@todo-app-team | 阶段 1:编写测试计划与脚本框架(Task #3) |
三人同时开工,互不阻塞。后端前端独立并行,QA 先输出测试框架,等开发完再进实测。完成时各 Agent 通过 SendMessage 通知 Team Lead。
并行,但不是乱跑。
四、开发阶段
接下来发生的事,有点像一个缩小版团队练习,但边界也很明显:这是 Todo Demo,只能说明这个小案例跑通了。
4.1 前端先到
Frontend Dev 第一个完成,生成 12 个文件:
package.json / vite.config.js / tailwind.config.js / postcss.config.js index.html / src/App.jsx / src/components/TodoItem.jsx / src/api.js...它还主动给 QA Engineer 发了条消息:“我搞定了,你可以来测了。”
4.2 后端跟上
Backend Dev 完成了 7 个文件,自测全部契约场景通过:
main.py / database.py / models.py / schemas.py / crud.py requirements.txt / README.md此时 Team Lead 的进度表:
┌──────────────┬───────────────────┬────────────────────────────────────┐ │ 角色 │ 状态 │ 进度 │ ├──────────────┼───────────────────┼────────────────────────────────────┤ │ Backend Dev │ ✅ Task#1 完成 │ 7 个文件,自测全部契约场景通过 ││ Frontend Dev │ ✅ Task#2 完成 │ 12 个文件,已就绪可检查 ││ QA Engineer │ 🟢 Task#3 进行中 │ 已收到双端完成通知,应进入阶段 2/3 │└──────────────┴───────────────────┴────────────────────────────────────┘两个开发者转入 standby。但 standby 不等于闲置,Team Lead 让 Backend Dev 提前准备 4 项 patch 预案(环境变量化 DATABASE_URL、Mapped 类型注解等)。后面 P2/P3 收口时用上了一部分。
4.3 QA 的十维度测试
QA Engineer 把测试拆成 10 个维度,逐项执行,跟 Prompt 里定义的完全一致:
| 维度 | 工具 | 覆盖内容 |
|---|---|---|
| 代码审查 | black / isort / mypy / ESLint | 代码风格、类型检查、构建验证 |
| 单元测试 | pytest / Vitest | Schema 校验、工具函数、组件 |
| 集成测试 | pytest + TestClient | 真实 SQLite 的 CRUD 全场景 |
| 契约测试 | pytest + jsonschema | 响应结构、字段类型、边界条件 |
| 性能测试 | Locust | 并发 10 用户;GET/PUT/DELETE P95 < 25ms,POST 写入长尾约 2.1s |
| 安全测试 | bandit / pip-audit / npm audit | SQL 注入、硬编码密钥、CORS |
| 系统测试 | Playwright | E2E 全链路用户操作 |
| 验收测试 | Given-When-Then | 7 个用户故事 + 14 条验收条件 |
| 数据整理 | SQL 查询 | 数据一致性、时间戳验证 |
| 测试报告 | Markdown / Allure | 汇总所有结果 |
阶段 1 先出 10 个框架文件,开发完成后直接进阶段 2/3 执行。
阶段性结果:56 个后端测试 + 16 个契约测试 = 72/72 自动化测试通过,覆盖率 99%,安全扫描 0 issue。后续 P2/P3 收口后,最终扩展到 92/92。
五、质量闭环
测试通过不代表没问题。QA 第一轮先发现 6 项问题,后续 P2/P3 收口又补出 F-002,最终 7 项全部闭环:
| 缺陷 ID | 描述 | 严重度 | 阶段处理 | 最终状态 |
|---|---|---|---|---|
| B-001 | datetime.utcnow 已废弃 | P1 | 派发 Task #4 修复 | 已闭环 |
| B-002 | 时间序列化拼 Z 不规范 | P1 | 派发 Task #4 修复 | 已闭环 |
| F-001 | 前端排序不一致 | P2 | 派发 Task #5 修复 | 已闭环 |
| B-003 | StrictBool 类型 | P2 | P2 收口修复 | 已闭环 |
| B-004 | PUT 空 body 处理 | P2 | P2 收口修复 | 已闭环 |
| B-005 | SQLite WAL 模式 | P2 | P2 收口验证 | WAL 已启用,POST 长尾作为 SQLite 单 writer 边界接受 |
| F-002 | 时间显示 tooltip 与相对时间 | P3 | P2/P3 收口新增 | 已闭环 |
这个过程分两段:第一轮先修 P1 和直接影响体验的 F-001,避免在实验主流程还没跑顺时扩大变量;后续再把 B-003/B-004/B-005/F-002 单独收口。这样阶段记录和最终结果能对上。
5.1 后端修复
B-001 的修复就一行:datetime.utcnow()换成datetime.now(timezone.utc)。但验证做了一整套,DeprecationWarning 提级为 error 模式下,INSERT 路径零告警。
B-002 更细:写了个serialize_created_at函数,兼容 tz-naive/aware 双场景,输出统一 ISO 8601 + Z。四个序列化场景全过。
5.2 前端修复
F-001 的修复,一行搞定:
// 修复前[...prev,created]// 修复后[created,...prev]新创建的 Todo 出现在列表顶部,跟 API 默认排序一致。
5.3 回归验证
修复完,QA 跑全量回归:
62backend +16contract +8E2E +6manual=92/92 ✅六、一个有意思的观察:QA 的 halt-on-conflict
整个过程让我印象最深的,不是 99% 覆盖率,而是 QA Engineer 的审慎。
它触发了 4 次 halt-on-conflict,就是数字或文字对不上时,先停下来确认,绝不猜着干。
举一例。QA 收到一条任务派单,内容跟之前已完成的任务一字不差。它做了四重校验:派发者是自己(不会自己给自己派单)、任务 ID 已删除(系统里查不到)、时间戳在历史窗口(早于本次会话)、内容完全一致(回放不是新单)。判定为消息总线自重放,忽略,继续待命。
另一次是 cleanup 任务,要求关进程、删数据库。QA 发现 description 里 taskId 写的 32,subject 写的 34,对不上,于是拒绝执行,要求 Team Lead 二次确认。对一个 demo 来说,这只是避免重跑;但这个动作提醒我,不可逆操作前的停顿很有价值。
这些纪律被固化为 3 条 memory,下次开团队自动生效:
- feedback_doc_consistency.md — 改哪里(顶底同步) - feedback_history_snapshot_immutable.md — 不改哪里(历史段落不动) - feedback_halt_when_facts_conflict.md — 数字/文字对不上时先停七、Demo 收尾
Team Lead 给三个 Agent 发 shutdown_request,附上各自的贡献:
- QA Engineer:92/92 全绿 + halt-on-conflict 4 次拦截
- Backend Dev:契约硬化 + WAL 优化
- Frontend Dev:F-001 修复 + E2E 配合
实验最终状态:
| 项 | 状态 |
|---|---|
| 测试 | 92/92 全绿 |
| 缺陷 | 7 全闭环 |
| TEST_REPORT.md | 终版锁定 |
| API_CONTRACT.md | 三联硬化 |
| 服务进程 | 已关闭 |
| 数据库 | 已清理 |
| Team 成员 | graceful shutdown |
| Team 资源 | TeamDelete 清理完毕 |
从空目录到 Demo 收尾,2 小时 49 分钟。
实验验证结论一览
| 维度 | 状态 | 工具 | 实际执行 | 关键指标 |
|---|---|---|---|---|
| 1. 代码审查 | ✅ 通过 | 人工 + black + isort + mypy + bandit | 已执行 | 后端、前端各一份审查文档;工具链全绿 |
| 2. 单元测试 | ✅ 通过 | pytest 8.3.3 | 已执行 | 25/25 通过(P2 后 +1:StrictBool 拒 int) |
| 3. 集成测试 | ✅ 通过 | pytest + TestClient | 已执行 | 37/37 通过(P2 后 +5:int completed 拒、extra_field 拒、PUT 空体 422、PUT 空体 detail 含 “At least one”、PUT 仅 title 仍 200) |
| 4. 契约测试 | ✅ 通过 | pytest + jsonschema + httpx | 已执行(启动后端 8000 后) | 16/16 通过 |
| 5. 性能测试 | ✅ 通过(WAL 复测后) | Locust 2.43.4 | 已执行(2 轮:基线 30s + WAL 复测 30s) | 0% 错误率,POST P95 ≈ 2.1s(WAL 后,与基线 2.2s 持平,长尾未消除但未劣化;详见维度 5) |
| 6. 安全测试 | ✅ 通过 | bandit + curl 主动探测 | 已执行 | 0 issue(114 行扫描);CORS/SQL/XSS 均合规 |
| 7. 系统测试(E2E) | ✅ 通过 | Playwright + chromium + 人工浏览器 | 已执行 | 自动 8/8(chromium,7.54s,含 F-001 顺序回归 + F-002 tooltip 回归)+ 人工 6/6 PASS(2026-05-03 team-lead 在 chromium 实测);详见维度 7、“## E2E 实测”、“## 人工 E2E 验收记录"与”## P2 收口" |
| 8. 验收测试 | ✅ 通过 | Given-When-Then + Playwright + 人工 | 已执行 | US-1~US-4 由自动 E2E 8 用例(含 F-002 tooltip 回归) + 人工 6 用例双路覆盖;US-5/US-6 仍待人工补做(实验记录后续可补) |
| 9. 数据整理 | ✅ 完成 | csv + html cov + bandit txt | 已执行 | 性能 csv(基线+WAL 复测两份)、覆盖率 HTML、安全报告 |
| 10. 测试报告汇总 | ✅ 完成 | 本文档 | 已执行 | 见下文 |
总体覆盖率: 后端99%(437 行 Stmts,6 行 Miss)。
八、复盘
8.1 并行省的是总历时
传统 AI 编程是串行的,写完后端写前端,写完前端写测试。Agent Teams 让三件事同时发生,总历时从三段时间相加变成取最长那段。
8.2 契约先行,不要靠猜
三个 Agent 都拿API_CONTRACT.md当唯一数据源,谁也不凭猜想做接口。变更必须经过 Team Lead。这跟团队协作里的接口评审是同一类思路,只是这里发生在一个 demo 里。
8.3 纪律比速度值钱
4 次 halt-on-conflict,每次都可能省几小时排错。AI Agent 的最佳策略就是遇到不确定就停。
8.4 闭环比单点结果更重要
开发、测试、修 Bug、回归、收尾,整个闭环 Team Lead 自己跑完了。人工只在最后确认"验收通过 + cleanup"时介入了一次。
九、最佳实践与注意事项
Agent Teams 带来了新能力,也带来了新成本。以下是从这次实验里整理出来的。
9.1 任务粒度要合适
不要为了用而用。如果任务是线性的(先改 A 再改 B),单个 Agent 就够了,甚至更快。Agent Teams 有启动、消息传递、上下文同步的开销,线性任务硬拆反而慢。
值得组团队的任务,特点是并行度高、模块隔离度高:前后端联调、多语言翻译、微服务拆分、开发与测试并行。能并行的才组队,必须串行的别硬拆。
9.2 关注 Token 成本
每个 Teammate 是一个独立的 Claude 实例,拥有独立上下文。5 人团队的 Token 消耗速度可能是平时的 5 倍。
这次 Todo 项目,3 个 Agent 并行 2 小时 49 分钟,输入 5.2M token,输出 514K,合计 52.3M(含缓存 50.1M)。没缓存的话更吓人。
省钱的关键:委派模式。创建团队后按 Shift+Tab 切过去,Team Lead 就只管协调不写代码,不会和开发者抢活。这次实践中 Team Lead 全程就做了四件事:输出契约、派发任务、转发消息、做决策。零代码、零文件写入,上下文很轻。
9.3 角色定义要鲜明
给每个 Teammate 写清楚它是什么角色。越鲜明,协作越好。
| 角色 | 定义 | 结果 |
|---|---|---|
| Backend Dev | “严格按照 API 契约实现,不擅自扩展接口” | 不会自作主张加字段 |
| Frontend Dev | “只读 API_CONTRACT.md,发现歧义发消息问 Team Lead” | 不会凭猜测理解接口 |
| QA Engineer | “最苛刻的质量守门人,宁可误报不可漏报” | 主动发现问题而非走过场 |
反面:三个角色都叫"开发者",你会看到它们互相抢活、职责混乱、重复实现。
角色定义的本质就是划定边界,让每个人知道自己的事是什么,以及别人的事不是自己的事。
9.4 显示模式
如果终端环境支持,推荐 Split Panes(tmux / iTerm2)模式。同时看所有 Agent 的思考过程,监控方便,体验也很科幻。
Windows 上用 Git Bash 或者远程 SSH 的话,进程内模式也够用,就是需要滚动。
十、给想试的人
如果你想用 Agent Teams 复现类似 Todo Demo,这是我觉得最有用的五条经验:
先写契约再开工。API_CONTRACT.md 是团队的基石,模糊的契约等于模糊的产出。在 Prompt 里直接把接口表写出来,比事后补文档有效。
角色任务具体到交付物。"写个后端"是糟糕的指令,"使用 FastAPI 搭建项目结构,实现 CRUD 路由,交付可独立运行的后端服务,运行命令uvicorn main:app --reload"才管用。Agent 知道什么算做完,就不会过早或过晚交付。
给 QA 独立地位。让 QA 先行写测试框架,不要等开发完了才想起来。这次 QA 的阶段 1 跟开发同步推进,开发完成时测试框架已就位,零等待。
设置 halt 机制。遇到冲突先停。不可逆操作(删库、关进程)前必须二次确认,这不叫低效,叫给错误留一个刹车。这个 demo 里类似情况出现了 4 次。
实验也要收尾。关进程、清数据库、删 Team 资源,否则下次复现实验会被脏状态干扰。QA 在 cleanup 阶段关了 uvicorn/vite 两个进程,删了 SQLite 数据库三件套(.db / .db-wal / .db-shm),6 项验证全过。
写在最后:一次小实验的价值
这次实验让我重新看了一眼人和 Agent 的协作方式。过去更像结对,你和一个 Agent 面对面,你说它写,一问一答,有效,但串行。不管 AI 多快,你一次通常只能盯住一件事。
Agent Teams 把串行变成了并行。Team Lead + Teammates 的架构,在本地模拟出一个很小的协作场景:有人定契约,有人写前后端,有人做 QA。每个角色有自己的上下文、判断力和行动边界,这跟传统 Sub-agents(一个人指挥多个工具)有本质区别。
但能力越大,成本越重。3 个 Agent 并行近 3 小时,Token 消耗是单人模式的数倍。它更适合并行度高、边界清楚的任务,不是所有任务都值得开团队。
92/92 全绿,99% 覆盖率,7 个缺陷全闭环,4 次安全拦截。这些数字来自这次实验记录,但它们只说明这个 Todo Demo 跑通了,不代表可以直接外推到真实业务项目。
这次实验给我的提醒是:以后使用 AI,不只是会不会写 prompt,还包括能不能拆角色、定契约、看验证结果,以及知道什么时候该停下来确认。
Agent Teams 还是实验特性。适合拿小案例试手,不适合一上来就押真实业务。
本文基于一次 Claude Code Agent Teams 实验运行日志撰写。样例是 FastAPI + React 的 Todo Demo,不是真实业务项目,也不构成生产实践建议。Agent Teams 为实验特性,具体表现可能随版本更新变化。