几十个技能说明,全塞进 prompt 吗?
本课一问:「怎么调试」「怎么写测试」「怎么做代码评审」这类流程性知识,一份就是几千 token。几十份这样的技能说明,全塞进 prompt 吗?
这一课先不碰:MCP 工具定义的按需加载(A2 第 4 课);skill 里的脚本在哪执行、归哪道权限闸管(A3、A4)。
从已有出发
前两课放进 prompt 的是两类知识:人写的规矩(AGENTS.md,几十到几百 token)和 agent 学到的事实(记忆,Hermes 上限 2,200 字符)。它们小,整份注入没问题。第三类是流程:遇到某种任务,该按什么步骤做。修 test_parse_date 这种 bug,一份讲系统调试的说明就可能用得上。
业界把这类说明写成 SKILL.md:一个目录里放一个 Markdown 文件,开头是 YAML frontmatter(至少 name 与 description),后面是正文,目录里还可以放脚本和参考资料。Claude Code、Codex、Pi、Hermes 都支持这个格式(agentskills.io 规范)。
本课的语料换了一个:本工作区自己只有 1 个 skill,撑不起「几十个」的问题;Hermes 的 pin 随包带了 77 个真实的 SKILL.md(分 15 个类别,安装时拷进 ~/.hermes/skills/),公开、可复现,正好用来算。
先自己设计:每个 SKILL.md 的全文都放进 system prompt
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
最大的三个(整个文件的 token 数):research-paper-writing(research)16,816、claude-code(autonomous-ai-agents)9,067、humanizer(creative)7,648;中位数 2,526。其中 6 个的正文超过了 agentskills.io 建议的 5,000 token,9 个超过建议的 500 行。本工作区的 interactive-course-builder 也一样:正文 7,718 token、250 行。
一轮修 bug 的任务里,真正用得上的通常只有一两份。
把一份 skill 拆成三层,按需往下读:
- 元数据:只有 name 与 description,常驻 system prompt(规范给的量级:每个约 100 token)。
- 正文:模型判断「这个任务和它有关」时,再用工具把整个 SKILL.md 读进来(规范建议 5,000 token 以内)。
- 附属文件:脚本、参考资料,正文里提到、真用到时才读。
改进:渐进披露,在真实文件上算
下面五条共用同一把尺子(模型窗口,可切换)。①②③④ 的文本都由 pin 源码的原函数在这 77 个文件上排出来,再用录制模型的 tokenizer 数;⑤ 是 ③ 加上你勾选的正文。
Hermes 随包的 77 个 skill:勾选「这一轮真的用到」的,它的正文加进「按需」那一条
口径:语料是 hermes-agent@56dc01d9 的 skills/ 目录(安装时由 skills_sync.py 拷进 ~/.hermes/skills/)。三种索引的原文都由 pin 源码的原函数排出:Hermes 用 build_skills_system_prompt(在临时 HERMES_HOME 里跑,macOS),Pi 用 formatSkillsForSystemPrompt(bun;location 按 Pi README 的约定目录构造)。token 用录制模型 Qwen/Qwen3-8B-MLX-4bit 的 tokenizer 数,正文按整个 SKILL.md 文件计;换成别的模型,绝对数会变,比例大体不变。规范上限据 agentskills.io 与 Claude Code skills 文档(2026-09-26 抓取)。
试三件事:① 尺子切到 200,000,全量那一条还是超出窗口吗?再看 ③ 占窗口百分之几。② 展开技能表,搜 debug,勾上你觉得修 test_parse_date 会用到的 skill,看 ⑤ 涨了多少——和 ① 比,还差几个数量级?③ 在截断试验台里,把默认的那段中文描述改短到 60 个字符以内,看 Hermes 那一行什么时候不再被截断;再把关键用途挪到最前面。
读数时的四件事:
- 索引很小。Hermes 实际注入的索引(9,322 字符)是 2,209 token,全量的 1.0%;其中一大段是固定的使用说明,不随 skill 数量增长。
- Pi 放完整描述,Hermes 截到 60 字符。Pi 的索引 4,639 token,是 Hermes 的 2.1 倍。Hermes 随包的 77 条描述都写在 60 字符以内,一条也没被截——截断是给用户和 agent 自己新写的 skill 兜底的。
- 编码场景还能再省。Hermes 的编码画像在 focus 模式下,把 18 个非编码类别(Apple、邮件、购物……)降为只列名字:1,461 token。名字仍然全在,想用照样能加载。
- 按需的代价只在用到的那一轮。正文是作为工具结果进入对话的,排在前缀的后面,不打穿前面的缓存;Claude Code 官方文档把「调用 skill」列在「保持缓存」的动作里——skill 的内容以 user 消息的形式追加在当前位置,前面的对话不变。
三家的索引长什么样
Pi 把每个 skill 写成三行 XML:名字、完整描述、文件位置,再加三句使用说明——「任务和描述对得上,就去读整个文件」:
Hermes 的截断只有几行,本页的截断试验台就是它的移植:
Claude Code 的做法写在官方 skills 文档里(2026-09-26 读取):description 与 when_to_use 合计超过 1,536 字符的部分被截掉;整个技能列表有一个字符预算,约为模型窗口的 1%,超了就先丢「最少被调用的 skill」的描述,名字始终保留;官方建议把关键用途写在描述最前面。压缩之后,调用过的 skill 正文会重新注入(每个最多 5,000 token、合计 25,000),技能列表本身不再重注入。learn-claude-code 的 s07 是最小教学版:system 里一份「名字: 描述」目录,正文靠一个 load_skill 工具返回。
不是一回事。工具是可执行的接口:有名字、有参数 schema,每个请求都把定义发给模型,模型调用它、harness 执行它。skill 是一段说明文本(可以附带脚本),平时只有名字和一句描述在 prompt 里,用到时才把正文读进对话;读它这个动作本身通常借一个工具完成(Hermes 的 skill_view、learn-claude-code 的 load_skill、Pi 直接用读文件的工具)。
常见误解二:「描述写得越详细,模型越能用对。」描述活在一个有预算的索引里:Hermes 截到 60 个字符,Claude Code 单条 1,536 字符、列表总共约窗口的 1%,超了还会整条丢掉。写太长,后半截模型根本看不到。把「什么时候用它」放在第一句。
规范与分发
- 格式:agentskills.io 规范(2026-09-26 读取原文;调研档案里这一条原先标「未核」,本章核过):
name最多 64 个字符、只能小写字母数字与连字符、必须与目录同名;description最多 1,024 字符;渐进披露三层写在规范里——元数据约 100 token 在启动时加载,正文建议 5,000 token 以内、500 行以内,附属文件按需。 - 分发:MCP 的 Skills Extension(SEP-2640)已于 2026-09-13 定稿(Final):MCP server 通过 Resources 原语把「含 SKILL.md 的目录」以
skill://资源暴露出来,客户端用skills/list先拿元数据、需要时再用skills/get与资源读取正文——同样是渐进披露。规范已发布;截至 2026-09 中旬,各语言 SDK 的实现还在合并中。
agent 自己写 skill:Hermes 的自我改进闭环
skill 不一定是人写的。Hermes 在一次任务里工具迭代累计到 10 次(可配置),就在后台 fork 出一个自省的 agent,问它「有没有值得存成 skill 或记忆的东西」:
agent 写出来的 skill 由一个定期运行的 curator 维护,规则里有一条「只归档、从不删除」:
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 流程性知识越攒越多,又不能每个请求都整份带着 |
| ② 为什么渐进披露省? | 常驻的只有索引,正文只在用到的那一轮、以追加的方式进入对话 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条记账恒等式:每个请求的 skill 开销 = 索引 + 本轮已读入的正文;上面五条的 token 都由 pin 原函数排出的真实文本算出。 出处待补 |
| ③ 实验上呢? | 各家的格式与机制有源码与官方文档为证 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条Pi formatSkillsForSystemPrompt、Hermes build_skills_system_prompt 在 pin 上原样运行;Claude Code 的上限来自官方 skills 文档;SEP-2640 的 Final 状态来自 MCP 官网(2026-09-26 读取)。 出处源码直证 + 官方文档 ↗需联网 ;「模型会不会在该读正文的时候去读」没有本课的实测——那取决于模型与描述写法,Böckeler 把它归为「由模型决定加载」固有的不确定性 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条设计层面的判断,没有对照实验;本课项目 miniagent 没有实现 skills。 出处待补 |
演进地图:你在这里
- 起点 把规矩写进第一条消息最省事的做法:任务说明里顺手写上「不许改测试文件」「日期用 DD/MM/YYYY」解决了不用改 harness,当场就生效。卡在A5 的分层压缩运行里,规矩写在任务说明中,17 份真实摘要只有 2 份还带着「不许改测试文件」;换一个新会话更彻底:T10 day2 的第一个请求只有 2 条消息、1,138 token,来自前一天对话的是 0 条。
- 人写的规矩 指令文件:每个请求都重新注入Claude Code 的 CLAUDE.md、Codex / OpenCode 的 AGENTS.md(Codex 从项目根到 cwd 逐级叠加、32 KiB 上限;OpenCode 同名文件 first-match)、Hermes 三段 prompt 的 context 段解决了会话开始从磁盘读一次,拼进每个请求;压缩之后从磁盘重新注入。T10 day2 的每一轮都带着 AGENTS.md 块(87 token),验收「按 AGENTS.md 的格式输出」:通过。卡在它只装人写好的规矩。agent 自己在干活时学到的东西(比如这个仓库怎么跑测试)写到哪、什么时候生效?
- 本课项目 miniagent 的 refresh 模式(T10 刷新组)解决了本会话马上就能用上刚学到的东西。卡在T10 刷新组 day1 第 7 轮:上一轮命中 2,072 token,刷新后这一轮 2,300 token 只命中 294——前缀在记忆块处断开,后面的工具定义与全部历史都要重算。
- Hermes MEMORY.md(2,200 字符)/ USER.md(1,375 字符);miniagent frozen 模式;仓库准则「Per-conversation prompt caching is sacred」解决了会话内 system 字节不变:T10 冻结组 day1 的 8 个后续请求里,8 个把上一轮的请求整个读回了缓存(最多差 1 个模板 token);day2 开新会话,第一个请求就带着前一天写的记忆。卡在流程性知识越攒越多:Hermes 随包的 77 个 SKILL.md 全文合计 215,494 token,是录制模型窗口(40,960)的 5.3 倍,全塞进快照放不下。
- Pi(name + description + location)、Hermes(描述截到 60 字符)、Claude Code(单条 1,536 字符上限)、agentskills.io 规范;分发:MCP Skills Extension(SEP-2640,2026-09-13 Final)解决了同样 77 个 skill,Hermes 实际注入的索引 2,209 token;模型觉得相关时再读正文。卡在知识的问题解决了,会话本身怎么存?想回到三轮前换条路:T10 从 e0005 分叉,线性列表只能删掉它后面的 15 条(原来那条成功的路径)。
- Pi(id / parentId,一个 JSONL,/tree /fork /clone)、Claude Code(/branch、--fork-session)、Codex rollout(append-only,压缩写成 CompactedItem)、miniagent session.py解决了两条分支并存,压缩有损、历史无损;分叉的第一个请求与原分支共享前缀:T10 fork 第 1 轮 1,236 token,实测命中 1,197。卡在一个会话、一个窗口的边界还在:一件事大到一个 agent 的上下文装不下、或需要别人把关时 → 下一章 A7 子 agent。
数字口径:A5 的摘要来自 pd-v2-layered-s1 的真实运行(a05-context.json);其余来自本课项目 miniagent 的 T10 两天会话(Qwen3-8B-MLX-4bit,本机 mlx_lm.server,2026-09-26),缓存命中是服务端报告的 cached_tokens;skill 的 token 数由录制模型的 tokenizer 在 Hermes pin 的 77 个 SKILL.md 上现算(a06-memory.json,2026-09-26)。
一句话
先停在这里:记住三层(元数据、正文、附属文件)和它们各自进入上下文的时机;描述要短、关键用途放最前。
再深一层:在实验课里换一个窗口大小,看同样 77 个 skill 在不同模型上各占多少。
下一个缺口
会话本身怎么存?想回到三轮前换条路呢? → 第 4 课:会话该存成列表还是树
规矩、记忆、技能都解决了「知识」放在哪。还剩会话自己:A5 说完整历史留在磁盘上,那磁盘上的它长什么样?想退回三轮前试另一条路,原来那条路还在不在?
你可能会问
- 「为什么本课不在本工作区的 skill 上算?」 本工作区只有 1 个(
interactive-course-builder,7,835 token,描述 170 个字符,在截断试验台里默认填的就是它的描述)。77 个的问题需要 77 个的语料;Hermes 随包的这批是公开的,任何人拉同一个 pin 都能算出同样的数。 - 「本课项目 miniagent 要不要实现 skills?」 M6 的里程碑没有要求。想加的话,最小做法就是 learn-claude-code s07:system 里放目录,一个读正文的工具。验收可以借用本页的数字:索引的 token 数、读入正文的那一轮前缀是否仍然命中。
- 「截断会不会截断在汉字中间?」 不会。Python 的字符串按字符(码点)切,本页的 JS 移植也按码点切,22 条超长描述(含本工作区那条中文描述)与原函数的输出逐字一致。