我们团队最近做了一件看起来有点“反直觉”的事:在项目仓库里,新增了一份专门写给AI看的代码规范。你没听错,不是给新人看的开发文档,是给Copilot、Cursor、通义灵码这些AI编程助手看的“行为准则”。这事我踩了不少坑,今天把完整的思路和落地方案整理出来,希望对同样在重度使用AI编程的团队有帮助。
先交代一下背景。我们项目组从去年开始大规模引入AI编程工具,日常开发里大概有40%的代码是AI生成的。一开始大家挺爽,但不到两个月问题就出来了:AI生成的代码风格飘忽不定、命名习惯一天一个样、有时候还会搞出一些看着没问题但根本不符合项目架构的实现。代码评审变成了“AI代码纠错大会”,reviewer怨声载道。我意识到问题不在AI本身,而在于我们没有告诉AI“入乡随俗”的规则。于是,我花了两周时间,在项目里新增了一份专门给AI制定的代码规范文件,效果出奇地好。
1.1 为什么AI写的代码会“水土不服”
要解决问题,得先理解问题是怎么来的。AI编程工具的本质是“根据上下文预测下一段最可能的代码”。它参考的是GitHub上数以亿计的开源项目,这些项目用了五花八门的风格:有的用分号,有的不用;有的喜欢长命名,有的偏好短命名;有的强制函数不超过10行,有的一个函数写300行。
最关键的是,AI在生成代码时,默认会往“统计上最可能”的方向走,而不是“你项目里最合适”的方向。这就像一个新来的同事,见多识广但不懂你的项目规矩。你如果只丢给他一个需求文档,他写出来的东西大概率是“通用风格”而不是“项目风格”。这时候一份清晰的、机器可读的代码规范,就是给AI的“入职手册”。
有意思的是,大模型对自然语言指令的理解能力远超我们想象。只要规范写得足够具体、无歧义,AI是真的会“照着做”的。我把这个发现跟几个同行聊过,他们也反馈:同样一个AI编程工具,在配置了项目级规范之后,生成代码的一次通过率能提升30%到50%。
1.2 传统代码规范为什么对AI“不友好”
我们项目里其实早就有代码规范文档,用的是ESLint配置加一份Word文档。但实践下来发现,这份规范对AI基本没什么约束力。我琢磨了一下,问题出在几个地方。
第一,传统的规范工具链(ESLint、Prettier等)是在代码写完之后做检查的,属于“事后校验”。AI生成代码的时候,它并不知道有这些规则,生成完了再让ESLint去格式化,虽然风格能统一,但架构层面的问题(比如该用策略模式却写了一大堆if-else)是Lint工具管不了的。
第二,人看的规范文档总是充满了“原则上”“尽量”“建议”这类模糊词汇。比如“优先使用组合而非继承”,这句话人懂,但AI会把它理解成概率问题,有时候组合,有时候继承。AI需要的是确定性规则:什么场景,用什么方案,没有例外。
第三,规范和实际代码之间没有建立关联。AI一次只能看有限的上下文(一般在几万token内),它不会主动去翻你的规范文档,除非你把它塞到它能看到的地方。
所以我们需要一份“AI原生”的代码规范:它不是给Lint工具用的配置文件,也不是纯文字说明文档,而是一份经过结构化设计、能够被AI理解和遵循的行为准则。
2.1 把规范翻译成“AI指令”
我做的第一件事,是重新梳理了一份规范,起名叫AGENTS.md。这个命名借鉴了GitHub Copilot识别的约定,放在仓库根目录,很多主流AI编程工具会自动读取它。内容上用中文撰写,因为我们的AI工具配置的就是中文交互,用中文写规则,AI理解的准确率更高。
核心的写法是:给定场景,给定约束,给定输出。不再是“应该怎样”的建议句式,而是“遇到X情况,必须Y”的命令句式。比如传统规范可能写:“请合理处理异常情况”,我改成:
当编写函数时,所有可能抛错的I/O操作必须用try-catch包裹。catch块中不得为空,必须记录日志并返回统一的错误响应结构。
我还加入了大量“禁忌清单”。AI很擅长遵循“不要做哪些事”的指令。比如:
禁止在Component内部直接定义函数并传递给子组件,除非使用useCallback包裹。禁止修改已提交的公共接口方法签名。
这类“负面清单”比“正面要求”更能有效限制AI的行为边界,因为AI的训练数据里包含大量“错误示范”,你必须明确告诉它哪些是项目中的禁忌。
2.2 区分“全局规范”和“模块规范”
代码规范不是一份文件打天下。不同模块、不同技术栈的代码风格差异很大,AI如果只看到一份全局规范,在处理具体任务时还是容易跑偏。我把规范分成了三个层级:
- 全局规范
AGENTS.md:适用于整个项目的通用规则,包括命名风格、Git提交规范、代码结构组织原则、注释语言等。 - 模块规范(如
frontend/AGENTS.md、backend/AGENTS.md):每个技术栈一个文件,比如前端强制使用TypeScript严格模式、禁止使用any、组件文件必须默认导出;后端则规定分层结构、事务边界等。 - 任务指令(Prompt Templates):当你在IDE里让AI做事时,你给的提示词本身就包含规范。我们把这些指令模板沉淀下来,做成团队共享的能力。
关于第三点,多说一句。我见过不少团队在“调教”AI时觉得难,其实问题往往就在于指令太泛。我们沉淀了一套任务指令模板,比如“帮我重构这个函数,要求保持外部行为不变,拆分后每个函数不超过15行,并补充单元测试”。这类模板写多了,AI的表现会稳定很多。
2.3 规范的内容结构设计
具体来说,我给AI制定的这份规范分成七个部分,每一部分都有明确的用意:
- 项目技术栈清单:用列表列出项目使用的语言、框架、核心库和版本。AI知道“底牌”后,不会擅自引入你项目里没有的新依赖,也不会用错误版本的API。
- 目录结构与职责边界:用树状图展示项目目录,并注释每个目录的职责。AI看到
src/modules/user/就知道业务逻辑放这里,不会往src/utils/里塞业务代码。 - 命名与风格强约束:给AI指定变量、函数、类、组件的命名风格。我明确写死了前缀规则,例如
use开头的Hook、is/has开头的布尔变量等。 - 编码模式规定:这是最核心的部分。列出项目中必须使用的设计模式、禁止使用的反模式。比如后端必须用依赖注入,禁止在Controller里写业务逻辑等。
- 错误处理与日志规范:明确统一的日志格式、错误码命名规则、异常处理策略。
- 测试要求:规定核心逻辑必须附带单元测试,测试文件命名规则、断言风格等。
- Git提交约定:AI有时候会自动生成提交信息,需要规范提交信息的格式,比如必须遵循Conventional Commits,类型限定为feat/fix/refactor/docs/test等。
3.1 让AI真正“读到”规范
规范写好了,接下来的问题是:怎么确保AI在生成代码的时候确实“看到”了这些规则?我试过几种方式,踩过一些坑,最后形成了三层保障机制。
第一层是工具级别。像GitHub Copilot这样深度集成在IDE里的工具,会默认读取仓库根目录下的AGENTS.md,把它作为项目上下文的一部分。Cursor的规则配置里还支持添加全局规则和项目规则,你可以把规范文件明确绑定到项目。这一层可以把90%的“AI自然生成”行为纳入规范。
第二层是Prompt级别。当使用Chat模式的AI工具时,第一句指令就把规范关键点加进去。我写了一个统一的兜底提示词:
你是本项目的资深开发者。在回答所有问题前,请先阅读仓库根目录的AGENTS.md和各模块内的AGENTS.md文件,严格遵守其中的代码规范。如果规范与你的惯常做法冲突,以规范为准。
这个提示词成本极低但效果显著,能让AI在处理复杂重构或跨文件修改时保持方向感。
第三层是反馈闭环。在代码评审中,凡是AI生成的代码违反了规范,我会把具体的违规情况、原因、正确写法全部回写进规范文件。比如我发现AI经常把常量定义在组件函数内部导致重复创建,我就在规范里加上一条:
禁止在React组件内部使用const定义不变的对象或数组字面量。此类定义必须提升到模块顶层或使用useMemo。
持续迭代规范本身,让AI越用越“懂”你的项目。这里我强烈建议把规范文件纳入版本管理,像维护代码一样维护规范,这样每个规范的修改都带有历史上下文,团队review起来也方便。
3.2 规范文件的具体写法示例
我把我们的全局规范文件AGENTS.md的核心段落摘出来,给大家做个参考。注意我使用的是规则清单方式,减少自由发挥空间。
# 项目开发规范(AI Agent 必读) ## 技术栈 - 语言:TypeScript(严格模式) - 框架:React 18 + Node.js 20 - 状态管理:Zustand - 样式方案:CSS Modules - HTTP请求:Axios(统一封装在src/api/目录下) ## 目录结构约束 - 禁止在src/utils/index.ts中放业务逻辑 - 页面组件统一存放于src/pages/{pageName}/index.tsx - 所有API请求必须经过src/api/modules/{domain}.ts封装,禁止在组件内直接调用axios ## 命名规范 - 组件文件名:PascalCase.tsx - 自定义Hook:use开头,useCamelCase - 常量:UPPER_SNAKE_CASE - 布尔变量:is/has/should/open等前缀 ## 编码规则 - 禁止使用any,未知类型使用unknown并完成类型收窄 - 函数长度不超过30行(超过必须说明理由) - 禁止在useEffect中直接使用async函数,须使用IIFE包裹 - 禁止在React组件内定义重复的普通函数,优先提升到模块作用域 ## 错误处理 - 所有外部请求必须try-catch,catch块内使用统一错误提示组件 - 错误日志必须包含:时间戳、错误码、请求URL、失败原因 ## 测试要求 - 重要工具函数必须附带单元测试 - 测试文件与被测文件同目录,命名为*.test.ts你可能会说这也不算特别,很多规范文档都这么写。但关键在于,我在文件中用了很多“禁止”句式,而且规定得很具体、可判否。大模型看到“禁止使用any”会比“建议使用unknown”执行得更彻底。你可以把AI想象成一个记忆力极好但缺乏常识的新人,你定得越细,他做得越好。
3.3 配套的评审与自动化检查机制
规范文件本身是“软约束”,它能让AI大概率生成合规代码,但总有“不听话”的时候。为了保证底线,我加了自动化检查兜底,在CI管道里做了三道关:
eslint --fix和prettier --write:处理代码格式层的规范。- 自定义脚本检查目录结构和命名:比如遍历文件命名,检查组件是否放对了目录,API是否走了封装层,用了正则和文件系统扫描。
- AI代码占比标记:这不是强制否决,但在PR描述里会标注“此PR包含AI生成代码”,提醒reviewer重点看AI产出部分。
这三道关卡并不能替代代码评审,但它们把AI生成代码的风险从“可能完全跑偏”降到了“只有业务逻辑需要人工把关”。实际运行了半年,我们的平均评审时长降低了大概40%。
我在这里必须多说一句:自动化检查只能兜住“硬规范”,也就是那些可以被程序判定的规则。架构设计、业务逻辑、边界条件的处理这类“软规范”,还是得靠AI理解力和你的Prompt设计来保证。
4.1 AI“无视”规范怎么办
这是大家最常问的问题:我明明把规范写进AGENTS.md了,AI还是违反。别急着骂AI,先检查几个方面。
第一,AI工具是否真的读取了这个文件。部分IDE的AI插件需要额外配置才能读取根目录的AGENTS.md。像Cursor比较友好,自动加载;但一些JetBrains系插件可能不会读,你需要把规范内容手动粘贴进上下文或使用插件配置。
第二,上下文窗口问题。AI在处理超长对话时,早期输入的内容有可能被截断或“遗忘”。这就是为什么我把规范文件的优先级设计成“任务指令 > 模块规范 > 全局规范”,最关键的限制条件需要在即时Prompt里重复一遍。
第三,规范与AI的默认行为冲突太大。比如AI的训练数据里90%的代码都用let而非const,你规范要求“尽量用const”,但它还是会本能地生成let。怎么办?两条路:一是把规范改成“禁止使用let,除非变量会被重新赋值”,让AI的判断逻辑更明确;二是把类似规则写进代码评审的检查清单,在人工环节兜底。
我实践中发现,绝大多数问题出在“规范写得不够死”上。比如你写“尽量使用函数式组件”,AI就会偶尔生成类组件。改成“统一使用函数式组件,禁止在新增代码中使用类组件”,AI就再也没犯过。
4.2 规范文件的“副作用”管理
给AI定规范,就像给团队定流程,一定会有副作用,这里提醒三个容易踩的坑。
第一个坑是规范膨胀。第一版写了20条规则,用了两周后膨胀到80条。副作用是AI在有限的上下文里抓不住重点,反而可能忽略最核心的规则。我的经验是定期做“减法”,把不痛不痒的规则删掉,只保留那些违反后会造成实质性问题的规范。一般来说,全局规范文件控制在50行以内效果最好。
第二个坑是过度限制导致AI能力退化。AI编程工具最大的价值在于它的创造力和跳跃性思维。如果你把每条路都堵死,AI就变成了一个“翻译机”,遇到问题只会按模板输出,反而失去了使用AI的意义。我对此的策略是:规范只管“底线问题”,开放区域留给AI自由发挥。
第三个坑是团队争论浪费精力。不是每个人都认同某条规则,特别是关于代码风格和架构决策的部分。我的建议是先小范围实验一个月,用数据说话,再决定是否作为团队规范。我们最初的node版本规范就折腾了两轮才最终定下来。
4.3 针对不同AI工具的经验差异
市面上常见的AI编程工具,对规范文件的读取机制还是有差异的,我大致总结一下实测经验。
GitHub Copilot:在IDE里对AGENTS.md的读取相对保守,它对当前打开文件的上下文更敏感。建议你在实际工作时,把相关规范片段直接写在Prompt中或者加在文件头部注释里。我们团队的公共代码文件顶部就有一段注释块,标注了本文件适用的特殊规范。
Cursor:对项目规则的支持最好,可以直接配置项目级Rules,AI在生成时基本都能读到。它的Agent模式(可以自动多文件修改)下,规范执行也比较听话,适合做跨文件重构。
通义灵码:对中文指令的理解比较自然,我们测试下来对规范的理解能力不错,但注意要把规范放在对话的开头部分,不要藏在很深的子目录里。
Codex CLI / Claude Code这类终端型Agent强在可以读取任意文件,所以只要规范文件在仓库里,它就会自动检索。只要文件路径写清楚,问题不大。
需要提醒的是,AI工具更新频率很高,以上经验可能在半年后就变了。我的习惯是每隔一段时间就做一次小测试:故意让AI写一段违反核心规范的代码,看它是否遵守,以此验证当前工具的行为特性。
我还有一个比较实用的技巧:把常见规范分歧写成一个Test Case文件放在代码库里,用写测试的思维来验证AI是否理解规范。比如我写了一个avoid-any.ts,里面故意写了几个使用any的反例,然后在注释里问AI“这段代码违反了哪条规范?应该怎么改?”实测下来,用这种“考考AI”的方式去训练它,比单纯写规范文档更有效。
5.1 规范与现有Lint工具的配合
有人可能会问,为什么有了ESLint和Prettier,还要给AI写规范?这里我花点篇幅聊聊两者的配合关系。
传统的Lint工具是“确定性”的:规则清晰明确,代码必须符合,但它的执行时机是在代码写完以后,所以叫“事后约束”。AI的代码规范是“语义化”的:它约束的是AI生成代码过程中对项目架构、模式选择的判断,是“事中指导”。两者不是替代关系,而是前后衔接的关系。
举个实际例子。ESLint能检查出“变量定义了但未使用”,但它检查不出“这个函数放在utils里违反了业务分层”。后者需要AI在写第一行代码的时候就有概念。反过来,AI再聪明,也不可能记住900条ESLint规则,它只关注规范文件中摘录的高优先级约束。所以ESLint规则要全、要细;AI规范要精、要准。
在配合上,我有两个小建议:
一是ESLint规则的错误提示要保持和AI规范文件用词一致。这样当开发者去修Lint错误时,AI也能从修复记录中学到这个项目的偏好。
二是每当AI规范新增一条核心规则时,尽量在ESLint配置里对应增加一条自动化检查规则。这样AI软约束加上Lint硬检查,双重保障,能最大程度降低“漏网之鱼”。
5.2 规范迭代:把AI当成团队新人来带
这次实践给我最大的感受是,给AI制定代码规范的本质,是建立一种“持续沟通”的机制。AI不是一次性学会规范的,它会根据你的反馈不断调整行为,前提是你得持续“喂”给它正确信息。
我现在的迭代节奏是:每两周评审一次规范文件,每次只改3到5个“点”,改完立刻让AI试跑新规则,观察效果。这个节奏下,规范的演进不会太快导致混乱,也不会太慢导致问题反复发生。
另外我建议规范文件建设初期,一定要让全团队参与Review。因为AI写的代码是团队共有的资产,规范如果只反映某一个人的偏好,其他人使用AI时会觉得别扭。我们团队的规范文件里,React组件写法的规则就是前后端同学一起敲定的,避免AI生成“前端看觉得合理、后端看不懂”的代码。
最后还有一个小心得,是关于“AI规范”和“AI能力”的关系。规范不是限制AI的天花板,反而是提升AI产出效率的助推器。有了明确的规范约束,AI生成的代码更少被驳回,开发者花在“纠错”和“返工”上的时间大幅减少,整体的开发幸福感其实是在上升的。
我个人在这里面的体会是:AI编程工具就像一把锋利的刀,规范就是刀鞘。没有刀鞘的刀容易伤人,但有了刀鞘的刀,才能安全地发挥它最大的作用。如果你也在团队里推AI编程但总觉得效果不稳定,不妨先停下来想想:你有没有给AI一本足够清晰的“项目入乡随俗指南”?如果你还没有,这份规范值得你花两周时间认真写一版。