5 min read
Day 13:AGENTS.md:把项目规则注入 Agent 上下文

上一篇:Approval 与 Sandbox:写入审批和工作区边界
下一篇:Mini Harness Recap:14 天架构复盘
English version: AGENTS.md for AI Coding Agents: Load Project Rules into LLM Context

文章介绍

Day 12 解决了 agent “能不能执行”和“可以影响哪里”的问题。今天处理另一个长期存在的工程问题:agent 如何知道每个项目自己的约定?

同一个模型进入不同代码库时,可能需要遵循完全不同的规则:

  • 使用 npm、pnpm 还是 bun。
  • 修改后运行哪个 typecheck 或 test 命令。
  • 哪些目录是生成代码,不能手动编辑。
  • 应该复用哪些项目内部 API。
  • 提交代码前需要满足哪些检查。

这些信息不适合每次都由用户重新输入。更合理的方式是把它们放进代码库中的 durable project guidance,例如根目录的 AGENTS.md,由 harness 在每次运行开始时自动发现并注入模型上下文。

AGENTS.md project rules loaded into an AI coding agent context

今天要解决什么

今天完成六个交付:

  1. 从 workspace 根目录读取 AGENTS.md
  2. 为规则内容设置字节上限,避免永久挤占 context window。
  3. 把项目规则注入 system prompt。
  4. 用独立的 rules context kind 记录规则来源和 token 占用。
  5. 为 CLI 增加 --workspace,方便在独立项目根目录运行 harness。
  6. 提供不会影响主仓库规则的 Day 13 fixture workspace。

运行演示:

npm run dev -- --workspace demos/day-13/workspace --context-report "load project rules"

它在 Cursor/Codex 里对应哪一层

今天实现的是 Project Guidance / Durable Rules Layer

它位于 context builder 和 model provider 之间:

workspace root
  -> discover AGENTS.md
  -> validate workspace path
  -> read with size limit
  -> add to system context
  -> report rules token usage
  -> model decides

项目规则不是一次性的聊天消息。它们会随着代码库一起版本管理,让团队成员和 coding agent 共享相同的工程约定。

为什么需要项目规则

1. 模型的通用能力不知道本地约定

模型可能知道 TypeScript、React 或 Node.js,但它不知道这个仓库是否要求:

Use npm workspaces.
Never edit generated files.
Run npm run typecheck before completion.
Prefer repository helpers over new dependencies.

这些规则来自项目,而不是来自通用训练知识。

2. README 和 AGENTS.md 职责不同

README 通常面向人类读者,介绍项目用途、安装和使用方式。AGENTS.md 更适合记录 agent 执行任务时需要遵守的约束。

两者可能有重叠,但关注点不同:

文件 主要读者 典型内容
README.md 用户与贡献者 项目介绍、安装、使用
AGENTS.md Coding agent 编辑边界、测试命令、代码规范

3. Rules 不等于 Safety

规则可能写着“不要修改 migrations”,但这仍然是一条模型指导,不是不可绕过的权限边界。

真正的执行路径仍然需要 Day 12 的安全层:

project rules guide behavior
approval authorizes side effects
sandbox limits reachable paths

三者不能互相替代。

设计思路

1. 第一版只读取根目录 AGENTS.md

大型 monorepo 可能需要目录级规则:根目录定义通用约定,子目录覆盖局部规则。

Day 13 先实现最小、可预测的版本:

workspace/AGENTS.md  -> active
workspace/apps/AGENTS.md -> not loaded yet

只支持 root-level guidance 可以避免过早引入规则继承、优先级和冲突合并。

2. 缺失规则不是错误

并不是每个仓库都有 AGENTS.md。加载器在文件不存在时返回空结果:

{
  content: "",
  bytes: 0,
  returnedBytes: 0,
  truncated: false
}

Context builder 会明确记录:

No root AGENTS.md project rules were found.

这样调试时可以区分“没有规则”和“加载器没有运行”。

3. 规则必须有长度上限

项目规则会进入每一次模型调用。如果文件无限增长,它会持续占用 context window,并增加延迟和成本。

Day 13 默认最多读取:

const DEFAULT_MAX_RULE_BYTES = 16_000;

超过上限时返回 truncated: true,并在 system prompt 中标记 (truncated)

4. Rules 作为独立 ContextPart

Day 09 的 Context Explorer 已经支持按 kind 汇总 token。共享类型中也提前定义了:

type ContextKind =
  | "system"
  | "tools"
  | "rules"
  | "files"
  | "conversation"
  | "tool-results";

Day 13 把规则作为独立 part,而不是只把文本拼进 system prompt 后失去来源信息。

实现步骤

1. 实现规则加载器

