给 Agent 修一个解析函数的任务,它先安装依赖,再跑全仓构建,构建报错后又花时间修了一个与任务无关的模块。你把“认真验证改动”补进 AGENTS.md,希望下一次更可靠;结果,它只是更认真地重复了这条弯路。

这是一个用于讨论的假设场景,没有对应的本地实验记录。但它指出了一个值得检查的问题:指令是否被遵守,和指令是否改善了任务结果,是两件事。 一条要求可以被完整执行,却只增加工作量;一份文件可以包含许多正确知识,却没有改变本次最关键的决策。

判断项目指令有没有价值,要回到具体任务:没有这条信息时,Agent 会在哪个分叉做错;加入以后,那个错误是否减少;为此付出的搜索、验证和维护成本是否合理。下面围绕“应该怎样验证这次修改”展开,把一条模糊要求改成可检查的候选指令,并给出能在自己仓库执行的对照方法。本文核验公开资料,不宣称已经测出作者仓库的提升比例。

1. 一个真实文件,记录了代码里不容易看见的工作方式

three-evidence-levels

repository-example

AGENTS.md 项目的官方仓库本身也有一份 AGENTS.md。在核对的固定提交中,它要求交互开发使用开发服务器,并明确避免在 Agent 会话里运行生产构建;文件给出的理由涉及 .next 产物和热更新状态。注意,这是一份仓库维护者写给其特定交互流程的要求,不能据此宣布所有 Next.js 项目都不应执行构建。官方仓库指令文件

这个例子有意思的地方,是同一文件的命令表同时列出了开发、检查、测试和生产构建。知道命令存在,不等于知道现在应该调用哪一个。 Agent 即使读到了 package.json,也只能知道脚本做什么,未必知道操作者正在依赖一个持续运行的预览会话。

因此,这条指令补充的是工作条件,而不是另一份命令目录。它可以改变“做完修改后顺手 build 一下”的决定。它也给出了范围:交互开发期间。将范围删掉,改成永久禁止构建,反而会妨碍发布验证;将原因删掉,后续维护者则难以判断切换开发环境后是否还需要保留。

这给检查自己文件提供了一个入口:找出那些只靠当前代码难以确定、却会影响动作选择的事实。例如某条测试会接触外部计费接口,某个目录由生成器维护,某份旧文档对应已经下线的运行环境。这些信息值得评估,但前提是它们仍真实,并且任务有机会碰到。

相反,把目录树重新描述一遍,并不自动获得同样的价值。它可能帮助定位,也可能只是在模型可以直接搜索的地方再放一份副本。是否值得常驻,需要看它有没有缩短寻找正确入口的路径,而不是看摘要写得是否完整。

2. 公开研究没有给“加一个文件”开出通用保证

study-scope

study-design

Gloaguen 等人的研究比较了无上下文文件、自动生成文件,以及开发者原有文件等条件。其 v1 使用 SWE-bench Lite,并构建了含 12 个 Python 仓库、138 个任务的 AGENTbench。结果中,自动生成文件没有带来一致的修复收益;开发者文件也不是所有 Agent 都受益。轨迹分析观察到更广的探索与测试活动。论文 v1,实验与轨迹分析

这份研究提供的关键提醒不是“文件无用”,而是不能用动作增多证明效果改善。它限定在所选仓库、任务、模型和运行方式;本文不把其中成本变化搬成自己项目的预期,也不把它解释为所有任务的定律。

另一项研究在 3 个仓库、17 个任务上比较无上下文、持续注入和按需读取,得到 288 次有效正确性评估。作者在该设计下没有测到明确的正确性改善,并将所分析失败更多归因于实现能力。其按需资料在部分仓库比原文件更广,比较不完全是同一内容的加载方式变化。Khatri,论文 v1

两项结果都不能替读者回答“我的这条规则该不该留”。一个解析器任务如果失败在边界条件推导,补上测试命令可能让错误更快暴露,却未必让模型有能力修好它。反过来,如果实现本来正确,只是选错了验证入口,精确说明入口就可能解决当下的流程问题。这是不同的失败,不能统一归为 Prompt 不够详细。

由此产生一个更实用的判断:先识别失败属于信息缺口还是实现缺口,再决定是否修改指令。否则,每次失败都往文件里追加一段要求,最后得到的可能只是更长的失败历史。

3. 把“认真测试”改成一个有条件的动作

conditional-rule

回到开头的假设项目。假设它用 Python 维护一个解析模块:src/parser/ 是实现,tests/parser/ 是相应测试;项目已经有可用的依赖环境,CI 另有完整检查。这些路径是教学设定,不是读者可以直接套用的真实仓库路径。

原来的要求只有一句:

修改后认真验证,确保质量。

它没有说验证对象,也没有区分局部修改和公共依赖变化。如果 Agent 把“认真”理解为尽量多运行命令,执行越努力,离维护者的本意可能越远。

可以先写成下面这个待验证版本:

只改 src/parser/ 内实现且未改变公共接口时,
先运行 python -m pytest tests/parser/。
若改动公共接口、依赖配置或被其他模块使用的行为,
按现有 CI 定义扩大验证范围。
失败时保留原始错误,并区分本次改动与已存在的环境问题;
不要为了得到通过结果修改无关模块或跳过失败用例。
完成说明需列出实际执行命令、结果与未覆盖部分。

这里有三个关键决定。第一,局部测试只对明确的变更范围成立;“先运行”并不等于“只需运行”。第二,扩大验证的依据指向现有 CI,避免在自然语言文件里维护另一套可能过期的全量命令。第三,输出要求让读者能核对行为,而不是只接受一句“已验证”。

