资讯动态

AI Agent写代码不守规矩?规范注入与校验闭环实践

发布时间:2026/10/15 23:29:06 来源:尧图企业网站定制
让AI Agent写代码最让人头疼的往往不是它写不出来而是它写得“不像自己人写的”。前阵子让Pi Agent生成一个接口模块功能完全正确跑测试也没问题但打开代码一看函数命名全是缩写错误处理被随手吞掉注释写得比没有还糟糕整个风格和现存代码库完全是两个世界。这几乎是所有把AI Agent接入一线研发的团队都会撞上的墙——AI能写、能跑但不守规矩。这篇文章就以Pi Agent为例聊聊我们是怎么解决这个问题的。这里的Pi Agent是一个内部自研的编码Agent框架核心能力是让大模型根据任务描述自动生成代码、补全接口、写测试甚至做简单的重构。但“能生成代码”和“能生成符合团队规范的代码”之间差着一整套工程化约束。我踩过不少坑也试过很多方案最后沉淀下来一套组合打法规范注入、规则校验、失败反馈、CI闭环。这套方法适用的场景很明确只要你的团队在用AI辅助编码并且希望产出物能过人工评审、能合入主干那这篇文章就值得读完。1. AI Agent为什么总在“规范性”上翻车1.1 大模型写代码的本质是“预测下一个Token”很多人对AI Agent期待太高觉得它既然能写出可运行的代码就应该天然懂“规范”。但实际运行机制不是这样。大模型写代码本质上是在做下一Token的概率预测给定已有上下文它根据海量训练语料里的统计规律生成最可能接续的Token。训练语料里确实有大量开源项目、技术博客、Stack Overflow问答但这些内容的风格极其分散。有的用驼峰有的用下划线有的喜欢把错误往上层抛有的习惯用Result封装吞掉异常。模型的“平均风格”往往是四不像恰好不是你们团队的标准。所以当Pi Agent第一次生成代码时它默认输出的风格来自它训练数据里的“最大公约数”而不是你们仓库里的“当前规范”。如果只是偶尔生成一小段代码手动改改还能接受。可一旦你让它批量生成十几个模块或者让它处理一个大型重构返工成本立刻爆炸。1.2 “代码规范”对AI来说是隐性知识咱们得承认一件事大多数团队的代码规范并没有形成机器能读的完整清单。规范散落在各种地方WIKI文档里有一段Code Review记录里有一些约定老员工的脑子里还有一堆“潜规则”。很多新同学进组第一个月都在默默观察别人怎么写代码慢慢才摸清团队风格。这种知识形态对AI极其不友好。大模型并没有在训练时见过你们公司内部的代码仓库也没读过你们的WIKI更不可能感知到上次Code Review时测试同学提的“这个异常不能用catch吞掉”。它不知道规范不是因为它笨而是因为根本没人把规范完整、显式、结构化地告诉它。你直接在Prompt里写一句“请遵守公司代码规范”它实际上不知道“公司代码规范”到底是什么内容只会在输出里给你塞一个注释“// TODO: 遵守规范”用来自欺欺人。1.3 单独靠提示词约束效果极不稳定很多团队第一次尝试让AI守规矩就是往Prompt里加约束“请使用驼峰命名”“请遵循项目现有风格”“错误处理要完整”。一开始可能有效尤其当任务简单时模型会认真模仿。但只要任务复杂一点上下文一长它就开始顾此失彼。原因有两层一是大模型的注意力会分散早期指令可能在长上下文中被稀释二是提示词里的自然语言约束本身就自带歧义比如“错误处理要完整”到底是“所有异常都要捕获”还是“所有异常都要往上抛”模型只能猜而猜就有概率出错。这也是我后来做技术方案时反复向团队强调的一点不要试图靠提示词当救世主提示词只是第一道防线真正兜底的必须是可执行的校验逻辑。AI Agent不守规矩本质不是态度问题而是工程上缺少强制反馈回路。2. Pi Agent的约束与校验体系设计2.1 三层结构规范注入层、校验执行层、反馈修复层Pi Agent这套方案的核心是把“规范”从一个抽象概念拆成三层可执行的结构。每一层承担不同职责合在一起才形成闭环。第一层是规范注入层。把团队代码规范翻译成两部分一部分是给大模型读的、用自然语言精简描述的关键规则另一部分是给机器用的、结构化规则文件。模型在生成代码前先把这两份东西加载进上下文相当于给新人发了入职手册和操作清单。第二层是校验执行层。Pi Agent生成代码后不直接交付而是先调用一系列静态检查工具和格式化工具用脚本检查产出物是否违反规范。这一步是关键跳跃AI说的话不承担责任但脚本检查不通过就是过不了。校验执行层像门禁系统规则文件怎么定义它就不打折扣地执行。第三层是反馈修复层。当校验失败Pi Agent不会把错误直接丢给人而是把校验工具的输出信息重新喂给模型让它根据报错信息有针对性地修改代码。改完再校验直到通过或者达到预设的最大循环次数。这相当于让Agent自己完成“被审查—修改—再被审查”的迭代过程。2.2 为什么必须做“规则文件”而不是“规则文档”先说一个血泪教训。最早我们做Pi Agent的时候直接把公司WIKI上的代码规范整段丢进Prompt结果非常糟糕。一是WIKI文档通常两三万字塞进上下文后Token占用太多模型处理主任务的空间直接被压缩二是文档里大量内容是为人类阅读写的铺垫、解释、案例图片描述机器读起来噪声极大三是文档里的很多规则是经验性描述比如“代码尽量简洁”这种话模型根本没法执行它不知道“尽量”的量化标准是什么。所以后来我们坚定地把规范转成了规则文件。规则文件的核心价值是任何一条规则都必须能被机器判断真伪。比如“函数命名必须使用驼峰风格”是可判断的“写代码要整洁”是不可判断的“禁止在catch块里吞掉异常”是可判断的“错误处理要完善”是不可判断的。规则文件的好处是既能让模型精准理解又能让脚本精准执行两边用同一套语言沟通减小信息损耗。2.3 强制校验必须放在“生成之后、交付之前”有人可能会说“我都把规则文件给模型了也告诉它遵守了为什么还要跑校验工具”我理解这种想法但现实中模型偶尔就是会“叛逆”。哪怕你把规范说得清清楚楚生成长度一上去前面记得、后面忘掉的情况非常常见。尤其当你让Agent一次生成多个文件时它很可能在前两个文件里严格执行了驼峰命名第三个文件就开始放飞自我。所以Pi Agent的流程里校验步骤是不可跳过的强制环节。写代码的人可以“忘了”规范但工具链不会。把校验放在生成之后、交付之前意味着每一份产出物都经过了客观检查而不是依赖模型的临场发挥。这个设计跟人在CI阶段跑测试是一个道理开发本地就算自我感觉良好CI不过就是不过没有讨价还价的余地。3. 把公司规范“翻译”成机器能读的规则3.1 规范分层强制级、建议级、风格级并不是所有规范都应该用机器强制卡死。如果你把每一条规范都设成error级Agent的生成流程会频繁被打断迭代燃尽情绪最后产出也支离破碎。我们整理规范时做了分级强制级规则涉及正确性和安全性必须机器阻断。比如不允许console.log直接上生产、不允许在catch里吞异常、不允许裸SQL拼接。建议级规则影响可维护性尽量机器提醒。比如函数行数不能太长、圈复杂度过高、重复代码片段。风格级规则属于审美范畴交格式化工具处理。比如缩进、引号、空格这类问题直接上Prettier或等价工具自动化不要浪费模型额外精力。这个分级的意义是给Pi Agent设定优先级。它不必在大脑里维护几十条规则的完整细节只需要在生成代码时重点遵守强制级然后让工具链去检查建议级。否则把几百条规则一次性塞给模型反而会让它在小规则上较劲、在大规则上翻车。3.2 用规则文件描述“允许什么、禁止什么”我们采用的做法是把规则文件写成JSON和YAML两种格式。YAML方便人读、方便评审JSON方便机器解析、方便程序加载。下面是一个简化的规则文件示例rules: - id: NO_CONSOLE_LOG type: error description: 禁止在生产代码中使用console.log target: js,ts pattern: - console.log - console.debug - id: FUNCTION_NAMING type: error description: 函数命名必须使用驼峰风格 target: js,ts pattern: ^[a-z][a-zA-Z0-9]*$ - id: MAX_LINE_LENGTH type: warning description: 单行长度不应超过100个字符 target: all max: 100 - id: EXCEPTION_SWALLOW type: error description: catch块中不允许只记录日志或置空异常 target: js,ts pattern: - catch { require: - throw - return error你可能注意到了有些规则用pattern可以直接查出违禁写法有些规则描述得还不够机器化。实际操作中正则匹配只是最原始的一层真正复杂规范的落地要靠AST解析器。比如“检查所有函数名的命名风格”你不能靠简单搜文本实现因为注释里也可能出现驼峰词反而误报。正确做法是先把代码解析成AST然后只扫描FunctionDeclaration和VariableDeclarator节点提取其中的函数名再拿正则去校验。我给一个Python实现的简化思路配合ESLint这类工具使用更稳import ast import re def check_snake_case_functions(source_code: str) - list: tree ast.parse(source_code) problems [] for node in ast.walk(tree): if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): name node.name if not re.match(r^[a-z][a-zA-Z0-9]*$, name): problems.append({ line: node.lineno, message: f函数名 {name} 不符合驼峰命名规范 }) return problems这里只是示意。不同语言要用不同的AST库但思路完全一致不要试图用字符串匹配去理解代码结构要让程序真正“读懂”语法树再去判断节点属性。这样既准确又可以给出行号方便反馈给模型时带着位置信息。3.3 可执行校验工具的选择与组合规范文件是标准真正动手检查得靠具体工具。如果你在JavaScript/TypeScript技术栈里ESLint是首选。它天然支持自定义规则也支持接入Prettier做风格统一。我们为Pi Agent做了两份ESLint配置一份人工时代就在用一份是专门给Agent用的简化了规则数量只保留机器判定稳定的部分。一个典型的ESLint配置长这样module.exports { root: true, parser: typescript-eslint/parser, plugins: [typescript-eslint], rules: { typescript-eslint/naming-convention: [ error, { selector: function, format: [camelCase], leadingUnderscore: allow } ], no-console: error, max-len: [warn, { code: 100, ignoreUrls: true }], no-empty: error } };其他语言也都有对应工具。比如Java的Checkstyle、Python的flake8/Ruff、Go的gofmt/go vet、C的clang-format。关键不在于具体用哪个工具而在于这些工具的退出码必须进入Pi Agent的执行流程。如果工具返回非零退出码Agent就知道此次产出不达标得回头修。这里我强烈建议把“格式化”和“静态检查”拆成两步。先让工具自动格式化再跑静态检查。否则很多风格问题会混在真实逻辑问题里干扰模型判断。格式化自动修完剩下的报错基本都是“硬错误”或需要人工决策的问题反馈给模型时也更好办。3.4 让Pi Agent真正“看到”校验结果规则文件准备好、校验工具也接上了接下来的问题是怎么让Pi Agent在生成代码后主动使用它们。我们在Pi Agent的推理工作流里增加了工具调用能力Agent先有权限执行Shell命令所以它可以自己调用ESLint、跑测试、执行格式化脚本。为了引导它正确使用工具我们在Prompt里写了一段操作指令模板你是团队编码Agent。代码生成规则如下 1. 所有函数和变量命名必须遵循项目rule.yaml中的naming规则 2. 生产代码禁止出现console.log如需日志请使用logger对象 3. 生成完成后必须依次执行 - npx eslint src/generated --exit-on-fatal-error - npm run format:check 4. 如果lint或format检查失败请根据报错信息逐条修复修复后重新运行检查直到通过 5. 最多尝试修复5次。若第5次仍未通过请保留最后一次修改并将错误信息汇总输出给用户。这个模板看起来简单但它解决了三个关键问题第一模型知道“做完代码之后要做什么”流程不再停在生成那一步第二模型知道“什么叫通过”有客观的退出条件第三模型知道“极限在哪”不会陷入无限自修修改的僵尸循环。很多Agent实现失败恰恰就是少了最后一条。4. 实操过程接入Pi Agent的完整流程4.1 初始化配置把历史规范导入新框架接入Pi Agent并不是直接改个Prompt就完事我们需要做一次“规范整治”。具体分四步走。第一步从WIKI、Code Review记录、老代码里提取所有规范条目逐条讨论分类确定它是强制级、建议级还是风格级。这一步很耗时但没有捷径不过这一步本身就是一次团队财富整理。第二步把确认过的规范写进规则文件。建议让熟悉工具链的工程师来写因为要对具体检查工具的能力边界有判断。比如效果上是“禁止使用”你可以写进ESLint的eqeqeq规则而不是在规则文件里手写正则。第三步在本地一个模拟仓库里把整套流程跑通。用Pi Agent生成一段已知有问题的代码让它自检并修复看能不能达到预期效果。这个模拟仓库要和真实仓库结构一致包括路径、依赖、lint脚本否则Agent学会的规矩在真实环境里不适用。第四步评审规则文件本身。让团队里最资深的工程师过一遍确认没有误伤正常写法的规则。比如“函数名必须驼峰”这条如果代码库里本来就允许某些美术、算法模块用全大写风格就要加豁免条件。否则Agent会把合规代码也改成不合规。4.2 Agent工作流编排生成、自检、修复、审查Pi Agent的完整工作流我们编排成了四个阶段。生成阶段Agent读取任务描述结合上下文找到相关文件和约定产出第一版代码。注意这里不需要把整个代码库塞给它只需要提供与当前任务相关的文件列表和接口定义减少上下文噪声降低规范稀释的概率。自检阶段Agent调用lint、format、甚至单元测试工具检查产出。单元测试这一步很有用因为很多规范性问题比如某个函数返回值缺失光靠静态检查发现不了但测试一跑就暴露了。如果测试没跑通代码风格再规范也没用。修复阶段Agent把自检阶段的报错信息解析成具体修改点逐项修复。修复的顺序很关键先修会改变程序行为的错误再修风格问题。否则模型可能一直纠结在引号格式上忽略了某个空指针错误。审查阶段Agent生成一份提交说明列出生成文件、检查结果、修改记录。然后整个改动交给人做最终Code Review。人工审查的工作量并没有完全消失但重点会从“吹毛求疵”转移到“看逻辑、评设计”效率显著上去。4.3 接入CI流水线卡住最后一道防线就算Pi Agent在本地跑通了全套检查也难保有人会绕过流程把未校验的代码直接提交。所以必须把校验结果绑定到CI流水线让不合规的代码根本没有合入机会。我们在CI流水线里加了一个专门的stagestages: - generate - lint - review lint: stage: lint script: - npm run lint:check - npm run format:check only: - merge_requests这样配置之后哪怕开发者手动修改了Pi Agent的产出只要改动不通过lintMR就没法合入。这种做法其实也在反向约束开发者如果你想绕过规范就别用AI生成代码既然用了AI生成代码就让AI和工具链配合把规范守住。还需在流水线里记录边界情况比如Agent修复循环达到上限后的异常退出。异常退出时CI不能默默通过必须触发告警让负责的工程师介入。否则Agent虽然在本地自修了五次最后推上来的代码还带一堆lint错误CI要是给过了前面的所有努力就白费了。4.4 结果观测合规率、修复率、耗时做到这一步还不能叫完事得量化结果。我们搭建了一个简单的看板给Pi Agent每次生成行为记录三类指标首次合规率Agent生成完第一版代码不经修复直接通过校验的比例。自修复成功率首次校验失败后Agent通过自我修复最终达到合规的比例。平均修复耗时从首次失败到最终通过花费的时间。这三个指标能帮你快速发现系统问题。如果首次合规率长期偏低说明Prompt或规则文件的语义跟模型理解有偏差如果自修复成功率不高大概率是校验工具报错信息给得不够清晰模型看不懂该改哪里如果修复耗时太长说明修复循环设计有问题可能是规则过严导致模型反复踩线。我们把这个看板提供给每个接入Pi Agent的项目组用来判断“Agent在这块业务上到底能不能用、值不值得用”。若某类任务的首次合规率能做到80%以上就可以把整个流程逐步放权人只做抽审若一直卡在50%上下那建议还是让它做草稿生成人工深度修改。5. 坑与避雷Pi Agent实践中的几个典型问题5.1 规范规则太多导致“指令冲突”第一次把所有规范都灌进去时我们很快发现模型开始纠结一条规则要求“不要使用any”另一条规则又写着“调用第三方库时可以放宽类型检查”模型在代码里反复横跳生成结果反而不稳定。这是典型的规则冲突问题。解决方案是建立优先级。在规则文件里增加priority字段当两条规则冲突时模型需要遵循高优先级规则。比如上面的冲突里“不要使用any”优先级高于“放宽第三方库检查”那模型就会安心地选择strict类型路径而不是自己纠结。规则不在于多而在于自洽。少而自洽的规则比多而矛盾的一百条有效得多。5.2 LLM对“禁止”和“必须”的理解没有你想象的强我原以为给模型下负面指令是最容易生效的比如“不要用console.log”。但实测发现当代码生成长度超过几百行时早期那些“禁止”指令经常被遗忘模型时不时还是会输出一两个console.log。相反“必须先把log通过logger输出”这种正面引导就稳定很多。所以我们在规则文件里不只写禁止项还写替代项。对每条禁止规则尽量给一个“应该怎么做”的正面指令让模型有明确的替换路径。不要让它“不要做X”要告诉它“应该做Y”。这个写法和给人培训很像光说别犯错不够还得告诉人家正确姿势。5.3 校验工具频繁报错导致Agent陷入死循环有一次Pi Agent在处理一个老模块时ESLint连续报了几十个“no-explicit-any”错误然后它开始一边修一边又引入新的错误循环了七八次也没通过最后时间全部消耗在无关紧要的细节上核心功能都还没完成。原因在于那个老模块本身就大量使用了anyAgent一改下游类型推断全乱了。后来我们加了两个机制一是设定修复上限超过后强制退出并把失败报告交给人类即使这个人类可能是开发者本人二是按文件增量做lint只检查Agent本次生成或修改的文件避免被仓库里历史遗留问题拖入泥潭。你要是发现Agent总在无限循环先看一眼是不是把整个仓库的存量问题都背到自己身上了。5.4 人工审查成本没有下降反而上升了引入AI Agent早期我们发现Code Review时间反而变长。原因很魔幻Agent改代码时会按规则修掉所有风格问题但也可能偷偷改掉了不该动的地方比如把别人手写的修复逻辑又“规范化”了一遍。评审人不仅要看新逻辑还要比对Agent误改的代码工作量不减反增。解决这个问题靠权限约束。Pi Agent的修改范围被严格限定在任务相关的文件里不允许顺手修改未指定的“路过文件”。同时在提交说明里生成diff摘要让评审人一眼看到“哪些文件是核心改动、哪些是工具自动格式化产物”快速跳过低风险的部分。实践下来这招效果最明显审查时间逐渐回到正常水平。5.5 把Agent当“新人”却不给上下文那就别怪它莽撞最后一个问题其实最根本。我们团队有些人用Pi Agent的方式是丢给它一句“给我重构登录模块”然后啥都不说等它产出。结果Agent只能对着一个模块名凭空猜连现有接口定义都拿不到。第一版代码风格倒是规范了但一运行就知道跟现有系统接不上。让Agent守规矩的前提是给它“足够的上下文”。我们做了一个上下文自动装配组件根据任务描述检索相关文件把模块入口、接口定义、依赖关系、示例代码一并打包进上下文。这让Pi Agent从“盲猜”变成了“照着团队现有代码的方式长大”。代码规范的第一个规则其实是新代码必须和老代码保持一致的语言和结构。你连接下来要改的代码都没见过聊规范就是空中楼阁。这里整理了一份常见问题速查表现象可能原因建议处理首次合规率低规则文件语义模糊Prompt上下文太长精简规则增加正面引导缩短上下文修复循环到上限仍未通过规则冲突或老模块历史问题拖累设置优先级按文件增量lint报告通过但代码质量差只做了静态检查缺少测试验证增加单测/集成测试到校验流程审查成本反而升高Agent修改范围失控限制修改文件范围输出diff摘要Agent完全无法起步任务上下文不足接入上下文装配检索相关文件6. 经验复盘与可复用架构6.1 从“人管代码”到“规则管代码”经过这段实践我对“AI Agent守规矩”这件事有了新的理解。过去团队管代码靠的是人的纪律性Code Review里老同学盯着发现不对就当场指正。但有了AI Agent后这个模式就崩了——Agent没有情感压力也不会因为被指正而记住教训它每次都是从零开始。想让Agent守规矩就得把规矩沉淀成客观的、自动化的执行脚本让人从“执法者”变成“规则制定者”。这个理念可以扩展到不止代码规范的领域。比如生成的注释有没有包含TODO标记、有没有带着死者接口文档生成的描述是不是一直在用空话套话甚至AI生成的测试用例是不是只测快乐路径只要把这些要求变成可校验的检查项接进Agent的工作流它就能从“生成完就完事”变成“生成完且满足标准才算完事”。6.2 这套架构可以迁移到哪些场景首先最直接的迁移是代码评审助手场景。Pi Agent的规则校验层和反馈修复层完全可以独立提取做成一个PR检查机器人有人提交代码机器人自动跑规范校验把问题清单贴在评论区。这一步切走了大量重复低级的审查工作。其次可以迁移到文档生成场景。把“文档必须包含示例代码”“标题层级不得超过三级”“不能出现语言块标注与实际语言不符”这类要求写成检查规则再让Agent生成后自检。文档规范和代码规范在结构上是同一个问题。再一个方向是代码迁移场景。比如把一个老项目从JavaScript迁移到TypeScript迁移过程中必然涉及大量“如何保持原行为又符合新规范”的决策。过去人肉迁移很容易出现“类型是加了但行为全变了”的问题。让Agent在迁移过程中始终保持“先比较编译产物、再检查差异”的循环效果会好很多。6.3 关于这套方案持续迭代的几点体会维持这套体系运转说难也不难说简单也不简单。难的是规则文件需要持续维护因为团队规范会随技术演进发生变化简单的是只要规则文件更新所有使用了这个规则文件的Agent和CI都会同步生效不用担心有人漏看通知。我的一个习惯是每次Code Review如果出现“居然没被规则卡住”的问题就会顺手把它记下来。攒到一定数量就沉淀成新的规则再向规则文件里补充。这些“漏网之鱼”往往是整个系统最有价值的增量反馈因为它们代表真实的、从实践中来的规范缺口比坐在会议室里拍脑袋想出的规则接地气得多。还有一点初期即使投入比较大也不要跳过规则分级。我见过很多团队把一切的绊脚石一股脑喂给Agent导致Agent在空格式上消耗大量精力而真正重要的逻辑错误反而没人关心。规范不是越严越好而是边界越清晰越好。给Agent一个少而明确、条条能被执行、执行后有反馈的规则集比一个庞大的、互相矛盾的“规范大全”要强太多。如果让我给刚起步的团队一个明确的入手路径那就是先挑出五条最让你痛恨的违规习惯写成规则文件接一个脚本验证让Agent生成本次任务代码后自动跑脚本。把这五条玩透了再慢慢往里加。不用一次把规范体系做得宏大先让“规”能落地再让“范”能传承。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