Skill 加载看起来像一个文件读取问题,实际包含两条不同的链路:

  • 宿主进程何时扫描、解析并缓存 SKILL.md
  • Skill 内容何时进入模型可见的上下文

两条链路可能一早一晚。OpenCode 会在宿主侧初始化 Skill registry,但模型仍要调用 skill 工具才会看到正文;Claude Code、Codex、Cursor 和 Kimi Code 也都把轻量目录与完整说明分开处理。用“启动时有没有读文件”判断是否按需加载,很容易得出相反结论。

更准确的问题有三个:模型启动时看到了什么,正文以什么形式进入会话,长会话压缩后哪些内容能够恢复。

核验日期:2026-07-17。产品实现会持续变化。正文把官方公开契约、源码观察和未知行为分开标注,不用一个产品的行为推断另一个产品。

比较对象必须处在同一层

模型、API、Harness 和最终产品经常共用一个名字,但它们负责的事情不同。

层级 负责什么 例子
模型 上下文上限、推理、工具调用能力、多模态 Claude、GPT、Kimi K2
API / Provider 请求协议、缓存计费、Tool Search、托管工具 Anthropic Messages、OpenAI Responses、Moonshot API
Harness 扫描文件、装配上下文、执行工具、compact、权限与 Hook Claude Code、Codex CLI、OpenCode、Cursor Agent、Kimi Code
能力包 可复用说明、脚本、参考资料和资源 Agent Skills、Rules、Commands、Plugins
产品 UI、会话管理、账户、配额和团队治理 Codex App、Cursor IDE、Kimi Agent

Kimi K2 是模型,不能和 Claude Code、OpenCode、Cursor 直接比较 Skill 扫描。初版 Kimi K2 的官方模型卡给出 128K 上下文;2025 年 9 月的 K2-0905 才升级到 256K。承担 Skill 发现和 compact 的同层对象是 Kimi Code。

同样,API 支持每次请求携带不同的 tools,不等于某个 Harness 每轮都会重建工具集合。Tool Search 是 API 或模型提供的延迟工具定义能力,也不等于 Agent Skills 的加载实现。

Agent Skills 的三级渐进披露

Agent Skills 开放标准把一个 Skill 定义为目录中的 SKILL.md,并允许附带脚本、参考资料和资源。常见结构如下:

1
2
3
4
5
my-skill/
├── SKILL.md
├── scripts/
├── references/
└── assets/

渐进披露分为三层。

层级 进入上下文的内容 目的
Discovery namedescription,有时还有路径或触发提示 让模型知道有哪些能力
Activation 被选中的 SKILL.md 正文 提供流程、边界和决策规则
Execution 特定 reference、脚本输出或资源 完成当前分支,不加载无关材料

这是一种上下文索引。目录负责召回,正文负责执行,支持文件负责展开细节。目录不是正文的摘要替代品;如果 description 已经足以让模型跳过正文,Skill 的分阶段流程反而容易失效。

组件结构:谁保存内容,谁决定进入窗口

Skill 系统至少包含来源、注册表、路由器、加载器和上下文装配器。长会话还需要缓存、压缩器和外部状态协同。

Skill 从文件来源进入模型上下文的组件结构

图中经常被混淆的是 Registry 和 Context Assembler。

  • Registry 面向宿主进程。它可以保存 metadata,也可以预先保存解析后的完整正文。
  • Router 面向当前任务。它根据显式命令、description、文件作用域或权限选择候选能力。
  • Loader 负责取得正文和支持文件。数据可能来自磁盘缓存、插件包、远程目录或已初始化的 registry。
  • Context Assembler 决定哪些内容进入 system、developer、user、tool description 或 tool result 等模型输入位置。
  • Compactor 处理历史增长;Rehydrator 决定 compact 后重新挂载哪些外部材料。

“宿主已读正文”不代表“正文已占用模型上下文”。反过来,正文进入会话历史后,也不代表每一轮都会重新从磁盘读取。

一次 Skill 调用的运行时生命周期

时序图只表达跨产品都能成立的抽象过程,不承诺具体消息 role 或 XML 包装。

