拆散巨型指令文件:Learn Harness Engineering 第 4 讲「AGENTS.md 越写越长、Agent 反而越用越差」的根因与拆分方案
2026/9/23 2:51:57 网站建设 项目流程

【免费下载链接】learn-harness-engineering

Harness engineering beginner tutorial, from 0 to 1

项目地址:https://gitcode.com/gh_mirrors/le/learn-harness-engineering
点击查看免费下载

导读:本讲聚焦 AI Agent 工程化中最常见的反模式——「巨型指令文件」(giant instruction file)。当AGENTS.md从 50 行膨胀到 600 行,Agent 的上下文预算被无关指令吞噬、关键安全约束被埋在文件中部而失效。你将掌握指令信噪比(SNR)、Lost in the Middle 效应、渐进式披露(Reveal on Demand)等核心概念,并学会用「50–200 行入口文件 + 按主题拆分的话题文档」架构重构指令体系。文中全部方案均在 learn-harness-engineering 仓库中有可直接运行或直接对照的示例代码与真实项目文件。

一、问题场景:你的指令文件正在“膨胀式失败”

假设你已经认真对待了 Harness 工程——创建了AGENTS.md,并把能想到的每一条规则、约束、经验教训都塞了进去。一个月后文件膨胀到 300 行,两个月 450 行,三个月 600 行。然后你发现 Agent 的表现反而在变差

  • 修一个简单的 bug,Agent 却烧掉大量上下文去处理无关的部署指令;
  • 一条写在第 300 行的安全硬约束(例如「所有数据库查询必须使用参数化查询」)被直接无视;
  • 三条互相矛盾的代码风格规则,导致 Agent 每次随机挑一条执行。

这就是「巨型指令文件陷阱」:每条指令单独看都有用,于是你全塞进去;结果为了找到某一条规则,Agent 必须翻遍整个文件。你写了 600 行,但对当前任务真正相关的可能只有三分之一。

根部的恶性循环

最常见的恶性循环是:

  1. Agent 犯了某个错误 → 你决定「加一条规则防止再犯」;
  2. 把规则加进AGENTS.md,短期有效;
  3. Agent 又犯了另一个错误 → 再加一条规则;
  4. 循环往复,直到文件失控膨胀。

「出问题就加规则」是再自然不过的反应,但累积效应是灾难性的。下面逐一拆解它到底错在哪里。

二、为什么单个大文件必然失败:五大失效机制

1. 上下文预算被吃光

Agent 的上下文窗口是有限的。以 200K token 窗口(Claude 的标准配置)为例:一份膨胀的指令文件可能就要消耗 10K–20K token,看似还剩很多余量,但一个复杂任务往往需要读取几十个源文件,工具执行输出同样占用上下文,对话历史还在不断累积。等到 Agent 真正需要理解代码时,预算早已耗尽。

2. Lost in the Middle:信息淹没在长文本中部

「Lost in the Middle」研究(Liu et al., 2023)已经明确证明:LLM 对长文本中部信息的利用效率,显著低于开头和结尾。你的AGENTS.md有 600 行,第 300 行写着「所有数据库查询必须使用参数化查询」——这是一条安全硬约束,但它埋在文件中部,Agent 几乎必然忽略它。

3. 优先级冲突:硬约束与软建议无法区分

文件把三类指令混在一起:

  • 不可妥协的硬约束(如「永远不要使用eval()」);
  • 重要的设计准则(如「优先使用函数式风格」);
  • 具体的历史经验(如「上周修过一个 WebSocket 内存泄漏,注意类似模式」)。

这三类指令的重要性完全不同,但在文件里看起来一模一样。Agent 没有任何可靠信号去区分哪条是红线、哪条只是建议。

4. 维护衰退:文件只增不减

大文件天然难以维护。过时的指令很少被删除——因为删除的后果不确定(「也许别的规则依赖它?」),而新增指令感觉零成本。结果是文件只增长、不收缩,信噪比持续下降。这与软件中的技术债积累是同一个问题。

