我在 Claude Code 里敲了一个
hello,然后抓下了它发往模型的完整 HTTP 请求体。 这个五个字母的问候,最终膨胀成了一个数万 token 的 JSON。 本文以这份日志为标本,结合近两年的论文与工程实践,解剖 Claude Code 背后的上下文工程(Context Engineering)哲学。
0. 一个 hello 的解剖
先看这份请求的骨架:
{
"model": "claude-fable-5",
"system": "[ 3 个 block,其中 2 个带 cache_control ]",
"tools": "[ 110+ 个工具定义:27 个内置 + 5 个 MCP server ]",
"messages": [
{ "role": "user", "content": [
"[reminder] SessionStart hook 输出(代码检索协议)",
"[reminder] MCP server 使用说明",
"[reminder] 可用 Skills 清单(约 40 个,每个一行)",
"[reminder] CLAUDE.md 项目宪法 + 记忆索引 + git 快照",
{ "text": "hello", "cache_control": { "type": "ephemeral" } }
]}
],
"context_management": { "edits": [{ "type": "clear_thinking_20251015", "keep": "all" }] },
"thinking": { "type": "adaptive" },
"max_tokens": 32000
}
用户输入占比不足十万分之一。剩下的一切,都是为模型建造的信息环境。
天真的反应是”这也太浪费了”。但如果你把它当作一个精心设计的系统去读,会发现每一个字段都在回答同一个问题——这正是 Anthropic 对上下文工程的定义:
“What configuration of context is most likely to generate our model’s desired behavior?” —— Anthropic, Effective Context Engineering for AI Agents (2025)
下面按层剥开。
1. 第一性原理:注意力是稀缺资源
上下文工程之所以成立为一门学科,前提是承认一个反直觉的事实:上下文窗口不是白板,是预算。
- Liu et al. 的 Lost in the Middle(TACL 2024, arXiv:2307.03172)证明了位置偏差:信息放在长上下文的中部时,模型的召回率呈 U 型塌陷。
- Chroma 的技术报告 Context Rot(Hong, Troynikov & Huber, 2025)进一步表明:即使是最强的模型,随着输入 token 增加,对上下文的利用能力也会普遍退化——差别只是退化得优雅还是难看。
- Anthropic 把这归纳为 “attention budget”:Transformer 的注意力是 n² 的配对关系,token 越多,每对关系摊到的”注意力资本”越薄,且训练分布中短序列远多于长序列。
由此推出上下文工程的黄金准则:
“Find the smallest possible set of high-signal tokens that maximize the likelihood of some desired outcome.”
Mei et al. 的 165 页综述 A Survey of Context Engineering for Large Language Models(arXiv:2507.13334)给了更形式化的表述:上下文不再是单一字符串 prompt,而是一个装配函数 C = A(c_instr, c_know, c_tools, c_mem, c_state, c_query) ——指令、知识、工具、记忆、状态、查询六种组件的动态编排,并在模型注意力约束下求解一个信息装配的优化问题。
带着这个视角回看那份 hello 日志:它不是”一大坨提示词”,而是六种组件各就各位的一次装配。剩下的章节,就是看 Claude Code 如何在这份装配里执行”少即是多”。
2. 缓存经济学:上下文是分层存储,不是一段字符串
日志里最容易被忽略、却最能暴露工程哲学的,是三个不起眼的标记:
"system": [
{ "text": "x-anthropic-billing-header: cc_version=2.1.132.c7b; ..." },
{ "text": "You are Claude Code, ...", "cache_control": { "type": "ephemeral" } },
{ "text": "<数万 token 的行为准则>", "cache_control": { "type": "ephemeral" } }
],
...
{ "text": "hello", "cache_control": { "type": "ephemeral" } }
cache_control 是 Anthropic prompt cache 的断点标记。缓存按前缀命中,顺序是 tools → system → messages。于是整个请求呈现出一个按变化频率排序的稳定性梯度:
| 层 | 内容 | 变化频率 |
|---|---|---|
| tools | 110+ 个工具定义 | 每次 CLI 升级 |
| system[0] | 版本/配置指纹 | 每次配置变更 |
| system[1..2] | 身份 + 行为准则 | 每次 CLI 升级 |
| messages 前缀 | 历史对话 + reminder | 每轮追加 |
| 最后一个 user block | ”hello” | 每轮 |
最稳定的在最前,最易变的在最后,断点打在层与层的边界上。连那个看似只管计费的 billing-header 都有一层意味:它包含版本号与配置哈希,放在缓存前缀的最前端,实际充当了 cache key 的版本戳——配置一变,整条缓存链条自动作废重建。
为什么如此在意缓存?Manus 创始人季逸超(Yichao ‘Peak’ Ji)在 Context Engineering for AI Agents: Lessons from Building Manus(2025)里给出了业界最直白的答案:
“KV-cache 命中率是生产级 AI Agent 最重要的单一指标。”
Agent 的输入输出 token 比约为 100:1,而缓存命中与未命中的价格差是 10 倍(3 /MTok)。由此推出的纪律——前缀保持稳定、上下文只追加不修改、系统提示开头绝不放时间戳、工具集不增删只做 logit 掩码——在这份日志里全部有对应的影子。
最惊人的证据藏在一个工具的说明书里。ScheduleWakeup(定时唤醒)的描述写道:
“Anthropic prompt cache 的 TTL 是 5 分钟。睡过 300 秒意味着下次唤醒要全量重读上下文……不要选 300s,它是两头不占的最差值。不要按’几分钟’思考,要按缓存窗口思考。”
甚至连 CronCreate 都在教模型”避开整点和半点,否则全球用户的定时任务会在同一瞬间砸向 API”。缓存经济学和集群负载工程,被直接写进了 agent 的行为策略。上下文不再只是被动的信息载体——它的物理成本结构反过来塑造了 agent 的时间观。这是把系统工程内化为认知习惯的罕见案例。
3. 动静分离:system 求稳,[reminder] 运送时变状态
一个自然的问题:git 状态、当前分支、可用技能、项目规范……这些”本轮会话的事实”为什么不放进 system prompt?
日志给出的答案是一个专门的带内协议。所有时变信息都以 [reminder] 块的形式注入到 user message 内部:
- SessionStart hook 的输出(用户自定义的代码检索协议)
- 各 MCP server 自带的使用说明
- 约 40 个技能的一行式清单
- CLAUDE.md、记忆索引、git status 快照
而 system prompt 中只有一句冷静的元规则来定义这个协议:
“Tool results and user messages may include system-reminder or other tags. Tags contain information from the system. They bear no direct relation to the specific tool results or user messages in which they appear.”
这个设计一石三鸟:
- 缓存:system 前缀保持逐字节稳定,时变内容顺着 messages 的追加流走,不破坏前缀命中;
- 新鲜度:状态贴着”现在”注入,天然规避 Lost in the Middle——最新的事实永远在注意力最好的位置附近;
- 安全边界:显式声明”标签内容来自系统、与其所在消息无关”,为区分指令通道与数据通道、防御 prompt injection 留下了结构化的锚点。
这就是上下文的”动静分离”架构:恒定的宪法住在缓存里,流动的事实坐在信使的口袋里。
4. 渐进式披露:Skills、Memory 与虚拟内存
日志里那 40 个技能,每个只占一行描述——“何时触发、做什么”。技能的完整正文(SKILL.md,可能数千 token)只有在真正调用时才被加载。记忆系统同理:一个被强制限制在 200 行以内的 MEMORY.md 索引常驻上下文,每条记忆一行指针,正文存在独立文件里按需读取。
这是教科书级的 progressive disclosure(渐进式披露),而它的理论原型早在 2023 年就被提出:Packer et al. 的 MemGPT(arXiv:2310.08560)主张把 LLM 当作操作系统——上下文窗口是 RAM,外部存储是磁盘,模型通过函数调用自主换页。对照日志:
| OS 概念 | Claude Code 对应物 |
|---|---|
| RAM | 上下文窗口 |
| 磁盘 | 文件系统(记忆目录、SKILL.md、计划文件) |
| 页表 | MEMORY.md 索引(≤200 行硬限制) |
| 缺页中断 | Skill 调用 / Read 记忆文件 |
| 换出 | compaction + “先写笔记再被清除” |
Manus 也殊途同归:“把文件系统当作终极上下文——无限大、持久化、agent 可自主读写”,并强调压缩必须可恢复:丢掉网页内容没关系,只要 URL 还在。
但 Claude Code 在记忆上多走了一步,处理了一个学术界正面交锋的问题:记忆的时效性。它的记忆协议里有一条冷峻的规则:
“A memory that names a specific function is a claim that it existed when the memory was written. … ‘The memory says X exists’ is not the same as ‘X exists now.’”
推荐任何来自记忆的东西之前,必须先 grep 验证。记忆被建模为带时间戳的断言(claim),而不是事实(fact)——这是对 RAG 与记忆系统中陈旧知识问题(staleness)最工程化的回答。
同样值得注意的是记忆的写入结构。反馈类记忆强制附带 Why:(用户给出的理由)和 How to apply:(适用边界)——不存”规则”,存”规则+成因”,让未来的自己能在边缘情形下自主裁量。这与 Park et al. Generative Agents(UIST 2023)中 reflection 机制的洞见一致:原始情节记忆必须蒸馏成带因果结构的语义记忆,才能泛化。
5. 隔离:子代理是上下文防火墙
日志中的 Agent 工具描述了一套多智能体机制:Explore(只读检索)、Plan(架构规划)、general-purpose……它们的价值被说得很直白:
“Subagents are valuable for parallelizing independent queries or for protecting the main context window from excessive results.”
子代理在独立的上下文窗口里烧掉几十次搜索和文件读取,最后只把一段摘要带回主干。这正是 Anthropic 在 How we built our multi-agent research system(2025)中的架构结论:搜索型任务天然适合并行的上下文隔离,主 agent 保持干净的推理线程。
但隔离有一条不可逾越的红线,写在工具说明里:
“Never delegate understanding. Don’t write ‘based on your findings, fix the bug.’ … Write prompts that prove you understood: include file paths, line numbers, what specifically to change.”
可以外包搜集,不可以外包综合。上下文可以分片,理解不能分片——否则系统里没有任何一个位置持有完整的因果模型,错误就没有归属。这是多智能体系统里最容易被忽视的架构纪律。
同样精彩的是对子代理能力边界的诚实披露:Explore 的说明主动声明”它读的是片段而不是全文,会漏掉读窗之外的内容,所以别用它做代码评审”。工具的自我贬低,是为了调用者的正确决策——这引出下一节。
6. 工具即课程:说明书里写满成本模型与反模式
把这 110+ 个工具的 description 连起来读,你会发现它们根本不是 API 文档,而是一门关于如何思考的课程:
- 成本模型:codegraph 的说明写着”8 次单点查询的代价远高于 1 次批量 explore,因为每次调用都要重读整个上下文”——把 token 经济学教给模型;
- 反模式:几乎每个工具都有 “When NOT to use” 段落;
TaskOutput整个被标记为 DEPRECATED 并给出迁移路径,甚至警告”不要 Read 子代理的输出文件——那是完整对话记录,会撑爆你的上下文窗口”; - 分页契约:MCP 工具的返回都带
total/has_more字段,说明书教模型”先收窄查询再翻页”——防止一次检索灌爆注意力预算; - 价值观:git 工具的说明里嵌着完整的安全协议(永不 force push main、hook 失败要查根因而不是 —no-verify 绕过)。
这印证了 Yang et al. 在 SWE-agent(NeurIPS 2024, arXiv:2405.15793)中提出的 ACI(Agent-Computer Interface) 论题:agent 的表现不仅取决于模型,同样取决于接口的设计。人类有 IDE,agent 需要为 LLM 的感知与操作特性量身定制的界面。Anthropic 的表述则更简洁:工具应当”自包含、对误用鲁棒、意图清晰”,就像”一个团队里如果每个工程师对同一问题给出矛盾答案,效率会崩溃——工具集对模型也一样,不能有模糊的重叠”。
换句话说:在上下文工程的世界里,接口即提示词,说明书即训练。
7. 遗忘的工程学:clear_thinking、compaction 与外化笔记
上下文工程的另一半是减法。日志里有一个安静但意味深长的字段:
"context_management": {
"edits": [{ "type": "clear_thinking_20251015", "keep": "all" }]
}
这是服务端上下文编辑策略的注册:思考块(thinking blocks)被列为第一顺位的可清除对象——它们生成时昂贵,但对后续轮次的边际价值最低。当前 keep: all 只是尚未触发,策略已经就位。
配套的是 system prompt 里的两条指令:
“The system will automatically compress prior messages as it approaches context limits.” “When working with tool results, write down any important information you might need later, as the original tool result may be cleared.”
这构成一个完整的遗忘协议:压缩(compaction)负责回收,笔记(note-taking)负责保值。模型被明确告知”你的工作记忆会被回收,重要的东西请自己落盘”。Anthropic 博客里那个玩 Pokémon 的 Claude 就是靠这种结构化笔记跨越数十小时的任务;Manus 则用了一个对偶技巧——recitation(复诵):不断重写 todo.md 并附在上下文末尾,把全局目标主动推进注意力最好的位置,对抗 lost-in-the-middle。
Manus 还有一条反直觉的补充:不要清除失败记录。错误的 action 和 stack trace 留在上下文里,是模型更新内部信念、避免重蹈覆辙的证据。遗忘要有选择性——丢弃冗余,保留教训。
8. 对偶面:CLAUDE.md 是用户写给机器的反漂移宪法
前面都是框架为模型做的策展。这份日志还展示了硬币的另一面——用户为框架做的策展。被注入的 CLAUDE.md(项目级指令文件)本身就是一件上下文工程作品:
- 反漂移契约:“以下 16 条规则是 anti-drift contract,任何 PR 偏离必须显式说明并更新本节”——用宪法条文的写法对抗多轮会话中的架构漂移;
- 单一事实源声明:“六个阶段名只在 digestion.py 定义一次,前端必须走 API 读取,禁止硬编码”——把 DRY 原则显式喂给模型;
- 对抗文档腐烂:迁移索引里用 ⚠️ 标注”原计划添加 X——实际没有落地,上文规则 4 因此是期望而非现实”。这是罕见的自我诚实:文档不仅记录做了什么,还记录声称做了但没做的,防止模型把愿景当事实;
- 坑位说明(gotchas):“永远用 make run-xxx 重启 agent,症状是 DNS 解析失败,修法不是加环境变量而是……”——把故障的症状-根因-修法三元组预先写进上下文。
这份文件的读者从头到尾只有一个:模型。人类工程师写给机器读的规范文学,是 2025 年之后才出现的文体。它提示我们:上下文工程不是框架厂商的独角戏,而是框架、用户、模型三方共同维护的一份活的契约。
9. 结语:从写咒语到造环境
回到最初的问题:一个 hello 为什么值得数万 token?
因为这数万 token 买到的不是那句 “Hi! How can I help?”,而是一个随时可以开始严肃工作的认知环境:缓存已预热、工具已陈列、项目宪法已生效、记忆索引已挂载、遗忘协议已注册。第一次问候摊销掉环境的构建成本,之后的每一轮都在 10 倍便宜的缓存轨道上运行。
Karpathy 的比喻在这里落地得异常精确:LLM 是 CPU,上下文窗口是 RAM。而这份日志展示的,就是一个操作系统该有的全部部件——
| 系统概念 | 在 hello 日志中 |
|---|---|
| 存储层级 | tools → system → messages 的稳定性梯度 + cache_control |
| 虚拟内存 | Skills / Memory 的渐进式披露,MEMORY.md 页表 |
| 进程隔离 | 子代理独立上下文,摘要作为 IPC |
| 换出策略 | clear_thinking 先行、compaction 兜底、笔记保值 |
| 系统调用规范 | 工具说明书里的成本模型与反模式 |
| 配置层级 | 官方 system < CLAUDE.md < 用户规则 < session hook |
如果说 prompt engineering 是给模型写咒语,context engineering 就是给模型造环境——一门关于策展(curation)、压缩(compression)、隔离(isolation)、外化(externalization)与验证(verification)的系统学科。它的全部技巧最终收敛于 Anthropic 那句朴素的告诫,也是这份日志每一个字节都在实践的原则:
对一个有限的注意力预算,做最小充分的高信号装配。Do the simplest thing that works.
参考文献
- Anthropic Applied AI Team. Effective Context Engineering for AI Agents. Anthropic Engineering Blog, 2025.
- Yichao ‘Peak’ Ji. Context Engineering for AI Agents: Lessons from Building Manus. Manus Blog, 2025.
- Lingrui Mei, et al. A Survey of Context Engineering for Large Language Models. arXiv:2507.13334, 2025.
- Nelson F. Liu, et al. Lost in the Middle: How Language Models Use Long Contexts. TACL 2024. arXiv:2307.03172.
- Kelly Hong, Anton Troynikov, Jeff Huber. Context Rot: How Increasing Input Tokens Impacts LLM Performance. Chroma Technical Report, 2025.
- Charles Packer, et al. MemGPT: Towards LLMs as Operating Systems. arXiv:2310.08560, 2023.
- John Yang, Carlos E. Jimenez, et al. SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering. NeurIPS 2024. arXiv:2405.15793.
- Joon Sung Park, et al. Generative Agents: Interactive Simulacra of Human Behavior. UIST 2023. arXiv:2304.03442.
- Anthropic. How We Built Our Multi-Agent Research System. Anthropic Engineering Blog, 2025.
- Anthropic. Prompt Caching 文档:缓存前缀顺序 tools → system → messages,5 分钟 TTL。