03 · 项目规则加载
从 AGENTS.md 加载项目级规则,让 agent 自动感知项目的代码规范和目录约定。
为什么需要项目规则
不同的项目有不同的约定:
- 有的项目用 TypeScript strict 模式,有的不用
- 有的项目测试文件放在
test/,有的放在__tests__/ - 有的项目要求 JSDoc 注释,有的不需要
- 有的项目用 pnpm,有的用 npm
如果 agent 不知道这些约定,它就会按"通用方式"操作——可能用 npm 安装依赖(但项目用 pnpm),可能不写注释(但项目要求 JSDoc)。
Claude Code 的做法是读取项目根目录下的 CLAUDE.md 文件——项目维护者可以在里面写任何规则,agent 会在执行任务时参考这些规则。
我们用同样的思路,支持读取 AGENTS.md 文件。
ProjectRulesLoader 实现
在 src/memory/rules.ts 中:
import { readFile } from "node:fs/promises";
import { join } from "node:path";
export class ProjectRulesLoader {
private static readonly RULE_FILES = ["AGENTS.md", ".agents.md"];
async load(workingDir: string): Promise<string | null> {
for (const filename of ProjectRulesLoader.RULE_FILES) {
try {
const filePath = join(workingDir, filename);
const content = await readFile(filePath, "utf-8");
if (content.trim().length > 0) {
return content.trim();
}
} catch {
continue;
}
}
return null;
}
}设计要点:
两个候选文件名。 AGENTS.md 是主文件,.agents.md 是隐藏文件形式的替代。有些项目维护者不想让规则文件太显眼,就可以用点文件。只加载找到的第一个,不做合并。
失败时静默返回 null。 文件不存在、权限不足、编码错误——任何情况都不应该让 agent 崩溃。没有规则文件,agent 就用默认行为。
空白文件等于没有文件。 content.trim().length > 0 确保空白文件被跳过。
规则加载的时机
规则在 agent 启动时加载一次,在整个会话期间保持不变。这是在 main.ts 中做的:
const rulesLoader = new ProjectRulesLoader();
const projectRules = await rulesLoader.load(workingDir);
if (projectRules) {
console.log("已加载项目规则: AGENTS.md\n");
}为什么不在每次 runAgent 调用时重新加载?两个原因:
- 性能。 读文件是 I/O 操作,没有必要每次都读同一个文件。
- 一致性。 如果规则在会话中途变了(比如用户在另一个终端编辑了 AGENTS.md),每次重新加载可能导致 agent 行为不一致。
注入系统提示词
项目规则通过 RunAgentOptions.projectRules 传入 agent 循环,然后在构建系统提示词时注入:
const systemParts: string[] = [
"你是一个代码仓库助手...",
// ... 工具列表、工作方式、行为准则
];
if (options?.projectRules) {
systemParts.push(
"",
"## 项目规则",
"",
"以下是从项目 AGENTS.md 文件加载的规则,请遵守:",
options.projectRules,
);
}
if (contextText) {
systemParts.push("", contextText);
}注入顺序很重要:项目规则在行为准则之后、工作目录之前。 这样系统提示词的结构是:
- 角色定位
- 工具列表
- 工作方式
- 行为准则
- 项目规则(如果有)
- 会话上下文(如果有)
- 工作目录
项目规则和会话上下文是可选的补充信息,放在核心指令之后。模型会先看到"我是谁、能做什么、该怎么做",然后才看到"这个项目有什么特殊要求"。
举个例子
假设项目根目录有一个 AGENTS.md:
# 项目规则
- 使用 pnpm,不要用 npm 或 yarn
- 所有代码使用 ESM 模块格式(import/export)
- 测试文件放在 test/ 目录,使用 vitest 框架
- 注释使用 JSDoc 风格加载后,agent 的系统提示词会多出这一段:
## 项目规则
以下是从项目 AGENTS.md 文件加载的规则,请遵守:
# 项目规则
- 使用 pnpm,不要用 npm 或 yarn
- 所有代码使用 ESM 模块格式(import/export)
- 测试文件放在 test/ 目录,使用 vitest 框架
- 注释使用 JSDoc 风格模型看到这段规则后,在执行任务时会遵守这些约定——比如执行命令时用 pnpm 而不是 npm,创建测试文件时放在 test/ 目录。
测试覆盖
ProjectRulesLoader 的测试使用临时目录来模拟文件系统:
it("加载 AGENTS.md 文件", async () => {
await writeFile(join(testDir, "AGENTS.md"), "# 规则\n使用 TypeScript");
const rules = await loader.load(testDir);
expect(rules).toBe("# 规则\n使用 TypeScript");
});测试覆盖了:正常加载、.agents.md 替代文件、优先级、无文件时返回 null、空白文件跳过等场景。完整的测试在 test/memory/rules.test.ts 中。
登录以继续阅读
解锁完整文档、代码示例及更多高级功能。