
三个月前我带着一个三人小团队接下了一家制造企业核心交易系统重构的活。为了赶工期我们全面切换到AI Coding工作流大量使用AI辅助生成代码。三个月后项目交付代码总量一统计——16万行。这里面大约八成以上是AI直接生成的剩下的是我们人肉修补和Review改出来的。整个过程中最重要的一次认知转变就是从单纯“让AI帮我写代码”的AI Coding状态进化成把AI当团队成员来管理、围绕AI建立整套研发流程的AI Engineering状态。这篇东西我就把这16万行代码背后的思路、方法、踩过的坑和沉淀下来的规范完整复盘一遍。对正在用或准备用AI编码工具的团队应该都能从里面找到点能直接用的东西。1. 16万行代码是怎么炼成的从“让AI写代码”到“让AI按规范写代码”1.1 项目背景传统业务系统重构的窘境客户的老系统是一个.NET Web Forms时代遗留的ERP中台单体应用代码耦合严重光一个订单模块就牵扯了十几个业务表的直接读写。老系统维护了六七年团队走了两拨人文档基本是空的。客户要求三个月内把核心交易链路重写一遍并且要支持后续逐步迁移。按传统人力这个量级至少需要一个8到10人的后端团队加上2个前端再配一个测试三个月都够呛。但我们手上只有3个后端加1个前端。所以我们做了一个大胆的决定所有业务代码包括API、数据库访问层、前端页面、单元测试全部用AI Coding工具来生成初稿人来负责设计、审查、修改和兜底。这个决定在今天看来很合理但实际操作中经历了一段痛苦的磨合期。刚开始确实像是在放飞自我——让AI写一个模块生成速度极快几分钟就是几百行但我们很快发现无约束地让AI写代码三个月后的代码库会变成一个无法维护的黑洞。16万行代码如果只是堆出来那么迎接我们的不是交付是灾难。1.2 为什么最终会累积到16万行AI Coding的加速效应很多没实际做过大规模AI生成的人会问一个交易系统重构人工写可能也就6到8万行为什么AI出来就成了16万行这里我直接说结论AI生成代码的体量天然会膨胀这是它的“生成模式”决定的。传统人写代码会有很多“复用”思维。你心里清楚已经有个工具函数了就会去调用它。AI并不天然具备这种全局记忆尤其是当上下文窗口有限时它为了确保某个功能“能跑通”倾向于把逻辑完整地、自包含地写在当前文件里。一个分页工具函数它可能在不同的Service里被复制了六七遍。一个相同的数据校验逻辑也可能在每个Controller里以略有差异的形态重复出现。另外AI Coding的试错成本极低这本身就鼓励了重写而不是重构。遇到需求变更我们经常直接让AI重新生成整个service而不是人工去改。功能确实变对了但代码量就成倍地涨。等代码量到了10万行左右我们做了一个代码体检坏味道集中爆发尤其是重复代码和过深的条件嵌套。那会儿我才认真思考一个问题AI Coding带来了数量但谁来保证质量这个问题的答案只有一个引入工程化手段。也就是我后面要重点讲的AI Engineering。1.3 AI Coding 与 AI Engineering一字之差天壤之别很多人把AI Coding理解成用Copilot补全代码或者让ChatGPT写个函数。这没错但这是最表层的东西。我自己对这两个概念做了个清晰划分AI Coding关注“单次代码生成”。输入需求产出代码人来看一眼能跑就过。AI Engineering关注“代码从生成到上线全生命周期的管控”。包括规范定义、上下文管理、质量门禁、审查流程、测试标准、甚至代码退役。我打个比方AI Coding是让一个实习生用最快速度帮你把方案初稿写出来AI Engineering是在此基础上你还得定写作规范、配校对、定审核流程、明确哪些内容能发出去。没有后者前者只是在制造文字垃圾。一个团队如果只停留在AI Coding阶段最典型的现象就是“AI写代码人给AI擦屁股”。代码跑不通把报错甩给AI逻辑有漏洞让人一点点查。看起来有AI加持实际效率比人肉写还低。真正进入AI Engineering阶段后我们做的事情变成了让AI在清晰边界内生成代码再用另一套AI工具和工程手段去审计、约束、修正第一篇AI生成的内容。从表格能看出两者的核心差异不是工具而是思维模型。对比维度AI CodingAI Engineering核心关注点单次生成代码的正确性整个代码库的健康度与可持续性主要动作写Prompt、生成代码定规范、管上下文、设门禁、多Agent协作代码质量保障靠人肉Review靠自动化规则分层审查团队结构个人开发者独立使用AI Agent分角色协作人做决策风险控制事后修复事前约束与事中拦截2. 整体设计思路把AI Agent当成有脾气的团队成员来管理2.1 像管团队一样管Agent如果你带过一个15人的开发团队你会发现一个规律完全放任每个人按自己的风格写代码项目必崩。你会有代码规范、有评审、有架构约束。AI Agent本质上也是在你的代码库上并行工作的“虚拟组员”不管理它它就会在你的仓库里“野蛮生长”。我给AI Agent设了三种岗位和真实团队一一对应架构师Agent负责全局技术选型、模块划分、接口契约。它不直接写业务代码但所有重要Prompt的上下文都来自它生成的架构设计。开发Agent负责按模块写具体实现。划分为订单、库存、用户、支付、报表等多个独立Agent每个Agent只专注于自己负责的领域。审查Agent负责审查开发Agent写出的代码对标代码规范、检查边界条件、寻找潜在bug。它和开发Agent之间形成了流水线式的协作关系。这样设置的好处是每个Agent的职责边界非常清晰。开发Agent不需要去思考什么全局架构审查Agent也不需要理解业务全貌。人的工作就是判断这三个环节的产出质量。2.2 代码生成规范示例Prompt模板是第一批交付物进入AI Engineering状态后的第一件事不是写代码而是写Prompt规范。我们内部管它叫“代码生成规范V1.0”。这不是让我们去背Prompt模板而是把团队真实的代码规范翻译成AI能理解的语言。一份合格的代码生成规范里应该包含这些要素角色定义告诉AI它现在扮演什么角色例如“你是一名Python后端工程师熟悉FastAPI和SQLAlchemy”。技术栈约束明确核心依赖版本、不允许使用的库。代码风格命名规范、注释规范、是否允许类型注解。错误处理要求禁止吞异常、统一异常响应格式。性能要求N1查询禁止、必须在数据库层分页。测试要求新功能必须生成配套单元测试。交付格式生成代码时同时返回简要说明和变更点。我贴一段我们实际用过的精简版Prompt模板# Role: Python后端工程师FastAPI SQLAlchemy 2.0 # Task 实现用户订单列表查询接口需求见下文。 # Rules - 所有查询必须使用SQLAlchemy 2.0的select()语句禁止使用原生SQL。 - 字段命名使用snake_case禁止缩写。 - 涉及列表查询必须分页分页参数page和page_size默认page1, page_size20。 - 不允许捕获Exception后返回None异常统一抛出由全局异常处理器处理。 - 接口响应统一使用response_model。 - 生成的代码必须包含对应的pytest单元测试测试数据使用factory_boy。 # Existing Code Context 相关模型定义如下 [贴模型代码] 相关依赖注入方式如下 [贴依赖代码] # User Request 实现GET /api/v1/orders接口支持按订单状态过滤返回当前用户所有订单。这个模板在执行中效果很好很核心的一点是把“Existing Code Context”放在最后。我看到很多失败案例就是把上下文放在开头AI会因为上下文过长而遗忘规则。而我给出的是一个清晰顺序角色先立住规则其次最后给具体代码语境。2.3 多智能体协作架构不同Agent各司其职我们把AI Agent的协作架构精炼成了三层逻辑编排层、执行层、质量层。编排层是人的工作台。我们用的是自建的任务管理看板每个任务卡片里写清楚需求描述、涉及模块、技术约束和验收标准。编好任务后会触发执行层的开发Agent进行编码。执行层是多个开发Agent的集合。这里一个常见误区是会有人问为什么不是一个全能的Agent从头写到尾因为上下文窗口是有限的。如果让一个Agent同时负责用户、订单、支付、库存四个模块它很快就会遗忘模块边界和接口定义然后开始生造函数。我们发现领域隔离是防止AI“精神分裂”的有效手段。每个Agent只维护自己领域内的相关上下文。质量层的审查Agent定期检查执行层的产出。它会使用静态分析工具扫描代码也会自己读代码做逻辑审查。发现问题时它不直接改代码而是生成一个“Review反馈单”里面包含问题描述、问题定位、修改建议和参考示例。开发Agent收到反馈单后再进行一轮修订。这很像真实研发流程里的“打回修改”。整套协作的核心一句话让AI之间先互相约束把人都要从“看代码的体力活”里解放出来。3. 核心实操把AI生成的16万行代码“跑”起来的完整流程3.1 先搭骨架人工划定模块边界和依赖规则在让任何Agent写代码之前我们手工搭好了整个项目的骨架。这不是出于控制欲而是出于对“AI天然缺乏全局观”的清醒认知。骨架的内容包括目录结构backend/app/modules下的订单、用户、支付等模块每个模块对外暴露的接口清单模块间的依赖方向例如支付模块不得反向依赖订单模块公共包utils、common、config的统一出口我们用一个最笨也最有效的方式强制执行依赖规则每个模块目录下放一个__init__.py只允许导出公开接口。模块内部定义的所有类和方法如果没被导出别的模块就import不到。这不是Java里的访问控制那么严格但至少让AI知道跨模块访问是有门槛的。这个骨架非常重要。没有它后续所有Agent生成的代码都会变成一锅粥。因为Prompt写再多“注意模块边界”AI也很容易在context里发现自己需要一个工具函数就直接在当前业务文件里重新写了一个。骨架加上物理目录的隔离能把这种“偷懒”限制在单一模块内。3.2 上下文投喂的质量决定AI生成代码的质量用AI Coding写过东西的人都知道上下文决定了AI的上限。在AI Engineering里这个上下文管理被提到了更重要的位置。实践中我总结了一套“三层上下文投喂法”。第一层是项目级上下文。我们维护了一份AGENTS.md文件放在代码库根目录里面包含了整个项目的技术栈、目录结构、命名规范、依赖白名单、以及最常用的公共函数说明。每个Agent在开工前会被要求先读这份文件。第二层是领域级上下文。比如订单Agent它除了读AGENTS.md还需要读订单模块的README.md里面描述了订单模块的领域模型、关键表结构、核心流程。这样它生成订单相关的代码时就不会跑偏到去操作库存表。第三层是任务级上下文。在每次具体任务里把相关的模型定义、接口契约、参考实现贴到Prompt里。前两层是长期记忆第三层是短期记忆三者缺一不可。我在实际推这个方案时团队里有人觉得维护三层上下文太累。后来发生了一件事改变了所有人的态度一个Agent在没看领域上下文的情况下生成了订单取消接口它自己定义了一个“已支付且出库”的组合状态这跟我们系统的状态机定义完全不符。那次事故之后“上下文不是给AI看的是给我们的保险”成了团队共识。3.3 代码诊断与代码审查把AI生成代码的“隐形炸弹”挖出来如果说AI Coding是在生产代码那AI Engineering就是要给这个生产线上装质检仪。我们的质检体系分两道第一道是自动化诊断。在CI管道里跑了四种工具ESLint前端静态检查、mypyPython类型检查、SonarQube重复率和圈复杂度检测、Bandit安全扫描。AI生成的代码会在跑完这些工具后才能进入代码评审环节。这里我发现一个很有趣的事AI生成的代码里安全漏洞类型和人写的很不一样。人写的漏洞更多是逻辑漏洞AI生成的漏洞则非常典型地集中在“信任外部输入”——比如直接拼SQL、没有对文件上传做类型校验。静态扫描工具抓这类问题效率极高。第二道是AI审查Agent。我一直在思考一个问题如果让开发Agent生成代码再让人来逐行Review那效率瓶颈还是在人身上。于是我们训练了一个专门的审查Agent规则是它必须站在“怀疑一切”的立场上审查代码不能因为代码风格好看就放过逻辑问题。它会对每个函数找边界值、追异常路径、检查数据一致性。审查Agent的输出会生成一个Markdown格式的Review报告按严重程度分级Blocker、Major、Minor、Nit。只有Blocker和Major被清零后代码才允许合入主干。人工在这个环节只做抽检抽检率控制在30%左右关键模块我们会重点抽。这样既压了成本也守住了质量线。3.4 测试才是“跑起来”的最后一道防线16万行代码靠人肉点界面做回归测试是不可能的事。所以从AI Coding转型AI Engineering时我们做了一个硬性规定AI生成代码时必须同步生成单元测试。很多开发者抱怨AI生成代码质量不高但没想过拿AI生成的代码去跑测试。我们尝试过几次后发现AI写单测的功力其实经常比写业务代码更靠谱尤其是在边界条件覆盖上。它能自然地想到空列表、超长字符串、非法状态这些用例比很多刚入行的新人覆盖面都要宽这部分帮助超出了我预期。配合单元测试我们还让测试Agent专门生成关键链路的集成测试脚本。例如支付回调、订单超时关闭、库存预占释放这几条主链路每个都有对应的集成测试用例全部数据跑在本地容器化的MySQL和Redis里。我们的CI流水线是这样的commit触发单测合入主分支触发集成测试集成测试通过后自动部署到Staging环境并跑一轮冒烟。有了这套测试体系我们才敢在后期频繁地让AI大规模重构代码。因为测试会替我们守住“改了A没坏B”的底线。4. 踩坑实录与排查技巧16万行代码里我最想删掉的5个瞬间4.1 问题一AI生成了看似正常但根本没跑过的“鬼代码”遇到过最诡异的一个bug系统上线两周后有一个定时任务突然报错报错的代码路径是一个我们从未见过的函数。拉出那个函数的代码一看外表完全正常有类型注解、有docstring、逻辑也通但函数内部调用了另一个模块里的一个私有方法。用git blame一查这段代码是开发Agent在两个月前生成的。因为当时单独测过接口Swagger返回正常而底层定时任务的调用路径完全没被入口测试覆盖到。等生产环境第一次触发这个路径才暴露出它依赖的私有接口早就被另外一个Agent改名了。这个问题的根因是开发Agent在生成代码时没能感知到跨模块私有方法的不稳定性。这也验证了让不同Agent各写各的模块所带来的信息偏差。排查与规避经验关键业务链路必须建立从入口到出口的集成测试不能只测单个API。在审查规则里明确禁止import其他模块的下划线私有方法一经发现直接打回。全局搜索私有方法引用的脚本要进入CI发现有引用就报警。4.2 问题二AI的“幻觉依赖”——明明不存在的包审查Agent在一个订单导出模块里发现了一行importfrom openpyxl import Workbook。当时系统里确实装了openpyxl但版本是2.6.4而AI生成的代码用到了一个2.6.4版本里不存在的参数。要命的是开发环境里其他人装的是3.1.2本地跑起来完全正常。只有部署到生产环境时因为锁定的依赖版本不同直接崩了。这也说明了一个AI Coding时代的常见现象AI会根据训练语料里的流行用法来写代码它可不知道你这个项目里锁的是什么版本。排查与规避经验团队必须维护一份“依赖白名单”白名单之外的库即便AI用了也要在代码评审里被拦截掉。所有Python依赖必须使用requirements.txt里的精确版本号禁用和*这类模糊范围。我让审查Agent在Review时专门核对import语句把它对应的库及其版本号列出来再和依赖白名单比对。4.3 问题三命名混乱造成的“逻辑幽灵”这个问题的典型表现是在一个模块里用户ID字段叫user_id到另一个模块同一个字段变成了accountId。如果每个命名都各自一致其实还能接受但问题是AI本身偏好模仿上下文里的写法如果不同任务的Prompt里给出来的示例代码命名不一致那AI就会忠实“继承”这种不一致最后把代码库搞成一个罗生门。更可怕的是这种命名混乱会直接导致“看起来像bug其实不是看起来没问题其实藏着bug”。我们在排查一个订单超时bug时发现有的代码用order_id做匹配有的用orderNo做匹配两边值一样但来源一个是数据库主键、一个是业务单号。在某些边界情况下它们并不相等于是本该超时关闭的订单漏掉了。排查与规避经验在代码生成规范里把实体字段名做成“业务字典”统一使用id作为主键order_no作为业务单号并声明两者严禁互换使用。审查Agent的规则里加入“术语一致性检查”让它找出所有可能对应同一个概念的字段别名。每周跑一次全局字段搜索报告人眼快速扫一遍重点看有没有高频字段名变体。4.4 问题四多Agent并行下的“合并地狱”我们前期让订单Agent和支付Agent同时开工两个Agent都涉及订单的状态流转逻辑。因为它们讲的是同一份领域模型的两种方言导致Git里的冲突多得像叙利亚战场一样。传统开发里的代码冲突靠人花时间就能解决。但AI生成的代码量大冲突引发的连带修改太多。有一次解决完冲突后支付回调里读取的订单状态值又对不上了折腾了一整天才定位到。排查与规避经验模块边界不是写给别人看的是高耦合模块之间“排他性产权”。订单和支付这种强关联模块同一时间只允许一个Agent在改动。把公共领域模型和数据表结构定义放在独立的核心包里业务Agent只能读取该包不允许直接修改。如果要改必须走人工流程。合并时不要用工具自动合并后盲目相信结果强制在合并后的代码上跑一遍完整集成测试。4.5 问题五僵尸模块和僵尸依赖到项目后期我们用了knip和depcheck做了一次全库扫描结果发现至少有5000行以上的代码全项目没有任何地方引用。这些僵尸模块大多是AI早期探索性生成的替代方案。它们还会拖累构建速度、让IDE索引变慢更严重的是某个僵尸模块依赖的第三方库存在已知漏洞安全扫描就被这个拖累。排查与规避经验每个功能合入前必须在任务描述里写明“入口引用点”没有引用点的代码不允许合入主干。CI里定期跑dead code检测超过一周未被引用的代码自动标记为“待清理”下个迭代删除。一开始觉得AI生成代码规模到16万行很吓人做完整理后真正在生产路径里活跃的代码大约是13万行。删掉的那些僵尸代码省下来的是长期的维护成本。5. 常见问题速查表AI Engineering实战者的Top问答一个人或者一个团队想完全拥抱AI Engineering时总会在各种细节上卡住。这里我整理了一些在实践和对外分享时被问得最多的问题结合自己的实操经验给出看法。问题我的处理方式与核心观点AI生成的代码真的能直接读吗初稿能看但别指望直接合入。我要求开发Agent在代码中额外提供“变更点说明”这样Review时人能快速抓住重点。16万行代码人就这几个怎么Review得过来分层Review静态工具抓低级错误审查Agent抓逻辑和规范人只盯架构和关键链路。人不需要看所有代码所有代码交给机器去看。用了AI之后代码质量是不是必然下降直接回答不一定。以此项目的最终交付为准缺陷密度相比老系统是显著下降的。关键在于有没有建立“质量门禁”和“代码规范”。做AI Engineering需要什么基础首先得懂代码懂软件工程懂项目管理。AI Engineering不是让你不用懂开发而是让你把开发管理能力从人扩展到AI Agent。用什么AI编码工具比较好工具迭代很快核心是看它是否支持项目级上下文管理、自定义规则注入、多Agent协作。具体工具不重要工作流才重要。上下文把我搞晕了有没有简单的原则项目级上下文一页、模块级上下文一页、任务级上下文每次按需贴。超出这个量的上下文管理都是在过度设计。需求频繁变更AI能顶得住吗能但需要配合敏捷的模块化设计。AI改代码的速度快但需求变更如果动了领域模型通常比人改还得慢一些因为所有依赖都要跟着改。线上出故障了怎么快速定位是不是AI代码的锅我们给所有AI生成的代码自动加上一个标记日志里会带上sourceai的标签。出问题后可以先按这个字段过滤快速圈定影响范围。团队里有人不愿意用AI怎么办不强推。让愿意用的人先用并分享成果用实际效率差距说话。实践下来抵触情绪大多来自“怕被替代”明确AI是工具、人是决策者会缓解。现在有些公司搞AI Coding笔试到底在考什么考的是你驾驭AI的工程能力。同一个需求高手会先拆解、定义接口和边界再让AI分段生成新手可能从头到尾一句Prompt之后就卡住了。差别不在用没用AI而在有没有工程化思维。6. 从AI Coding到AI Engineering我个人的真实体会如果只看数字16万行代码听起来很多。但真正让这个项目能交付、能上线、能维护的并不是AI生成代码的速度而是围绕AI建立的整套工程化约束。我最大的体会简单概括AI Coding解决的是“从无到有”AI Engineering解决的是“从有到稳”。无约束的AI Coding会在三个月里造出一个你不敢重构、不敢上线的代码怪物而加上规范、上下文管理、代码审查、测试门禁这些工程化手段AI才真正变成一个“靠谱的高产组员”。这个项目做完以后我们复盘时算了一笔账如果完全靠人力按原来的老团队规模这个改造需要大约7个月。而实际用了AI加工程化管控3个月出头就交付了算上人工Review的成本整体开发效率大概提升了一倍多。没有翻倍以上的提升因为质检、规范和上下文管理本身也要消耗人的精力。把这部分成本重视起来才不会对AI Coding抱有不切实际的期望。此外还有一个细节想分享给所有带团队的人别把AI生成的代码直接扔给新人去改也别把AI排除在团队之外。最好的方式是让有经验的工程师先定义好规范让AI在规范里干活让新人在旁观摩AI如何遵守规范。这套模式下新人上手比看老代码快很多团队整体战斗力反而上来了。最后再提一个小技巧也是在这次迭代中我一直坚持的每隔两周强制对代码库做一次“AI自检日”。这半天不做新功能只让审查Agent全面巡检一遍现有代码查找规范偏离、死代码、以及潜在的错误处理盲区。这个习惯帮我们拦下了不少潜在的生产事故。如果你正带队走上AI Coding这条路建议从第一天就把它制度化。