提示词设计
静态骨架 — 找对高度、把指令结构化成模型真正能解析的形态、用示例作为主要的引导手段、排布 prompt 块让缓存真正生效
静态骨架
系统提示词是 Agent 始终会看到的那一部分上下文。和消息历史(会增长)、工具结果(来来去去)不同,骨架写一次、每轮都被重读一次。这种不对称改变了它的设计方式:
- 你写进去的每个 token 都每一轮都要付一次费 — 开了 prompt 缓存后便宜,没开就不免费。
- 落进骨架的 token 会和所有后续的用户消息、工具结果抢注意力。一个臃肿的骨架会悄无声息地劣化每一轮未来对话。
- 这是你完全可控的唯一一部分上下文。其余都由用户问什么、工具返回什么塑造。
骨架的职责,是紧凑地、在合适的抽象层,编码 Agent 的角色、能力和行为默认值。
正确的高度 (Right Altitude)
最常见的系统提示词失误,是选错了规格化的高度 (altitude) —— 指令的抽象层级。Anthropic 点出两种失败模式:
避免在提示词里写复杂、脆弱的逻辑去硬驱出精确的 Agent 行为。[…] 也避免模糊、高层次的指导,给不了 LLM 具体信号。 — Effective Context Engineering for AI Agents
目标在两者之间:具体到能可靠引导行为,灵活到能处理提示词没预见过的情况。
一个快速的检验:外部一个变化(新的边界情况、新工具、用户新措辞)发生时,不用重写提示词能处理吗?
- 太具体:“如果用户说
migrate,调用db_migrate。如果说import,调用data_import。” — 脆弱。第十一个动词就把提示词撑爆了。 - 太模糊:“帮助用户处理数据库任务。” — 无用。任何非平凡场景,模型都会自己编造”帮助”是什么意思。
- 正确高度:“你执行数据库管理任务。用户请求 schema 变更时,先检查当前 schema、提出迁移方案、获得确认、再应用。不经明确确认不得删除数据。”
正确高度的版本写明了做什么、以什么顺序、红线在哪 — 同时没有穷举每个动词或每张表。
经验法则:写一份新来的工程师照着就能执行的提示词。如果他对每一个现实中的 X 都要问”那 X 呢”,说明你太模糊;如果他不用思考就能照做,说明你太具体。
提示词解剖学
一份可用的系统提示词通常包含这些段落,大致按此顺序:
| 段落 | 作用 | 示例内容 |
|---|---|---|
| 角色 / 身份 | Agent 是谁、为何存在 | ”你是 Zapvol 代码库的代码审查助手。“ |
| 能力 | Agent 能做什么 — 通常通过可用工具表达 | ”你可以读文件、跑测试、提出补丁。“ |
| 行为规则 | 不可妥协的默认值 — 规则冲突时的优先级 | ”绝不修改工作目录之外的文件。“ |
| 工作流 | 任务的典型流向 — 是指南不是死流程 | ”提议之前先读相关文件。汇报完成前先跑测试。“ |
| 输出规范 | 格式、语气、长度预期 | ”用简洁的散文汇报。每个结论给出 file:line 引用。“ |
| 兜底通道 | 模型困惑时怎么办 | ”用户意图不清时,问一个澄清问题。” |
两个原则统领整个解剖:
用策略代替枚举。 别列每个情况,给模型一条能套用的小策略:
不要:“如果 X 做 A。如果 Y 做 B。如果 Z 做 C。”
更好:“区分只读操作和破坏性操作。破坏性操作一律先确认。”
约束只在最高适用层说一次。 如果一条规则对所有工具都适用,写在行为规则里 — 别塞进每个工具的描述。骨架里的重复就是注意力税。
角色声明是超比例杠杆 (Role as Disproportionate Lever)
一句话声明模型”是谁”,对语气、用词、细节深度、行动意愿的影响,通常超过同等长度的一条规则。值得单独拎出来讲,是因为写长提示词时很容易写着写着忘了明确角色。
对比:
- 无角色:“帮用户处理代码。”
- 有角色:“你是 TypeScript 后端的资深代码审查员。审查聚焦正确性,不管风格。”
第二版在每一个下游决策上都在引导模型 — 它选择标记什么、措辞多简洁、是直接改动还是提问。你不用在提示词里到处重复”作为资深审查员” — 开头的角色声明会贯穿下文。
两条经验:
- 一个角色、具体。 “TypeScript 后端的资深代码审查员”胜过”乐于助人的助手”。抽象角色产生抽象行为。
- 别堆角色。 “你是代码审查员、产品经理和文案” —— 产出的是一个糊成一团的平均值。如果一个 Agent 需要多种模式,按轮显式切换,或者拆成独立 Agent。
结构:XML vs Markdown
Claude 能同时解析 XML 标签和 Markdown 标题。用哪个取决于你在分隔什么:
-
Markdown 标题(
##、###) — 用于提示词自身的段落:角色、工作流、输出规范等。标题给模型一个天然的目录;每段内用散文就够。 -
XML 标签 — 用于模型必须当成数据而非指令的内容。最常见的用法:
<example>/<examples>— few-shot 示例<document>/<document_content>/<source>— 需要模型分析的文档<context>/<input>— 每次调用会变的变量输入- 任何你想让模型在输出中也产生的自定义标签:“在
<thinking>标签里写你的推理”
经验法则:指令用 Markdown,负载用 XML。 XML 给模型一个毫不含糊的边界,分开”我在问什么”和”我在问关于什么”。
多文档分析时,Anthropic 建议每份文档单独包装:
<documents>
<document index="1">
<source>report_q3.pdf</source>
<document_content>{{CONTENT}}</document_content>
</document>
<document index="2">
<source>competitor_brief.md</source>
<document_content>{{CONTENT}}</document_content>
</document>
</documents>
对比这两份文档,指出三个战略缺口。
示例优于规则
对 LLM 来说,示例是”胜过千言万语的图片”。
几个好示例常常胜过几页规则。示例特别擅长:
- 格式 / 结构 — 演示一次答案的形态,模型就能照着仿。
- 语气 — 在目标语气里写两三条示范,模型会对齐。
- 边界情况 — 不用穷举”如果 X、Y、Z”,给几个示例共同覆盖决策边界。
挑示例的要点:
| 质量 | 含义 |
|---|---|
| 相关 | 映射真实输入,不是玩具样例 |
| 多样 | 覆盖多个维度 — 不要让模型过拟合单一模式 |
| 结构化 | 用 <example> 标签包起来,别和当前输入混淆 |
| 校准 | 包含临界样例,不只是简单胜场 — 模型从中学到决策线 |
3-5 个示例通常是甜蜜点。再少,模型泛化不足;再多,你在为”前三个已经教会的东西”付 token 钱。
必要时用反例。 一条标注清楚的”不要这样做”,有时比十条规则管用 — 特别是对常见失败模式。但慎用:否定比正向示范对模型更难。
说该做什么,不说不该做什么
否定性指令写起来容易,效果比正向指令弱:
| 较弱 | 较强 |
|---|---|
| ”不要用 markdown。" | "用纯散文段落回答。" |
| "不要啰嗦。" | "除非任务需要,否则回答控制在 100 字以内。" |
| "绝不拒绝合理请求。" | "请求含糊时,挑最可能的解释并执行。" |
| "不要啥都用 bullet。" | "推理用散文;只在呈现清单时用 bullet。” |
原因:模型被训练来产出文本。“不要做 X”仍然把 X 作为活跃概念放进了上下文;“改做 Y”则给了模型一个可以实际生成的东西。正向表达也更好地扛过压缩和微调 — 模型保留的是行为,不是禁令。
确实需要否定时,配一个正向替代:
“绝不编造文件路径。不确定时,先用搜索工具验证。“
先引用、再作答 (Grounding in Quotes)
当模型需要在长输入上推理(一份大文档、一段对话记录、多文件上下文 dump)时,让它先引用相关段落,再基于引用作答。形态:
<document>{{LONG_INPUT}}</document>
从文档中找出与用户问题相关的段落,放进 <quotes> 标签。然后回答问题,每一条论断都要**锚定**在某段引用上。
为什么奏效:
- 注意力锚点。 产出引用这个动作让模型重新聚焦到具体段落,穿透周边噪音。
- 可验证。 每条论断都可追溯到源段落。和引用对不上的编造内容肉眼可见地错。
- 廉价自检。 不用单独加一个验证步,“先引用”的模式就能抓住**大多数”模型自信地编了个东西”**的失败。
同样的模式也适用于 Agent 的工具结果:当工具返回一大段输出(长搜索结果、文件 dump),让 Agent 在行动前先摘相关行。这比完整摘要更轻,又保留了精确引用。
工具定义就是提示词的一部分
每个工具定义都会进上下文窗口。一个 15 个工具的普通 Agent,工具定义轻易占到骨架 3-5k token。三个推论:
- 工具数量要紧。 每个工具都必须配得上它的位置。如果两个工具用途重叠,模型就要花思考 token 在它们之间选 — 合并或删除。
- 工具描述本身就是提示词。 每份描述每一轮都会被重读。简洁、不含糊,同时说明何时用、何时不用。
- 参数名和文档也在引导模型。
search(query: string)比search(query: string, /** 自然语言搜索短语,3-10 词 */)弱。JSDoc 风格的指引是提示词里的提示词。
设计良好的工具的检查清单:
- 名字:动词-名词、不含糊(
read_file胜过file) - 描述:单段、说明用途、列出何时用、列出何时不用
- 参数:每个都有文档;必填 vs 可选清楚
- 输出:形态可预测;错误情况明确
- 不和其他工具重叠。若不可避免,描述里主动把用户引向对的那个(“语义查询用
search_code;精确字符串用grep”)。
缓存感知的排序
Anthropic API 和同类服务支持的 prompt 缓存,首次写入 1.25× 基础价,命中时 0.1×。Agent 每轮都会重读完整提示词,所以缓存通常在单个任务内就已经回本。但缓存按前缀匹配:缓存部分必须出现在开头,在任何动态内容之前。
正确的顺序,从最稳定到最动态:
- 工具 — 通常整个任务不变
- 系统提示词 — 同一 Agent 在不同任务间不变
- 长期上下文 — 用户开始时附的文件、之前会话的摘要
- 耐用示例 — 每轮都不变的 few-shot
- 消息历史 — 动态
- 当前用户轮 — 最动态
如果你把动态时间戳放在系统提示词的第一行,什么都不会缓存。顶部一个挥发性 token 会废掉后面的所有前缀。挥发性内容往后挪;能塞进当前用户轮就塞进去。
对写法的推论:别顺手把每轮的数据(用户当前时间、最近的工具结果、上一次错误)塞进系统提示词去”个性化”。那些内容属于消息历史或工具结果上下文,不属于骨架。
与长文档放置的张力
另一条并行的最佳实践是:分析大文档时,把文档放在提示词顶部、问题之前。在复杂多文档任务上,这能把响应质量提升多达 30%。
当”长文档”每次调用都变时,缓存排序和长文档排序就冲突了:
- 如果文档在整个任务中稳定(仓库文件、项目简报),它属于被缓存的前缀 —— 早放、被缓存。
- 如果文档是一次性的(用户刚粘贴的报告、新鲜的搜索结果),放在系统提示词顶部每轮都废掉缓存。把它塞进用户轮,用独立的
<document>包装。
这不是”二选一”。解法是:让内容的稳定性决定它该放哪。 稳定且长 → 缓存前缀;一次性且长 → 用户轮。
反模式
设计时的错 —— 提示词写作里常见的作者级失误。对应的运行时失败见 上下文管理 → 失败模式。
| 反模式 | 为什么伤 |
|---|---|
| 防御式规则堆积 | 每次失败都加一条规则;骨架膨胀、注意力稀释。修根因,别堆规则。 |
| 冲突指令 | 规则之间互相矛盾,模型自己挑 — 行为变得不可预测。 |
| 过度触发语言 | ”CRITICAL: You MUST…” 在弱模型上管用;新模型上会过度触发。 |
| 给工具该做的事写提示词 | ”记住你有个 search_code 工具” 是工具描述的问题,不是提示词的问题。 |
| 顶部放动态内容 | 废掉缓存。每轮付全价。 |
| 过早优化 | 在三个样例上调一版提示词。没评测就是在猜。 |
何时停止迭代
一份提示词完成了,当:
- 测量指标(任务完成率、正确率、格式符合度)达到目标。
- 失败模式和之前定性地不同了 — 不再是上一版试图修的那种失败。
- 新加的规则在一个维度回归的同时修好了另一个维度。这个信号说明你已经摸到提示词高度的天花板。再往前需要换机制 — 更好的工具、更好的示例、更好的记忆 — 而不是更多提示词文字。
要避免的失败模式:为了处理最新的边界情况加了第 47 条规则,却没在多样化评测集上检查它会不会破坏规则 #1-46。没有评测的迭代不是迭代,是随机游走。
如何度量 (Measuring It)
提示词是工程件,值得和代码一样的度量纪律。一套最小评测装置:
- 一组固定输入 —— 真实、多样、包含你在意的边界情况。20-50 条起步就够。
- 每条输入的期望行为 —— 金标答案、打分量规、或一个检查函数。不必严格;“必须提到 X、不得推荐 Y”就够。
- 一种批跑方式 —— 脚本、notebook 或 CI 任务。
- 回归基线 —— 改 prompt 之前跑一遍、保存结果;改完再跑一遍、对 diff。
pass/fail 之外有用的信号:
- 每次调用的 token 成本 —— 质量提升但成本 3× 的版本可能不值。
- 缓存命中率 —— 缓存感知排序奏效时,重复任务类型的命中率会爬到 80%+。
- 失败模式是否变化 —— 出现新失败无所谓,老失败还在就说明这版没帮上忙。
没有这个回路,每次 prompt 改动都是观点。有了,它就是可度量的一步。
相关阅读
- 记忆设计 —— 提示词骨架是放稳定信息的一个地方;记忆是另一个。两者组合:召回工具的描述住在提示词里,它取出的记忆住在窗口外。
- 上下文管理 —— 决定提示词如何与所有动态部分互动:工具结果、消息历史、子 Agent 轨迹。脱离运行时单独优化的 prompt,会被糟糕的运行时管理抵消。
来源
- Effective Context Engineering for AI Agents — Anthropic, 2026
- Prompting best practices — Anthropic, Claude API 文档
- Prompt caching — Anthropic, Claude API 文档
- OpenAI Prompt Engineering Guide — 对 role-setting、结构化输出、few-shot 挑选的互补论述
- The Prompt Report: A Systematic Survey of Prompting Techniques — Schulhoff et al., 2024,跨文献的 prompting 技法分类