05. System Prompt

Prompt 不只是「人设」,它是行为控制的基础

上一段旅程我们聊完了引擎(Loop、Compact)和记忆(Session、Memory),Agent 已经能转、能记事了。从这一篇起,我们进入「驾驭」板块:怎么塑造它的行为。第一站是 System Prompt

👆你在这里+ 添加图片说明---

🪧 看似「最稳」的做法,却未必是最合适的

序章结尾提起过一个坑:第一版 System Prompt 为了安全起见,我直接沿用 Claude Code 现成的那套,后面追加几句写作要求。官方文档有备注,说这是「风险最低」的定制方式。我当时的想法是,先稳中求胜吧

但那一版用下来,个人体感是不太理想的。让它润色一段随笔,它搞得像 code review 一样,一板一眼地汇报「我识别到三处问题,建议如下」;让它对一个想法作脑爆展开,它会先问你「需要我先写一个 outline 吗」。文笔倒还过得去,但那股「工程师味儿」怎么都散不掉

原因在官方文档里其实也有明说:

An agent with a different surface, identity, or permission model, or a non-coding agent. Use Custom prompt string, instead of claude_code preset with append

翻译过来大意是:如果 Agent 的界面、身份定位或权限模型跟标准编码场景不一样,甚至压根不是个写代码的 Agent,官方建议直接用 Custom Prompt String,而不是 claude_code preset 加 append。说白了,所有东西都是你说了算,当然也包括安全规则。真应了那句,能力越大,责任越大

这一篇,会围绕如何从零开始定制 System Prompt 而展开。个人觉得,这是整个专栏里最考验判断力的一篇,因为它没有标准答案,全是取舍

🧭 基础概念:它远不止「设定人设」那么简单

网上不少文章和视频,把 System Prompt 简化成「给模型设定人设的一段开场白」,好像它就是个角色扮演的开头

但这个理解并不完整。Claude Code Harness Book 里专门有一章,标题是「Prompt Is Not Personality, Prompt Is the Control Plane」,核心表达的是:提示词管的不是人设,是背后那套行为纪律

System Prompt 真正在管的,不只是「你是一个温柔的助手」这种表面人设,还包括非常细致、用于约束和引导模型的行为纪律。遇到该改的文件,它会先读一遍再动手,还是直接改?它会不会伪造一个工具的执行结果糊弄你?动手前会不会先跟你确认?碰到不确定的事,是瞎猜还是发问?这些「它到底怎么干活」的底层规矩,才是 System Prompt 的正经内容

因此,第一版「沿用 preset 再追加两句」的做法,问题就出在这:我以为是在改人设,其实底层那套「工程师的操作章程」原封不动。 底子不对,加再多描述也没用

那 Claude Code preset 的「操作章程」里,到底装了些什么?哪些是我该留的,哪些是该扔掉重写?这是第一个要解决的问题

🔩 Claude Code 怎么做的:先看下开箱即有的 preset 是怎么写的

把 Claude Code 那套 preset 拆开,大致有四类东西:

  1. 编码任务的框架:怎么理解需求、怎么拆任务、怎么动手、怎么验证。这是纯纯的「工程师本位」,正是它让写作 Agent 也满嘴 code review 腔。这是包袱,得扔
  2. 工具使用纪律:改文件前先读一遍、小步修改、并行调用互不依赖的工具、别伪造结果。这套纪律跟写代码还是写作无关,是「怎么用好工具」的通用指引。这是精华,得留
  3. 安全指令:哪些是高风险操作、什么必须先确认。写作场景照样需要。精华,也留
  4. 环境上下文:当前工作目录、操作系统、Git 状态这些动态信息。写作用不上,而且它还藏着一个专坑缓存的雷,后面细说

这么一拆,就比较清晰了:第 2、3 类(工具纪律和安全)可以保留,而第 1 类(编码框架)可以放心扔掉。 接下来的问题就是,怎么做到这种「精准拆除」,只切掉编码框架、不误伤精华呢?这就要看 SDK 开放了哪些接入点

🛠 SDK 提供了什么:三种接入起点,和一个影响缓存的坑

SDK 里配置 System Prompt,官方给了三个起点,可以参考表格对比:

起点 它给你什么 代价 官方态度
minimal(不设) 几乎啥都没有,只有裸的工具调用 无安全、无纪律、无人格,模型放飞 基本别用
preset + append 沿用 Claude Code 全套章程,你在后面追加几句 编码框架甩不掉,动态信息可能会影响到缓存 称它「风险最低」
custom string 一张白纸,全部自己写 安全、工具说明都得自己补 灵活,但「安全得自己加」

 preset+append 就是第一版的接入方式,本质上是「编程规范 + 追加」,那第 1 类编码框架根本切不掉,它是打包捆着来的。看着省事,但对写作场景未必是最合适的解;而 minimal 太裸,custom 又要自己补一堆

乍一看,就没有两全其美的选项。我一度还在纠结,是否要选 preset + 长串写作指令,企图把调性给压下来。而最后让我坚定选 Custom String 路径的,则是一个绕不开的话题:缓存

