【Harness Engineering】02_Prompt 不是人格,Prompt 是控制平面

源码地址: https://github.com/wquguru/harness-books

一、一个常见误会

1.1 人设思维的问题

一说起 system prompt,很多人首先想到的是一段熟悉的话术:你是谁、你擅长什么、最好再有一点稳定人格。对聊天系统这种理解够用,对要读文件、调工具、动 shell、跨轮执行的代理系统则明显不够。

人设 解决的是"它像什么",控制平面 解决的是"它能做什么、什么时候做、做错了怎么办、谁来兜底"。两者不在同一层。

1.2 Claude Code 的答案

Claude Code 的实现说明了这一点:它的 system prompt 是一组分层拼装的行为区块,更接近一套运行时协议,而不是一篇人物小传。


二、分层结构:Prompt 从一开始就不是一块整布

2.1 多 Section 拼装

getSystemPrompt() 里,Claude Code 返回的是一个由多个 section 组成的数组,而不是一段完整字符串。这个细节很重要------一旦 prompt 变成多个块,系统就正式承认它内部包含一组职责不同的约束。

2.2 三类核心内容

这些 section 至少包含三类东西:

第一,身份和总任务说明。 系统说明自己是一个交互式代理,要用可用工具帮助用户完成软件工程任务,同时嵌入了一些安全约束,比如不要乱猜 URL。

第二,系统级规则。 系统明确规定:

  • 用户能看见的是哪些文本

  • 工具调用可能触发权限审批

  • 用户拒绝后不能机械重试

  • tool result 和 user message 里可能混入 system-reminder

  • 上下文会被自动压缩

这些内容有一个显著特征:它们并不关心模型"像不像一个聪明助手",而是关心它是否是一个守规矩的执行体。这就是控制平面的语气,它的核心任务是定义边界。

第三,工程性指令。 不要随意增加需求,不要越权优化,不要为了让结果显得完整而隐瞒验证失败,不要在没有必要时制造抽象。这些内容看起来像写作风格要求,其实它们和工程约束绑得很紧。一个会自动"顺手优化一切"的模型,从产品角度看也许很热情,从工程角度看则相当危险。

所以,从源码结构上就能看出来:Claude Code 的 prompt 要解决的是如何让模型在复杂运行时里遵守边界


三、优先级:Prompt 真正的价值不在文字本身

3.1 明确的优先级链

如果 prompt 只是写在那里,还不够说明问题。真正决定它是否属于控制平面的,是系统是否给它定义了严格优先级。

buildEffectiveSystemPrompt() 把 prompt 的来源明确排成一条链:

  1. override system prompt(覆盖系统提示)

  2. coordinator system prompt(协调系统提示)

  3. agent system prompt(代理系统提示)

  4. custom system prompt(自定义系统提示)

  5. default system prompt(默认系统提示)

最后还会统一拼接 appendSystemPrompt

3.2 特例与不变式

proactive mode 的处理更直白:如果 agent prompt 和 proactive mode 同时存在,agent prompt 不再替换默认 prompt,而是附加在其后。通用制度可以叠加岗位说明书,但不能被岗位说明书直接冲掉。

核心骨架如下:

python 复制代码
sources = [override, coordinator, agent, custom, default]
base = first_present(sources)           // 高优先级源会整段替换默认
if proactive_mode and agent:
    base = default + agent              // 特例:叠加而非替换
return base + appendSystemPrompt        // append 永远在最后一层

三条不变式:

复制代码
1. 基线必须唯一        —— 存在且只有一个 base
2. 顺序硬编码          —— 不靠"后写为准"
3. append 只能附加     —— 不替换任何内容

这三条一旦被破坏,prompt 就会退化成一块谁后写谁说了算的涂鸦板。


四、记忆系统:Prompt 不只是约束当前行为

4.1 连接长期记忆

如果说前面这些内容已经像一套运行时说明书,那么看到 Claude Code 如何处理 memory 和 CLAUDE.md 后,就会更清楚地意识到:这里的 prompt 已经是整个上下文治理入口,而不只是"写给模型看的一段话"。

系统会把 project instructions、local instructions、team memory、auto memory 等不同来源的内容整理成统一格式,再拼接进 prompt 相关上下文中,连每种内容的来源说明都写得很细。

4.2 用 Prompt 规定记忆如何形成

更关键的是,系统连"如何保存记忆"这件事都变成了 prompt 的一部分。它会明确告诉模型:

  • memory 是文件化持久系统

  • MEMORY.md 是索引,不是正文

  • 要如何写 frontmatter

  • 哪些信息不该保存

  • plan 和 task 不该被误用成 memory

这件事非常关键。它把 prompt 的职责从"约束当前行为"扩展到了**"约束未来知识的沉淀方式"**。这已经超出了通常意义上的提示词,更接近一份写给运行时参与者的知识治理协议。

换句话说,Claude Code 不只是用 prompt 规定"这一轮怎么说话",还用 prompt 规定"长期记忆如何形成"。一个系统只要走到这一步,它的 prompt 就不可能再只是语气问题,而必然进入制度问题


