Skip to content

5.4 缓存边界设计:SYSTEM_PROMPT_DYNAMIC_BOUNDARY ​

学习目标 ​

  • 解释 边界标记 在「静态前缀 + 动态后缀」架构中的角色。
  • 对比 边界之上 与 边界之下 的内容在 稳定性、缓存、风险 上的差异。
  • 说明为何边界设计是 工程上的精妙一刀,而非文档排版技巧。
  • 能向同事用一张表说清:什么必须永远在边界 上方。

生活类比:精装书的「固定正文」与「可撕便签」 ​

一本教材:

  • 胶印正文:出版社一次排版,成千上万册相同 → 像 可缓存的静态宪法。
  • 便签 / 勘误条:贴在末页,每个学生拿到的可能不同 → 像 动态政策。

SYSTEM_PROMPT_DYNAMIC_BOUNDARY 就是 出版社规定的「便签只能贴在勘误页」:

  • 你改便签,不必重印整本书(类比:不必使整个 system 前缀失效)。
  • 若你把便签糊在第一章中间,整本书的「相同页」定义就崩了(类比:缓存前缀无法稳定命中)。

核心概念:边界是「缓存一致性」的语义锚点 ​

在支持 prompt caching(或前缀缓存)的推理栈中,供应商通常对 完全相同的前缀 给予较低单价。

因此产品侧目标非常明确:

  1. 最大化 从 system 开头到某一点为止的 字节级稳定。
  2. 把必然变化的内容 挤到该点 之后,使变化 局部化。

边界标记 SYSTEM_PROMPT_DYNAMIC_BOUNDARY(名称教学化;实现可能是常量字符串)正是 切分点声明:

text
[ 静态:系统宪法 · 超长稳定前缀 ]
<<< SYSTEM_PROMPT_DYNAMIC_BOUNDARY >>>
[ 动态:当期政策 · 每会话/每轮可变 ]

模型会把整段都读进去;缓存子系统 则可能对 前半 与 后半 采用不同计费与失效策略。


边界「之上」与「之下」:对比表 ​

维度边界之上(静态宪法)边界之下(动态政策)
变化频率低(版本发布级)高(会话 / 轮次级)
典型内容身份、规范、哲学、风险、工具总则、语气会话引导、记忆、环境、CLAUDE.md、MCP、预算
缓存诉求强烈希望长期命中接受频繁失效
隐私敏感一般较低(无用户数据)高(记忆、路径、仓库信息)
调试归因变更应可版本化变更常与上下文采集相关

精妙设计体现在哪里? ​

1. 失效局部化(Localization of invalidation) ​

没有边界时,常见反模式是:

  • 在静态块末尾 顺手 拼接 new Date().toISOString()「方便调试」。
  • 结果:整个 system 每秒变一次,缓存 永久报废。

有边界时,工程约定清晰:

  • 时间戳、会话 ID、记忆 → 只能出现在边界 下。
  • Code review 一眼可抓违规。

2. 心智模型对齐(Human + machine) ​

新同事读代码:

  • 看到常量 SYSTEM_PROMPT_DYNAMIC_BOUNDARY 即理解 架构分層。
  • 比散落在各处的 if (dynamic) 更易维护。

3. 与安全策略同构(Optional coupling) ​

部分实现会把 「可审计的静态红线」 完整放在边界上侧,使得:

  • 动态块再花里胡哨,也 较难 在结构上「盖掉」宪法(仍需防 语义冲突)。

Mermaid:边界在拼装中的「刀位」 ​


Mermaid:错误放置导致的缓存雪崩(反例) ​


源码片段(概念):边界常量与拼接 ​

typescript
/** 教学用:显式可检索的切分标记 */
export const SYSTEM_PROMPT_DYNAMIC_BOUNDARY =
  "<<<<CC_DYNAMIC_POLICY_BOUNDARY>>>>";

export function assembleSystemPrompt(parts: {
  staticConstitution: string;
  dynamicPolicy: string;
}): string {
  return [
    parts.staticConstitution.trimEnd(),
    "",
    SYSTEM_PROMPT_DYNAMIC_BOUNDARY,
    "",
    parts.dynamicPolicy.trim(),
  ].join("\n");
}

注意:真实产品中的标记字符串可能 刻意避免 与用户/仓库内容撞车;有时会用极少见 Unicode 或长随机常量(教学简化为可读字符串)。


边界上下内容示例(虚构、缩略) ​

边界之上(摘录) ​

text
你是 CLI 中的编程助手。你必须遵守工具纪律:读文件用专用读取工具,不得用 shell 文本命令替代……
(中略:风险、语气)

边界之下(摘录) ​

text
## 当前会话
工作目录: /Users/alice/proj-foo
Shell: zsh, OS: darwin

## 记忆(最多 5 条)
- 用户偏好:提交信息用中文。

## CLAUDE.md
运行测试:pnpm test

## MCP 工具
- mcp__linear__create_issue …

可见:上侧 像员工手册;下侧 像 今日值班白板。


与「ToolSearchTool / 延迟加载」的边界关系(预告) ​

工具细则可能 不在 全量塞进静态块,而是通过 ToolSearchTool 按需检索各工具目录的 prompt.ts(见 5.8)。

此时仍建议:

  • 工具总则(并行、先读后写、Fail-closed)留在 边界之上 或 极稳定 区域。
  • 单个工具的长说明 可走检索链,避免 静态前缀无限膨胀。

Checklist:Code Review 问句 ​

  1. 本次 MR 是否改变了边界 之上 的文本?若是,是否评估缓存与全用户影响?
  2. 是否有 用户数据 误入边界之上?(隐私与缓存复用风险)
  3. 动态块是否 重复 了宪法内容导致维护分叉?

自测题 ​

  1. 为什么说边界标记主要是 工程与计费结构 问题,而不只是「排版好看」?
  2. 若把 CLAUDE.md 全文挪到边界之上,对 多仓库场景 有何后果?
  3. 边界之下的内容是否「可以随便写」?还有哪些约束(长度、冲突、安全)?

导航 ​

本项目仅用于教育学习目的。Claude Code 源码版权归 Anthropic, PBC 所有。