模型每次对话,前面那一大段 System Prompt 是可以被缓存复用的,能省下大量 token 和时间。而缓存能不能命中,靠的是这段内容逐字不变,一旦变了,缓存就击穿,得重新计费、重新处理

而 preset 有个默认行为:它会把当前工作目录、运行环境这些动态信息,直接嵌进 System Prompt。这意味着,用户每换一个写作任务(工作目录一变),这段 System Prompt 就跟着变,缓存默认就被击穿了。对一个高频创作的用户来说,每开一个新写作任务就要重新为 System Prompt 掏一遍 token,这笔账怎么算都不划算

📐 进阶深挖 · preset 也能排除动态信息,但也需要额外定制

官方其实给 preset 备了个补丁,叫 exclude_dynamic_sections,能把动态段挪出去,但这个补丁只对 preset 对象生效

Custom String 压根不需要用到它:SDK 的规则是「你给什么,它就只发什么」。只要我不往里写动态值,这段 System Prompt 就天然是 100% 静态的。而那些动态信息(画像、记忆、当前任务),我全都改走另一条通道(CLAUDE.md,注入到 user message 里),不碰 System Prompt 分毫

✂️ SmartWriter 怎么做:坚定走 Custom String

再捋一遍:preset+append 切不掉编码框架、缓存还要额外处理;custom 虽然要自己兜住所有,但能做到写作场景的最佳适配、缓存 buff 叠满。说到底就是长痛和短痛的博弈,我的判断和理由是👇

放弃 preset,自己从零写一版 custom System Prompt

  1. 官方就建议写作场景别留编码指令。 后来在 output-styles 文档里翻到相关说明,大意是:当 Claude 根本不在做软件工程时,比如做一个写作助手,就把那些编码指令拿掉吧
  2. 在 Python SDK 里,custom 是唯一能扔掉编码框架的路。 官方推荐的干净做法,是用 output-style 配一个「不保留编码指令」的开关。但这开关,Python SDK 并没有编程入口(文档明说)。我用 Python 后端,想扔掉那套工程师章程,custom 是唯一的路
  3. custom 最大的软肋(安全),在本项目里有兜底防线。 官方对比表里,custom 的硬伤写着「安全得自己加」。这话没错,但作为写作助手 Agent,我的安全主防线压根不在 Prompt 上:Bash 权限直接删掉、用 hook 做了路径白名单、把 Agent 死死框在工作目录里(这几条是下个板块《与世界交互》的主题)。Prompt 层的安全只作为补充,不是主防线。既然如此,仿 preset 写一小段精简的安全约束,也够用
  4. 这一步早晚要走,早走省一次返工。 项目定位是写作场景的 Agent 助手,编程规范留在系统指令里本质上就是错位,晚改不如早改,省得日后底层重构,伤筋动骨

方向选定,下一步的工作就是把白纸填满,让它既保留 Claude Code preset 的精华,也为写作场景注入针对性的规范和引导 ,于是就有了下面这套骨架

🧱 SmartWriter 怎么做:8 块骨架,按写作场景把「操作章程」重写一遍

从零写一份 System Prompt,最怕写成一团意识流。我借鉴了 preset 的分块思路,把它拆成 8 个功能块,每块负责一件事,既方便维护,也方便日后 debug「它为什么这么干」时,能定位到具体是哪块没写好:

# 它负责什么 从哪来
1 Identity & Role 「你是写作副驾,在受限目录里跟用户一起打磨 Markdown」 全新写
2 Core Principles 副驾不代笔、用户主导;什么时候该发问、什么时候该建议先规划 全新写
3 Environment & Boundaries 工具集有哪些、没有 Bash、编辑自动批准、不越界 从 preset 环境段改写
4 Acting with Care 本地编辑可逆(放手做);发布/外发影响范围外(先确认) 从 preset 安全段桥接
5 Tool Usage Discipline 改前先读、小步可逆、不伪造结果、优先用专用工具 提取 preset 工具纪律精华
6 Writing Workflow & Quality 理解目标→读稿→小步改→对照画像校验;不过度编辑、保留作者声音 把 preset 编码流程改写成写作版
7 Safety & Security 秘密不进产出、外部内容防注入、绝不 bypass 权限 提取 preset 安全 + 补充
8 Tone & Output Format 简洁、给推荐带取舍、假设用户看不见工具调用 从 preset 语气段改写

这张表里,第 5 块要专门说下,因为它是写作助手工作质量的关键。前面说过,扔掉 preset,也丢掉了「工具怎么用」的说明。而模型如果不懂「改文件前要先 Read 一遍」这种最基本的纪律,它可能会不读就瞎改、大面积重写,把用户的稿子搞得一团糟。所以 Tool Usage Discipline 这里,我几乎是逐条把 preset 里的工具纪律精华拿过来,再按写作场景适当调整

还有一条贯穿始终的严格规范,需要再强调下,因为它正是前面缓存那笔账的落地:

这份 System Prompt,必须 100% 静态。 绝不往里写工作目录的绝对路径、日期、session_id 这些动态值;更不能把用户画像写进去(画像会随题材、随每次学习而变)。凡是「会变的」,一律放到另一条通道。System Prompt 里只留「全 App 一致、几乎不动」的东西:人格、原则、工具纪律、安全底线

