关于 writing-system-prompts
这项 skill 指导编写引导 LLM 行为并便于提示缓存复用的系统提示词,面向提示词作者,涵盖内容排序、分隔结构、缓存断点与检查流程。
主要功能
- 01角色置于提示词开头
- 02静态内容优先的缓存排序
- 03按提供商设置缓存断点
- 04使用分隔符和明确规则
- 05提示词验证清单
适用场景
- 01起草系统提示词
- 02减少重复前缀的输入成本
- 03部署前检查提示词结构
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ lwlee2608/ agent-skills --skill writing-system-prompts安装后在 Claude Code 中输入/writing-system-prompts确认已加载。
详细介绍
编写大模型系统提示词
精心编写的系统提示词可以在整个对话中引导模型的行为;如果采用便于复用 KV 缓存的结构,在提供提示词缓存的服务商(Anthropic、OpenAI、Bedrock、Vertex 等)上,其成本仅为未缓存前缀的一小部分。
规则
-
将角色放在最前面,用一句话说明。 在系统字段(而非用户轮次)中用一句描述性的话来锚定语气和词汇,例如:
You are a helpful coding assistant specializing in Python.顶部使用普通文字,不要用标记语言包裹。 -
先放静态内容,动态内容放最后。 缓存命中要求前缀的字节完全一致。顺序为:角色 → 工具/策略 → 长篇参考文档/少样本示例 → 缓存断点 → 动态上下文 → 用户轮次。**原因:**断点前哪怕只改动一个词元,也会让你从缓存读取价格(约为输入价格的 10%)变成按完整输入计费。
-
服务商支持时,明确标记缓存断点。 大多数缓存功能需要显式启用(例如 Anthropic 的
cache_control、Bedrock 的 cachePoint)。在每个要复用的稳定区块末尾放置断点。缓存写入通常比基础输入更贵;缓存读取只需支付其一小部分费用。TTL 各不相同(通常约为 5 分钟,有时也有更长的档位)。只缓存 TTL 内会复用的前缀;流量稀疏时,反复写入缓存会持续产生额外费用。# Anthropic example — adapt to your provider's syntax system=[ {"type": "text", "text": ROLE_AND_POLICIES}, {"type": "text", "text": LONG_REFERENCE_DOC, "cache_control": {"type": "ephemeral"}}, ] -
不要将频繁变化的内容放在前缀中。 将当前时间、请求 ID、用户 ID 或对话摘要放在顶部,会使整个提示词无法命中缓存。将这些内容移到断点之后——权威事实(如日期/ID)可以放在第二条系统消息中,任务材料(如问题和文档)可以放在用户轮次中。这两种方式都能同样保留缓存复用。
-
使用结构化分隔符区分不同区块。 用清晰的分隔符包裹长篇输入和行为指令——XML 标签(
<documents><document>…</document></documents>、<default_to_action>…</default_to_action>)、Markdown 标题或命名的 JSON 字段。**原因:**与大段连续文字相比,分隔后的区块在长上下文中更易于保留;而且多个模型系列(尤其是 Claude)都经过了针对 XML 结构的专门训练。 -
在用户轮次中,将长篇数据放在指令之前。 对于 20k+ 词元的输入,先放文档,最后放问题——在主要模型的多文档任务中,测得的质量提升最高可达 30%。
-
编写字面明确、范围清晰的指令。 现代指令微调模型会越来越按字面理解提示词,不会默默进行泛化。如果规则适用于多个部分,就明确说明:
Apply this formatting to every section, not just the first one.避免使用全大写文字大声强调(CRITICAL、MUST)——这会导致较新的 Claude 模型过度触发,而对其他模型助益甚微;请使用普通的祈使语气。 -
仅当默认行为不合适时,才调整简洁程度、语气、工具使用和子 Agent 的生成。 例如:
Provide concise, focused responses. Skip non-essential context./Use a warm, collaborative tone./Spawn multiple subagents in the same turn when fanning out across items. Do not spawn a subagent for work you can complete in a single response.只有在观察到问题后才覆盖默认行为,不要预先干预。
验证流程
起草或编辑后,逐项检查:
- 角色检查 — 系统字段最开头是否有一句话说明角色?
- 缓存顺序检查 — 按从上到下的顺序列出各个区块。断点之前的每个区块在不同请求之间是否都保持稳定?将每次请求都不同的值移到断点之后(第二条系统消息或用户轮次)。
- 断点检查 — 断点是否位于最后一个静态区块?缓存前缀是否达到服务商要求的最低词元数(例如 Anthropic Opus/Sonnet 为 1024 个词元,Haiku 为 2048 个词元,OpenAI 为 1024 个词元)?低于最低词元数时,断点会被静默忽略。
- 结构检查 — 长篇文档是否用分隔符包裹?行为区块是否使用命名标签或分节?
- 字面理解检查 — 如果指令写着“格式化输出”,但实际意图是“格式化每个部分”,请改写为明确说明适用范围。
需要留意的常见错误
- 在顶部放置时间戳。 在角色行中写入
Current date: {{today}}会导致缓存每次请求都失效。将其移到断点之后——第二条系统消息或用户轮次中。 - 缓存过短的前缀。 如果系统提示词低于提供商规定的最小长度,断点会被静默忽略,你仍需支付写入附加费。要么扩大缓存块,要么移除断点。
- 在断点之前放置对话历史。 历史记录会随着每次请求增长,因此断点之后的内容永远无法缓存。将断点放在不断增长的历史记录之前。
- 照搬旧版的
CRITICAL: YOU MUST…式大喊大叫。 这会导致近期模型过度触发。请改写为普通的祈使句。 - 将角色设定放在用户消息中。 在
messages[0]中写You are a…,而不是放在 system 字段中,会削弱引导效果,并浪费一个可缓存的位置。