文件:apps/mini-harness/src/rules/loader.ts

加载器返回内容、来源和截断信息:

export type LoadedProjectRules = {
  content: string;
  source?: string;
  bytes: number;
  returnedBytes: number;
  truncated: boolean;
};

读取前复用 Day 12 的 workspace guard:

const rulePath = await resolveWorkspacePath(workspaceRoot, "AGENTS.md");
const buffer = await readOptionalFile(rulePath.absolutePath);

虽然文件名是固定的,这个校验仍然让规则加载与其他 workspace 文件访问保持同一安全边界。

2. 区分文件缺失和真实读取错误

加载器只把 ENOENT 当成“没有规则”:

if (isFileNotFound(error)) {
  return undefined;
}
throw error;

权限错误、I/O 错误不应该静默降级,否则用户会误以为规则已经生效。

3. 注入 Context Builder

文件:apps/mini-harness/src/context/builder.ts

构建上下文时并行概念上包含这些来源:

system instructions
project rules
history summary
tool definitions
selected project snippets
user request

System prompt 中新增:

Project rules:
--- AGENTS.md ---
...repository guidance...

同时增加一个可观测的 part:

{
  label: "Project rules",
  kind: "rules",
  source: projectRules.source ?? "not-found",
  content: projectRulesContext,
}

4. Context Explorer 自动显示规则成本

不需要修改 Context Explorer 的统计逻辑。因为它本来就根据 ContextPart.kind 分组,新增 part 后会自动产生:

rules    ~62 tokens    2.3%    1 part

并在 All parts 中显示:

Project rules  rules  ~62 tokens  source: AGENTS.md

5. 增加 workspace 参数

文件:apps/mini-harness/src/cli.ts

CLI 新增:

--workspace <path>

这个目录同时成为:

  • 文件工具根目录。
  • Git 工具根目录。
  • Patch sandbox 根目录。
  • Context snippets 根目录。
  • Project rules 查找根目录。

因此规则和工具不会使用不同的 workspace 定义。

6. 创建独立 demo workspace

文件:demos/day-13/workspace/AGENTS.md

Demo 规则包括:

- Use TypeScript strict mode for source code.
- Prefer focused patches over whole-file rewrites.
- Run the typecheck command before reporting completion.
- Keep generated files out of source directories.

把 fixture 放在 demos/day-13/workspace,可以验证规则加载,又不会在仓库根目录创建一份会影响整个项目的真实 agent 指令。

Demo

文件:demos/day-13/README.md

运行:

npm run dev -- --workspace demos/day-13/workspace --context-report "load project rules"

Mock provider 会返回:

The root `AGENTS.md` rules were loaded into the system context before model execution.

Context Explorer 的关键输出:

By kind
rules              ~62 tokens     2.3%  1 part

All parts
Project rules      rules          ~62 tokens     source: AGENTS.md

具体 token 数会随着工具定义和规则内容变化,重点是 rules 有独立的来源和预算占比。

当前系统能力变化

Day 13 后,一次运行的完整输入链路变成:

workspace root
  -> AGENTS.md rules
  -> selected project snippets
  -> tool definitions
  -> history + user task
  -> model decision
  -> approval + sandbox
  -> tool execution
  -> transcript + context report

Mini harness 不再只理解代码内容,还能带着项目约定执行任务。

遇到的问题

1. 规则优先级怎么处理

当前实现把根规则放入 system prompt,并明确要求它们不能覆盖更高优先级指令。生产系统还需要定义 system、developer、user、project rules 和目录规则之间的完整优先级。

2. AGENTS.md 是否可信

加载器假设 workspace 是用户选择并信任的代码库。来自未知仓库的规则可能包含 prompt injection,因此真实产品应在打开不可信项目时显示来源,并限制规则能够影响的工具权限。

3. 为什么不用工具临时读取规则

如果依赖模型自己调用 read_file,模型可能忘记读取,也可能在做出第一次决策后才发现规则。

规则属于运行初始化上下文,应该由 harness 确定性加载。

4. 为什么暂不支持嵌套规则

目录级规则需要回答:

  • 根据当前任务还是目标文件选择规则?
  • 多个规则文件如何合并?
  • 子目录规则能否覆盖根规则?
  • 删除或移动文件时使用哪个目录的规则?

这些问题值得单独设计,不适合塞进最小 root loader。

明天做什么

Day 14 将完成 Mini Harness Recap。

我们会串联 14 天的能力,回顾从 context、tools、agent loop 到 patch、approval、rules 和 observability 的完整架构,并给出下一阶段的扩展边界。

Comments

  • Loading comments…

Comments are posted immediately and emailed to the site owner. No account needed.