sequenceDiagram
    participant FS as Skill sources
    participant REG as Registry
    participant ASM as Context assembler
    participant M as Model
    participant LOAD as Loader
    participant T as Tools / scripts
    participant C as Compactor

    FS->>REG: 扫描并解析 metadata
    REG->>ASM: 提供可用能力目录
    ASM->>M: 轻量 catalog 随当前上下文进入模型
    M->>M: 根据任务、description、权限与作用域选择
    M->>LOAD: 显式命令或 Skill 调用
    LOAD->>REG: 取得 SKILL.md 正文
    LOAD-->>M: 正文进入当前会话
    M->>T: 按需读取 reference 或运行 script
    T-->>M: 返回与当前任务相关的结果
    M->>C: 长会话接近阈值时触发 compact
    C-->>ASM: 摘要、保留尾部与可恢复材料
    ASM-->>M: 重建下一段工作上下文

这条链路可以由用户手动触发,也可以由模型自动路由。两种方式共享正文和资源,差别只在选择器。

正文第一次进入会话后通常成为历史的一部分。后续 API 请求会携带仍在工作窗口内的历史,但这叫“保留已有上下文”,不是“每轮新增一份 Skill”。如果 Harness 采用精确前缀缓存,历史前缀还可能命中缓存,不能把累计输入 token 直接当成每轮新增计算量。

两种加载:宿主加载与上下文加载

OpenCode 很适合说明这一区别。当前官方文档和 dev 分支源码显示:

  1. Skill service 扫描目录、解析 frontmatter,并可把正文存入 registry。
  2. 模型初始获得可用 Skill 目录。
  3. 模型调用内置 skill({name}) 后,工具才把正文、base directory 和部分支持文件信息返回到当前会话。

因此,OpenCode 的文件读取可以是 eager,正文对模型的暴露仍然是 lazy。调用时也不是新增一个专属 tool schema;skill 是预先注册的元工具,按需变化的是返回的 Skill 内容。

Claude Code、Codex 和 Kimi Code 的公开文档同样采用轻量目录与正文按调用展开。Cursor 则同时保留两套机制:

  • Rules / AGENTS.md 提供静态或条件式指令
  • Agent Skills 提供由模型或用户选择的动态能力

把 Cursor 简化为 glob Rules,会漏掉 2026 年加入的 Agent Skills、Subagents、Plugins 和动态上下文发现。

消息形态是实现细节,不是跨产品标准

Skill 内容最终必须以某种形式进入模型输入,但具体 role、包装标签和数组位置可能随 Provider、模型或版本变化。稳定比较应该停在语义槽位。

语义槽位 常见内容 生命周期
Initial instructions Harness 基线、项目指令、无条件 Rules 会话启动或作用域切换
Capability catalog Skill metadata、延迟工具目录 启动装配,受预算和权限过滤
Tool definitions 内置工具、MCP schema、Skill 元工具 由 Harness 和 API 能力决定
Conversation history 用户请求、模型输出、已加载 Skill 正文 随轮次增长,可能被 compact
Tool output 文件内容、脚本结果、Skill 工具返回 靠近当前调用,之后进入历史
Rehydrated context compact 摘要、根指令、最近 Skill、记忆指针 压缩后重新装配

Claude Code 官方文档只承诺 Skill listing 和调用后的正文生命周期,不承诺 listing 永远位于固定 API role,也不承诺使用固定 <system-reminder> 包装。把一次运行时 trace 提升成长期产品契约,会让文章很快过期。

热更新不等于重复注入

热更新解决的是 Registry 和未来调用看到哪个版本,重复注入讨论的是会话历史是否增加副本。两者没有必然关系。

截至核验日期,各产品公开边界如下。

Harness 已确认行为 不能据此推出
Claude Code 监视已存在的个人、项目和附加目录;更新 SKILL.md 后影响 catalog 与未来调用 历史中的旧正文会被原地替换
Codex 文档描述 Skill 变更可被检测,异常时仍可能需要重启 所有 surface 都有相同的实时刷新语义
OpenCode 当前源码从初始化后的 registry 返回正文 下一次调用一定重新读取磁盘
Cursor 官方承诺启动时发现 Skills 当前聊天必然实时更新 catalog
Kimi Code 官方说明扫描来源和调用方式 新增或修改 Skill 必然在下一轮生效

Claude Code 的边界更具体:启动后新建顶层 Skill 目录可能需要重启;热检测主要覆盖 SKILL.md,插件中的 Hook、MCP 和 Agent 变化需要单独 reload。已加载的旧正文不会追溯替换。相同渲染结果的重复调用在当前版本只附加短提示;正文发生变化时,新的渲染结果才会作为新内容进入会话。

