1. 为什么给 Coding Agent 立规矩比选模型更重要
很多人上手 Coding Agent 的第一反应是纠结模型选型——到底用哪个 CLI、哪个后端模型更聪明。我一开始也是这个思路,折腾了小半个月,换了好几个组合,最后发现真正决定日常体验的,根本不是模型本身,而是你有没有给它立好规矩。
这个结论听起来有点反直觉,但只要你真正把 Coding Agent 用进日常开发流程,就会立刻明白。模型再强,如果每次都要你从头解释项目结构、代码规范、测试命令、提交格式,那它本质上只是一个"更聪明的补全工具",而不是一个能替你干活的协作者。反过来,一个中等能力的模型,只要上下文喂得准、边界划得清、约束写得死,产出质量往往比"裸奔"的强模型更稳定。
我踩过的典型坑是这样的:早期我直接开一个 CLI,扔一句"帮我加个接口",它就开始自由发挥——文件放错目录、命名风格和项目不一致、测试没跑、顺手改了两个不相关的文件。你还不能说它错,因为它确实"完成了任务",只是完成的方式和你的项目格格不入。问题不在模型,在于我从来没告诉过它这个项目的规矩是什么。
所以这篇内容我想聊的不是"哪个 CLI 最好用",而是一套我自己反复打磨、现在团队里也在用的六层治理架构。它的目标很朴素:让 Coding Agent 从"随机发挥的实习生"变成"懂规矩的靠谱同事"。这套架构不绑定具体工具,无论你用的是哪家的命令行 Agent,思路都能直接迁移。适合已经在用或准备用 Coding Agent 的开发者,尤其是那些"用了几次觉得不靠谱就放弃了"的人——大概率不是工具的问题,是规矩没立。
下面我按六个层次拆开讲,从最基础的上下文约定,到最外层的自动化钩子,一层层往上搭。每一层我都会说清楚:它解决什么问题、为什么这么设计、具体怎么落地、以及我在实操中踩过的坑。
2. 第一层:用 AGENTS.md 把项目规矩写成"员工手册"
2.1 AGENTS.md 到底该写什么
治理架构的地基是上下文约定文件,业界现在比较通用的叫法是AGENTS.md(有些工具里叫context.md或类似名字,本质一样)。你可以把它理解成给 Agent 看的"员工手册"——它每次开工前都会读一遍,知道这个项目是什么、该怎么干活。
我见过太多人把这个文件写成一句"这是一个 React 项目",然后抱怨 Agent 不懂事。这就好比你招了个新人,只告诉他"我们是个公司",然后指望他直接上手核心业务。AGENTS.md的信息密度直接决定了 Agent 的输出质量,我的经验是至少覆盖这几块:
- 项目定位与技术栈:一句话说清项目干什么,主要语言、框架、运行时版本。版本一定要写死,比如"Node 20.x,pnpm 管理依赖",否则 Agent 可能给你装个不兼容的包。
- 目录结构与职责边界:哪些目录放业务代码、哪些放工具函数、哪些是自动生成的不要动。这一条能挡掉大量"文件放错地方"的问题。
- 编码规范:命名风格、导入顺序、是否允许默认导出、注释语言。别嫌琐碎,Agent 最擅长的就是严格执行明文规则。
- 常用命令:安装、启动、测试、构建、lint 的准确命令。这是被严重低估的一块,后面第三层还会展开。
- 禁区清单:哪些文件绝对不能改、哪些操作必须先问、哪些依赖不许引入。
我自己的AGENTS.md大概 80 到 150 行,控制在 Agent 能完整读进上下文又不至于淹没重点的范围内。太短没约束力,太长反而稀释了关键信息。
2.2 为什么"写死"比"描述"更有效
这里有个反直觉的经验:给 Agent 的规矩要尽量写成可判定的硬规则,而不是模糊的描述。
举个例子,"代码要写得清晰"这种话等于没说,Agent 无法判定什么叫清晰。但"函数超过 40 行必须拆分""禁止使用 any 类型""所有导出函数必须有 JSDoc"就是可判定的——Agent 能逐条对照检查,你也能在 review 时逐条验收。
我在早期版本里写过"尽量保持代码风格一致",结果 Agent 每次风格都不一样,因为它根本不知道"一致"的基准是什么。后来我改成"参考src/utils/format.ts的风格",它立刻就稳了。给参照物,别给形容词,这是写AGENTS.md最核心的一条心法。
2.3 一个可直接抄的 AGENTS.md 骨架
下面是我现在项目里用的骨架,你可以按自己项目改:
# 项目约定 ## 项目概述 - 用途:内部数据看板,前后端同仓 - 技术栈:TypeScript 5.x + React 18 + Vite,后端 Node 20 + Fastify - 包管理:pnpm,禁止使用 npm/yarn ## 目录职责 - src/components:纯 UI 组件,不含业务逻辑 - src/features:按功能模块划分的业务代码 - src/lib:通用工具,改动需谨慎 - generated/:自动生成,禁止手动修改 ## 编码规范 - 命名:组件 PascalCase,函数 camelCase,常量 UPPER_SNAKE - 禁止默认导出,统一具名导出 - 禁止 any,必要时用 unknown + 类型守卫 - 注释用中文,仅解释"为什么",不解释"是什么" ## 常用命令 - 安装:pnpm install - 开发:pnpm dev - 测试:pnpm test(改完必须跑) - 类型检查:pnpm typecheck - 格式化:pnpm lint --fix ## 禁区 - 不修改 generated/ 下任何文件 - 不新增依赖,需要时先说明理由 - 不改动 .env 与 CI 配置这份文件我迭代了七八版,每加一条都是因为踩过一次坑。比如"禁止默认导出"这条,就是因为 Agent 混用两种导出风格导致 import 报错;"改完必须跑测试"这条,是因为它曾经改完直接说"完成了",结果测试全红。
提示:
AGENTS.md不是写完就完事,它应该跟着项目一起演进。每次 Agent 犯了新错误,先别急着骂它,想想是不是规矩里没写清楚,补上就行。
3. 第二层:用上下文分层喂料,别把整个仓库塞进去
3.1 全量塞上下文的代价
很多人对 Coding Agent 有个误解:以为把整个项目都塞给它,它就能"理解全局"。实测下来这是灾难。上下文窗口是有限资源,塞得越满,关键信息越容易被淹没,Agent 反而抓不住重点。而且大仓库动辄几万行,全量喂进去既慢又贵,还容易触发各种截断。
我的做法是分层喂料:把上下文按"永远需要""按需加载""临时提供"三档管理。
- 永远需要:
AGENTS.md这类全局约定,每次必带。 - 按需加载:具体模块的说明文档,只在动到那个模块时才引入。
- 临时提供:当前任务相关的几个文件,由 Agent 自己按需读取。
关键在于第二档。我会在每个核心模块目录下放一个简短的README.md或CONTEXT.md,说明这个模块的职责、对外接口、注意事项。Agent 在动这个目录时,会自然读到它。这比把所有模块说明堆在一个巨型文件里有效得多。
3.2 让 Agent 自己"按需取书"
更进阶的做法是:不主动喂,而是告诉 Agent 去哪里找。在AGENTS.md里写清楚"模块说明在各目录的 CONTEXT.md 中,动手前先读对应文件",然后依赖 Agent 的自主读取能力。
这就像给新人一个文档库的索引,而不是把整个文档库打印出来塞他手里。他需要哪块就翻哪块,效率高得多。我实测下来,这种方式下 Agent 对模块边界的理解明显更准,越界改动少了很多。
3.3 上下文污染的排查经验
有个坑我踩得很深:上下文污染。有一次 Agent 反复在一个已经废弃的旧接口上改代码,我查了半天才发现,是因为仓库里还留着一份过时的文档,Agent 读到后把它当成了当前规范。
从那以后我养成了一个习惯:定期清理仓库里的"僵尸文档"。凡是和当前代码不符的说明、注释、示例,要么更新要么删掉。对 Agent 来说,它无法判断哪份文档是新的哪份是旧的,你留着它就可能被误读。这一点在多人协作的项目里尤其重要,因为文档腐烂是常态。
注意:上下文治理不只是"加什么",更是"减什么"。一个干净、无歧义的仓库,对 Agent 的价值不亚于一份详尽的规范。
4. 第三层:把测试和校验命令变成 Agent 的"验收标准"
4.1 为什么命令比描述更能约束行为
这一层是我认为整套架构里性价比最高的一环。核心思路很简单:把项目的测试、类型检查、lint 命令明确写进约定,并要求 Agent 每次改完必须自己跑一遍。
为什么这招管用?因为命令的输出是客观的、可判定的。Agent 说"我改好了"没有意义,但pnpm test全绿就是硬证据。你把验收标准从"主观描述"变成"客观命令",Agent 的行为立刻就有了锚点。
我在AGENTS.md里专门有一段"完成定义"(Definition of Done),写清楚什么才算真正完成:
## 完成定义 一个任务只有在以下全部满足时才算完成: 1. pnpm typecheck 无错误 2. pnpm test 全部通过 3. pnpm lint 无警告 4. 新增逻辑有对应测试 5. 变更说明写清楚改了什么、为什么自从加了这段,Agent"假装完成"的情况几乎消失了。因为它知道,不跑命令就没法交差。
4.2 测试命令要"快、准、可复现"
这里有个实操细节:给 Agent 用的测试命令必须足够快。如果你让它每次改完跑一个要五分钟的全量测试,它要么偷懒跳过,要么你等得抓狂。
我的做法是准备两套命令:
| 场景 | 命令 | 耗时 | 用途 |
|---|---|---|---|
| 快速反馈 | pnpm test:unit --changed | 秒级 | Agent 改完立即自检 |
| 完整验收 | pnpm test | 分钟级 | 提交前或 CI 跑 |
在AGENTS.md里明确告诉 Agent:日常改动跑快速命令,准备提交时跑完整命令。这样既保证了反馈速度,又不牺牲最终质量。
4.3 让失败信息"可读"
还有一个容易被忽略的点:测试失败时的报错信息要足够清晰,因为这是 Agent 自我修复的主要依据。如果报错是一堆堆栈没有上下文,Agent 很难定位问题。
我会在测试里加一些辅助断言信息,比如expect(result, '用户名为空时应返回 400').toBe(400)。这种带说明的断言,Agent 读起来一目了然,修复准确率明显提升。这算是给"人"和"Agent"双重优化的写法,一举两得。
5. 第四层:用 Subagents 做任务分工,别让一个 Agent 干所有事
5.1 单 Agent 的"注意力涣散"问题
当任务变复杂,单个 Agent 容易"注意力涣散"——它既要理解需求,又要写代码,又要跑测试,又要写文档,结果每样都做得马马虎虎。这跟人一样,一个人同时干五件事,质量必然下降。
Subagents(子代理)的思路就是把任务拆开,每个子代理专注一件事。比如一个负责"探索代码库、定位相关文件",一个负责"写实现",一个负责"写测试",一个负责"review 改动"。每个子代理的上下文更聚焦,输出质量自然更高。
5.2 怎么划分 Subagent 的职责
划分的核心原则是按"关注点"拆,而不是按"文件"拆。我常用的几个角色:
- 探索者:只读不写,负责在动手前摸清相关代码、依赖关系、潜在影响面。它的产出是一份"现状报告",供后续使用。
- 实现者:基于探索者的报告写代码,专注逻辑正确性。
- 测试者:为改动补测试,专注边界和异常。
- 审查者:以"挑刺"为目标 review 前面的产出,专门找问题。
这套分工的好处是每个角色的"成功标准"都很清晰。探索者的成功是"信息准确完整",实现者的成功是"逻辑正确",测试者的成功是"覆盖到位",审查者的成功是"找出问题"。目标清晰,行为就稳定。
5.3 子代理之间的"交接"是关键
Subagent 架构最容易出问题的地方是交接。如果探索者的报告写得含糊,实现者就会跑偏;如果实现者不说明改了什么,审查者就无从下手。
我的经验是:强制每个子代理产出结构化的交接物。探索者必须输出"相关文件清单 + 关键函数说明 + 潜在风险点";实现者必须输出"改动文件清单 + 改动理由 + 未决问题"。这些交接物既是下一环的输入,也是你事后 review 的依据。
提示:Subagent 不是越多越好。我一般控制在 3 到 4 个角色,再多协调成本就超过收益了。任务简单时,一个 Agent 加清晰的规矩反而更快。
6. 第五层:用 Hooks 把"事后检查"变成"事前拦截"
6.1 Hooks 解决的是"信任"问题
前面几层都是"约定"和"分工",本质上是靠 Agent 自觉。但现实是,Agent 再听话也可能犯错,尤其是涉及危险操作时——比如误删文件、误改配置、提交敏感信息。
Hooks(钩子)就是用来兜底的。它是在 Agent 执行特定动作前后自动触发的脚本,可以拦截、校验、甚至阻止某些操作。这一层解决的是"信任"问题:你不需要完全相信 Agent,因为关键节点有硬性拦截。
6.2 我实际配置的几个关键 Hook
我目前用得最多的几个 Hook:
- 提交前 Hook:在 Agent 执行 git 提交前,自动跑 lint 和类型检查,不通过就阻止提交。这挡住了大量"带病提交"。
- 文件写入 Hook:监控对敏感目录(如配置、CI 文件)的写入,触发时要求二次确认。
- 命令执行 Hook:拦截危险命令模式,比如递归删除、强制推送等,直接阻断。
- 格式化 Hook:文件写入后自动跑格式化,保证风格统一,省得 Agent 自己纠结格式。
这些 Hook 的价值在于把规则从"建议"升级成"强制"。约定是软的,Hook 是硬的。两者配合,才能既灵活又安全。
6.3 Hook 设计的一条铁律:快、静、准
Hook 有个大坑:如果它太慢或太吵,就会变成负担。我早期配了个每次写入都跑全量测试的 Hook,结果每次改文件都要等半分钟,体验极差,最后只能关掉。
后来我总结出 Hook 设计的三条原则:
- 快:单个 Hook 执行控制在秒级,重活交给专门的命令,别塞进 Hook。
- 静:只在真正需要时输出信息,别每次都刷屏。
- 准:拦截规则要精确,宁可少拦也别误伤,误报多了你会想直接关掉它。
7. 第六层:CLI 工作流与人工把关的边界
7.1 CLI 是入口,不是全部
最外层是工作流本身。无论你用哪个命令行 Agent,它都只是整个流程的入口。真正决定效率的,是你怎么组织"人机协作"的节奏。
我的日常节奏是这样的:先用探索型任务让 Agent 摸清现状,我确认方向没问题;再让它实现,实现过程中它自己跑快速测试;完成后我 review 关键改动,跑完整测试;最后提交,提交前 Hook 自动校验。整个流程里,Agent 干了大部分体力活,我负责方向和验收。
7.2 哪些环节必须人工把关
有些环节我坚持人工介入,绝不放手:
- 架构决策:涉及模块划分、接口设计的改动,必须我先定方向。
- 依赖引入:新增任何依赖都要我确认,防止供应链风险。
- 数据相关操作:涉及数据库迁移、数据删除的,必须人工复核。
- 最终提交:提交信息、提交范围由我确认,不让 Agent 自作主张。
这些环节的共同点是影响面大、不可逆。Agent 擅长的是可逆的、局部的、有明确验收标准的活,把这些交给它,把不可逆的决策留给自己,这是人机协作的基本分工。
7.3 六层架构的落地顺序建议
如果你现在想从零搭这套架构,别想着一次全上。我的建议顺序是:
- 先写
AGENTS.md,这是地基,投入产出比最高。 - 再把测试和校验命令写进"完成定义",让 Agent 有验收标准。
- 然后做上下文分层,清理僵尸文档。
- 任务复杂了再引入 Subagents。
- 最后按需加 Hooks,从提交前校验开始。
这个顺序的逻辑是从软约束到硬约束、从简单到复杂。每加一层,你都能立刻感受到体验的提升,而不是一上来就被复杂的配置劝退。
8. 我在实际落地中踩过的几个坑
聊完架构,说几个具体的坑,都是真金白银换来的。
第一个坑:规矩写太多,Agent 反而记不住。我一度把AGENTS.md写到三百多行,结果 Agent 开始忽略后面的内容。后来砍到一百行左右,只留最关键的,效果反而更好。规矩要精,不要多。
第二个坑:Hook 误伤导致流程卡死。有次我配了个拦截规则,结果把正常的文件写入也拦了,Agent 直接卡住不动。排查半天才发现是正则写得太宽。Hook 上线前一定要在测试环境验证,别直接上生产。
第三个坑:Subagent 交接信息丢失。早期我没强制结构化交接,探索者的结论传到实现者那里就变味了。后来强制每个子代理输出固定格式的交接物,问题才解决。交接物要有固定 schema,不能靠自然语言自由发挥。
第四个坑:过度依赖 Agent 导致自己不看代码。有一阵我完全放手,结果积累了一堆"能跑但很丑"的代码,回头重构花的时间比省下的还多。Agent 是加速器,不是替代品,关键代码还是要自己过一遍。
第五个坑:忘了更新规矩。项目演进后,AGENTS.md里的命令过时了,Agent 照着跑一直失败。规矩文件要纳入日常维护,改项目时顺手更新它,别让它腐烂。
9. 关于这套架构,我最后想说的几句实在话
这套六层治理架构不是银弹,它解决的是"让 Coding Agent 稳定产出"这个问题,而不是"让 Agent 无所不能"。它的核心思想其实很朴素:把模糊的期望变成明确的规则,把主观的判断变成客观的验收,把不可逆的决策留给人。
我用了大半年,最大的感受是:Agent 的能力上限取决于模型,但它的产出下限取决于你的治理。模型再强,没有规矩就是一匹脱缰的野马;模型一般,规矩到位也能稳定干活。对绝大多数日常开发场景来说,下限比上限重要得多。
如果你现在只打算做一件事,那就先把AGENTS.md写好,把测试命令写进完成定义。这两件事加起来可能就花你一个小时,但带来的体验提升是立竿见影的。剩下的几层,等你真正遇到对应的问题时再补,完全来得及。
工具会一直变,今天流行的 CLI 明天可能就换了,但"立规矩"这件事的思路是不变的。把这套思路内化,无论换什么工具,你都能快速搭起一套靠谱的工作流。这比追任何一个具体工具都值。