跳到主要内容

第 3 章 · 客户端集成生命周期

第 1 章讲“文件长什么样”,第 2 章讲“怎么解析校验”。本章讲一个 agent 产品怎么真正支持 Skills——从扫描磁盘到把指令塞进模型、再到全程不丢失它。来源:docs/client-implementation/adding-skills-support.mdx。规范只定义文件内部,不规定 skill 放在哪、怎么加载;这些落地决定都在客户端,本章就是这些决定的“最佳实践集合”。

3.0 五步全景

① 发现 ② 解析 ③ 披露 ④ 激活 ⑤ 上下文管理
扫目录 抽frontmatter name+desc 进 任务匹配→读 防压缩 / 去重 /
找 SKILL.md 存 location 系统提示 整篇正文进上下文 (可选)子 agent
───────────▶ ───────────▶ ──────────────▶ ──────────────▶ ──────────────▶
tier 1 准备 tier 1 投放 tier 2 维持 tier 2/3

两个决定整套实现差异的变量(docs/client-implementation/adding-skills-support.mdx:9-13):

  • skill 住在哪? 本地 agent 扫文件系统;云端/沙箱 agent 得换机制(API、远程仓库、内置资产)。
  • 模型怎么拿到内容? 模型能读文件就直接读 SKILL.md;不能就给它一个专用工具或直接注入。

3.1 第一步:发现 skill

扫哪些目录:.agents/skills/ 约定

本地 agent 通常至少扫两个作用域:项目级(相对工作目录)和用户级(相对家目录)。每个作用域里又常扫两类路径(docs/client-implementation/adding-skills-support.mdx:45-54):

作用域路径用途
项目<project>/.<your-client>/skills/你客户端的原生位置
项目<project>/.agents/skills/跨客户端互通
用户~/.<your-client>/skills/你客户端的原生位置
用户~/.agents/skills/跨客户端互通

关键点:.agents/skills/ 已成为跨客户端共享的事实约定——扫它意味着别的兼容客户端装的 skill 你也能看见,反之亦然(:54)。规范本身不规定位置,这个约定是生态自发形成的。很多实现还会额外.claude/skills/,因为现存大量 skill 装在那(:56-58)。

扫什么:含 SKILL.md 的子目录

在每个 skills 目录里找“正好叫 SKILL.md 的文件所在的子目录”(:62-73)。实践规则:跳过 .git/node_modules/;可选尊重 .gitignore;设深度/数量上限(如最深 4–6 层、最多 2000 目录)防失控扫描(:75-79)。

重名冲突:项目级压用户级

两个 skill 同名时要有确定的优先级。通行约定:项目级覆盖用户级(:82-87)。同作用域内部的冲突,first-found 或 last-found 都行,选一个保持一致,并打 warning 告诉用户某个 skill 被遮蔽了。

信任门槛(安全关键)

项目级 skill 来自“正在处理的仓库”,可能是刚 clone 的不可信开源项目。规范建议:把项目级 skill 的加载挂在“用户已信任该目录”的检查上(docs/client-implementation/adding-skills-support.mdx:89-91)。否则一个恶意仓库就能往 agent 上下文里静默注入指令——这是 skill 作为“可执行指令载体”的天然攻击面。

云端 / 沙箱的不同处理

沙箱里没有用户本地文件系统(:93-101):项目级 skill 随代码进沙箱、最好办;用户级/组织级要从外部源(配置仓库、上传)provision;内置 skill 打包成部署资产。

3.2 第二步:解析(以及“宽松校验”)

解析逻辑和第 2 章的 parse_frontmatter 一致:找两道 ---、parse 中间的 YAML、其余 strip 作正文(docs/client-implementation/adding-skills-support.mdx:108-115)。但生产集成多了两层现实容忍:

容错坏 YAML

最常见的坑是未加引号、值里带冒号(:117-126):

# 技术上非法的 YAML——冒号破坏解析
description: Use this skill when: the user asks about PDFs

建议加个 fallback:把这类值用引号包起来、或转成 YAML block scalar 再重试,低成本提升跨客户端兼容。

宽松校验:warn 而非拒(关键权衡)

这里和第 2 章的 skills-ref 有意不同skills-ref 是严格校验器;而生产客户端建议宽松(docs/client-implementation/adding-skills-support.mdx:128-141):

问题严格校验器(skills-ref)生产客户端建议
name 不匹配目录名报错warn,照样加载
name 超 64 字符报错warn,照样加载
description 缺失/空报错跳过(没描述就没法披露)
YAML 完全解析不了报错跳过

理由:别让“无伤大雅的瑕疵”挡住加载,尤其要兼容别家客户端写的 skill。规范自己点明:严格约束在 spec,这里是“为兼容性故意放松”(:139-141)。

存什么