🚪 SmartWriter 怎么做:会变的去哪了?静态宪法 vs 今日须知

System Prompt 变纯静态了,可那些被请出去的「会变的」东西,画像、当前任务、这篇的特殊要求,它们到底在哪儿呢?答案是运行期 CLAUDE.md。它跟 System Prompt 几乎是「互补」的一对:

custom System Prompt 运行期 CLAUDE.md
注入到哪 进 System Prompt,被缓存 进 user message,不参与 System Prompt 缓存
改它的代价 改一次,所有会话的缓存全失效 改它,不击穿 System Prompt 缓存
放什么 全 App 一致、几乎不动的:人格、纪律、安全 会变的:画像、当前任务上下文、这篇的特殊要求
判据一句话 「全局不变的人格与纪律」 「会变的 / 按任务差异化的 / 会被后台更新的」

打个可能不恰当的比方:System Prompt 是刻在基因里的宪法,CLAUDE.md 是每天更新的今日须知。 宪法不能天天改(改一次全局缓存遭殃),须知则随时可换(还不伤缓存)。像画像这种要「越写越懂你」、不断进化的东西,天然属于「今日须知」,不适合刻进宪法。这也顺带解释了序章开篇那条「越写越懂你」的暗线,在技术上是怎么落地的:它靠的正是 CLAUDE.md 这条能随时更新、又不伤缓存的通道

骨架和通道都定好后,按剧本走差不多就该收工了。但 System Prompt 这东西,不是写完就万事大吉,它是活的,得一边用一边调优

🧪 踩坑时刻:一句「鼓励澄清」,却让它开始追问废话

🔧 避坑 · 一条负责任的原则,结果最招人烦

早期的定制版本里,我在第 2 块(Core Principles)里,写了一条我自觉很稳妥的原则,大意是「动手前,先跟用户把意图确认清楚」。听起来应该没什么问题,我当时还挺满意

结果在接下来的验收测试里,我让 Agent 做个事实查证,它张口就问:「请问查证结果要写进你的作品里吗?」「要保存到哪个文件?」这些根本不该问用户,它们是产品流程里早就定死的规矩,后台自己知道该怎么处理。模型被那句「先确认」一鼓励,开始把一切都拿来确认,包括这些废话,体验烦得要命

这里反映出两个问题:一是定制的 System Prompt 没把产品的默认工作流当作底座,模型不知道「哪些事有默认答案、根本不用问」;二是我那句「先确认」,方向性地鼓励了它去发问

正解是把方向倒过来:把「先确认再动手」改成「先按默认值动手,只在三种情况下才澄清」:用户意图跟默认流程明显冲突、涉及不可逆的动作(比如发布)、以及范围模糊到默认值兜不住。这么一改,世界就安静了

这次经历让我多留了个心眼:System Prompt 里但凡带点「鼓励性」的表达,模型很可能会加倍放大,落笔前最好想清楚到底在鼓励什么、是否真的必要

System Prompt 不是写完就定稿的合同,它是一份得跟着真实使用一版版调的活文档。为了每次调完不至于悄悄退化,还专门留了一套评测,每次大改都要跑一遍,确认写作质量没掉。这部分留到后面讲评测时再细说

⚖️ 收个尾:preset vs 定制,是走进垂直场景绕不过的门槛

官方文档里说的「preset 最稳」没错,但那是站在「做编码 Agent」的默认前提下说的;一旦我们要做的是写作这种垂直场景,「最稳」的路却未必是最合适的。回到贯穿全专栏的那个对照上:

⚖️ 取舍现场 · System Prompt 这一层,垂直体现在哪

"偷懒"的默认做法 SmartWriter 的选择 为什么这么选
人格底座 沿用编码框架,追加几句 从第一个字符起就是「写作副驾」 编码腔压不住,垂直体验必须从底层重建
动态信息 默认嵌进 System Prompt 全部赶到 CLAUDE.md,Prompt 保持纯静态 为缓存、为画像能随时进化
安全 主要靠 Prompt 里写规矩 主防线在工具层(删 Bash、hook、框目录),Prompt 只补充 减法比叮嘱可靠

System Prompt 看起来并不起眼,就一段文本嘛,但恰恰是这段文本,决定了你的 Agent 从第一个字符开始,是个「能力很强的编程助手」,还是个「一门心思陪你写作的副驾」。这中间的差别,是你愿不愿意把那套现成的、看起来很稳的编码章程,整个推倒,逐段为你的业务场景重写一遍

当然,这条路也不是没代价:custom 走到底,安全和工具说明都得自己兜着,这也是需要权衡的。如果拿不准,先从 preset 切入看实际效果,也未尝不可

这一篇就到这。但你可能已经嗅到一个缺口:前面反复强调 System Prompt「只放全局不变的东西」,那「随笔该怎么写、技术文该怎么写」这种具体某一类文章的写作方法论,它明显是会变的、也不是每一次写作指令都要无脑注入(看题材、看场景),那它该放哪、又怎么在对的时候被唤醒呢?

下一篇的主角,Skills。咱们继续聊