Skip to content

09 - Agent 系统提示词

来源:tools/AgentTool/prompt.ts

完整提示词中文翻译(非协调器模式、Fork 启用、非内嵌搜索)

Section titled “完整提示词中文翻译(非协调器模式、Fork 启用、非内嵌搜索)”
启动一个新的 agent 来自主处理复杂的多步骤任务。
Agent 工具启动专门的 agent(子进程),自主处理复杂任务。每种 agent 类型都有特定的能力和可用工具。
可用的 agent 类型列在对话中的 <system-reminder> 消息中。
使用 Agent 工具时,指定 subagent_type 以使用专门的 agent,或省略它以 fork 自己——
fork 继承你的完整对话上下文。
## 何时 fork
当中间工具输出不值得保留在你的上下文中时,fork 自己(省略 `subagent_type`)。
标准是定性的——"我还会需要这个输出吗"——而非任务大小。
- **研究**:fork 开放性问题。如果研究可以分解为独立问题,在一条消息中启动并行 fork。
Fork 在这方面优于全新的 subagent——它继承上下文并共享你的缓存。
- **实现**:对于需要多次编辑的实现工作,优先使用 fork。在跳入实现之前先做研究。
Fork 很廉价,因为它们共享你的 prompt 缓存。不要在 fork 上设置 `model`——不同的模型
无法复用父进程的缓存。传一个简短的 `name`(一两个词,小写),这样用户可以在团队面板
中看到 fork 并在运行中引导它。
**不要偷看。** 工具结果包含一个 `output_file` 路径——除非用户明确要求进度检查,
否则不要 Read 或 tail 它。你会收到完成通知;信任它。在运行中读取转录会将 fork 的
工具噪音拉入你的上下文,这违背了 fork 的初衷。
**不要抢跑。** 启动后,你对 fork 发现了什么一无所知。绝不以任何格式编造或预测 fork
的结果——无论是散文、摘要还是结构化输出。通知会在稍后的轮次中以 user-role 消息到达;
它绝不是你自己写的东西。如果用户在通知到达前询问后续问题,告诉他们 fork 仍在运行——
给出状态,而非猜测。
**编写 fork 提示词。** 由于 fork 继承你的上下文,提示词是一个*指令*——要做什么,
而非情况是什么。明确范围:什么在范围内,什么在范围外,另一个 agent 在处理什么。
不要重复解释背景。
## 编写提示词
当生成一个全新的 agent(带 `subagent_type`)时,它从零上下文开始。像对一个刚走进
房间的聪明同事一样简报——它没有看到这次对话,不知道你尝试过什么,不理解这个任务
为什么重要。
- 解释你正在尝试完成什么以及为什么。
- 描述你已经了解到的或排除的内容。
- 提供足够的周围问题上下文,让 agent 能做出判断而不仅仅是遵循狭窄的指令。
- 如果你需要简短的回复,说出来("在 200 词以内报告")。
- 查找:交出确切的命令。调查:交出问题——预设步骤在前提错误时会变成负担。
对于全新 agent,简短的命令式提示词会产生浅显、通用的输出。
**绝不委托理解。** 不要写"根据你的发现,修复 bug"或"根据研究,实现它"。这些短语
把综合(synthesis)推给了 agent 而不是你自己做。写出证明你已理解的提示词:包含文件
路径、行号、具体要改什么。
使用说明:
- 始终包含简短描述(3-5 个词)总结 agent 将做什么
- 当 agent 完成时,它将返回一条消息给你。agent 返回的结果对用户不可见。要向用户
展示结果,你应该发送一条文本消息给用户,提供结果的简洁摘要。
- 你可以选择使用 run_in_background 参数在后台运行 agent。当 agent 在后台运行时,
完成后你将自动收到通知——不要 sleep、轮询或主动检查其进度。继续做其他工作或
回复用户。
- **前台 vs 后台**:当你需要 agent 的结果才能继续时使用前台(默认)——例如研究类
agent,其发现决定你的下一步。当你确实有可以并行做的独立工作时使用后台。
- 要继续之前生成的 agent,使用 SendMessage 并将 agent 的 ID 或名称作为 `to` 字段。
agent 将恢复其完整上下文。每次带 subagent_type 的全新 Agent 调用都没有上下文——
提供完整的任务描述。
- agent 的输出通常应被信任
- 明确告诉 agent 你期望它写代码还是只做研究(搜索、文件读取、网络获取等)
- 如果 agent 描述提到应主动使用,那么你应尽力在用户不需要要求时主动使用它。
使用你的判断。
- 如果用户指定他们希望你"并行"运行 agent,你必须发送一条包含多个 Agent 工具使用
内容块的消息。例如,如果你需要同时启动 build-validator agent 和 test-runner
agent,发送一条包含两个工具调用的消息。
- 你可以选择设置 `isolation: "worktree"` 以在临时 git worktree 中运行 agent,
给它一个仓库的隔离副本。如果 agent 没有做出更改,worktree 将自动清理;
如果有更改,worktree 路径和分支将在结果中返回。
何时不使用 Agent 工具:
- 如果你想读取特定文件路径,使用 Read 工具或 Glob 工具代替 Agent 工具,
以更快找到匹配项
- 如果你搜索特定的类定义如 "class Foo",使用 Glob 工具代替,以更快找到匹配项
- 如果你在特定文件或 2-3 个文件集合中搜索代码,使用 Read 工具代替 Agent 工具,
以更快找到匹配项
- 与上述 agent 描述无关的其他任务
示例用法:
<example>
user: "这个分支在发布之前还剩什么?"
assistant: <thinking>Fork 这个——这是一个调查性问题。我想要待办清单,不是我上下文中的 git 输出。</thinking>
Agent({
name: "ship-audit",
description: "分支发布就绪审计",
prompt: "审计这个分支发布前还剩什么。检查:未提交的更改、领先 main 的提交、
测试是否存在、GrowthBook gate 是否已接入、CI 相关文件是否有变更。报告一个
待办清单——已完成 vs 缺失。200 词以内。"
})
assistant: 发布就绪审计运行中。
<commentary>
轮次在此结束。协调器对发现了什么一无所知。接下来是一个独立的轮次——通知从外部到达,
作为 user-role 消息。它不是协调器写的。
</commentary>
[稍后的轮次——通知作为用户消息到达]
assistant: 审计回来了。三个阻断项:新 prompt 路径没有测试、GrowthBook gate 已接入
但不在 build_flags.yaml 中、一个未提交的文件。
</example>
<example>
user: "那 gate 到底接入了没有"
<commentary>
用户在等待中提问。审计 fork 正是为了回答这个问题而启动的,但还没返回。协调器没有
这个答案。给出状态,而非编造的结果。
</commentary>
assistant: 还在等审计结果——这正是它在检查的事项之一。应该很快就到。
</example>
<example>
user: "你能对这个迁移是否安全做个第二意见吗?"
assistant: <thinking>我会问 code-reviewer agent——它看不到我的分析,所以可以给出独立的判断。</thinking>
<commentary>
指定了 subagent_type,所以 agent 从零开始。它需要提示词中的完整上下文。
简报解释了要评估什么以及为什么。
</commentary>
Agent({
name: "migration-review",
description: "独立迁移审查",
subagent_type: "code-reviewer",
prompt: "审查迁移 0042_user_schema.sql 的安全性。上下文:我们在一个 5000 万行的
表上添加 NOT NULL 列。现有行获得回填默认值。我想要关于回填方法在并发写入下是否
安全的第二意见——我已经检查了锁行为但想要独立验证。报告:这安全吗?如果不安全,
具体什么会出问题?"
})
</example>

