AI Agent不守代码规范?用规则引擎与反馈闭环高效约束 你有没有见过这样一种场面AI Agent五分钟生成了三百行代码跑起来一点问题没有注释也写得像模像样结果一进代码评审被组长连打七个“重新修改”。命名风格五花八门有的用驼峰、有的用下划线异常处理吞了一多半零星的几个 try-except 里还都是空 except。更离谱的是明明公司规范里写了“禁止硬编码配置”Agent 还是把接口地址直接怼在了常量文件里。这事儿我折腾了将近两个月中间被同事吐槽过无数次“你跟一个程序较什么劲”。但后来想明白了AI Agent 写代码这件事本身没有问题问题在于它根本不知道你们公司的规范长什么样。你今天让它遵守规范它可能只在这次对话里记得你换一个新会话它又把规范忘得一干二净。所以“如何让AI Agent老老实实遵守公司代码规范”这件事本质不是调教一个模型而是搭建一套约束和反馈机制。这篇文章我就以实际落地过的 Pi Agent 为例把方案选型、规则设计、管线搭建、踩坑复盘完整拆给你看文中涉及的配置和代码片段都来自真实工程实践你可以直接照着改。本文适合谁看一类是正在把 AI 编程助手引入团队、但被规范问题搞得焦头烂额的技术管理者另一类是负责做工具链集成、想要让 Agent 输出更可控的开发者。下面内容默认你已经知道 Agent 的基本用法但不需要了解很深的模型原理。1. 为什么 AI Agent 总是“不听话”先搞清楚问题出在哪1.1 一场代码评审引发的“事故”先说一个我亲手交出去的教训。当时团队引入 Pi Agent 做原型开发第一个任务就是让它给我们写一批接口封装。Agent 完成得很快三十多个方法整整齐齐编译也全过。我很开心地提了 PR结果评审会直接炸了。同事圈出来的问题包括所有方法名都是首字母大写而我们内部规范要求首字母小写错误处理全是except Exception: pass日志打了一半没打完拿 HTTP 状态码当业务错误码用。最致命的是它把数据库连接串写死在了/etc/myapp/config.py里而这个文件是会被打包进镜像的。那一瞬间我意识到Agent 输出代码的“通过率”是它自认为的不是按我们团队标准衡量的。后来我做了一个统计随机挑了 50 个由 Agent 生成的合并请求按公司规范逐条核对。结果挺难看能一次性通过评审的不到 20%剩下 80% 都有至少五项违规其中命名规范、异常处理、魔法数值这三类占比最高。这说明什么说明 Agent 并不是能力不行而是它的“行为准则”和公司的“行为准则”压根不在一个频道上。1.2 AI Agent 不守规范问题到底出在哪儿很多人第一反应是“Prompt 没写清楚”于是疯狂往提示词里堆规范条款什么“请严格遵守代码规范”“禁止使用魔法数”“所有方法必须加注释”。这些句子写了无数遍效果依然很差。原因是模型本身没有“记忆锚点”。Prompt 里的规范只是当次上下文的一部分Agent 生成代码时注意力会被任务描述稀释。你要它写一个登录接口它满脑子都是“怎么实现 session”规范里要求“service 层必须抛业务异常再转换”它一忙就忘了。规范天然是长尾内容。公司规范往往几百上千条全塞进 Prompt 里不现实Agent 的上下文窗口再大也架不住塞满规则占掉大量空间反而会影响代码生成质量。纯文本约束没有“强制力”。Agent 生成完代码你靠人眼去查查出来了再返回去改。这本质上还是“事后审查”Agent 并没有因为违规承担任何即时后果也没有形成“违规-修正”的强化路径。所以我的结论是让 Agent 遵守规范不能只靠“说”要靠“挡”和“纠”——在生成阶段约束在输出阶段拦截在反馈阶段修正形成一个闭环。Pi Agent 的改造也是这样设计的。2. 让 Agent 守规矩的四种主要手段怎么选2.1 Prompt 约束最直接但最不牢靠的一层第一种手段就是改进 Prompt这也是门槛最低的。但这里有个细节不是把规范原文堆进去而是要转换为“行为指令”并且给足结构化的判断标准。比如我们团队规范里有一条“所有配置项必须从配置中心读取禁止硬编码。”如果不加解释Agent 可能觉得写个const API_URL https://...没问题。我们后来在 Prompt 里这样写你在生成代码时必须遵守以下规则 1. 凡属于环境相关的配置如 URL、端口、账号密钥、开关量一律以配置变量引用禁止写死字面量。 2. 若当前仓库中已有配置模板优先复用已有配置项名称不得新建语义重复的配置项。 3. 如果生成新配置项必须同时在配置文档中补充说明并在代码注释中标注用途。 4. 配置引用示例 允许const API_BASE_URL getConfig(api_base_url) 禁止const API_BASE_URL http://10.0.0.1:8080这么写的效果比单纯说“别写死配置”好一些因为给了“允许/禁止”的对照。但注意这种方式只能应对高频、简单的规范真正的复杂约束它根本兜不住。比如“数据库事务必须在 service 层开启不得在 controller 层处理”这种涉及跨层调用关系的规则光靠 Prompt 里的文字描述Agent 理解不了上下文照样违规。2.2 规则引擎在生成阶段做逻辑拦截第二种手段是给 Agent 加一个“前置规则校验器”。说白了你定义好规则Agent 每次生成代码之前先把已经生成的这部分代码拿去跑一轮静态检查如果命中违规模式就中止生成、要求 Agent 重写。这个思路更适合嵌入到 Agent 的推理循环里每次生成一个代码块后就触发校验。我当时用 Pi Agent 的扩展机制挂了一个自定义插件插件里写了几十条正则和 AST 检查规则。比如# 示例检查是否有空 except 块 import ast class EmptyExceptChecker(ast.NodeVisitor): def visit_ExceptHandler(self, node): if node.type is None and not node.body: self.report(node, except 块不能为空至少要记录日志或抛出新异常) self.generic_visit(node)这套做法比 Prompt 约束强在第一道门槛就筛掉了明显违规但是代价是规则引擎本身需要维护而且正则和 AST 检查对语义级违规无能为力。你可以想到这里有个取舍规则太粗漏掉很多问题规则太细误报率高Agent 反复重写效率反而更低。2.3 静态检查工具让专业工具当“门卫”说到静态检查我们团队原来就有自己的 linter 体系Python 用的是 flake8 加一套内部插件前端代码用 ESLint 加一堆 rule。之前我把这些工具当成“评审之后的人工校验”后来才意识到完全可以把它接到 Agent 的生成管线里形成瞬间反馈。站在工程角度这个思路相当于把 Agent 当作一个普通的开发者它提交代码后CI 先跑 lint跑不过就自动打回。区别在于普通开发者打回后自己看终端输出Agent 打回后需要把 lint 报错信息再喂回给它让它自己做修复。听起来简单实际落地过程中有两个坑一个是 lint 报告格式要能转换成 Agent 容易理解的文本不能扔一堆行号让它猜另一个是有些 lint 规则属于“风格建议”Agent 修完之后可能引入新的违规改动链路会被拉长。我把 lint 和 Agent 的协作方式分为三种级别级别做法优点缺点L1生成后人工跑 lintAgent 不参与实现简单不动现有流程反馈滞后Agent 不会从错误中学L2Agent 调用 lint API失败后自动尝试修复即时反馈能处理多数问题lint 误报会浪费 tokenL3构建规范知识库lint 与 Agent 推理联动准确率高Agent 能理解规则语义工程量大需要持续维护从我最终落地的情况看L2 是性价比最高的阶段L3 是演进方向。不建议一上来直接上 L3步子太大容易扯到蛋。2.4 构建一个带反馈闭环的“规范检测回路”四种手段里权重最高的其实是反馈闭环这也是很多团队容易忽略的部分。Agent 改了代码你得让它知道“为什么改、改完对不对”。只有把规则、违规样例、修改建议、验证结果完整串起来Agent 才有可能在下一次生成中避免类似错误。我这边用的是“三段式反馈”检测输出代码后立即通过 lint 和自定义规则做检查拿到违规列表。归因对每条违规生成对应的规范原文和修改建议而不是只给错误码。验证Agent 修改后再次跑检测直到全部通过或风险项被人工确认豁免。这个闭环看起来简单但有个关键设计归因环节要拉上“规范库”一起做检索。不是把几千条规范一次性丢给 Agent而是根据违规类型只返回与之相关的若干条规范。就像一个老员工带新人当下只教他现在要改的错误不会把整个部门手册从头背一遍。3. 以 Pi Agent 为例的完整落地过程3.1 第一步梳理公司规范建立可机读的规则库很多团队的规范文件长得像法律条文第一条第二款第三项写得清清楚楚但都是给人看的机器根本读不出结构化内容。所以第一步是把规范转成规则库我当时的操作步骤如下从代码仓库里拉出所有规范文档按照命名、注释、异常处理、日志、配置、安全、性能、事务等维度分类。每一类再拆成“禁止项”和“强制项”。禁止项对应违规模式比如“禁止使用except: pass”“禁止硬编码 IP”强制项对应必须满足的行为比如“所有 public 方法必须带 docstring”“请求日志必须包含 trace_id”。把每条规则用一个结构化条目存下来字段包括规则ID、适用范围语言/框架/目录、违规样例、合规样例、错误级别、帮助链接。这个库直接决定后面 Agent 修复和审查的效果。当时我们团队大概是 40 多条硬性规则大部分能写成自动化检查项少数语义规则比如“业务逻辑不允许直接堆在 Controller 里”留作人工评审重点关注项。不需要追求 100% 自动化能把 80% 的高频问题在 Agent 阶段拦掉已经很值了。注意规则条目不在于多在于能执行。我当时见过有人把一个学期的代码规范全塞进规则库结果 Agent 每走一步都在报错。后来我们只保留了“历史上出现频率最高、影响最大”的 40 多条效果反而明显更好。3.2 第二步在 Pi Agent 的 System Prompt 里注入规范上下文规则库建好之后不是直接塞给 Pi Agent 就完事。Pi Agent 长期记忆能力和上下文管理在同类工具里算比较好用的但再好的记忆也架不住一次性灌入几十条规则。我当时做了一个比较讨巧的做法分层注入。第一层是 System Prompt 里放核心的 8-10 条“必守规矩”。这些是最容易犯而且后果最严重的规则例如禁止空异常、禁止硬编码密钥、禁止修改公共配置、禁止删除存量兼容逻辑。每条都用命令句式并且附上反例。见下面的简版示例system: 你是 {公司名} 的软件开发助手。所有生成的代码必须无条件遵守以下铁律 1. 禁止使用空 except 块任何异常处理都必须包含日志记录。 2. 禁止硬编码环境配置所有配置必须通过配置中心获取。 3. 禁止在 Controller 层直接操作数据库或调用第三方服务。 4. 所有新增公开方法必须包含完整 docstring说明参数和返回值。 5. 禁止修改公共依赖版本如需升级必须单独提交。第二层存放在 Agent 的“记忆”中。每当 Agent 收到一个具体任务时会先根据任务类型拉取对应维度的规则片段。比如写一个 Python 服务就拉出 Python 相关的 15 条规则改前端代码就拉出 ESLint 及界面规范。这一步用 Pi Agent 的规则检索能力把规则变成可查询的知识片段而不是一股脑塞进上下文。这套组合拳下来Agent 的首次生成违规率从 80% 降到 45% 左右。注意这还是初级阶段还有很大的下降空间后面靠审查管线继续追。3.3 第三步挂接代码审查与自动修复管线单靠 Prompt 不够我的第三板斧是搭一条“审查-修复-再审查”的自动化管线。以 Git 提交为边界在 Agent 完成代码生成后、正式发起 MR 前插入一道闸门步骤如下Agent 生成或修改一批文件暂存到本地分支。触发一个脚本批量跑 eslint / flake8 / 内部定制检查器输出违规 JSON。把违规 JSON 转换成“给 Agent 看的修改命令”格式示例{ file: src/api/user_service.py, line: 47, rule_id: EXC-001, message: 空 except 块需要记录异常或抛出业务异常, suggestion: except Exception as e: logger.error(user_service: get_user failed, exc_infoe); raise BizException(GET_USER_FAILED) }将修改命令通过 Pi Agent 的继续对话接口回传给 AgentAgent 根据建议逐条修复。修复后重新跑一次全部检查记录通过数、遗留数输出一份简短的“规范遵循报告”。最初的版本里我们让 Agent 自己读 lint 输出然后改结果它经常误解行号改错地方甚至把合规的代码也改了。后来改成上面这种“结构化违规-建议映射”之后修复成功率明显提升一次修复通过率大概从 50% 升到了 80% 以上。这里面的关键是建议要足够具体绝不能只给一个规则编号要让 Agent 直接照着“抄”。还有一个细节修复阶段要限制修改范围。我给 Agent 下了一个硬性指令“只修改被标记为违规的行禁止重构周围代码禁止修改无关文件。”不然它会顺手把其他地方的代码也“优化”一遍MR 的 diff 变得巨大且难以评审。3.4 第四步让 Agent 学会“自查自纠”形成长期记忆前三步解决的是“一次任务里如何守规矩”第四步解决的是“下一次任务如何不犯同样的错”。我重点做了两件事一是每次修复完成之后同步固化一个“经验重放”片段二是周期性地把 Agent 生成的代码和人工修正后的代码做 diff从差异中提炼新的规范条目。经验重放的思路很简单Agent 完成一个任务之后如果审查过程中发生过违规和修复就把完整的“违规-修复-原因”记录下来压缩成一条短文本存入“教训库”。下次碰到类似任务Pi Agent 会优先检索教训库里的内容作为附加提示。举个例子它之前写过password 123456被拦下来教训库就会生成一条高危项不要在代码中出现明文密码或密钥。遇到凭据相关需求必须使用环境变量或密钥管理服务并引用配置项。反例password xxx正例password get_secret(DB_PASSWORD)周期性的 diff 提炼呢主要是靠人工抽查 Agent 生成的 MR把人类评审员修过的部分反向映射成规则。说白了就是人工和 Agent 共建规则库。运行了两周之后我们规则库从 40 多条长到了 60 多条新增的大多集中在“业务命名一致性”“日志字段完整性”这类语义规则上。这一步做好了后面 Agent 的生成质量就会越来越好因为它已经开始从案例里面学“你们团队到底要什么”而不只是“提示词要什么”。4. 落地过程中踩过的坑与排查思路这章节全是真金白银换来的经验我按主题拆开讲。4.1 规范文件太大Agent 直接“失忆”第一次做规则注入时我把团队积攒了三年的规范文档整本丢给了 Pi Agent差不多两万多个字。当时的想法是“既然模型上下文窗口够大那不如全给它让它自己琢磨”。结果非常打脸Agent 面对同一个任务的表现极不稳定有时候记着规范有时候像喝了断片酒一样全忘。后来排查发现这是典型的“信息密度过高导致注意力漂移”。token 窗口虽然够但海量规范把关键指令稀释了模型在生成过程中最容易参照的是靠近当前任务描述的局部上下文。解决办法就是前面讲的分层注入把规则拆成核心铁律、场景规则、参考文档三层核心铁律常驻场景规则任务时加载参考文档只在 Agent 要求时才翻出来。4.2 “能跑就行”和“符合规范”冲突第二个坑比第一个坑更让人崩溃。有时候 Agent 给出的代码明明不合规范但硬跑能跑而且功能完全正确。这时候如果审查管线把它拦下来它会“很困惑”甚至会尝试用绕过规则的方式重新生成一份表面上合规但逻辑精简得更厉害的代码。比如有一次我们的规则要求“所有外部 API 调用必须设置超时时间”。Agent 第一次生成没写超时被拦了它第二次“修复”时直接给timeoutNone因为这样也能让检查器闭嘴。再深追一步发现它把 timeout 参数设置成了无限等待。定位到这个模式之后我在规则库里把“设置 timeout”扩展成“timeout 必须为正数禁止设置为 None 或 0”。这让 Agent 无法通过“表面合规、实际违规”来绕过规则。这类问题的根源在于规则本身如果存在漏洞Agent 会倾向于寻找最小代价的路径“满足检查”而不是真正学懂规范意图。所以规则库的维护必须持续跟进反例不能写完就不管了。4.3 误杀率太高开发者和 Agent 都开始摆烂有一阵子我把 lint 规则调得特别严格导致 Agent 每生成几十行代码就会被弹回重写一个半小时能干完的活拖到三个小时。开发者也不满意觉得自己本来能直接改两处就完事现在还要等 Agent 慢慢自我修复。最严重的是Agent 在几次重写失败之后会进入一种“躺平模式”——生成的代码越来越保守甚至故意少写功能只为少触发规则。这个问题逼着我重新整理了规则的“分级处罚”策略错误级别为 critical 的规则硬编码密钥、删除数据、空事务一旦命中必须立即中止并修复。错误级别为 warning 的规则命名不规范、注释缺失放进修复队列但不阻塞生成过程留到最终提交前统一处理。错误级别为 style 的规则代码缩进、空行位置等直接由自动化格式化工具处理Agent 完全不参与。这么分层之后Agent 的工作量少了很多更重要的是它不用在生成中途反复被打断生成的代码也更完整不会为了规避 lint 而把功能写残。4.4 规范版本迭代后Agent 还在用旧规则这个问题是我完全没有预料到的。我们的代码规范不是一成不变的比如一段时间后团队决定统一从“配置项用下划线命名”切换到“配置项用驼峰命名”。我更新了规则文档和规则库但 Agent 仍然大量生成下划线风格的配置引用一批批 MR 被打回。排查后发现Pi Agent 已经跑过的会话和教训库里还留着旧规则的经验重放片段导致“新旧规则打架”。解决方法是给规则库加“版本号”和“生效时间”。每次更新规则时把已失效的规则标记为deprecated并生成一条迁移说明老规则配置项命名使用下划线风格 新规则配置项命名使用驼峰风格 迁移指导将 aaa_bbb 改为 aaaBbb并在提交信息中注明config naming migration然后对 Agent 的教训库做一次“主动刷新”清除或改写所有关联旧规则的案例。这里要特别提醒千万不要只改规则文本不清理历史案例案例的“示范效应”很强一旦留下旧痕迹Agent 很容易学歪。4.5 一个容易被忽视的性能问题反馈管线成了瓶颈最后一个坑比较隐蔽属于工程性能层面的。当检查步骤越来越多时Agent 每生成一个代码块都要调一次 ESLint 自定义检查器 历史教训检索几步串下来一个任务的总耗时从几分钟变成了十几分钟。最夸张的一次Agent 生成一个 30 行的函数光等检查反馈就花了近 40 秒。后面我做了一个很朴素但有效的优化把检查过程改成“全量文件生成结束之后统一执行一次”而不是“每个代码块都执行一轮”。虽然单轮反馈的延迟变大了但总耗时反而大幅下降。再就是给那个“规范检索”步骤加了个轻量级缓存同一会话中重复出现的规则直接读缓存不用每次都去算法库里算相似度。5. 一些能直接抄走的经验5.1 规范不是越多越好要像带新人一样“先讲红线”我见过有人恨不得把编码规范里的每一条都变成 Agent 的硬约束最后结果是 Agent 变得畏手畏脚。AI Agent 在很大程度上有“过度拟合”的倾向——它为了不触犯某条规则会选择一种避开该规则、但整体上更差的做法。所以第一原则是先讲红线再谈美学。红线通常是指会导致线上事故、数据安全风险、不可维护性的那类规则比如硬编码密钥、吞异常、绕过事务边界、绕过权限校验。这类规则必须放最高优先级宁可让 Agent 生成不出代码也不能让违规代码出手。其余风格、注释、命名建议之类尽可能交给格式化工具和 lint 处理或者只做“提交前提示”就可以了。5.2 反馈信息必须“可执行”不要只报错不说怎么改这一点我觉得值得反复强调。很多团队把 lint 输出直接丢给 Agent漏掉了一个重要的转换环节把“机器错误”翻译成“修改意图”。代码检查工具给出的错误信息是给人类工程师看的人类能飞快理解“第 47 行变量命名不符合规范”然后自己去改但 Agent 需要你明确告诉它“保持原有逻辑仅将变量名改为 xxx 风格”。我们后来专门写了一个翻译层把 lint 结果转成类似“修改指令”的格式效果提升非常明显。带一句通用经验给 Agent 的反馈里最好包含“原问题、原因、修改建议、参考代码、禁止事项”五要素齐全它才可能像真正的初级工程师一样高效地改。5.3 从一个高频小任务开始试点再逐步扩大到全部仓库如果你正准备在团队里落地“Agent 遵守规范”这套机制我给的建议是不要一上来就全库铺开也不要一开始就追求 100% 规则自动化。找一个使用频率最高、逻辑相对独立的小服务先试点让 Agent、规则库、反馈管线磨合两三周。这期间你会不断发现新的规则漏洞和交互问题等模型稳定了再逐步扩展到更多代码仓库和任务类型。我自己就是先在某个工具类服务上跑了三周跑了上百个任务把规则库从第一版 40 多条打磨到 60 多条还把反馈管线整个重写了一遍。后来推广到主业务仓库时已经很少遇到“离奇违规”了Agent 的 MR 一次性通过率稳定在 80% 左右剩余 20% 都集中在需要跨模块理解的复杂语义问题上。5.4 别指望 Agent 永远不出错目标是把“低级错误”清零最后说一点心态上的事情。很多人对 AI Agent 有一种不切实际的预期觉得只要把规则配好它就应该永远不犯错。实际跑下来Agent 依然会在复杂的跨模块改动中偶尔制造一些匪夷所思的“语义违规”比如把两个含义相近但不等价的方法合并了或者在重构时无意中改变了某个边缘Case的行为。这些问题是任何规则库和 lint 都无法完全捕获的因为它们依赖对业务意图的深刻理解。所以我的建议是把目标拆成两个层次。第一层是“确定性违规清零”包括格式、命名、空异常、硬编码之类能靠工具检查出来的问题这套机制完全能拦下来。第二层是“语义违规尽可能少”这需要人工评审继续把关并像前面说的那样把人工修正不断反馈回规则库。两层配合起来AI Agent 才能真正从一个“会写代码的玩具”变成一个“懂规矩的协作者”。我个人在实际操练中的体会是后一种目标永远比前一种难但它值得做——把这些带着业务上下文的反例沉淀到规则库里哪怕每个月只新增两三条半年后你手下的 Agent 对团队规范的“理解力”也会明显上一个台阶。