← 全部极客知识库

主流 Agent 入门教程 / CodeBuddy

10. 案例7-让它守规矩

原文备份 · 第 12 / 16 篇 · 查看极客时间原知识库 ↗

本篇目录 · 13 节

来源:CodeBuddy

场景

前面六个案例,你每次都在提示词里重复同样的要求:

  • "提交信息用 Conventional Commits"
  • "改完跑测试"
  • "不要改我没让你改的文件"
  • "金额计算要有测试,边界要测"

说第三遍的时候你就该意识到:这些不该在提示词里说,应该写成规则让它自己记住。

这一章你会带走:一套提交进仓库的项目规范、一个自定义的审查子代理、一个接进来的外部工具。

先分清四样东西

很多人把它们搞混。一句话一个:

东西 是什么 什么时候加载
记忆(CODEBUDDY.md) 项目背景知识 每次都加载
规则(.codebuddy/rules/*.md) 具体的行为约束 按条件触发(或常驻)
子代理 一个有独立上下文的专职角色 你点名或它自动派活时
MCP 外部工具/数据源的接入 需要时调用

记忆回答"这是什么",规则回答"该怎么做",子代理回答"谁来干",MCP 回答"能用什么工具"。

第一步:把规矩写成规则文件

先让它帮你整理:

回顾我们前面几章做过的所有要求和项目约定,
把它们整理成一组规则文件,放在 .codebuddy/rules/ 下。

要求:
1. 一个主题一个文件,不要塞进一个大文件
2. 每条规则必须是可检查的(能判断做没做到),
   不能是"要写好代码"这种没法验证的话
3. 用 frontmatter 标注触发条件:
   - 有些规则要一直生效(比如提交信息格式)
   - 有些只在改特定文件时生效(比如改到 pricing.py 才提醒金额测试)
4. 每条规则给出正反例子

先列一份清单给我看,确认后你再写文件。

它整理的清单大概是这样:

文件 触发条件 内容
commit.md 常驻 提交信息用 Conventional Commits,标题 ≤50 字
testing.md tests/**、**/*pricing* 金额与边界必须有测试,禁止假断言
python-style.md **/*.py 类型注解、禁止裸 except、路径用 pathlib
git-workflow.md 常驻 重构与修 bug 分分支;危险命令先确认
security.md 常驻 禁止把密钥写进代码;禁止读 .env

单个规则文件长这样(frontmatter 的字段名以你当前版本为准,不确定就在会话里问它一句):

---
description: 金额计算相关的改动必须有边界测试
paths: ["**/pricing*.py", "**/models.py", "**/invoice*.py"]
alwaysApply: false
---

# 金额计算改动规范

修改任何涉及金额计算的代码时,必须同时补测试。

## 必须覆盖

- 档位/门槛的边界值(恰好等于、刚好超过、刚好不足)
- 负数、零、空输入
- 浮点精度(断言用 `pytest.approx`,不要直接 `==`)

## 禁止

- `assert result is not None` 这类不验证数值的断言
- 只测正常流程不测异常

## 正例

    assert tiered_price(10000, "basic") == pytest.approx(200.0)

## 反例

    assert tiered_price(10000, "basic") is not None

注意"正反例子"这部分。 抽象的规则它容易理解偏,给个反例它就不会犯。这是写规则最有效的一招。

再看一个常驻规则的写法:

---
description: 提交信息格式
alwaysApply: true
---

# 提交信息规范

格式:`<type>(<scope>): <subject>`

type 只能是:feat / fix / refactor / test / docs / chore / perf / build
subject 用中文或英文都可以,但同一仓库要统一,不超过 50 字,结尾不加句号。

正文(可选)说明"为什么改",不是"改了什么"——改了什么看 diff 就知道。

## 反例

    改了点东西
    fix bug
    Update files

第二步:写一个自定义审查子代理

规则是"它自己记住",子代理是"派一个专职的人去干"。

我们来写一个 code-reviewer:

帮我定义一个子代理 code-reviewer,放在 .codebuddy/agents/code-reviewer.md。

它的职责:改完代码之后做一次独立审查。

要求:
1. 只读,不允许修改任何文件(要在定义里写死它的工具权限)
2. 审查清单:
   - 逻辑正确性(边界、异常、并发)
   - 安全性(注入、越权、敏感信息)
   - 是否符合 .codebuddy/rules/ 里的所有规则
   - 是否有遗漏的测试
   - 与项目既有约定的一致性
3. 输出格式:按 [阻塞] [建议] [可选] 三类,每条标注文件名和行号
4. 每条问题必须给出具体的修改建议,不能只说"这里有问题"
5. 如果没发现问题,就明确说"没发现问题",不要硬凑

定义文件大概是这样:

---
name: code-reviewer
description: 代码改动完成后做独立审查。改完代码、提交前、或需要第二意见时使用。
tools:
  - Read
  - Grep
  - Glob
---

你是这个项目的代码审查者。你只做审查,不修改任何文件。

## 审查清单

1. 逻辑正确性:边界条件、异常处理、并发问题
2. 安全性:注入、越权、敏感信息是否可能被打印或提交
3. 规范符合度:逐条对照 .codebuddy/rules/ 下的规则
4. 测试覆盖:这次改动有没有对应的测试
5. 一致性:命名、错误处理风格是否和既有代码一致

## 输出格式

    [阻塞] 文件路径:行号 —— 问题描述 —— 建议怎么改
    [建议] ...
    [可选] ...

没问题的分类写"无"。不要为了显得有输出而凑问题。

tools 那一栏是关键——只给它只读工具,它就没法改代码。这比在提示词里说"不要改"可靠得多。

用起来:

用 code-reviewer 审查一下我刚才的改动

或者让它自动跑:

以后每次我让你改完代码并且跑通测试之后,
自动用 code-reviewer 子代理再审查一遍,把结果给我。

用 /agents 可以查看和管理所有子代理。

子代理的真正价值是上下文隔离。 它去翻一百个文件找线索,翻完只把结论交给你——你的主上下文不会被那些搜索过程污染。审查、考古、调研这类"要翻很多东西但结论很短"的活,都该派子代理。

第三步:接一个外部工具(MCP)

MCP 是让 CodeBuddy 能调用外部服务的标准协议——数据库、Jira、内部 API、文档系统,都能接进来。

我想让你可以直接查我们项目的数据库(只读)。
帮我:
1. 说明 MCP 配置应该放在哪个文件、什么格式
2. 给出一个只读数据库 MCP server 的配置示例
3. 告诉我怎么验证它真的接上了
4. 提醒我这类配置里哪些东西绝对不能提交进仓库

会话里敲 /mcp 可以看到当前接入了哪些服务和它们的状态。

第 4 点那个提醒很重要:MCP 配置里通常是连接串、token、账号密码。这类东西要么放 settings.local.json(自动被忽略),要么用环境变量引用,绝对不要写进共享的 settings.json。

第四步:配置分层,哪些共享哪些不共享

.codebuddy/
├── settings.json         团队共享:权限规则、允许/禁止的工具   → 提交
├── settings.local.json   个人覆盖:我自己喜欢的输出风格、本地路径 → 不提交
├── rules/                项目规则                              → 提交
├── agents/               自定义子代理                          → 提交
└── CODEBUDDY.md          项目记忆                              → 提交

~/.codebuddy/
├── CODEBUDDY.md          我的个人偏好(所有项目生效)           → 不提交
└── rules/                我的个人规则                          → 不提交

判断标准就一条:这条规矩换个人来还成立吗? 成立就提交,不成立就放 local。

比如"提交信息用 Conventional Commits"是团队约定 → 提交;"我习惯让它回答简短一点"是个人偏好 → 放 local。

检查一下有没有漏网的:

检查 .gitignore 是否正确忽略了 .codebuddy/settings.local.json
和任何含密钥的文件。然后用 git status 确认一遍:
现在待提交的文件里有没有包含密钥、token、本机绝对路径?

踩一次坑:写一堆正确的废话

对比一下两种规则写法。

没用的写法:

---
description: 代码规范
alwaysApply: true
---

# 代码规范

- 要写好代码
- 注意代码质量
- 遵循最佳实践
- 保持代码整洁

这四条它都会"遵守"——因为它本来就觉得自己一直在遵守。这类规则等于没写,还白白占上下文。

有用的写法:

---
description: Python 代码规范
paths: ["**/*.py"]
---

1. 所有公开函数必须有类型注解和 docstring
2. 禁止裸 `except:` 和 `except Exception: pass`
3. 文件路径一律用 `pathlib.Path`,不要字符串拼接
4. 单个函数不超过 50 行,超了就拆
5. 金额计算必须用 Decimal 或明确说明为什么用 float

每条都能一眼判断做没做到。判断不了的规则,就是无效规则。

还有一条经验:规则不要一次写太多。写 30 条规则,它每条都打折扣;写 8 条精准的,它每条都执行到位。先写最痛的那几条,跑一段时间再补。

Git:共享配置提交,个人配置忽略

git add .codebuddy/settings.json .codebuddy/rules .codebuddy/agents CODEBUDDY.md
git commit -m "chore: 建立项目级 AI 协作规范

- rules/:提交信息、测试、Python 风格、安全、git 工作流五条规则
- agents/code-reviewer:只读审查子代理
- settings.json:禁止读取 .env 与执行破坏性命令
- 个人偏好放 settings.local.json,已加入 gitignore"

平台差异:配置目录在哪

环境 用户级配置目录
macOS / Linux ~/.codebuddy/
Windows PowerShell %USERPROFILE%\.codebuddy\(通常是 C:\Users\你\.codebuddy)
WSL2 ~/.codebuddy/(WSL 内部,和 Windows 侧不共享)

WSL 和 Windows 各有一份用户级配置,不互通。项目级配置(.codebuddy/)因为跟着仓库走,两边都能读到——所以团队共享的东西一定要放在项目级,别放用户级。

另外,Windows 上做软链(ln -s)和 Unix 行为不一样。想把个人规则软链到项目里的话,Windows 上要用 mklink 或者直接复制,别指望 ln -s 能正常工作。

本章你多了什么

  • .codebuddy/rules/ 下五条可检查的规则
  • 一个只读的 code-reviewer 子代理
  • 一份权限与工具配置,敏感文件已被挡住
  • 一套"什么该共享、什么该本地"的判断标准

本章新知识点

知识点 说明
规则比提示词可靠 写一次,之后每次都生效
规则要可检查 判断不了的规则等于没写
正反例子 给反例它就不会犯
paths 条件触发 不是所有规则都要常驻,省上下文
子代理的 tools 限制 只给只读工具,没有授予写文件和 Bash 工具
上下文隔离 子代理翻文件的"过程"不占主上下文
配置分层 团队共享 vs 个人偏好

延伸练习

  1. 再加一个 test-writer 子代理,专门负责按规则写测试,并且让它只能用 Write 写 tests/ 下的文件
  2. 写一条规则:改动数据库 schema 时必须同时检查 migrations 目录,看看会发生什么
  3. 把第 9 章那个 PR 审查工作流改成调用 code-reviewer 子代理,对比一下输出质量

常见坑

规则写了很多,但感觉没生效。 检查三件事:frontmatter 语法对不对、文件路径是不是 .codebuddy/rules/、触发条件是不是没匹配上。可以让它自己确认:"列出你当前加载的所有规则"。

规则之间互相冲突。 比如一条说"函数要短",另一条说"不要把逻辑拆太散"。规则多了容易打架,定期让它检查一遍:"读一遍所有规则,找出互相冲突或重复的地方"。

子代理还是改了代码。 检查它的 tools 列表里有没有 Write / Edit / Bash(不带限制的 Bash 等于什么都能干)。

密钥被提交上去了。 每次提交前跑一遍那句检查:"待提交的文件里有没有密钥?"发现已经提交了,立刻改密钥——git 历史里的密钥删不掉,只能作废。


到这里,你已经能让它按你的规矩干活了。但规矩之外还有一层:在它动手之前和之后各插一道卡子,以及把整套做事方法打包成可复用的能力——那是 Plan 模式、子代理、Skills 和 Hooks 的事。

下一章就把这四个讲透,每个都配能直接抄走的配置。

规则验收:分别打开匹配 paths 的 pricing.py 与不匹配的文本文件,检查规则加载情况。子代理只给 Read、Grep、Glob;需要 diff 时由外部先生成后提供。规则和提示词不是系统访问控制,最终仍检查实际工具授权与文件差异。