
【Skills 系统从入门到精通】第 3 篇Progressive Disclosure 详解——三级加载机制如何节省 Token本篇你将学到为什么把所有知识塞进系统提示是一条走不通的路Progressive Disclosure渐进式披露的三级加载模型Level 0、Level 1、Level 2每一级加载的触发条件、返回内容和 Token 消耗量通过实际数据对比全量加载与渐进加载的开销差异这套机制背后的设计哲学如何应用到其他系统设计中读完本篇你将透彻理解 Skills 系统最核心的设计理念以及它为什么能支撑上百个技能共存而不撑爆上下文窗口。一、问题上下文窗口是稀缺资源1.1 朴素方案的失败假设我们有一个 AI Agent安装了 50 个技能每个技能平均 3000 Token。最朴素的做法是——把所有技能的完整内容都塞进系统提示50 技能 × 3,000 Token/技能 150,000 Token这只是一个技能部分的开销。系统提示还包括模型身份、工具定义、记忆信息、安全规则等加起来轻松超过 200,000 Token。这会带来三个严重问题问题一上下文窗口不够用当前主流模型的上下文窗口在 128K 到 200K Token 之间。如果系统提示本身就占了 150K留给用户对话的空间就所剩无几。用户聊不了几轮就得触发上下文压缩。问题二性能下降研究表明大语言模型在处理超长上下文时存在中间遗忘Lost in the Middle现象——位于上下文中部的信息容易被忽略。技能内容堆积在系统提示中大部分位于中段恰好是模型注意力最薄弱的位置。问题三成本浪费每次对话都要发送完整的系统提示包括那些当前任务完全用不到的技能。如果模型按 Token 计费这意味着你每轮对话都在为无关技能付费。50 个技能中一次任务可能只需要 1-2 个其余 48 个的 Token 开销完全浪费。1.2 人类专家的启示上一篇文章中用过一个类比运维工程师小王不会时刻在脑子里运行所有运维手册。她只记得有哪些手册目录索引遇到具体问题时才去翻手册加载详情。这个类比揭示了一个重要的信息检索原则分层展示。图书馆的运作方式也是如此图书馆总目录Level 0 → 知道有哪些书、每本书大概讲什么 → 翻开某本书Level 1 → 阅读具体章节 → 查阅附录/参考文献Level 2你不会在走进图书馆时把所有书的内容都装进脑子。你先查目录找到目标书再翻阅。Skills 系统的 Progressive Disclosure 机制正是基于这个原则设计的。二、Progressive Disclosure 三级模型2.1 三级加载概览Skills 系统将技能信息的加载分为三个级别Level 0技能索引 → skills_list() → 所有技能的名称描述 Level 1技能完整内容 → skill_view(name) → 某个技能的完整 SKILL.md Level 2技能辅助文件 → skill_view(name, path) → 技能下的特定引用文件任务匹配 description正文引用且需要细节Level 0 技能索引skills_list()所有技能的名称描述Level 1 完整内容skill_view name某个技能的完整 SKILL.mdLevel 2 辅助文件skill_view name path特定引用文件每一级的加载都需要理由——Agent 不会无缘无故从 Level 0 跳到 Level 1更不会无缘无故跳到 Level 2。加载的驱动力来自当前任务的需求。2.2 Level 0技能索引始终在场触发条件会话启动时自动加载。返回内容所有已安装技能的名称、描述和分类。不包含技能的具体内容。数据格式Level 0 调用skills_list() 返回示例 [ {name: code-review, description: Use when reviewing code. ..., category: devops}, {name: deploy-k8s, description: Use when deploying to Kubernetes. ..., category: devops}, {name: log-analysis, description: Use when analyzing server logs. ..., category: devops}, {name: gif-search, description: Search/download GIFs from Tenor. ..., category: media}, // ... 更多技能 ]Token 消耗与技能数量成正比但每个技能只占很少的 Token约 20-40 个 Token因为只包含名称和一行描述。对于一个安装了 50 个技能的系统50 技能 × ~30 Token/技能 ~1,500 Token如果安装了 100 个技能100 技能 × ~30 Token/技能 ~3,000 Token这个开销是固定的——无论用户当前做什么任务Level 0 的索引始终在上下文中。但 3,000 Token 对于现代大语言模型来说微不足道通常只占上下文窗口的 2% 左右。2.3 Level 1技能完整内容按需加载触发条件Agent 判断当前任务需要某个技能时主动调用skill_view(name)。返回内容该技能的完整 SKILL.md 文件内容——包括 Frontmatter元数据、When to Use触发条件、Procedure操作步骤、Pitfalls陷阱列表、Verification验证步骤以及该技能包含的辅助文件列表。数据格式Level 1 调用skill_view(namelog-analysis) 返回内容简化示例 --- name: log-analysis description: Use when analyzing server logs. ... --- # 日志分析技能 ## When to Use - 服务器日志中出现重复错误 - 需要定位异常的根因 - 日志量突然增大 ## Procedure 1. 确定日志文件路径和格式 2. 提取关键错误行grep 正则 3. 按时间范围过滤 4. 按错误类型分类统计 5. 提取上下文错误前后各 5 行 ## Pitfalls - 不要直接打开超大日志文件先用 wc -l 看行数 - 注意时区问题应用日志可能是 UTC ## Verification - 确认提取的错误行数与统计一致 - 确认时间范围过滤正确 ## Linked Files - references/log-format-catalog.md - scripts/log_parser.pyToken 消耗取决于技能大小。典型范围技能类型典型大小Token 数简单技能单一场景2,000-4,000 字符500-1,200 Token中等技能多步骤流程5,000-10,000 字符1,500-3,000 Token复杂技能完整参考手册10,000-20,000 字符3,000-6,000 Token关键特征Level 1 的内容是临时加载的。它在当前任务执行期间指导 Agent 的行为但并不是永久的系统提示一部分。当任务完成、对话继续时这部分内容会逐渐被新的对话内容推远最终可能在上下文压缩时被清除。2.4 Level 2技能辅助文件深度加载触发条件Agent 在阅读 Level 1 内容后发现需要查看某个辅助文件references、scripts 等的详细内容时调用skill_view(name, file_path)。返回内容指定辅助文件的完整内容。数据格式Level 2 调用skill_view(namelog-analysis, file_pathscripts/log_parser.py) 返回内容 #!/usr/bin/env python3 日志解析脚本 - 提取和分类错误日志 import re from collections import Counter def parse_log(file_path, error_pattern, time_range): 解析日志文件提取匹配的错误行 # ...完整代码...Token 消耗取决于辅助文件大小。通常在 500-3,000 Token 之间。关键特征Level 2 是最深的加载级别。不是所有任务都会到达 Level 2——只有当技能的正文内容引用了辅助文件且 Agent 判断当前任务确实需要查看该文件的细节时才会触发。三、Token 消耗实测对比3.1 场景设定为了直观展示 Progressive Disclosure 的价值设定一个具体场景系统安装了 50 个技能每个技能平均 3,000 TokenLevel 1 内容每个技能平均有 1 个辅助文件约 1,500 TokenLevel 2 内容每个技能的 Level 0 索引约 30 Token当前任务需要使用 2 个技能各查看 1 个辅助文件3.2 方案对比方案 A全量加载朴素方案把所有技能的完整内容辅助文件都塞进系统提示。Level 1 内容50 × 3,000 150,000 Token Level 2 内容50 × 1,500 75,000 Token Level 0 索引50 × 30 1,500 Token ──────────────────────────────────── 总计226,500 Token超出大多数模型的上下文窗口结论完全不可行。上下文窗口直接溢出。方案 BLevel 0 按需 Level 1Skills 基本模式索引常驻需要时加载完整内容不加载辅助文件。Level 0 索引常驻50 × 30 1,500 Token Level 1 内容按需2个技能2 × 3,000 6,000 Token ──────────────────────────────────── 总计7,500 Token结论7,500 Token。仅占方案 A 的 3.3%。为对话留出了充足的上下文空间。方案 CLevel 0 按需 Level 1 按需 Level 2Skills 完整模式Level 0 索引常驻50 × 30 1,500 Token Level 1 内容按需2个技能2 × 3,000 6,000 Token Level 2 内容按需2个文件2 × 1,500 3,000 Token ──────────────────────────────────── 总计10,500 Token结论10,500 Token。仅占方案 A 的 4.6%。3.3 对比总结表方案Token 消耗占上下文比可行性全量加载A226,500113%❌ 上下文溢出Level 0 按需 L1B7,5003.75%✅ 轻松Level 0 按需 L1 按需 L2C10,5005.25%✅ 轻松注百分比以 200K Token 上下文窗口计算缩减96%以上增加按需L2仅占200K窗口的5%方案A 全量加载226500 Token上下文溢出方案B 索引按需L17500 Token方案C 完整模式10500 Token上下文窗口 200K TokenProgressive Disclosure 实现了95% 以上的 Token 节省同时确保 Agent 能够获取完成任务所需的全部信息。3.4 不同技能规模下的索引开销Level 0 的索引开销随技能数量线性增长但增长率极低技能数量Level 0 索引 Token占 200K 上下文比20 个~6000.3%50 个~1,5000.75%100 个~3,0001.5%200 个~6,0003.0%500 个~15,0007.5%即使在 500 个技能的极端场景下索引开销也只占上下文的 7.5%——这是完全可接受的代价换来了 500 个可用的专业能力。四、加载决策的内部机制4.1 Agent 如何决定加载哪个技能了解了三级加载的结构后一个自然的问题是Agent 是怎么判断当前任务需要加载哪个技能的核心机制是描述匹配。当用户发出一个请求时Agent 会将请求内容与 Level 0 索引中所有技能的 description 进行语义匹配。description 的质量直接决定了匹配的准确性。考虑三个技能的 description1. {name: code-review, description: Use when reviewing code. Pre-commit security scan, quality gates, auto-fix.} 2. {name: deploy-k8s, description: Use when deploying to Kubernetes. Rolling updates, rollback, health checks.} 3. {name: log-analysis, description: Use when analyzing server logs. Error extraction, pattern matching, root cause.}当用户说帮我审查这段代码时Agent 会匹配到技能 1code-review。当用户说线上有报错帮我看看日志时会匹配到技能 3log-analysis。这就是为什么 description 字段的写作如此重要——它不仅是给用户看的描述更是 Agent 自动发现技能的触发信号。在后续编写技能的模块中我们会详细讲解如何写好 description。4.2 何时从 Level 1 跳到 Level 2Level 1 到 Level 2 的跳转取决于技能正文内容是否引用了辅助文件以及 Agent 是否判断需要查看该文件。典型场景是否是否Agent 已加载 Level 1 技能正文正文引用 references 日志格式目录正文引用 scripts 解析脚本任务涉及解析 Nginx 日志需要了解格式触发 Level 2加载 log-format-catalog跳过 不加载需要了解脚本接口才能正确调用触发 Level 2加载 log_parser.py跳过 不加载Agent 并不会加载所有引用的辅助文件而是根据当前任务的需要点菜式地加载。如果正文只是顺带提到某个参考文件但当前任务并不需要它的细节Agent 就不会触发 Level 2。4.3 一次完整任务的三级加载流程用一个实际例子完整展示三级加载的时序用户帮我分析 /var/log/nginx/access.log 中的异常请求 ─── Level 0已常驻──────────────────────────────────── 索引中匹配到log-analysis 技能 description: Use when analyzing server logs. ... ────────────────────────────────────────────────────── ─── Level 1按需加载────────────────────────────────── skill_view(log-analysis) 返回 - When to Use: 服务器日志异常分析 - 步骤1确定日志格式Nginx/Apache/自定义 - 步骤2grep 提取异常状态码行 - 步骤3按 IP 统计高频请求 - 步骤4交叉分析时间窗口 - Pitfalls: 注意日志轮转、时区问题 - 引用文件references/log-format-catalog.md - 脚本scripts/log_parser.py ────────────────────────────────────────────────────── Agent 分析用户要分析 Nginx 日志。步骤1提到需要确认格式 日志格式目录中有 Nginx 的详细说明。 ─── Level 2深度加载────────────────────────────────── skill_view(log-analysis, references/log-format-catalog.md) 返回Nginx access.log 各字段含义、状态码定义、异常模式... ────────────────────────────────────────────────────── Agent 按照技能步骤执行 terminal(grep 5[0-9][0-9] /var/log/nginx/access.log | head -20) → 提取 5xx 错误行 terminal(awk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10) → 统计高频 IP 任务完成输出分析报告。整个过程中只有 1 个技能的 Level 1 和 1 个辅助文件的 Level 2 被加载。其余 49 个技能始终停留在 Level 0 索引状态——它们只贡献了约 30 Token 的索引开销。Level2 辅助文件Level1 技能正文Level0 索引Agent用户Level2 辅助文件Level1 技能正文Level0 索引Agent用户索引已常驻上下文分析 access.log 异常请求description 语义匹配命中 log-analysisskill_view 加载完整内容步骤 陷阱 引用文件清单加载日志格式目录Nginx 字段含义 状态码定义grep 提取5xx awk 统计高频IP输出分析报告五、设计哲学与启示5.1 Progressive Disclosure 的设计哲学Progressive Disclosure 不是凭空发明的概念它植根于几个成熟的计算机科学原则原则一惰性求值Lazy Evaluation只在需要时才计算/加载是函数式编程中的经典原则。Skills 系统把它应用到了知识加载上——不是启动时全量加载而是任务驱动时按需加载。原则二信息隐藏Information HidingDavid Parnas 在 1972 年提出的模块化设计原则模块只暴露必要的接口隐藏内部实现细节。Skills 的三级加载是信息隐藏的体现——Level 0 暴露有什么Level 1 暴露怎么做Level 2 暴露最细节。原则三注意力经济Attention Economy大语言模型的上下文窗口是注意力资源。Progressive Disclosure 确保这有限的资源被分配给当前最相关的信息而不是被无关内容稀释。5.2 对技能编写的启示理解了 Progressive Disclosure 后在编写技能时应该有意识地利用三级结构启示一description 是第一印象Level 0 的 description 是 Agent 决定是否加载你技能的唯一线索。如果 description 写得模糊、不包含关键词Agent 可能不会在需要时想到你的技能。好的做法Use when deploying to Kubernetes. Rolling updates, rollback, health checks.差的做法Deployment skill.启示二正文保持适中细节移入辅助文件既然 Level 1 是按需加载的是不是内容越多越好不是。Level 1 的内容应该聚焦于核心操作流程把详尽的参考资料、大型脚本、长篇配置示例移入 Level 2 的辅助文件。这样做的好处是双重的减少 Level 1 加载时的 Token 开销同时让 Agent 在需要细节时能通过 Level 2 精准获取。启示三辅助文件要有明确的引用理由Agent 不会无缘无故加载 Level 2。在 Level 1 的正文中当你提到辅助文件时要说明它的用途让 Agent 判断是否需要加载。好的做法详细的 Nginx 日志字段说明参见 references/nginx-log-format.md差的做法references/ 目录下有一些文件5.3 超越 Skills通用的分层加载思想Progressive Disclosure 的思想不局限于 Skills 系统。在任何需要管理大量信息的 AI 系统中分层加载都是一种值得借鉴的模式应用场景Level 0Level 1Level 2文档问答文档标题摘要相关段落完整页面代码搜索函数签名函数实现调用关系图知识管理知识卡片标题知识卡片内容原始来源链接核心原则始终是概览先行细节按需避免信息淹没。本篇小结知识点核心内容问题根源上下文窗口有限全量加载技能内容会导致溢出、性能下降、成本浪费Progressive Disclosure三级分层加载机制索引→完整内容→辅助文件Level 0skills_list()返回所有技能名称描述始终常驻~30 Token/技能Level 1skill_view(name)返回完整 SKILL.md按需加载500-6000 Token/技能Level 2skill_view(name, path)返回特定辅助文件深度按需500-3000 Token/文件Token 节省效果相比全量加载节省 95%50 个技能场景下仅占 5% 上下文加载决策Level 0→1 靠 description 语义匹配Level 1→2 靠正文引用任务需求判断设计哲学惰性求值 信息隐藏 注意力经济编写启示description 精准、正文适中、辅助文件有明确引用下篇预告下一篇我们将把视角从 Agent 内部机制扩展到外部生态——agentskills.io 开放标准。Skills 不是一个封闭的系统它遵循一个跨平台的开放规范这意味着 Hermes 的技能可以与 Claude、Codex 等其他 AI Agent 框架互通。我们将探讨这个开放标准对整个 AI Agent 生态的意义。如果本篇内容对你有帮助欢迎点赞收藏有任何疑问欢迎在评论区交流。