Compact 之后,Skill 怎样回来

压缩恢复是产品差异最大的环节,也是最不适合互相类推的环节。

stateDiagram-v2
    [*] --> Discovered
    Discovered --> Selected: route / explicit invoke
    Selected --> Loaded: SKILL.md enters context
    Loaded --> Active: references / scripts / tools
    Active --> Resident: retained in recent history
    Resident --> Summarized: full compaction
    Resident --> Pruned: tool-output pruning
    Summarized --> Rehydrated: product-specific restore
    Pruned --> Selected: invoke again
    Rehydrated --> Active
    Summarized --> Selected: invoke again if not restored
Harness 公开可确认的恢复行为 仍然未知或没有保证
Claude Code system prompt 保持;根 CLAUDE.md、无条件 Rules、auto memory 重新注入;最近调用的 Skill 正文按预算重挂 超出预算的旧 Skill 不会全部保留
OpenCode 原生 Skill 工具输出受普通 tool-output prune 保护 full LLM compaction 没有 Skill 正文自动原样重挂保证
Cursor Always Rules 跨 summarization 保持;历史会话可作为文件检索 Agent Skill 正文的精确保留和重注入算法未公开
Codex 自动或手动 compact 可产生 opaque compaction item 本地 Skill 与 AGENTS.md 的逐项恢复规则未完整公开
Kimi Code 支持自动压缩和 /compact Skill 正文如何保留、淘汰或重挂未公开

Claude Code 当前公开了最明确的预算:compact 后每个已调用 Skill 最多重附加 5000 token,全部 Skill 合计最多 25000 token,最近调用优先。这里的 5000 是恢复上限,不是“单个 Skill 平均大小”。

OpenCode 还要区分普通 pruning 与 full compaction。核验日固定 commit 的 compaction 源码把原生 skill 放入 prune 保护名单,因此启用普通工具输出裁剪时不会直接擦掉它;full compaction 会把旧消息总结成摘要,旧 Skill 是否留下足够细节取决于摘要。模型仍可再次调用 skill,但那是恢复路径,不是自动恢复承诺。

Rules、Skill、Tool Search 与 MCP 分别解决什么

这些机制都可能减少前置上下文,却不属于同一层。

机制 被选择的对象 选择器 进入上下文的内容
Rules / AGENTS 项目约束或文件作用域指令 always、路径、glob、层级覆盖 规则正文
Agent Skills 可复用工作流与资源包 description、显式命令、权限 SKILL.md 与按需资源
Tool Search 延迟工具定义 模型搜索或 Provider 检索 具体 tool schema
MCP 外部工具、资源与提示词协议 Host 配置、权限、Tool Search 工具定义和调用结果
Plugin 安装、分发与治理单元 用户、项目或组织配置 内含组件按各自生命周期工作

Anthropic 的 Tool Search 使用 tool_search_tool_regex_20251119tool_search_tool_bm25_20251119 等工具类型。Deferred tool 的完整定义仍随请求提交给 API,但在被发现前不进入模型上下文;发现后以 tool_reference 对应的定义追加到上下文尾部。它优化的是 tool schema 暴露,不是 SKILL.md 的路由。

Codex 所用模型与 Responses API也提供 Tool Search 能力,但不能据此断言所有 Codex CLI、IDE、App 和 Cloud surface 都默认对相同工具集合启用它。API 原语与产品配置仍要分开。

Prompt Cache 不能用“上下文更小”推断命中率

Prompt cache 依赖精确前缀、模型、工具顺序和 Provider 策略。上下文小可能降低单次输入量,但不会自动提高命中率。

一次 Skill 会话的成本至少要拆成:

1
2
3
4
5
6
7
8
初始常驻成本
= 项目指令 + Skill catalog + tool definitions + 其他固定基线

单次 Skill 调用增量
= Skill 正文 + 资源片段 + 工具协议包装 + 当前输出

长会话成本
= 未缓存尾部 + cache creation + cache read + compact / rehydration

Anthropic 的缓存层级以 tools、system、messages 组成前缀。改变工具集合或顺序可能使后续前缀失效。Tool Search 把新发现的定义追加在后部,目的之一就是避免改写已缓存的前缀。Skill 正文进入对话尾部也通常比修改最前面的 system 内容更容易保持前缀稳定,但实际 cache read/write 仍要看 Provider 返回的计量字段。

