开场:System Prompt 是代码,不是作文
生产级的 System Prompt 不是想到什么写什么。它是分层管理的:身份层、环境层、工具层、行为层,各管各的,改一层不影响其他层。
本文讲透四件事:怎么把一坨文本拆成分层结构、工具描述怎么按需加载、Skill 怎么做成可运营的模块、动态内容怎么毁掉 KV Cache。
一、分层管理:一坨文本 → 四层各司其职
「一坨文本」长什么样
你是一个 AI 助手,名字叫 Alice。你可以搜索网页、读写文件,现在是 2026 年,用户在中国。当用户让你搜索时用 web_search 工具,回答时先思考再回答,不要编造信息。你的性格温暖友善,文件操作用 file_read 和 file_write,用户的语言偏好是中文,如果不确定就告诉用户你不知道…
身份、环境、工具、行为全混在一起。 改一处可能影响全部,谁也说不清哪段影响了哪个行为。
四层各司其职
| 层 | 管什么 | 示例 |
|---|---|---|
| 身份层 | 我是谁? | 性格、角色、基本人设 |
| 环境层 | 现在什么情况? | 系统状态、用户上下文 |
| 工具层 | 能用什么? | 可调用的工具和 API |
| 行为层 | 怎么行动? | 输出格式、决策规则 |
分层的好处
- 改一层不影响其他层:加个新工具?只改工具层。调整回答风格?只动行为层。不会牵一发而动全身。
- 多人协作不冲突:产品改行为、工程师加工具、运营调人设,各改各的文件,Git 合并不冲突。
- A/B 测试更精准:想测试不同的回答策略?只替换行为层,其他三层保持不变,变量单一。
- 排查问题更容易:AI 行为异常?按层检查:是身份搞错了、环境信息过时、工具描述有误、还是规则冲突?
一坨文本改一处可能影响全部。分层管理,改一层不影响其他层。 生产级的 System Prompt 是四个独立管理的模块。
二、不用的东西别给 AI 看:工具按需加载
如果你有 100 个工具,全部描述塞进 System Prompt,光工具描述就占几万 Token。AI 和人一样:给太多信息反而找不到重点。
全量加载 vs 按需加载
| 维度 | 全量加载 | 按需加载 |
|---|---|---|
| 工具描述 | 每个工具 ~350 Token 完整描述 | 每个工具 ~28 Token 仅名称 |
| 50 个工具总计 | ~17,500 Token | ~1,550 Token |
| 节省 | — | 91% |
按需加载怎么做:三步走
- 首轮只给名字列表:System Prompt 里只放工具名 + 一句话说明,AI 知道有这个能力就行。
- 用到时再展开:AI 决定调用某个工具时,系统动态注入该工具的完整描述和参数格式。
- 用完就收回:工具用完后,下一轮对话不再带完整描述,回到只有名字的状态。
类比:就像公司通讯录——你不需要每个人的完整简历,只需要名字和职位。真要找谁合作时,再去看详细资料。
AI 和人一样:给太多信息反而找不到重点。 按需给、用到再展开。工具描述的按需加载,既省 Token 又提高准确率。
三、Skill:可运营的 Prompt 模块
System Prompt 管「我是谁」,Tool 管「我能做什么」,那 Skill 管什么?它管的是遇到某件事,怎么一步一步做好。文件即配置,版本可追溯。
三者对比
| 维度 | System Prompt | Tool | Skill |
|---|---|---|---|
| 定位 | 全局身份 | 能力注册 | 流程指引 |
| 定义 | AI 是谁:名字、性格、原则 | 有什么工具:名字、参数、功能 | 完整执行方案:何时触发、用什么工具、按什么步骤 |
| 作用范围 | 全局 | 单次调用 | 特定任务 |
| 修改频率 | 很少 | 中等 | 高频迭代 |
| 生命周期 | 整个产品 | 功能迭代 | 独立版本 |
一个 Skill 的结构
- 触发条件:什么时候启用这个 Skill
- 允许的工具列表:这个任务能用哪些工具
- 执行流程:一步一步怎么做
- 输出格式要求:最终产出长什么样
Skill 的生命周期
- 编写:一个文件,纯文本
- 注册:放到指定目录即生效
- 触发:匹配条件时自动加载
- 迭代:改文件 = 改行为,Git 追溯
为什么不直接写在 System Prompt 里?
System Prompt 是全局的,改了影响所有场景。Skill 是按需加载的,只在特定场景注入,不会污染其他任务的行为。而且 Skill 文件可以独立版本管理:谁改了什么、什么时候改的,一目了然。
Prompt 也需要可复用、可迭代、可追溯。 Skill 就是 Prompt 的模块化——像管理代码一样管理 AI 的行为指引,每个任务一个文件,改了就生效。
四、提示词和缓存的微妙关系:别动前缀
KV Cache 的规则极其简单:前缀一模一样就命中,差一个字就全部重算。 所以,往 System Prompt 里插入任何动态内容,都可能让缓存永远打不中。
指纹变了 = 缓存作废
每次请求,系统会对 System Prompt 算一个指纹(hash):
System: 你是助手。当前时间: 14:35:22 → a3f7c2 → MISS
System: 你是助手。当前时间: 14:35:23 → b8e1d9 → MISS
System: 你是助手。当前时间: 14:35:24 → c4a2f6 → MISS
每一秒时间不同 → 指纹不同 → 缓存永远命不中 → 每次都要从头算 → 成本翻倍。 这不只是时间戳的问题:任何动态内容插在 System Prompt 里都有同样效果。
Skill 的注入方式也影响缓存
| 注入方式 | 效果 |
|---|---|
| 把 Skill 插进 System(System 每次随 Skill 变化) | 切换 Skill 时 System 变了 → 缓存失效,命中率约 20% |
| Skill 作为独立消息追加(System 永远不变) | 前缀缓存始终命中,命中率约 90% |
回顾之前的结论:动态时间戳是最贵的反模式。 这一课的结论更广:不只是时间戳,所有动态注入到 System Prompt 的内容都是缓存杀手——Skill、用户 ID、Session 标记…任何变化的东西,都不该出现在前缀里。
KV Cache 的规则很简单:前缀一样就命中。所以,别动前缀。 把所有可能变化的内容(Skill、上下文、时间)放到 System Prompt 之后,让前缀永远稳定。
结语:像写代码一样写 System Prompt
分层管结构,按需管体积,Skill 管复用,前缀管缓存。
回顾全文:System Prompt 要分层管理——身份、环境、工具、行为四层各管各的,改一层不影响其他层;工具描述要按需加载——先用名字列表,用到再展开,用完收回,省 Token 又提准确率;Skill 是 Prompt 的模块化——一个任务一个文件,可复用、可迭代、可追溯;最后,别动前缀——KV Cache 对前缀极度敏感,所有动态内容都要放到 System Prompt 之后,让前缀永远稳定。
记住那句最关键的:动态内容进前缀,就是给 KV Cache 判死刑。 System Prompt 的第一原则,是保持前缀稳定;第二原则,是把该有的结构分层、把不该有的内容删掉。