这段候选仍可能有错。例如解析模块的某个内部函数虽然没有改签名,却改变了下游排序语义;只看目录和公共接口就会低估影响。生产前应由熟悉依赖关系的人修正条件。不能因为文字写得更具体,就把范围判断外包给这几行文本。

还要核实命令本身:解释器是否来自项目环境,测试路径是否存在,前置服务是否可用,CI 是否真的覆盖了所说的行为。如果入口已经封装在维护中的脚本里,直接引用脚本通常比把细节抄进指令更省维护。指令负责告诉 Agent 什么时候选它,脚本负责准确执行它。

4. 先确认信息到达,再观察它改变了什么

如果新指令没有效果,第一步并不是继续加强语气。应先确认当前运行环境实际加载了哪份文件;仓库里有文件,不能证明本轮会话读到了它。

Claude Code 的官方文档把 CLAUDE.md 定位为上下文中的行为指导,而非强制配置,并提供查看实际加载情况的排障入口。这里借用的是一个产品明确区分的两类证据:加载记录证明信息进入了会话,执行记录才证明具体动作发生。其他工具应使用各自可用的记录,不能假定同名文件拥有相同语义。Claude Code memory 文档

对上面的候选指令,检查点应该落在可观察动作上:是否从项目环境运行对应测试,是否因为公共行为变化扩大验证,遇到环境故障是否保留错误,是否修改了任务之外的模块。让 Agent 复述规则,最多证明它能够回答问题,不能代替这些记录。

也别把“遵循了命令”直接计为成功。测试命令跑完,但修复没覆盖原始缺陷,是实现失败;修复通过正确性检查,却跳过团队要求的集成验证,是交付仍有缺口。两者都值得记录,但需要不同处理:前者可能需要更好的任务分解或实现能力,后者才可能直接受指令措辞和加载方式影响。

如果必须限制某种外部操作,应在权限或执行环境中实施限制,再用指令解释允许路径。自然语言提示可以帮助选择,不能凭自身撤销一个进程已经拥有的能力。这一点不需要靠堆叠更多“必须”“绝对禁止”来补救。

5. 用删除对照决定是否保留这条要求

single-rule-ablation

要在自己的仓库评估,最容易犯的错是拿昨天无规则的失败,和今天加规则的成功相比。期间模型、任务描述、代码状态甚至网络环境都可能变了,不能把差异全部归给指令。

可以从已完成、能在隔离副本复现的任务开始,保留同一初始提交和同一任务描述。设置两个条件:一组保留原有其他指令,去掉刚写的这条候选;另一组只增加这条候选。相比删除所有文件,这更直接回答它自身是否有增量。执行前固定 Agent 与模型标识、预算、权限、依赖和验证方式,保存实际配置而不是只写一个产品名。

每次从新的会话和相同初始状态开始。避免让第一组留下的修复、自动记忆或缓存中的任务答案泄漏给第二组;共享依赖下载缓存可以减少环境噪声,但必须记录并保持条件一致。如果工具不允许关闭某种记忆或无法固定服务端模型,应如实写入限制,不把结果称作严格因果证明。

评估用例应覆盖候选规则真正会影响的情况:一个只改解析实现的任务,一个改变下游行为的任务,以及一个会遇到已知环境错误的任务。第三类不能靠故意破坏生产系统制造;在隔离环境中使用已记录、可还原的故障即可。只挑最容易受益的任务,会把适用性误写成普遍优势。

同一个任务需要重复运行,运行次序可以交错,减少时间段差异的影响。重复次数取决于预算与波动程度;少量运行只适合发现明显问题,不足以宣称稳定提升。正确性应由预先固定的测试和人工检查判断,不能由刚执行任务的 Agent 自己给自己打分。

最后把记录放到同一张表中。下面是空白记录结构,不是已经完成的实验结果:

任务与初始提交候选规则状态加载证据正确性结果指令相关动作时间与工具成本越界或未覆盖项
局部修复 / 待填删除 / 保留待填待填测试入口与范围待填待填
下游行为变化 / 待填删除 / 保留待填待填是否扩大验证待填待填
环境故障 / 待填删除 / 保留待填待填错误保留与处置待填待填

看表时先问正确性和必要约束,再看成本。若两组都能正确完成,但候选组减少无效构建,这是值得保留的流程收益,不能夸成模型变聪明。若候选组只是多跑测试、缺陷没有减少,则要判断这些检查是否属于团队必须承担的质量成本;必须的检查可以保留,但应说明目的,而不是包装成提效。

若遵循率提高、正确性反而下降,优先审查规则是否把范围限制得过窄。若两组没有可辨差异,也不必马上宣布无用:可能任务没有触发条件,或者样本不足。此时应保留不确定结论,重新选择相关任务,而不是换一个更漂亮的成功率口径。

6. 文件应该随着问题消失而缩小

keep-or-revise

一条规则的价值还会随仓库变化而衰减。测试入口已经统一、旧脚本被删除以后,原来用于消歧的说明可能不再必要;流程已由自动化检查可靠执行以后,重复写操作细节也可能只增加同步负担。

维护时可以沿着具体失败记录回查:这条信息当初阻止了什么错误,现在那个错误还能发生吗;其条件是否仍成立;有没有更可靠的脚本或权限机制承担了相同责任。如果答案发生变化,就删除、缩短或改成指向维护中入口的一句话。并非文件越短越好,而是每条常驻信息都应有目前仍成立的使用理由。

回到最初那句“认真验证”:真正需要保存的,并不是对认真程度的期待,而是项目特有的验证选择、扩大范围的条件,以及能证明做过什么的记录。读者最后要带走的是一条可以被删除对照的候选规则,而不是一份越写越长的通用模板。只有把具体错误、具体动作和具体结果连起来,才能判断这份项目指令究竟帮了什么忙。