产品比较不应再写“缓存利用率高、中、低”。可复现实验至少需要固定:

  • Harness 和版本
  • Provider 与模型
  • Skill 集合、description 长度和权限过滤结果
  • tokenizer 与初始工作目录
  • 首次请求、重复请求、调用 Skill、修改 Skill、compact 后请求五个测量点
  • input、cache creation、cache read、output 和 wall time 的原始记录

没有这些条件,80k2554500135k 之类数字只是环境快照,不能当成产品属性。

Lost in the Middle 是风险,不是固定注意力公式

Lost in the Middle在特定模型和任务上观察到:相关信息放在上下文开头或结尾时,表现往往优于放在中间。论文没有给当前 Claude、GPT 或 Kimi 产品提供统一的 0.9、0.3–0.5 注意力系数,也没有证明某个 Skill 在第 100 轮必然衰减到固定比例。

这项研究对 Skill 设计仍有价值,但结论应该收敛为三个工程判断:

  • 目录必须短而可区分,避免候选能力互相遮蔽。
  • 当前任务需要的正文应在选择后进入工作上下文,不靠很早以前的一次说明维持。
  • 长会话需要明确恢复路径:自动重挂、再次调用、外部指针或重新检索,至少要有一种可观察机制。

更大的最大上下文可以推迟容量耗尽。如果实际 Prompt 内容和位置都不变,仅把模型上限从 128K 换成 256K,并不会自动改变其中 token 的顺序,也不能据此证明注意力分布改善。

五个 Harness 的当前共同点与差异

Harness 启动目录 正文进入时机 主要差异
Claude Code 预算治理后的 Skill listing 用户或模型调用 热更新边界、重复调用去重、compact 重挂预算公开较细
Codex name + description + path,受目录预算约束 显式 $skill 或隐式匹配后 AGENTS.md 链、Skill、API Skill 和 Plugin 分属不同执行面
OpenCode system prompt 与 skill 工具描述中均有目录 调用内置 skill 元工具 宿主 registry 可预读正文,普通 prune 与 full compact 分开
Cursor Rules / AGENTS.md 与 Skill catalog 并存 Rule 按模式应用;Skill 动态或手动调用 静态指令、动态能力、Subagent、Hook 和 Plugin 已组成完整体系
Kimi Code 按项目、用户、额外目录和内置来源发现 模型路由或 /skill:name 可使用不同 Provider,不能把 K2 模型窗口当作 Harness 策略

主流实现已经不再是“Claude Code 全量加载、OpenCode 按需加载、Cursor 只有 glob、Kimi 靠大窗口”这条四分法。它们正在收敛到轻量目录与正文渐进展开,差异转向目录预算、路由、消息形态、刷新边界、压缩恢复、权限和分发。

设计一个可维护的 Skill 加载器

一个新的 Harness 若要实现 Skill,最低限度应把以下契约写清楚。

Discovery

  • 支持哪些目录和优先级
  • 重名 Skill 如何覆盖
  • catalog 的字段、预算和截断告警
  • 权限拒绝的 Skill 是否从目录隐藏

Routing

  • 显式调用和自动调用是否共用入口
  • description 如何参与选择
  • 文件作用域、项目规则和用户指令冲突时谁优先
  • 路由失败是否可观察

Loading

  • 宿主何时读磁盘,是否缓存正文
  • 正文以哪类语义消息进入会话
  • references、scripts、assets 怎样按需展开
  • 重复调用是复用、短提示还是正文副本

Recovery

  • tool-output pruning 是否保护 Skill
  • full compact 是否摘要、重挂或要求再次调用
  • compact 后的目录是否重建
  • 旧正文与磁盘新版本冲突时采用哪个版本

Observability

  • 能否看到 catalog 实际占用
  • 能否区分 cache creation、cache read 和未缓存输入
  • 能否追踪哪个 Skill 被选择、加载、裁剪和恢复
  • 能否用固定 prompt 集测试触发率与执行质量

这五组契约比“支持 Agent Skills”这个布尔值更有解释力。同样读取 SKILL.md 的产品,运行时成本和长会话可靠性仍可能完全不同。

系列文章

参考资料