5. 矛盾累积

不同时期加入的指令开始互相冲突——一条说「使用 TypeScript strict mode」,另一条说「部分遗留文件允许使用any」。Agent 每次随机选一条执行。

三、核心概念速查

概念定义与要点
Instruction Bloat(指令膨胀)指令文件占上下文窗口 10–15% 时,开始挤占代码阅读与任务推理的预算。一份 600 行的AGENTS.md可能消耗 10,000–20,000 token——即 128K 窗口的 8–15%。
Lost in the Middle长文本中部的信息容易被忽略。Liu et al. 2023 年的研究表明,LLM 对长文本中间信息的利用效率显著低于两端。600 行文件里埋在第 300 行的关键约束,被忽略的概率非常高。
Instruction SNR(指令信噪比)文件中与当前任务相关的指令占比。修 bug 时被迫读 50 行部署指令——这就是低 SNR。
Entry File(入口文件)一个简短入口文件,作用是引导 Agent 去读更详细的文档,而不是自己装下一切。50–200 行足够。
Reveal on Demand(按需披露)先给概览信息,需要时再给详细信息。好的 Harness 设计就像好的 UI 设计——不要把全部选项一次性砸给用户。
Can't Tell What Matters(无法判断轻重)当所有指令以相同的格式和位置出现时,Agent 无法区分不可妥协的硬约束与建议性的软准则。

四、指令架构对比:单体文件 vs 拆分布局

原讲义的架构图可用文字还原如下。

单体文件路线

一个巨大的 AGENTS.md └─ 即使是小 bug 修复,也要读完全部部署规则和旧笔记 └─ 关键规则埋在文件中部,极易被漏掉

拆分入口路线

短小的 AGENTS.md(路由器) └─ 只有当本任务需要时,才读取 API / 数据库 / 测试文档 └─ 把更多上下文留给代码阅读与验证

位置效应(针对 600 行单体文件):

  • 顶部(quick start + 硬约束)→ 高召回概率;
  • 中部(第 300 行的安全规则)→ 高概率被稀释或忽略;
  • 底部(明确的收尾检查清单)→ 高召回概率。

五、如何拆分:入口文件 + 话题文档

核心原则

高频信息放在手边,低频信息收进抽屉,永远用不上的别带。

入口文件AGENTS.md:保持 50–200 行

只包含最必要的内容:

  • 项目概览:一两句话讲清这是什么项目;
  • 首次运行命令:如make setup && make test
  • 全局硬约束:不超过 15 条不可妥协的规则;
  • 话题文档链接:一行描述 + 适用条件。

原讲义的示例模板:

# AGENTS.md ## Project Overview Python 3.11 FastAPI backend, PostgreSQL 15 database. ## Quick Start - Install: `make setup` - Test: `make test` - Full verification: `make check` ## Hard Constraints - All APIs must use OAuth 2.0 authentication - All database queries must use SQLAlchemy 2.0 syntax - All PRs must pass pytest + mypy --strict + ruff check ## Topic Docs - API Design Patterns (`docs/api-patterns.md`) — Required reading when adding endpoints - Database Rules (`docs/database-rules.md`) — Required when modifying database operations - Testing Standards (`docs/testing-standards.md`) — Reference when writing tests

话题文档:每个 50–150 行

按主题组织,放在docs/目录或对应模块旁边。Agent 只在需要时读取。可以类比行李箱的收纳袋——内裤一格、洗漱用品一格、充电器一格;找东西时不需要把整个包倒空。

适合直接放进代码的信息

类型定义、接口注释、配置文件中的说明,Agent 读代码时自然会看到,不需要在指令里重复。

每条指令的生命周期管理

每条指令都应记录:

  • 来源(「为什么加这条规则?」);
  • 适用条件(「什么时候需要这条规则?」);
  • 过期条件(「什么情况下可以删除这条规则?」)。

