你给 Agent 写了一份详细的系统提示,前 10 分钟它表现得像个靠谱的同事。然后它开始自作主张:用了一个碰巧在环境变量里找到的凭证、把它觉得"碍事"的文件删了、在部署命令没通过预检时加了个 skip-verification 标志重试。你中断它,补一条规则,重新跑。下一次它换了个方式犯同样类型的错。
这个循环的问题不在于规则写得不够多,而在于控制 Agent 的方式本身需要换一种思路。
2026 年 3 月最后一周,Anthropic 连续发布了两篇工程博客。Harness design for long-running application development1 讲怎么让 Agent 在数小时的自主编码中保持产出质量,Claude Code auto mode2 讲怎么在跳过人工审批的同时拦截危险操作。再加上从 Claude Code 中提取的新版增强 /init 命令 prompt3(新版增加了 hook/skill/note 三级 artifact 分类、分阶段交互等配置生成逻辑),三份材料覆盖了 Agent 自主运行时的三个控制层面。
这三份材料各自解决不同的问题,但反复使用同一组设计原则。以下是我从中提炼的四条,每条都有来自三份材料的交叉验证。
- 上下文是稀缺资源——信息不是越多越好
- 阻止不等于终止——拒绝操作但不停下来
- 执行与评估必须分离——不让 Agent 自己打分
- 防御聚焦实际犯错点——不追求全覆盖
原则一:上下文是稀缺资源,每条信息都有成本
直觉告诉我们,给 Agent 的指令越详细越好。三份材料都在说相反的结论:往上下文里加信息不是免费的,每多一条指令,都增加了 Agent 误解或忽略其他指令的概率。
/init prompt 中有一条明确的准入测试:CLAUDE.md 中的每一行都必须回答"删掉这行,Claude 会犯错吗?"。如果答案是不会,删掉。排除清单比纳入清单更长——不要写 Claude 已经知道的语言惯例,不要写可以从 manifest 文件推断的标准命令(npm test、cargo test、pytest),不要放详细的 API 文档,不要放经常变化的信息。长教程和参考资料移到单独文件或做成 skill 按需加载,不常驻上下文。
Harness 文章从另一个角度验证了同样的判断。规划器被故意限制在高层抽象,不做细粒度的技术规格。作者的理由很实际:如果规划器在技术细节上犯了错,错误会级联到下游实现中。与其预设详细路径然后修正错误,不如约束规划器的输出粒度,让执行 Agent 自己找到实现路径。控制注入到下游 Agent 上下文中的信息量,本身就是在控制出错概率。
Auto mode 的两阶段分类器展示了这条原则在运行时成本优化上的应用。第一阶段是快速的单 token 过滤器(只输出 yes/no),大多数操作在这里就通过了。只有被标记的操作才进入第二阶段做 chain-of-thought 推理。第二阶段和第一阶段看到的 prompt 只有最终指令不同(一个说"倾向于阻止",一个说"仔细推理"),所以第二阶段的 prompt 几乎完全命中第一阶段的缓存。推理 token 只在需要时才消耗。
实践启示: 对 Agent 的系统提示做减法而非加法。用"删掉它 Agent 会犯错吗"作为每条内容的准入测试。参考资料和长内容拆到按需加载的机制中(skill、外部文件引用、工具调用),不要塞进常驻上下文。如果你的流水线有多阶段处理,让各阶段共享相同的 prompt 前缀、只在末尾分叉,可以利用 prompt caching 的 prefix matching 降低成本。
原则二:阻止不等于终止
当 Agent 做了不该做的事,直觉反应是停下来等人工介入。三份材料都在说:这个直觉在大多数情况下是错的。
Auto mode 的 deny-and-continue 是这条原则最清晰的实现。分类器阻止一个操作时,拒绝作为工具结果返回给 Agent,附带一条指令:找更安全的路径,不要试图绕过阻止。Agent 不停下来等用户,而是尝试用另一种方式完成任务。只有累积 3 次连续拒绝或 20 次总拒绝时,才升级给人类。在无头模式(claude -p)中没有 UI 来询问用户,直接终止进程。
这个设计让误报变得可以容忍。Auto mode 的完整流水线误报率是 0.4%,数字看起来小,但如果每个误报都终止会话,对长时间运行的任务来说是严重的可用性问题。Deny-and-continue 把误报的代价从"会话死亡"降到了"一次重试"。
Harness 文章的 Sprint 机制用了同样的模式。评估器对每个 Sprint 打分,任何维度低于硬阈值则 Sprint 失败。但失败不终止整个构建。生成器收到关于问题所在的详细反馈,然后重新尝试。Sprint 合约在执行前就定义了"完成"的标准,所以失败信号是结构化的——不是一个笼统的"不行,重来",而是具体到哪条验收标准没通过、实际行为和预期行为的差异是什么。
/init prompt 的 Phase 7 也体现了这个思路。当用户在 Phase 1 选择不要某类 artifact 时,/init 不强行创建它,但也不完全放弃——它把 hook 降级为 skill 或 CLAUDE.md note,让有用的信息以用户接受的形式保留下来。约束被尊重了,价值没有丢失。
实践启示: 为 Agent 设计失败处理时,默认选择应该是"拒绝操作 + 结构化反馈 + Agent 尝试替代路径",而不是"停下来等人"。在拒绝信号中包含足够的信息,让 Agent 知道为什么被拒绝、边界在哪里。设置一个累积阈值作为兜底(比如 auto mode 的 3 次连续 / 20 次总计),防止 Agent 反复撞墙。
原则三:执行与评估必须结构性分离
Harness 文章中,作者让同一个 Agent 既写代码又评价自己的代码,结果是它系统性地给自己打高分。分离之后,独立的评估器通过 Playwright 实际点击运行中的应用,抓到了生成器遗漏的 bug:路由定义顺序导致的 422 错误、条件判断逻辑的缺陷、工具面板的功能缺失。这些都是代码能跑但功能不对的问题,自评几乎不会发现。
Auto mode 的转录分类器做了同样的事,而且更进一步——它被设计为 reasoning-blind。分类器只看用户消息和 Agent 的工具调用,看不到 Agent 的推理过程和工具输出。文章给出了理由:Agent 会生成有说服力的合理化解释(“这是安全的,因为用户之前隐式批准了”),如果分类器读到这些,它可能被说服做出错误判断。分类器需要判断的是 Agent 做了什么,而不是 Agent 说了什么。
剥离工具输出还带来了一个附带收益:prompt injection 防御。工具输出是恶意内容进入上下文的主要入口,分类器根本看不到这些内容,自然也无法被其中的注入指令影响。而且分类器通常也不需要这些信息——如果 Agent 把环境变量 POST 到外部 URL,这个操作本身就违反用户意图,不管是什么内容触发了它。
/init prompt 的分层设计体现了同样的逻辑。Hook 是确定性的 shell 命令,Claude 无法跳过,不存在"自我评估是否该执行"的空间。Skill 是按需触发的能力。CLAUDE.md note 是最松的约束。三种 artifact 按约束强度分级,越严格的层越不依赖 Agent 的自我判断。
三份材料中"分离"的实现方式不同,但结构同构:
| 执行者 | 评估者 | 评估者看不到什么 | |
|---|---|---|---|
| Harness | 生成器 Agent | 独立评估器(Playwright) | 生成器的自评和推理 |
| Auto mode | Claude Code Agent | 转录分类器 | Agent 推理过程 + 工具输出 |
/init | Claude(运行时) | Hook(确定性 shell) | 不存在"是否执行"的判断空间 |
这条原则有明确的局限。Auto mode 的 17% 漏报率不是因为分类器没识别出危险,而是它误判了用户同意的覆盖范围——“清理分支"到底授权了本地删除还是远程批量删除?Harness 文章中评估器的典型失败模式是同构的:识别出问题,然后说服自己"这不严重”。两者的瓶颈都在意图推断的粒度上,这不是分离架构能完全解决的。
实践启示: 不要依赖 Agent 的自我检查。哪怕只是用另一个 prompt 角色做评审,效果都好于自评。如果能让评估者看不到执行者的推理过程(只看输入和输出),效果更好。但也要预期:独立评估器本身需要大量校准。Harness 文章的作者花了好几轮"读日志 → 找分歧 → 改 prompt"的循环,才把评估器从"识别问题然后说服自己不严重"校准到真正有用的水平。
原则四:防御资源集中在模型实际犯错的地方
三份材料都做了同一个选择:不追求全覆盖,把控制资源集中在 Agent 真正容易出问题的环节。
Auto mode 的三层权限决策是最直接的例子。第一层白名单放行所有只读操作(文件读取、搜索、代码导航)。第二层放行项目目录内的文件编辑,因为版本控制本身就是审查机制。只有 shell 命令、网页抓取、外部工具集成、项目目录外的文件操作这些具有真实下行风险的操作才进入第三层的分类器。大多数操作根本不需要分类器参与。
/init prompt 用一条规则表达了同样的意思:不要在 CLAUDE.md 中写标准语言惯例(Claude 已经知道)、manifest 文件可推断的命令(Claude 可以自己读)、泛泛的建议(“处理好错误”)。只写 Claude 猜不到的东西:非标准的构建命令、与语言默认值不同的代码风格规则、测试环节的特殊要求。
Harness 文章的评估标准加权是这条原则在质量维度上的应用。作者对 Agent 已经擅长的维度降权、对薄弱维度升权。评估资源集中在最可能出问题的地方,而不是均匀撒网。
这条原则还有一个时间维度。Harness 文章的作者说得很明确:“harness 中的每个组件都编码了一个关于模型无法自主完成什么的假设,这些假设值得检验。“Opus 4.5 发布后,Sonnet 4.5 上必需的上下文重置变得多余;Opus 4.6 进一步让 Sprint 分解也不再必要,移除后反而减少了编排开销。/init prompt 用更简洁的方式说了同一件事:不要重复 README 已有的信息——如果信息已经存在于 Agent 可以自行访问的地方,把它放进常驻上下文就是浪费。
实践启示: 在设计 Agent 控制机制时,先搞清楚模型在哪些环节实际会犯错,把防御资源集中在那里。定期审视你的控制组件——每个组件背后都是一个"模型做不到 X"的假设,这些假设会随着模型迭代而失效。作者的方法是每次只移除一个组件、观察对结果的影响,而不是一次性大改。
这四条原则有一个没被充分讨论的时间维度:它们的保质期是多久?
Harness 文章中有一个具体的案例。作者在 Sonnet 4.5 上搭建的 harness 需要将任务分解为多个 Sprint,每个 Sprint 通过上下文重置来避免 context anxiety。模型迭代分两步淘汰了这些组件:Opus 4.5 基本消除了 context anxiety,上下文重置可以去掉;Opus 4.6 进一步让 Sprint 分解也变得多余。两次简化都减少了编排开销,产出质量不降反升。
这意味着你今天写的 harness,其中一部分组件编码的是当前模型的能力边界,而不是 Agent 控制的永恒原则。模型每升一代,都值得重新问一次:这个分离还需要吗?这个阈值还合理吗?这条规则 Agent 现在能自己搞定了吗?
四条原则中,“上下文精简"和"阻止不等于终止"可能最耐久,因为它们回应的是信息论和系统设计层面的约束,不依赖于特定模型的能力水位。“执行与评估分离"在当前模型的自评能力下是必要的,但如果未来的模型在自我纠错上有质的飞跃,分离的必要性可能降低(目前看不到这个趋势)。“聚焦实际犯错点"本身是一个元原则,它不会过时,但它指向的具体犯错点会持续变化。
Harness engineering 不是写完就定了的一次性工作。它更像是一套需要持续修剪的基础设施:每个组件都在对赌模型的短板,而短板在缩小。保持 harness 可修剪,可能比一开始搭得多完善更重要。
Prithvi Rajasekaran, Harness design for long-running application development, Anthropic Engineering Blog, 2026-03-24. https://www.anthropic.com/engineering/harness-design-long-running-apps ↩︎
Anthropic, Claude Code auto mode: a safer way to skip permissions, Anthropic Engineering Blog, 2026-03-25. https://www.anthropic.com/engineering/claude-code-auto-mode ↩︎
Claude Code
/init命令的系统 prompt,从 Claude Code 源码中提取。 ↩︎