
最近团队里讨论 AI 编程代理AI Coding Agent的频率明显变高了。不少同学开始在真实项目里尝试让 AI 直接改代码、提 PR但问题也随之出现功能看着能跑代码却经不起 review局部需求实现了整体架构却被带偏提交记录里全是动辄几百行的大块改动出了问题根本不知道从哪查起。这段时间我结合 Figma 工程师在 AI Engineer 方向上的分享思路加上自己在业务项目里的落地经验整理了一套相对完整的落地方法。核心观点不复杂AI 编程代理能不能安全落地不取决于模型多强而取决于你有没有在它前面立好“约束”在它后面设好“审查”在它周围搭好“反馈闭环”。这篇文章会把这套方法拆开讲包含项目规则文件怎么写、提示词怎么约束、代码审查和 CI 怎么配合以及最常见的几类翻车场景和排查思路。不管你是刚接触 AI 编程代理的开发者还是准备在团队里推动落地都可以直接参考。1. 背景AI 编程代理为什么会写出“垃圾代码”1.1 先理解 AI 编程代理是什么AI 编程代理和我们平时用的代码补全工具不太一样。代码补全工具比如常见的 Copilot 补全模式是在你写代码的过程中给出下一段建议主动权在你手里而 AI 编程代理是接收一个相对完整的任务描述后自己去读代码、改文件、跑命令、甚至提交代码的“半个工程师”。它通常具备几个能力读取项目文件、理解仓库结构、跨文件修改、执行测试命令、根据报错自我修正、最后生成 diff。也正因为这些能力它能完成的不再是“几行代码”级别的辅助而是“一个功能点”甚至“一个模块”级别的任务。听起来很美好。但问题恰恰出在这里代理的能力边界越大它闯祸的空间也越大。它可以在你不在场的情况下连续修改十几个文件而你对它的改动意图、取舍逻辑、潜在影响可能一无所知。1.2 垃圾代码产生的三个根源结合我自己项目的踩坑经验AI 编程代理产出低质量代码基本逃不出下面三个原因。第一个是任务边界模糊。很多开发者给代理下达的指令是“帮我优化一下登录逻辑”或者“把这个页面改成响应式布局”。这种描述在人类同事听起来可能还能猜个大概但代理会根据自己的理解“自由发挥”。它可能在你没想到的地方改了接口签名可能把原本统一封装的请求函数替换成新的实现也可能把一整套样式方案推翻重写。当你拿到 diff 时发现改动范围远超预期这就是典型的边界失控。第二个是缺少领域的隐性知识。代码质量不只是“语法正确”和“功能跑通”。一个资深的团队工程师知道哪些模块是历史包袱不能乱动知道某个工具函数在高并发下不能直接用知道某个字段在数据链路里还有三个下游依赖。这些知识往往不在代码注释里而在团队成员的脑海里。AI 代理没有这些背景它只会按“最常规”的方式去写代码于是经常出现“技术正确但业务错误”的改动。第三个是反馈机制太慢。正常情况下代码质量靠 code review 和测试兜底。但 AI 代理生成代码的速度太快了如果团队没有在流程上强制加入审查节点很容易出现“AI 写代码人类只负责点合并”的情况。等问题暴露到测试环境甚至生产环境时修 bug 的成本已经成倍上升。1.3 不是所有代码都适合交给代理这不是说 AI 编程代理不能用而是要区分场景。从实践来看下面几类任务适合交给代理机械重复的改动比如批量替换废弃 API、统一日志格式、给一组接口补充参数校验。单点明确的 bug 修复比如某个函数在特定输入下抛异常定位范围很小。测试代码补全比如根据已有函数签名生成单元测试骨架。新项目脚手架搭建比如创建规范的项目目录、初始化配置、编写基础 CRUD 代码。这几类任务的共同点是边界清晰、影响面可控、有明确的验证标准。反过来涉及核心架构调整、跨模块链路改造、历史兼容性判断的任务现阶段还是应该由人来主导代理最多负责辅助执行。2. 安全落地的核心思路先立约束再谈效率2.1 三条核心原则我在反复踩坑之后把 AI 编程代理的安全落地总结成三个原则缩小授权范围、强制人工审查、建立反馈闭环。缩小授权范围是指每次只给代理一个足够小的任务而不是把一个需求完整丢给它。比如“给订单查询接口增加分页参数”就比“优化订单模块”安全得多。任务越小代理的自由度越小diff 越容易被人类看懂出问题的概率天然就低。强制人工审查是指在代理生成代码之后、合并代码之前必须有一个真正理解这段代码的人对改动负责。审查不是敷衍地看一眼而是要回答三个问题这个改动解决的是不是任务描述的问题有没有引入不必要的连带修改有没有违反项目里既有的设计约束建立反馈闭环是指代理产生的每一次失败都应该沉淀为规则。比如它经常忘记处理空指针那就在项目规则文件里明确写“所有可能为 null 的外部返回值必须判空”它经常把工具函数复制到业务代码里那就明确写“公共逻辑必须放到 shared 目录不允许复制粘贴”。代理本身不会从错误中学习但你的约束库会。2.2 人类工程师的位置没有变有些团队引入 AI 编程代理之后容易产生一种错觉以后写代码可以交给 AI 了工程师只要描述需求就行。这种想法很危险。在 Figma 工程师的分享里有一个观点我印象很深AI 编程代理改变的不是“要不要写代码”而是“工程师把精力花在哪里”。以前你花大量时间在“敲代码”本身现在这部分被压缩了但“理解需求、拆解任务、定义约束、审查质量、解决边界问题”这些工作反而变得更重了。换句话说AI 编程代理是把工程师的位置从“生产者”推向了“审查者和架构师”。你不再对每一行代码负责但你必须对每一个决策负责。如果你不理解它为什么这么改不知道为什么这么改是对的还是错的那你就没有资格让这段代码进入主干。2.3 从“写代码”到“定义约束”这套思路落到日常工作中核心变化是你的主要产出不再是一行行代码而是一套让代码质量可控的约束规则。约束可以分为两个层面。项目层面通过AGENTS.md这类文件告诉代理“这个项目有哪些约定、哪些地方不能碰、完成任务需要走什么流程”任务层面通过提示词告诉代理“这次任务的目标是什么、边界在哪里、验收标准是什么”。这两个层面的约束配合起来才能把代理从“一个很会写代码但不懂事的实习生”变成一个“知道边界、按规范办事的执行者”。下面两章我会分别展开讲。3. 团队级防护机制规矩先写在前面3.1 用 AGENTS.md 给代理立规矩现在主流的 AI 编程代理都支持在项目根目录放一个规则文件比如AGENTS.md、CLAUDE.md或者.cursor/rules/下的规则文件。代理在开始任务之前会先读取这些文件把它当作“项目说明书”。这是目前成本最低、效果最明显的防护手段。一个比较实用的AGENTS.md至少应该包含四块内容项目结构和模块职责让代理知道哪里有什么避免在错误的位置修改。编码规范命名、错误处理、日志、测试要求越具体越好。禁止事项哪些目录不能动哪些模式不允许出现哪些历史代码不要重构。工作流要求先读哪些文件、改动上限、提交前必须做什么验证。下面是一个参考示例# AGENTS.md ## 项目概述 这是一个订单管理后端服务使用 TypeScript Node.js 编写。 核心模块包括订单模块、支付模块、用户模块、消息队列消费端。 ## 目录结构 - src/modules/orders/ 订单模块包含 controller/service/repo - src/modules/payments/ 支付模块禁止直接修改改动需联系支付组 - src/shared/ 公共工具函数与公共类型 - src/config/ 环境配置与配置校验 - tests/ 单元测试与集成测试 ## 编码规范 - 所有文件使用 TypeScript 严格模式。 - 业务错误必须抛出 BizError禁止抛出裸 Error。 - 所有外部输入必须经过 zod 校验。 - 日志使用 logger.info/logger.error禁止使用 console.log。 - 公共逻辑统一放在 src/shared 下禁止在业务代码中复制粘贴。 ## 禁止事项 - 禁止修改 src/modules/payments 下的任何文件。 - 禁止在仓库中新增全局可变状态。 - 禁止将多个业务逻辑写进一个函数一个函数只做一件事。 - 禁止对历史模块做大规模重构除非任务中明确要求。 ## 工作流要求 1. 开始任务前先阅读相关模块的 README 和现有测试文件。 2. 单次改动尽量控制在一个模块内不要跨多个模块一起改。 3. 一次任务提交的改动量不超过 200 行超出需要分多次完成。 4. 每次改动必须补充或更新对应测试测试必须能通过。 5. 提交前运行 npm run lint 和 npm test保证没有新增报错。这个文件写清楚之后代理在大部分情况下都会“照着规矩办事”。当然它不是万能的代理偶尔还是会忽略某些规则但整体上能把那些最伤害项目的低级错误挡住一大半。3.2 代码审查不许走过场代码审查是安全落地的第二道防线也是最关键的一道。代理生成代码的速度再快只要审查这一关是硬的垃圾代码就很难进入主干。针对 AI 代理生成的代码审查时要额外关注几个点。第一个是改动范围这个 PR 里有没有跟任务无关的改动比如任务只是加一个接口字段结果它还顺手改掉了另一个文件的缩进风格这种必须打回。第二个是重复代码代理很倾向于“在当前位置写一份能用的代码”而不是去复用已有的工具函数。审查时如果发现类似逻辑已经存在于 shared 目录应该要求代理改写为复用。第三个是过度设计有些代理为了“优雅”会引入一层额外抽象比如为一个简单的参数校验封装一个工厂函数。这种代码虽然能跑但增加了维护成本不符合项目现状时需要指出。为了不让人工审查变成形式主义我建议团队在 PR 模板里增加 AI 生成代码的专项检查项强制审查者确认。示例### 审查清单 - [ ] 改动是否与任务描述一致没有无关修改 - [ ] 是否复用了现有工具函数而不是复制相似逻辑 - [ ] 是否引入了不必要的新依赖或抽象 - [ ] 错误处理是否符合项目规范BizError / 日志 / 上下文 - [ ] 测试是否覆盖了正常路径和关键异常路径 - [ ] 是否存在安全风险SQL 注入、越权、敏感信息泄露 - [ ] 是否使用最小权限原则访问外部资源3.3 CI 自动化校验不能少人工审查有遗漏的时候CI 是最后的兜底。AI 代理生成的代码在 CI 阶段需要至少跑三类检查静态检查、测试覆盖、构建验证。静态检查是成本最低的一关比如 ESLint、TypeScript 类型检查、格式检查。代理经常会在缩进、命名、类型标注上出现小问题这些交给工具自动拦截不要浪费人工审查的时间。测试覆盖这一关要特别强调。代理生成逻辑时经常只保证“主流程能跑通”对边界条件考虑不足。如果团队有覆盖率门槛把它们加进 CI低于阈值的 PR 不允许合并。构建验证同样重要。很多代理只关注“我改的这个文件”忽略整体构建容易出现“单文件没毛病整个项目编不过”的情况。CI 里加上构建步骤可以第一时间暴露这类问题。一个简单的 CI 配置参考如下name: ai-change-quality on: pull_request: types: [opened, synchronize] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - run: npm ci - run: npm run lint - run: npx tsc --noEmit test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - run: npm ci - run: npm test -- --coverage --coverage.threshold804. 实战一个可复制的 AI 编码工作流4.1 把任务拆到“可审查”的粒度前面的约束讲得再多最后都要落到任务执行上。这里最值得花时间的环节是任务拆分。我在实践中常用的拆分标准是一个任务生成的 diff 应该能在 15 分钟内审查完少于 200 行并且只涉及一个模块。如果任务超出这个范围就继续往下拆。举个例子。需求是“给订单列表增加筛选状态和分页”。我不会直接把这个需求扔给代理而是拆成三个连续任务在订单查询接口中新增 status 筛选参数补充单元测试。在订单查询接口中新增分页参数返回分页结构补充单元测试。更新前端调用逻辑展示筛选状态和分页控件。每一步跑完先审查、合并再进行下一步。这样做的好处是一旦某一步出了问题定位范围非常小而且前一步的成果已经被验证过不会被后一步的失败连累。4.2 给代理一份“任务卡”在向代理描述任务时光写一句“帮我加个筛选”是不够的。我习惯把任务写成一张结构化的任务卡包含四个部分背景、目标、约束、验收标准。背景说明这个任务为什么存在涉及的现有代码在哪里。目标用一两句话说明期望的结果避免歧义。约束说明不能改什么、必须遵守哪些规范、边界在哪里。验收标准用可验证的方式说明“什么算完成”比如“新增测试全部通过”“接口返回符合 swagger 定义”。一个参考模板如下【背景】 订单列表页目前在 order.controller.ts 的 getOrders 接口中实现 只支持分页不支持按状态筛选。前端需要新增“待支付/已支付/已取消”三个筛选项。 【目标】 为 getOrders 接口增加 status 查询参数值为 pending | paid | cancelled 允许为空为空表示查询全部状态。 【约束】 - 只修改 src/modules/orders 目录下的文件。 - 禁止修改支付模块和公共配置。 - 参数校验使用已有 zod schema不要新增校验库。 - 保持现有响应结构不变只增加筛选逻辑。 【验收标准】 1. 传给 statuspending 时只返回待支付订单。 2. status 为空时返回全部订单与旧行为一致。 3. status 传入非法值如 abc时返回 400。 4. 新增对应单元测试覆盖上述三种情况。 5. npm run lint 与 npm test 全部通过。把这份任务卡交给代理你会发现它的产出质量比“帮我加个筛选”高出一个档次因为它不再需要猜测你的意图所有关键决策你已经替它做了。4.3 一次完整的执行循环任务卡准备好之后完整的执行循环应该是这样的第一步让代理先“读”再“改”。在任务卡里明确要求它先阅读相关文件甚至让它先输出它对现有代码的理解确认无误后再动手。这一步能避免大量“答非所问”的改动。第二步要求代理分步提交。如果任务确实比较大让它先输出修改计划说明打算改哪几个文件、每一步做什么、每步怎么验证。你确认计划之后再让它执行比让它一口气改完要安全得多。第三步代理生成 diff 之后先由工具检查再进人工审查。工具检查指 lint、类型检查、测试这些自动化步骤人工审查则按前面说的审查清单逐项确认。第四步审查发现的问题不要自己动手改而是把问题反馈给代理让它自己修正。这样做有两个好处一是代理能在修正过程中理解规则后续类似问题会减少二是你能持续观察它是否真的理解了项目规范如果多次犯同样的错误说明你给它的约束还不够明确需要回到规则文件去补充。4.4 提交信息也要规范AI 代理生成的提交信息经常是“fix something”或者“update code”这种毫无信息量的内容。这在做历史回溯时非常痛苦。我建议在规则文件里明确提交信息格式比如要求使用 Conventional Commits 规范并且信息中必须引用对应任务编号或需求单号fix(orders): 增加状态筛选参数支持待支付/已支付/已取消 - 在 getOrders 接口中新增 status 查询参数 - 使用 zod 校验参数合法值 - 补充单元测试 Refs: OMS-1234提交信息实际上是“代理改了什么”的最小记录。规范之后即使哪次改动出了问题翻提交历史也能快速定位到任务卡大幅降低排查成本。5. 常见问题与排查思路AI 编程代理落地过程中有很多反复出现的坑。下面把我在项目中遇到的高频问题整理成一张速查表并补充每个问题的排查思路。问题现象常见原因解决思路改动范围远超任务描述任务边界描述不清晰代理自由发挥重写任务卡明确“只修改哪些文件、禁止修改哪些目录”代码功能正常但风格与项目不一致规则文件中缺少编码规范说明在 AGENTS.md 中补充命名、错误处理、日志规范并让 CI 强制检查反复产生重复代码代理没有全局搜索已有工具函数规则中明确“先搜索 shared 目录再决定是否新增代码”测试覆盖率高但业务逻辑错误测试只覆盖了代理自己写的路径缺少对既有行为的回归人工审查时重点看“旧行为是否被破坏”必要时补充回归用例代理修改了不该动的历史模块规则文件中没有列出禁止修改的模块把敏感模块明确写进 AGENTS.md 的禁止事项提交信息无意义历史无法回溯没有对提交信息做约束在规则中规定 Conventional Commits 格式并关联任务编号代理陷入死循环反复修改仍报错任务描述与代码现状不符或代理理解偏差停止循环重新审查任务卡补充现有代码上下文必要时人工介入PR 合并后马上在生产出现异常审查只看功能忽略了异常分支和容错逻辑审查清单中增加边界条件检查并要求补关键异常路径测试下面挑两个高频问题展开说说。第一个是“改动范围失控”。这几乎是使用 AI 编程代理最容易遇到的问题根本原因是任务描述里没有“负向约束”。你只说了要做什么没说不能做什么。解决方案是在任务卡里增加“禁止修改”清单并且尽量把允许修改的范围缩小到一个文件或一个目录。不要相信代理会自动克制它默认会采取“最容易实现目标”的方案而这个方案未必是最小改动。第二个是“测试看着全绿实际上没测到点子上”。代理生成的测试有一个通病就是会针对它自己写的代码路径构造测试所以测试通过只能说明“代理认为的逻辑是对的”不能说明“业务的逻辑是对的”。破解方法是审查者用“反向思维”检查测试先想“旧功能有没有可能被改坏”再想“有哪些异常输入测试没覆盖”把这两个方向补充进测试要求里。6. 工程建议让 AI 代理的代码长期可控6.1 先有小步提交的习惯再谈 AI 提效很多团队没有引入 AI 代理之前代码提交就是大块大块地来。这种情况下引入代理只会让问题更严重因为代理会继承团队已有的坏习惯甚至放大它。安全使用 AI 编程代理的前提是团队本身已经有小步提交、频繁自测、清晰提交信息的工程习惯。如果你的项目目前还是“一周一次大提交”那第一步不是引入代理而是先把提交粒度降下来。代理只是一个放大镜它放大的是你已有的工程能力。6.2 让代理在测试的约束下工作测试不仅是质量保障也是给 AI 代理的“导航仪”。代理在改代码时如果能看到相关模块的测试它就更不容易跑偏。实际操作中我习惯在任务卡里把相关测试文件路径直接列出来让代理在修改前先读测试。要求它保证新改动不破坏已有测试同时为新增逻辑补充测试。这样做还有一个额外好处测试本身就是对“预期行为”最精确的描述代理读懂了测试往往比读注释更能理解业务意图。6.3 权限与安全边界要收窄AI 编程代理在执行任务时可能需要访问代码仓库、运行命令、操作文件甚至调用外部 API。这里必须坚持最小权限原则。不要让代理拥有生产环境的密钥不要让代理随意执行数据库变更命令更不要让代理接触到不必要的用户数据。在团队协作场景里还应该考虑让代理在独立的沙箱环境里运行与主仓库隔离合并前必须经过严格审查。安全这一点没有妥协空间宁可牺牲一点效率也不能让一个不可控的自动化程序拥有过大的破坏能力。6.4 定期评估“代理到底省了多少事”不要凭感觉判断代理是否有效。我建议团队每两周做一次简单复盘重点看三个指标合并的代理生成代码占总量比例、代理生成的 PR 被打回率、因代理代码引入线上问题的次数。打回率尤其值得关注。如果代理生成的 PR 频繁被拒说明不是代理不行而是你给它的约束还没建立起来。这时候优先补充规则文件而不是批评代理。用数据说话持续迭代约束团队的 AI 编程代理会越用越顺手。7. 怎么迈出第一步如果你准备在团队里安全地引入 AI 编程代理我给出一条最小可执行的起步路径。第一步选一个低风险项目试用不要一上来就动核心业务。第二步花半小时写好AGENTS.md把目录结构、编码规范、禁止事项列清楚。第三步选一个边界清晰的小需求用任务卡的方式交给代理执行。第四步认真完成一次代码审查把审查意见和项目规则做对比看看哪些问题其实可以提前通过规则规避回头补进规则文件。第五步重复这个过程直到你发现规则文件开始稳定、需要频繁修改的次数变少再扩大使用范围。在这个过程中你把规则文件逐渐补充完整就是在把自己对于代码质量的隐性理解沉淀成团队资产。以后不只 AI 代理会参照它新入职的同学同样可以靠它快速上手项目规范。到这一步AI 编程代理就不再是一个“需要盯着的风险源”而是团队工程体系里的一个正常协作角色。AI 编程代理不会消失只会越来越强。与其等它推着团队走不如现在就把约束、审查、反馈这套机制建立起来。写垃圾代码的从来不是工具而是缺少边界的流程。这套流程建好了AI 写得越快团队受益就越大。