五、缓存与成本:控制平面还要算账

5.1 Prompt 也是计算成本

多数人理解 prompt 时,很少会想到性能。常见想法是 prompt 只是喂给模型的文本,写好即可。Claude Code 的实现更务实:prompt 同时也是计算成本。它越复杂、变化越频繁,缓存命中就越差,系统运行就越贵、越慢。

5.2 可缓存与不可缓存

系统把 prompt section 区分成两类:

  • 可缓存的 systemPromptSection

  • 会打破缓存的 DANGEROUS_uncachedSystemPromptSection

resolveSystemPromptSections() 会优先从缓存里拿已经计算过的内容,只在必要时重算。系统还会在 /clear/compact 之后清空这些状态。

这件事看起来像优化,实际上同样属于控制平面。一个真正可运行的 prompt 系统,不可能只考虑表达能力,而不考虑它对吞吐、延迟和缓存的影响。系统甚至把静态部分和动态部分用 boundary 显式分开------这说明它在设计时已经承认:有些内容在会话中相对稳定,有些内容会逐轮变化,二者不能混在一起消耗缓存

一个工程系统只要开始关心"哪部分 prompt 会导致缓存失效",它就已经不再把 prompt 当作文案创作。文案追求完整表达,控制平面追求可治理、可复用、可预测的行为成本。


六、用户覆盖:可以改内容,但不能跳过结构

6.1 支持自定义

Claude Code 并没有把用户锁死在默认 prompt 上。CLI 明确支持覆盖和追加:--system-prompt--system-prompt-file--append-system-prompt--append-system-prompt-file 等选项。用户当然可以带着自己的规约来。

6.2 秩序优先

但这里有个关键点:系统虽然允许覆盖和追加,却仍然坚持用统一的 buildEffectiveSystemPrompt() 做最终装配。这说明它允许自定义,但不放弃秩序。用户可以改内容,系统仍然保留结构。

没有结构的可定制,最后往往会退化成另一种随意。今天加一段,明天减一段,后天某个 agent 又替换掉基线约束,系统行为就会越来越像临时口头通知。Claude Code 的选择是让用户修改,但修改必须发生在既定优先级和分层机制里。


七、为什么说 Prompt 更像宪法,而不是台词

7.1 台词 vs 宪法

如果把前面各节放在一起看,可以得到一个相当明确的结论:Claude Code 的 prompt 更像宪法

所谓台词,是给角色在场上说的;所谓宪法,是规定权力边界、责任关系和例外情况如何处理。Claude Code 的 prompt 更接近后者。

7.2 五个结构条件

它满足了几个结构条件:

维度 说明
分层 不是一块写到底
优先级 不是谁后写谁说了算
完整控制平面 与 memory、CLAUDE.md、agent instructions、MCP instructions 一起组成
缓存机制 有缓存和动态 section 机制,不是随手拼一段文本
与 Runtime 耦合 不是游离于系统之外的装饰物

这也是为什么"写一个好 prompt"单独拿出来时价值有限。更重要的问题是:prompt 在系统里处于什么位置,它和哪些模块配合,它是否参与权限、状态、上下文和长期记忆的治理。如果不回答这些问题,所谓好 prompt 往往只是在某个顺利场景里暂时成立。


八、总结

8.1 核心原则

这一章可以归纳成一句话:

Prompt 的价值,在于它是否被纳入一套清楚的控制结构。

8.2 五个源码位置指向同一结论

源码位置 结论
constants/prompts.ts prompt 写成分段控制结构,不是统一宣言
utils/systemPrompt.ts 明确规定了 prompt 来源的优先级
utils/claudemd.ts 项目级和长期记忆内容纳入上下文装配
memdir/memdir.ts 用 prompt 规定了长期记忆的保存规则
constants/systemPromptSections.ts prompt 变成可缓存、可失效、可按段重算的运行时对象

8.3 最终结论

所以,一个成熟代理系统里的 prompt,不该被理解成"让模型入戏的开场白"。它更像一套运行中的制度文本 。制度文本当然也可以写得清楚,但最重要的部分始终是约束力

相关推荐
暂时先用这个名字1 小时前
安装deepseek harness及插件
人工智能·ai·npm·pnpm·deepseek·深度求索·harness
skywalk81631 小时前
用WorkBuddy成功把Deepseek Harness移植到FreeBSD
人工智能·deepseek·harness
GoCodingInMyWay2 小时前
DeepSeek Harness 开始
ai·agent·deepseek·harness
lovingsoft2 小时前
Harness Engineering 系列教程 ·实战与落地
harness
番茄不是西红柿kk19 小时前
DeepSeek Harness 开源解读
人工智能·开源·agent·harness·deekseep
阿萨德528号1 天前
DeepSeek Harness 开源了,但先别叫“正式版”:从封闭内测到 Developer Preview,只隔了两周
人工智能·deepseek·harness
奈斯先生Vector1 天前
AI 视频不是会动的图片:用 Shot Contract、时间码与音画质检构建可交付流水线
人工智能·重构·架构·prompt·aigc·音视频