每条 skill 记录至少三字段:namedescriptionlocation(指向 SKILL.md 的绝对路径),按 name 建内存索引(:144-153)。正文可以发现时就存(激活快)或激活时再读(省内存、能拾取文件变更)。

3.3 第三步:披露(tier 1)

把每个 skill 的 name/description/(可选)location 拼成目录清单塞进上下文(docs/client-implementation/adding-skills-support.mdx:159-184)。格式 XML/JSON/列表都行——和第 2 章 to_prompt 同源:

<available_skills>
<skill>
<name>pdf-processing</name>
<description>Extract PDF text, fill forms, merge files. Use when handling PDFs.</description>
<location>/home/user/.agents/skills/pdf-processing/SKILL.md</location>
</skill>
</available_skills>

要点:

  • location 双重作用:既让模型能 file-read 激活,又给它解析相对路径(如 scripts/x.py)的基准(:182)。
  • 放哪里:系统提示里一个小节(最简单、最通用),或塞进专用激活工具的描述(系统提示更干净)(:186-194)。
  • 过滤:被禁用/无权限/选择退出模型激活的 skill,直接不列,别列出来再在激活时拦——免得模型白白浪费回合(:220-228)。
  • 没有 skill 时:整块清单和说明都省掉,别塞空的 <available_skills/>(:230-232)。

3.4 第四步:激活(tier 2)

主力是“模型自己判断”

绝大多数实现在 harness 侧做关键词匹配,而是让模型读完目录自己决定哪个 skill 相关(docs/client-implementation/adding-skills-support.mdx:238-240)。两种落地:

  • file-read 激活:模型用标准读文件工具读 SKILL.md,零额外基础设施(:244)。
  • 专用工具激活:注册个 activate_skill(name) 工具返回内容。模型不能直接读文件时必需;能读时也有好处——可控制返回内容、包结构化标签、列出资源、做权限/分析(:246-256)。建议把工具的 name 参数约束成合法 skill 名的 enum,防模型瞎编(:254-256)。

用户也能显式激活

常见是 slash 命令 / mention 语法(/skill-name$skill-name),由 harness 拦截直接注入,模型不用自己动手激活(:258-262)。具体语法由客户端自定。

模型收到什么:全文 vs 仅正文

两种都可行(:264-272):

  • 全文(含 frontmatter):file-read 激活的自然结果;compatibility 等字段在激活时可能有用。
  • 仅正文(剥掉 frontmatter):用专用工具的实现多数这么做。

结构化包裹

用专用工具时,建议把内容包进识别标签,并列出(但不预读)bundled 资源(docs/client-implementation/adding-skills-support.mdx:274-308):

<skill_content name="pdf-processing">
... SKILL.md 正文 ...
Skill directory: /home/user/.agents/skills/pdf-processing
<skill_resources>
<file>scripts/extract.py</file>
<file>references/pdf-spec-summary.md</file>
</skill_resources>
</skill_content>

好处:模型能区分 skill 指令与普通对话;harness 能在压缩时识别并保护;资源被“摆出来”但不急着读。

权限白名单(易踩的体验坑)

如果 agent 有文件访问权限系统,要把 skill 目录加白名单,否则每读一个 bundled 脚本都弹确认框,带资源的 skill 完全没法用(:310-312)。

3.5 第五步:全程管理 skill 上下文

防压缩(静默退化的隐患)

如果 agent 会在上下文满时截断/摘要旧消息,要把 skill 内容豁免出去(docs/client-implementation/adding-skills-support.mdx:316-326)。skill 指令是“持久行为指引”,中途被压没不会报错,模型继续跑但悄悄丢了专长——最阴险的失败。可用 §3.4 的结构化标签来识别并保护。

去重 + (可选)子 agent

  • 去重:跟踪本会话已激活的 skill,重复激活就跳过,避免同一指令出现多份(:328-329)。
  • 子 agent 委派(高级、部分客户端):把 skill 放进独立子会话跑,完事只把摘要带回主对话——适合复杂工作流(:331-335)。

3.6 代码地图

本章源在文档而非代码;锚点便于 grep:

主题文件锚点
五步生命周期总览docs/client-implementation/adding-skills-support.mdx“progressive disclosure” 表(:22-30)
扫描目录约定docs/client-implementation/adding-skills-support.mdx“Where to scan” 表(:45-54)
重名冲突docs/client-implementation/adding-skills-support.mdx“Handling name collisions”(:82-87)
信任门槛docs/client-implementation/adding-skills-support.mdx“Trust considerations”(:89-91)
坏 YAML 容错docs/client-implementation/adding-skills-support.mdx“Handling malformed YAML”(:117-126)
宽松校验docs/client-implementation/adding-skills-support.mdx“Lenient validation”(:128-141)
模型自主激活docs/client-implementation/adding-skills-support.mdx“Model-driven activation”(:238-256)
防压缩docs/client-implementation/adding-skills-support.mdx“Protect skill content…”(:318-326)