1. 接下项目后的第一件事:把"2个月"拆成人天预算表
1.1 那个排给4人团队的项目到底长什么样
今年开年我接了个看似不太可能完成的活儿:一个企业内部的工单流转与审批管理系统重构,原计划排给4个人做两个月,最后被压到我一个人身上,周期三周。项目本身不复杂,但足够"企业级"——有用户认证和角色权限、工单流转状态机、审批链、附件上传、操作审计日志、Excel报表导出、跟两个外部系统的接口对接,外加一堆历史数据要从老系统迁过来。
团队原本的配置是1个产品经理、1个后端、1个前端、1个测试。技术栈定的是后端FastAPI + PostgreSQL + Redis,前端Vue,部署走Docker。这种项目在中大型企业内部非常典型:体量不大,但杂事特别多,涉及的角色多,沟通链路长。正因为"典型",它才有拆解和复制的价值。
我在动手之前先冷静做了一件事:把这两个月的人天预算摊开来看,找出里面到底有多少是"真活",有多少是"流程消耗"。因为如果你连项目水分在哪都看不清,那用3个AI Agent去替代就更无从谈起。
1.2 16人周的估算里,水分到底在哪里
4人团队干2个月,按22个工作日、每天8小时算,大概是16人周,也就是接近640小时的总工时预算。我把典型企业项目的工时结构拆了一下,大概是这样的:
| 工作内容 | 原团队估算(人天) | 我的判断 |
|---|---|---|
| 需求收集、澄清、评审 | 25 | 大头在跨部门沟通,纯脑力分析其实不多 |
| UI设计、原型确认 | 15 | 后端主导项目,改成了简单管理端界面 |
| 后端编码 | 30 | Agent可以覆盖60%-70% |
| 前端编码 | 25 | 用现成后台模板 + Agent生成页面代码 |
| 联调、自测、修bug | 30 | 最容易返工的环节,但Agent闭环可压缩 |
| 文档、部署、数据迁移验证 | 20 | 文档是Agent强项,数据迁移要人工盯 |
| 会议、同步、等待审批等隐性消耗 | 15 | 这部分彻底省不掉,但也别算进有效工时 |
一眼就能看出来,原团队预算的大部分时间并不是纯粹的编码,而是分散在需求反复确认、跨角色沟通、等待依赖方反馈、联调扯皮、评审修改这些环节上。这些"隐性消耗"在传统协作模式下几乎无法压缩,因为人和人之间天然存在信息损耗。
但对于一个人带Agent干活的模式来说,情况完全不同:需求理解可以直接让Agent读文档生成假设清单,方案设计可以自动化产出,编码更是Agent的主场。真正需要我人工参与的,其实只剩下对外沟通、关键决策和最终验收。
1.3 我判断这个项目能"单挑"的三个条件
接单之前我给自己列了三个硬性门槛,都满足我才敢干。第一,项目必须是业务规则密集但边界清晰的系统,不能是探索性质的技术预研;工单审批流这类的状态机逻辑虽然繁琐,但每一条规则都是明确的,AI理解起来没有模糊空间。第二,交付物要尽量数字化,代码、接口文档、部署脚本、测试报告都可以生成和验证,不需要我碰物理设备或去现场操作。第三,我有权在技术栈上做简化,比如砍掉复杂的权限微服务设计,用清晰的RBAC模型替代,把弹性留给Agent发挥的空间。
三个条件全都满足之后,我才开始真正搭建那套"3个AI Agent"的交付流水线。
2. 3个AI Agent的角色分工:不是三个对话框,而是一条流水线
2.1 Agent A:把"需求翻译成能落地的工程规格"
很多人以为用AI Agent就是开几个对话窗口,分别提问,拼凑结果。我这次的做法完全不一样。我用LangGraph搭了一条有明确角色、状态流转和质量检查的自动化流水线,3个Agent是流水线上的三个节点,每个Agent都有自己独立的职责边界、输入输出格式和验收标准。
Agent A的角色相当于传统团队里的"产品经理 + 架构师"。它的输入是原始需求文档、旧系统的数据库字典、残缺的接口文档,甚至还包括我从业务方那里录下来的会议纪要文本。我提前把这堆资料做了清洗,转成Markdown和JSON格式,灌进Agent A的上下文里。
Agent A的输出非常结构化:一份需求假设清单、一套数据库表设计、一份API契约文档(字段名、类型、必填项、枚举值)、一份按优先级排序的任务拆解列表。关键点在我要求它把每一条需求里"不确定、需要人来拍板"的地方单独列成假设清单。这一步极大地减少了后期返工,因为AI理解的中文需求经常有歧义,提前暴露比等到代码写完再发现好得多。
2.2 Agent B:照着规格把模块批量写出来
Agent B是最累的角色,对应传统团队里的后端工程师。它从Agent A的任务列表里拿每个模块的规格说明,按模块批量生成代码。它生成的东西不光是业务逻辑,还包括数据库迁移脚本、Pydantic模型、单元测试用例。
为了保证产出质量,我在Agent B的系统提示词里写死了非常具体的工程约束:必须使用async def定义端点、所有数据库查询走SQLAlchemy异步引擎、分页必须封装统一函数、不允许出现N+1查询、错误处理必须走全局异常处理器。这些约束不是建议,而是强制。我宁可在提示词里啰嗦一点,也不愿意事后花大量时间review每一行代码。
Agent B和普通大模型编程的最大区别在于:它具备执行工具的能力。它可以读取指定目录下的数据库迁移文件、运行pytest测试用例、调用代码静态检查工具,然后根据执行结果迭代修改自己的代码输出。也就是说,它不是一个"生成完就结束"的对话模型,而是会自己动手验证、看报错、修bug的Agent。
2.3 Agent C:负责验收、补文档、盯住质量线
Agent C在传统团队里对应"测试工程师 + 运维 + 技术文档工程师"的组合。它的输入是Agent B提交的代码产物,输出是静态分析报告、自动化联调脚本、部署文档、用户操作手册。
Agent C最核心的价值不是写文档,而是"把关"。它会先对Agent B提交的代码做一套完整的质量巡检:跑一遍ruff做代码风格检查、跑mypy做类型检查、跑pytest做单元测试,再把Agent A定义的API契约文档跟实际代码里的路由定义做字段级比对。只要有任何一项不通过,Agent C就会带着具体的错误日志,把任务打回给Agent B重新处理。
这套"返工回路"是整条流水线的灵魂。传统线性Chain做不到的这种"检查-修复-再检查"的循环,我通过LangGraph的条件状态跳转实现。没有这个回路,3个Agent本质上就只是3个各干各的脚本,不可能产出企业可用的交付物。
2.4 为什么这个分工比"一个Agent全干"更稳
可能有读者会问:为什么不直接让一个Agent从头干到尾?原因很简单:上下文窗口装不下,角色目标会互相污染。让一个Agent既做架构设计又写代码又做测试,它会为了展示"能力全面"而牺牲质量一致性。比如架构设计阶段的开放性会带进编码阶段,导致代码结构漂移;编码阶段的局部视角又会让文档缺失全局说明。
拆成3个Agent之后,每个Agent的上下文都干净多了:Agent A只接触需求资料,Agent B只看规格和任务,Agent C只管代码和测试结果。任何一个环节出问题,都能精确定位到对应节点,不会出现"代码写得烂是因为需求理解跑偏"这类扯皮问题。这其实就是把传统软件工程里的关注点分离原则,应用到了AI工作流里。
3. 流水线的工程骨架:FastAPI + LangChain + LangGraph的组合逻辑
3.1 选型理由:三个框架各管哪一摊
技术选型上,我锁定了FastAPI + LangChain + LangGraph的组合。这个选择不是赶时髦,而是三个框架在里面的角色定位非常清晰,互相不重叠。
FastAPI负责的是"业务系统的骨架"和Agent工作流的宿主环境。企业项目最终要交付的是一个可运行的HTTP服务,FastAPI的APIRouter天然适合按模块拆文件,Pydantic又能直接承担数据校验,这两点极大地降低了Agent生成代码时出现结构混乱的概率。
LangChain在这条流水线里扮演的是"AI工程基础设施"的角色。Agent A读取文档和数据库字典时,用的是LangChain的文档加载器和向量检索能力;Agent调用工具时,靠的是它的Tool框架。LangChain提供了大量的胶水代码,省掉了我自己造轮子的时间。
LangGraph则负责最关键的工作流编排。它把3个Agent连接成有状态、可循环、可暂停恢复的图结构,而不是一条直线跑到底的Chain。我后面会细讲为什么状态图和循环能力是这个项目能落地的关键。
3.2 用LangGraph搭一条支持"返工"的状态机
流水线的核心状态机代码大致长这样:
from typing import TypedDict, Literal from langgraph.graph import StateGraph, END class DeliveryState(TypedDict): requirements_raw: list assumptions: list data_model: dict api_contract: dict task_queue: list code_outputs: dict lint_results: dict test_results: dict docs: dict def requirements_agent(state: DeliveryState) -> DeliveryState: # Agent A:解析需求,产出数据模型和API契约 ... def coder_agent(state: DeliveryState) -> DeliveryState: # Agent B:按任务队列生成代码,运行单测并自检 ... def reviewer_agent(state: DeliveryState) -> DeliveryState: # Agent C:跑静态检查、契约比对,产出文档 ... def should_rework(state: DeliveryState) -> Literal["rework", "pass"]: # 判断质量门禁是否通过,决定是继续还是打回 errors = state["lint_results"].get("errors", []) tests_failed = state["test_results"].get("failed", 0) if errors or tests_failed: return "rework" return "pass" workflow = StateGraph(DeliveryState) workflow.add_node("requirements_agent", requirements_agent) workflow.add_node("coder_agent", coder_agent) workflow.add_node("reviewer_agent", reviewer_agent) workflow.add_edge("requirements_agent", "coder_agent") workflow.add_conditional_edges( "coder_agent", should_rework, {"rework": "coder_agent", "pass": "reviewer_agent"} ) workflow.add_edge("reviewer_agent", END) app = workflow.compile()这里最值得看的地方是add_conditional_edges。Agent B提交代码后,系统会根据Agent C跑出的质量结果自行判断:如果测试有失败或静态检查报错,就跳回Agent B继续修;如果全部通过,才放行到Agent C做最终文档。
我刻意让整个图的状态保存在一个统一的DeliveryState里,Agent之间不通过对话历史传递信息,而是通过这份状态数据。这个设计带来了一个额外好处:任何一步出了问题,我都能翻看状态里的中间产物,快速定位是哪个Agent、哪个环节出的错,而不是在好几万字聊天记录里大海捞针。
3.3 给Agent装上"手":工具调用是流水线的关键
光靠Agent"思考"是写不出企业项目的,必须让Agent能真正操作系统里的文件、命令和接口。我在这条流水线里给Agent挂了几类关键工具:
- 文件读写工具:按指定路径创建和修改代码文件,权限限制在项目工程目录内。
- Shell命令工具:运行ruff、mypy、pytest、alembic migration等命令。
- 数据库Schema读取工具:直接连接PostgreSQL读取表结构,让Agent知道它操作的表长什么样。
- 日志读取工具:跑完测试后读取错误日志,反馈给Agent做修复依据。
这些工具全部通过LangChain的Tool接口注册,Agent在调用时会被强制要求"先说明动机再执行命令"。本质上,我是在教Agent遵守工程纪律:每一步操作都要有明确目的,不能瞎猜乱改。这是很多AI生成代码工具缺乏的——能写代码,但不知道自己在写什么、为谁写。
3.4 上下文管理的坑:关键约束要进状态,而不是堆Prompt
开发过程中踩过最经典的坑是:Agent做着做着就"忘掉"了前期的关键约束。比如在第一批模块生成时,Agent B还知道所有端点要走异步;等写到靠后的报表模块时,它突然生成了一堆同步的def端点,理由竟然是"这个模块计算量小,同步更快"。
我花了小半天去定位这个问题,最后发现根源不是模型能力,而是我把约束全写进了对话上下文,随着代码内容越来越多,早期约束被挤出了注意力窗口。我的修复方案是:把不可妥协的约束写进LangGraph的状态里,让每个Agent节点在执行前都强制读取状态中的"工程规范"字段,而不是依赖上下文记忆。
这个改动效果立竿见影。从那以后,并发约束、命名规范、目录结构约定这类东西就再也没有丢过。我的体会是,在AI Agent工作流里,状态的可靠性强过模型的记忆能力,你永远不应该指望大模型用"记忆"去承载重要规则。
4. 当Agent开始写"要上线"的代码:并发、压测与质量门禁
4.1 企业项目和Demo的分水岭:你一上来就要谈并发
我最烦听到的一句话是"AI写的代码能跑就行"。能跑和能上线之间,隔着一整座大山,那座山叫并发。
企业项目哪怕只是内部系统,一旦过了几十个用户同时操作,同步代码和糟糕的查询就会立刻暴露问题。项目既要支持工单流转,又要在月底做报表导出,高峰时段几百个并发请求非常正常。让Agent在"写功能"的同时记住"扛压",必须在Agent B的任务规格里提前写死硬性工程约束。
我在Agent B的提示词中强制规定了这样一套基线:
| 规范项 | 强制要求 |
|---|---|
| 路由定义 | 一律用async def,禁止同步阻塞端点 |
| 数据库驱动 | SQLAlchemy异步引擎 + asyncpg |
| 连接池配置 | pool_size=20,max_overflow=10 |
| 查询优化 | 禁止N+1,列表接口必须用selectinload预加载 |
| 缓存策略 | 热点数据走Redis,缓存时间按业务容忍度设置 |
| 超时与重试 | 外部HTTP调用必须设置timeout和重试退避 |
| 分页封装 | 统一基于游标的分页函数,禁止深分页 |
这些规范不是我拍的脑袋,而是从常见的企业级FastAPI实践里沉淀出来的。关键不在于Agent"知道"这些规则,而在于它"必须执行"。
4.2 压测出来的第一个"背锅点":N+1查询和连接池占满
代码写完只是第一步,真正见真章的是压测。我搭了一套基于Locust的简易压测环境,模拟300个并发用户,持续压了10分钟,做了混合读写场景。第一次的压测结果相当难看:
| 指标 | 初测结果 | 问题指向 |
|---|---|---|
| TPS峰值 | 280 | 远低于预期 |
| 平均响应时间 | 420ms | 明显劣化 |
| P95响应时间 | 1.2s | 用户能感知到的卡顿 |
| 数据库连接池 | 30个连接被打满 | 连接池配置失效 |
| 最慢接口 | 工单列表页 | N+1查询严重 |
我把这个压测报告喂给Agent C,让它做诊断分析。Agent C给出的判断很准确:工单列表接口没走selectinload,导致加载100条工单时额外产生了几百条关联查询;同时部分路由虽然用了async,但内部还是同步调用了一个第三方SDK,等于把线程池资源白白耗掉了。
诊断结论回流到Agent B,它在半小时内就完成了修复,重新生成代码并自动跑了pytest验证。第二轮压测的数据明显好看了很多:
| 指标 | 修复后结果 |
|---|---|
| TPS峰值 | 640 |
| 平均响应时间 | 110ms |
| P95响应时间 | 240ms |
| P99响应时间 | 450ms |
| 连接池占用 | 稳定在12-18个 |
这个结果对于企业内部系统已经够用了。要说明的是,Agent B能快速修复,不是因为它比人类工程师聪明,而是因为"压测报告-诊断-修复-验证"这条闭环链路被流水线自动化了,模型只需在诊断结论的引导下精准改代码,不需要从头分析排查。
4.3 质量门禁怎么落进流水线里,而不是挂在嘴边上
为了保证输出的代码不是"看着能用",而是"确实能过",我立了一套机械化的质量门禁规则。每次Agent B完成一组代码,流水线会自动执行以下检查:
- 代码风格:ruff跑全量,error级别为0。
- 类型安全:mypy严格模式,no_implicit_optional必须开启。
- 单元测试:pytest覆盖率不低于80%,关键业务状态机覆盖到全部分支。
- 契约测试:代码里的路由、请求体、响应字段,和Agent A定义的API文档做字段级比对。
- 数据库迁移:alembic upgrade head && downgrade base来回跑一遍,确保迁移可回滚。
这套门禁全部跑通,才允许Agent C生成最终交付文档。当时有个小插曲:契约测试跑出了三处不一致,原因是Agent A定义的接口字段名用了created_at,Agent B在实现时写成了create_time。这种错误在人工review时很耗时间,但机器契约比对一秒就能抓出来。海量代码里的人工review本来就不可靠,契约测试才是不讲情面的监督者。
5. 三周时间线复盘:哪些环节被加速了,哪些环节一点没省
5.1 第一周:干掉需求文档、数据模型和70%的代码骨架
第一天到第二天我的重点不是让Agent写代码,而是喂数据。我把需求文档、旧库结构、接口文档统一清洗成结构化格式,灌给Agent A跑了两轮需求解析。它对需求的拆分和假设清单输出,基本达到一个中高级产品经理的水准,省掉了我两天手工整理的时间。
第三天到第五天是Agent B的高产期。我按模块把任务队列提交进去,它一个模块一个模块地生成代码,每个模块生成完立刻跑单测和lint,质量检查通过再进入下一个模块。一周结束时,用户认证、RBAC权限、工单CRUD、状态机流转这四大核心模块已经全部完成,数据库迁移脚本也顺带生成好了。
这一周里我干的人工活是:逐条审核Agent A输出的数据字典,跟实际业务核对字段含义,修正了三处字段歧义;手写了一段Agent始终没搞对的复杂递归权限继承逻辑。除此之外,我几乎没有手动写过业务代码。
5.2 第二周:业务闭环、首批返工和卡住两天的外部对接
进入第二周开始做业务闭环。审批链、附件上传、审计日志、消息通知这些模块在Agent B手里一个个落地。真正的麻烦发生在两个地方。
第一个麻烦是我前面提到的上下文约束丢失问题,导致部分模块的代码风格偏离了工程基线。我花了大半天去调整状态机制,并把工程规范固化进了状态字段。第二个麻烦跟Agent无关,是要跟两个外部系统做接口联调,一边只有测试环境文档,一边的文档还过期了。那两天我几乎全程在处理接口字段对不上的问题,一边打电话找对方确认,一边手工修补联调脚本。这种跨组织的沟通成本完全不是Agent能压缩的。
不过,也正是这一周里返工回路体现出了价值。某次Agent B生成的审批状态机漏掉了一个"已撤回"分支,Agent C的测试用例跑出了一个未覆盖异常,直接把代码打回,Agent B自己根据报错日志补上了分支逻辑和对应测试。整个"发现-修复-回归"的循环自动完成了,我只是在旁边观摩。
5.3 第三周:压测、修复、部署文档和上线前夜
第三周前半段在做并发优化,就是前面提到的N+1和连接池修复。压测通过之后,后半段进入部署交付阶段:写Dockerfile、docker-compose编排、Nginx反向代理配置、Gunicorn + Uvicorn的多worker启动方案,全部由Agent C根据线上环境生成,我审核后应用。
这周的人工工作集中在数据迁移的最终验证。老库里有几万条历史工单数据,Agent写出的迁移脚本跑通了,但真实数据的脏值让状态字段出现了两条异常记录。我花了整整一个下午手工修补数据,写了个一次性修复脚本。这种脏数据处理,是AI从未见过也不该由AI擅自处理的坑。
三周结束时,这个原本排给4人团队两个月的项目,进入可交付状态:代码全部入库,测试覆盖达标,部署文档和用户手册齐全,压测报告也装订好了。
5.4 完全没被AI加速的环节:我必须交底
我不打算把这件事讲成"一个人+3个Agent就能包打天下"的神话。下面这些环节,时间一点都没省,甚至比团队协作模式下更累:
- 与外部系统联调时,等对方的响应、确认字段含义,纯粹是耐心活。
- 老数据里的脏值清洗,必须靠人来判断业务语义,Agent不敢碰,我也不敢让它碰。
- 业务方对某些权限边界始终表达不清,来回确认了三次。这种需求本质上的模糊,再强的Agent也没办法替你拍板。
- 最后一天的部署上线,仍然瑟瑟发抖地盯着日志看了一个小时。Agent能生成部署脚本,但承担不了"上线出问题谁负责"的心理压力。
这些环节提醒我保持清醒:AI Agent压缩的是"确定性工作"的时间,而对于"不确定性"和"责任"部分,它只能辅助,不能替代。
6. 隐形成本与边界认知:我一个人带3个Agent的账本和坑
6.1 我付出的真实成本:搭建流水线的时间和模型费用
讲完提速的部分,必须算一笔诚实的经济账。3周里,我实际花在"非业务"上的成本包括三块:
第一块是搭建流水线本身。从清洗资料、配置LangGraph图、挂工具,到跑通第一个最小闭环,我花了大约1.5个整天。对于没接触过LangChain和LangGraph的读者,这个时间可能要翻一倍到3天。
第二块是调试和观察成本。Agent干活期间,我必须持续盯着输出质量,每天大概花1到2小时查看中间产物、处理Agent卡住的情况。整个算下来,人肉投入仍然相当于1.5个人全职的三周,只是从"4个人类协作"变成了"1个人类协调+3个Agent执行"。
第三块是模型API调用费用。Agent A和B、C在多轮迭代、工具调用、返工重试中,消耗了大量token,前前后后的费用大概在八百多块人民币。相比省下的人力成本,这个钱几乎可以忽略不计。
6.2 四类典型坑和我的应对方案
第一,Agent过度自信。有次Agent A在没查数据库字典的情况下,凭经验生成了一张含冗余字段的表结构,还自信地给了"符合业界最佳实践"的评价。我要求Agent A所有数据模型设计必须附带从数据库Schema读取到的证据,拿不出依据就不允许输出。
第二,中文需求歧义。Agent B把"审批通过后通知申请人和审批人"理解成了"只通知审批人"。单测没覆盖到这一条,联调时才发现。修复方案是我在Agent A的需求解析阶段强制要求输出"需求断言列表",每条断言对应一条可执行的测试用例,让歧义在早期暴露。
第三,重复代码和模块化差。生成大量模块后,出现了三个功能几乎一样的工具函数分散在不同文件里的情况。我加了一条流水线规则:每次生成新模块前,Agent B必须读一遍公共工具目录清单,已有的函数优先复用。
第四,上下文窗口溢出导致早期约束丢失。前面已说过,修复方法是把工程规范固化到LangGraph的状态里,而不是塞在对话上下文中。后来每一次状态更新都会保留工程规范字段,Agent任何时候都能重新读到。
6.3 什么样的项目不适合用3个Agent单挑
经过这个项目,我对AI Agent的适用边界有了更具体的认知。下面这几类项目,我不会建议一个人拿Agent去硬扛:
第一,强探索性质的项目。技术选型不确定、需要大量实验验证可行性的项目,Agent给出的方案常常看起来自信满满,但后续会暴露出明显缺陷。这种不确定性需要人来承担试错成本。
第二,合规和责任认定严格的领域。比如金融对账、医疗数据、涉及法律责任的系统,审计最终要落到"哪个人签的字"。Agent可以辅助生成代码和文档,但"责任主体"必须是人,这类项目的主导者也没法完全交给Agent。
第三,需要大量物理世界交互的工作。接入硬件设备、现场部署、硬件调优这类项目,Agent根本无法触达真实物理环境,再聪明也没有意义。
第四,需求极度模糊、业务方自己都没想清楚的系统。Agent最怕的不是复杂,而是没有边界。你要是连"做一个数据看板"具体看什么指标都说不清,Agent生成的看板大概率不是你要的。
6.4 一个人带3个Agent的现实建议
如果看完这篇文章你也有类似的冲动,想把某个项目用AI Agent单挑下来,我会给你三条实在建议。
第一,先花两天做工作量审计和可行性判断。把项目拆成输入输出明确的模块,估算出"确定性工作"和"沟通等待工作"的比例,如果前者不到一半,这事就不要干。
第二,第一次跑的时候,把Agent的职责边界画小一点、再小一点。宁可让Agent只负责某个模块的编码,也不要让它从需求一路做到测试。等你对模型输出质量有了稳定预期,再逐步扩大Agent的职责范围。
第三,无条件给自己留两天的缓冲时间。Agent工作流虽然快,但"环境依赖安装、外部系统对接、数据脏值处理"这类不确定性事件一定会发生。没有缓冲,你会在第三周面临一边压测一边补数据的绝望状态。
最后再说一点个人体会。这个项目结束后,我自己最大的变化是不再单纯用"写代码快不快"来评价Agent,而是更看重它的工程纪律和闭环能力。代码能不能扛住并发、有没有测试兜底、文档是不是完整,这些才是企业项目的及格线。AI Agent真正帮我省下的,不是敲键盘的时间,而是把"从需求到交付"这条流水线上所有确定性环节自动化之后,重新交回到我手里的掌控感。