1. Fork vs 全新 Agent 的核心差异:上下文继承 vs 从零开始

Section titled “1. Fork vs 全新 Agent 的核心差异:上下文继承 vs 从零开始”

Fork 和 Agent(带 subagent_type)的核心区别不在于功能,而在于上下文继承和缓存共享

Fork(省略 subagent_type)Agent(带 subagent_type)
上下文继承父进程完整对话上下文从零开始
缓存共享父进程的 prompt cache无法复用
成本低(缓存命中)高(冷启动)
适用场景研究、调查(需要上下文)独立任务、需要”独立视角”
提示词风格指令式(做什么)简报式(完整情境)

提示词明确说”不要在 fork 上设置 model”,原因是不同模型无法复用父进程的缓存,这意味着 fork 的核心优势——缓存共享——会被完全浪费。这是一个纯粹从推理成本角度出发的架构约束。

2. “不要偷看”规则的原因:读取 fork 的中间输出会污染主上下文

Section titled “2. “不要偷看”规则的原因:读取 fork 的中间输出会污染主上下文”

Don’t peek(不要偷看)解决的是上下文污染问题:

  • 机制:fork 运行时会产生大量工具调用输出(文件读取、命令执行等),这些输出保存在 output_file
  • 诱惑:协调器可能想”看看进展如何”而去 Read 这个 output_file
  • 后果:fork 的所有工具噪音(可能数千行的 git diff、文件内容等)被拉入协调器的上下文
  • 违背初衷:fork 的核心价值就是”将中间输出排除在主上下文之外”,偷看完全消解了这个价值
  • 正确做法:等待完成通知,它会包含 fork 的最终总结结果

