阅读顺序决定理解深度
三篇的发布顺序:Prompt Caching Is Everything(2月19日)→ Seeing like an Agent(2月27日)→ How We Use Skills(3月初)。时间顺序恰好也是逻辑顺序,但不是"从基础到高级"的递进,而是从约束到设计到扩展的推演。
先搞清楚你受什么限制(Caching),再在限制内设计 agent 的感知与行动(Seeing like an Agent),最后在不破坏前两层的前提下让系统持续生长(Skills)。
第一层:Prompt Caching 不是优化,是物理定律
"Cache Rules Everything Around Me." 很多人把这当性能优化建议,这是误解。
Prompt Caching 的工作机制是前缀匹配——API 从请求开头开始缓存,直到每个 cache_control 断点。这意味着你的前缀必须是稳定的、可预测的、跨会话几乎不变的。
Claude Code 团队对缓存命中率的态度很能说明问题:他们对命中率设了告警,命中率过低直接宣布 SEV(严重事件)。缓存命中率不是性能指标,是运营指标——它直接决定成本和延迟,进而决定能给用户多大的速率限制。
由此倒逼出一些反直觉的设计决策。最典型的例子是 Plan Mode:直觉上,进入 Plan Mode 应该把工具集切换成只读工具。但这会破坏缓存前缀。所以 Claude Code 的解法是——工具集始终不变,用一个专门的工具来表达"进入/退出 Plan Mode"的状态转换。
核心原则:前缀稳定性是第一设计原则。 工具集的组织方式、信息注入时机、模型切换策略,全部围绕它展开。违反它的代价不是"慢一点",而是系统在规模上直接无法运转。
第二层:工具的形状是认知的外骨骼
第一篇说工具集不能中途改变。第二篇回答紧接着的问题:那你应该把什么工具放进那个不变的集合里?
Thariq 用了一个数学题类比:如果给你一道很难的数学题,你想要什么工具?纸是最低配,但受限于手动计算;计算器更好,但你得会用高级功能;电脑最强,但你必须会写代码。
这里有个关键洞察:工具的最优集合不是由任务决定的,而是由 agent 的认知能力决定的。 你需要给它跟它能力形状匹配的工具。怎么知道它的能力形状?没有捷径——观察、实验、读输出,"see like an agent"。
几个具体的设计教训:
工具数量的悖论。 太少,能力受限;太多,认知过载。Claude Code 维护约 20 个工具,每增加一个都要认真权衡——每个额外选项都是 agent 在每一步必须考虑的认知负担。这个数量不是历史积累的结果,是持续精简后的答案。
渐进式披露(Progressive Disclosure)。 这是连接第二篇和第三篇的枢纽概念。不能无限增加工具,但需要无限扩展能力,怎么办?让 agent 按需发现能力——不是初始化时把所有东西装进 working memory,而是需要时去读、去找、去组合。
AskUserQuestion 工具的演进也很有意思。 最初在系统提示里教 Claude 如何提问,结果提问方式不一致、结构不可预测。最终方案:设计一个专用工具,触发时弹出 modal,阻塞 agent 循环直到用户回答。Claude 天然喜欢调用工具,输出也更稳定。结论是:结构化的工具调用界面,比系统提示里的自然语言指令,能更可靠地产生结构化行为。 你不只是在给 agent 知识,你是在给它一个行动的模具。
同样的逻辑解释了为什么"把使用文档塞进系统提示"是错的——信息被用到的频率远低于它占用上下文的代价。更好的做法是让 Claude 在需要时调用子 agent 搜索文档。子 agent 本身就是一种工具。
核心原则:从 agent 的感知视角设计行动空间,不是从你的视角。 Agent 看到的是工具定义、schema、被提示召唤的可能性——不是你以为你告诉了它什么。
第三层:Skills 让系统在双重约束下长出手脚
第一层:工具集不能中途改变(缓存约束)。第二层:工具集必须精简(认知约束)。第三层要回答:在这双重约束下怎么让能力持续扩展?
先破除一个常见误解:Skills 不是 Markdown 文件,它们是文件夹——包含脚本、模板、数据、配置甚至动态 hook 的文件夹。这个区别在执行层面是天壤之别。当 Skill 只是文字说明时,agent 需要从头推理所有执行上下文;当 Skill 是一个可探索的文件夹时,agent 可以直接发现它需要的东西。探索的认知负荷远低于推理的认知负荷。
这里有个精妙的设计:description 字段同时服务两个受众。人类读它来理解这个 Skill 是什么,agent 读它来判断是否触发。一个面向理解,一个面向匹配,写法完全不同。
Skills 怎么解决缓存约束?通过渐进式披露添加能力,不修改 cached prefix。安装新 Skill 时,系统提示里只增加名字和 description——几十个字符。Skill 的全部内容只有在 agent 决定调用时才被读入。轻量级存根在缓存中,完整能力按需加载。
Skills 的几种典型形态:
- 知识类: 内部库的边界情况与 gotchas;症状→工具→查询模式的 Runbook 映射
- 执行类: 驱动真实 UI 的端到端测试;构建→烟雾测试→流量切换→回滚的 CI/CD 流程
其中信号量最高的部分是 Gotchas 区块——从 agent 实际失败点中积累的经验,把历史错误编码成下次执行的先验。因为 agent 没有跨会话记忆,Gotchas 是人类把"某次执行的失败"传递给"未来某次执行的 agent"的唯一机制。
三层架构的统一逻辑
大多数人构建 AI 应用是自上而下的:我想让 agent 做什么→怎么告诉它→技术细节最后搞。Thariq 描述的是相反的工程哲学:自下而上——先理解物理约束,再在约束内设计认知接口,最后构建扩展生态。
三层还有一个更深的统一性,它们都在回答同一个根本问题:如何在 agent 的认知限制内,实现超越这个限制的系统能力。
- Caching 解决 agent 无法承担无限计算的问题
- Action Space 设计解决 agent 无法处理无限选项的问题
- Skills 解决 agent 无法在单次会话内掌握所有领域知识的问题
本质上是同一件事:agent 是资源有限的存在,harness engineering 是在这个前提下构建无限延伸能力的工程艺术。
对独立开发者的实操意义
如果你在用 Claude Code 或者自己搭 agent 系统,这套方法论的启示很直接:别急着往系统提示里塞东西,先画清楚你的缓存边界在哪里;工具不是越多越好,20 个是 Claude Code 团队反复精简后的数字;能力扩展走 Skills 的路子——轻量级存根加按需加载,别让你的 agent 在每次对话开始时就背着整个知识库跑。
最后有个自指的美妙之处:最好的 Skill 是用 agent 来写的,最好的 harness 改进是用 agent 分析 agent 的失败而产生的。这不是循环,是自举——让 agent 参与构建容纳自己的结构。