定期审计,删除过时、冗余、矛盾的内容。管理指令要像管理代码依赖一样——未使用的依赖应当移除,否则只会拖慢系统。

位置效应的正确利用

如果某条指令必须留在入口文件里,放在顶部或底部,永远不要放中部。「Lost in the Middle」告诉我们,LLM 对长文本两端信息的利用远好于中部。但更优的做法是把指令移入话题文档,实现按需加载。

行业共识

OpenAI 与 Anthropic 都认可这种拆分方式:OpenAI 认为入口文件应当「简短且路由导向」,Anthropic 认为面向长时运行 Agent 的控制信息应当「简洁且高优先级」。两者的意思相同——不要把一切都塞进单个文件。

六、仓库中的真实示例:本仓库自己就是拆分的范本

精简入口文件示例

讲义配套代码目录提供了可直接对照的极简入口文件:code/AGENTS-short.md,全文只有「Start Here」(读哪些文档、如何启动与校验)和三条 Hard Rules(不改层边界、不标完成不验证、给下个会话留干净状态),约 15 行——远低于 200 行上限,但足以让 Agent 起步。

反模式清单

code/anti-patterns.md 给出了五条反面清单,可作为自查工具:

  • 把全部仓库知识塞进一个文件;
  • 在多个地方重复同一条规则;
  • 编码了没人审计的过时规则;
  • 写出具体到几乎不生效的条件指令;
  • 把长篇工具手册嵌入启动上下文。

可量化的对比模拟

code/split-vs-monolithic.ts 是一个可运行的模拟脚本:它生成一份约 200 行的单体指令文件(Project Overview / Code Style / Testing / Deployment 四个区段各 50 行),再拆成 4 个聚焦文件,然后模拟 Agent 搜索特定规则时各读取了多少行。

# 运行方式(工作目录:仓库根目录) npx tsx docs/en/lectures/lecture-04-why-one-giant-instruction-file-fails/code/split-vs-monolithic.ts

从源码结构看,脚本的核心逻辑是两种搜索策略的对比:

  • searchMonolithic()从文件顶部逐行扫描直到命中规则,最坏情况要读全部 200 行;
  • searchSplit()根据查询所属区段直接定位到对应文件(如03-testing.md),只读那 50 行。

四条模拟查询(返回类型规则、部署窗口规则、集成测试规则、测试文件结构规则)在两种策略下的平均行数差即为「节省」比例。脚本输出的 KEY INSIGHT 一句话点明了结论:单体文件下每次查询都要扫描最多 200 行,拆分后只需读取相关的 50 行文件——上下文占用更少、幻觉更少、执行更快

真实项目中的入口文件:project-02 solution

配套实践项目 Project 02: Agent-Readable Workspace 的解决方案目录中,projects/project-02/solution/AGENTS.md 是一个现实世界里的「路由器」入口文件。它没有堆砌细节,而是:

  • Startup Rules:规定写代码前按顺序完成 5 个动作(读本文件 → 读docs/ARCHITECTURE.md→ 读docs/PRODUCT.md→ 跑npm install && npm run check→ 读feature_list.json);
  • Docs Hierarchy:只用 5 行说明docs/下两个文档各自负责什么,把细节留给话题文档;
  • Electron Layer Boundaries:四个层的职责各用 3–4 行概括,详细约束指向docs/ARCHITECTURE.md
  • Conventions + Definition of Done + Session Handoff:收尾清单与交接约定放在底部(利用位置效应)。

对比项目 01 的入口文件 projects/project-01/solution/AGENTS.md 可以看到演进:project-01 的版本更长、把层边界细节直接写进了入口;project-02 则把细节下推到docs/,入口变得更短、更路由化。从仓库结构看,project-02 的 starter 目录同样保留了简短的 projects/project-02/starter/AGENTS.md,用于对照「薄 workspace」与「厚 workspace」下第二次会话的重新发现成本。