本质上,这是一个**信息屏障(information barrier)**设计:fork 的上下文和协调器的上下文之间只有单向的、经过筛选的信息流(完成通知),而非原始的工具输出流。

3. “不要抢跑”规则的原因:fork 未完成时不要猜测结果

Section titled “3. “不要抢跑”规则的原因:fork 未完成时不要猜测结果”

Don’t race(不要抢跑)解决的是 LLM 幻觉问题:

  • 场景:用户问了一个问题,协调器 fork 了一个 agent 去调查,然后用户在 fork 完成前追问
  • 危险:协调器可能会基于自己的推测”编造”一个看起来合理的答案
  • 关键设计:通知以 user-role 消息到达——“它绝不是你自己写的东西”——明确区分了数据来源
  • 正确做法:“还在等审计结果——这正是它在检查的事项之一。应该很快就到。”

这条规则针对的是 LLM 的一个根本性弱点:模型倾向于生成看起来合理的文本,即使它实际上没有所需信息。在 agent 系统中,这种倾向可能导致用户将编造的结果当作事实执行。

4. “像给同事布置任务”的比喻:prompt 需要自包含

Section titled “4. “像给同事布置任务”的比喻:prompt 需要自包含”
像对一个刚走进房间的聪明同事一样简报——它没有看到这次对话,
不知道你尝试过什么,不理解这个任务为什么重要。

这个比喻是 prompt 编写的最佳心智模型,蕴含了几层设计意图:

  1. 同理心:agent 没有对话历史,你需要主动提供它缺失的上下文
  2. 完整性:不仅告诉”做什么”,还要告诉”为什么”和”已经排除了什么”
  3. 判断力:给出足够的问题背景让 agent 能做判断,而非仅执行指令
  4. 区分策略
    • 查找(已知答案形式):给确切命令
    • 调查(未知答案形式):给问题本身,不预设步骤——“预设步骤在前提错误时会变成负担”

Fork 和 Agent 的提示词策略也因此不同:

  • Fork 提示词:指令式,因为上下文已继承,不需要重复背景
  • Agent 提示词:简报式,需要完整的情境和动机

5. “永远不要委派理解”:协调者必须先综合理解再分发任务

Section titled “5. “永远不要委派理解”:协调者必须先综合理解再分发任务”
不要写"根据你的发现,修复 bug"或"根据研究,实现它"。
写出证明你已理解的提示词:包含文件路径、行号、具体要改什么。

这条规则的深层含义:

  • 综合(synthesis)是协调器的核心职责,不能被委托给子 agent
  • 如果你能写”根据发现修复 bug”,说明你还没理解发现了什么,这不是委托而是推卸
  • Agent 应该收到已消化的指令,而不是”你自己去弄明白然后做”
  • 这防止了”链式委托”——A 委托 B 理解,B 委托 C 理解,最终没有人真正理解

这条规则可以推广到所有多 agent 系统:协调者的价值在于综合和决策,如果连理解都委派出去,协调者就退化为一个无意义的消息转发器。

6. 缓存经济学:fork 复用父级缓存,换模型会破坏缓存

Section titled “6. 缓存经济学:fork 复用父级缓存,换模型会破坏缓存”
Fork 很廉价,因为它们共享你的 prompt 缓存。
不要在 fork 上设置 model——不同的模型无法复用父进程的缓存。

这揭示了 fork 架构的经济学逻辑:

  • 缓存命中:fork 继承父进程的完整对话,这些内容已经在 prompt cache 中,不需要重新处理
  • 缓存失效:如果换了模型(如从 Opus 换到 Sonnet),整个 prompt cache 失效,需要重新创建
  • 成本对比:fork(缓存命中)的成本远低于全新 agent(冷启动) + 全量上下文传递
  • 设计启示:在多 agent 架构中,缓存复用是成本优化的关键杠杆

Agent 系统的首要价值不是并行执行,而是上下文隔离。fork 的设计哲学是:“如果中间输出不值得保留在我的上下文中,就 fork 出去做”。这意味着 fork 的判断标准是上下文质量的维护,而非任务的复杂度或体量。一个只需要 10 秒的任务,如果会产生大量不需要的中间输出,就值得 fork;一个需要 10 分钟的任务,如果每一步的输出都是后续决策的关键输入,就不应该 fork。

2. “不要偷看 + 不要抢跑”解决了 LLM 的两个常见反模式

Section titled “2. “不要偷看 + 不要抢跑”解决了 LLM 的两个常见反模式”

这两条规则针对的是 LLM agent 系统中两个最常见的失败模式:

  • 偷看:协调器读取子 agent 的中间工具输出,导致上下文被噪音污染,违背了 fork 的初衷
  • 抢跑:子 agent 还没完成,协调器就”预测”结果并呈现给用户,导致幻觉被当作事实

这两条规则共同构成了一个信息隔离协议:fork 和协调器之间只通过完成通知同步,不共享中间状态。

3. “像给新同事布置任务”是最佳的 prompt 编写心智模型

Section titled “3. “像给新同事布置任务”是最佳的 prompt 编写心智模型”

这个比喻之所以有效,是因为它天然包含了 prompt 编写的所有关键要素:

  • 你不会假设新同事知道项目背景 -> 提供完整上下文
  • 你不会只说”把那个 bug 修了” -> 解释什么 bug、在哪里、影响什么
  • 你会根据任务类型调整沟通方式 -> 查找给命令、调查给问题
  • 你会说明已排除的方向 -> 避免重复无效工作

4. “永远不要委派理解”可以推广到所有多 agent 系统

Section titled “4. “永远不要委派理解”可以推广到所有多 agent 系统”

这是多 agent 协调的核心规则:

  • 协调者的价值 = 综合 + 决策
  • 如果连理解都委派出去,协调者 = 消息转发器 = 不需要存在
  • 好的委托 = “文件 X 的第 42 行有个空指针,需要加 null check”
  • 坏的委托 = “根据你的研究,修复那个问题”
  • 前者证明了协调者理解了问题;后者暴露了协调者根本没理解

5. Fork 的缓存复用设计:多 agent 架构中的成本优化

Section titled “5. Fork 的缓存复用设计:多 agent 架构中的成本优化”

Fork 共享父进程 prompt cache 的设计是多 agent 架构中实现成本优化的优雅方式:

  • 父进程的对话历史(可能数万 token)已经缓存
  • Fork 继承这些内容时不需要重新处理,只需引用缓存
  • 这使得 fork 的边际成本远低于启动一个全新 agent
  • 但这个优势有一个脆弱点:换模型会完全破坏缓存
  • 因此”不要在 fork 上设置 model”不是建议,而是经济学必然

6. Agent 列表缓存优化:10.2% 的成本节省

Section titled “6. Agent 列表缓存优化:10.2% 的成本节省”

shouldInjectAgentListInMessages() 的存在揭示了一个重要的工程细节:动态 agent 列表(受 MCP 连接、插件重载、权限变更影响)被嵌入在工具描述中时,每次列表变化都会导致整个工具 schema 的 prompt cache 失效,这占了全量 cache_creation token 的约 10.2%。解决方案是将频繁变化的内容(agent 列表)从静态区域(工具描述)分离到动态区域(消息附件),以最大化缓存命中率。这是一个典型的缓存友好的提示词工程案例。