支撑入口文件的话题文档示例可见 projects/project-02/solution/docs/ARCHITECTURE.md:它完整描述了层架构图、preload 暴露的window.knowledgeBase类型化 API、导入流程的 11 步 IPC 调用链与数据存储目录结构——这些内容若全部塞进入口文件,就是典型的膨胀。

此外,仓库根目录的 CLAUDE.md 本身也是同样的拆分实践:项目概览、命令、仓库结构、架构、关键模式各占一小节,共约 60 行,细节全部由「阅读对应目录」的指引替代。

七、真实案例:SaaS 团队的拆分重构

某 SaaS 团队的AGENTS.md从 50 行膨胀到 600 行,混入了技术栈版本、编码标准、历史 bug 修复笔记、API 使用指南、部署流程、团队成员的个人偏好——什么都有,但找到与当前任务相关的部分如同大海捞针。

Agent 表现明显下滑:修简单 bug 时消耗大量上下文处理无关部署指令;第 300 行的安全约束「所有数据库查询必须使用参数化查询」频繁被忽略;三条互相矛盾的代码风格规则导致随机选择。

团队执行了拆分重构:

  1. AGENTS.md精简到 80 行:只保留项目概览、运行命令、15 条全局硬约束;
  2. 创建话题文档:docs/api-patterns.md(120 行)、docs/database-rules.md(60 行)、docs/testing-standards.md(80 行);
  3. 在入口文件中加入话题文档链接;
  4. 历史笔记要么转化为测试用例,要么直接删除。

重构后:同一任务集的成功率从 45% 提升到 72%;安全约束合规率从 60% 提升到 95%——因为规则从文件中部移到了入口文件顶部,不再「Lost in the Middle」。

八、关键要点

  • 「加一条规则」是短期的止痛药、长期的毒药。加任何规则前,先想清楚它是否该进话题文档。
  • 入口文件是路由器,不是百科全书。50–200 行:只放概览、硬约束与链接。
  • 善用 Lost in the Middle 效应:重要信息放顶部或底部,次要内容移入话题文档。
  • 像治理技术债一样治理指令膨胀:定期审计,每条指令都要有来源、适用条件、过期条件。
  • 拆分后 SNR 提升,Agent 把更多上下文预算花在真实任务上,而不是处理无关指令。

九、动手练习

练习 1:SNR 审计。取出你当前的入口指令文件,列出所有指令条目;挑 5 种常见任务类型,逐一标记每条指令是否与该任务相关,计算每种任务的 SNR。对大多数任务都是噪音的指令,应移入话题文档。

练习 2:按需披露重构。如果你有超过 300 行的指令文件,把它拆成:(a) 小于 100 行的入口文件,(b) 3–5 个话题文档。重构前后运行同一组任务(至少 5 个),对比成功率。可参照 docs/en/projects/project-02-agent-readable-workspace/index.md 中 starter 与 solution 的对照实验设计。

练习 3:Lost in the Middle 验证。在一份长指令文件中,分别把一条关键约束放在顶部、中部、底部,每个位置至少运行 5 次同一任务集,观察合规率差异。位置效应的强度可能会让你吃惊。

十、延伸阅读

  • OpenAI 官方文章《Harness Engineering》——入口文件「简短且路由导向」的观点来源;
  • Anthropic 工程博客《Effective Harnesses for Long-Running Agents》——长时运行 Agent 控制信息「简洁且高优先级」的工程实践;
  • 论文《Lost in the Middle: How Language Models Use Long Contexts》(Liu et al., 2023, arXiv 2307.03172)——本文所有位置效应结论的实证出处;
  • HumanLayer 博客《Harness Engineering for Coding Agents》——面向编码 Agent 的 Harness 工程实践;
  • Nielsen Norman Group 的 Progressive Disclosure 研究——「按需披露」设计原则的原始出处(好的 Harness 设计就是好的 UI 设计)。

【免费下载链接】learn-harness-engineering

Harness engineering beginner tutorial, from 0 to 1

项目地址:https://gitcode.com/gh_mirrors/le/learn-harness-engineering
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询