Volume 2 · Chapter 23
技能与命令:把知识变成工具、把动作变成命令
技能(skill)是「给模型的即用知识包」,命令(command)是「无需模型轮次的直接动作」。两者都是模型能力的补充面:skill 通过注入进入上下文,command 通过 ctx.commands 免轮次分派。
(卷一连接点) 08 页 inject(不唤醒)· 12 页 prompt 片段
→
本域:skill / skill-filesystem / tool-skill / commands / agent-instructions / command-feedback
→
(回心脏) 技能内容经 inject 进 inbox → preStep 进模型上下文
示例本次示例:模型加载一个技能
示例轨迹 23-1 · 拉取式:模型主动调 skill 工具
# 技能发现:skill-filesystem 扫描 ~/.dsh/skills/ 与工作区的 SKILL.md
# → 注册进 SkillRegistry(skill/src/index.ts:357)
# 模型不知道某技能的细节 → 调用 skill 工具(tool-skill 注册,161 行):
# ① 列出技能 → "你有哪些技能" → [ {name:'pdf-to-text', description:'...'} ]
# ② 读取技能 → 返回 SKILL.md 正文(作为 tool/result 进入 13/14 页流水线)
# 模型现在按技能指引行动——全程模型主动、时机确定
来源:23 页 §3 拉取式 + tool-skill/src/index.ts:25,161
示例轨迹 23-2 · 推送式:AGENTS.md 的注入
# agent-instructions 扫描工作区 → 发现子目录的 AGENTS.md # → agent.inject(AGENTS.md 内容)(08 页 inject:next-step,不唤醒) # → 下个 step 边界 preStep claim 到它(08 页 229 行) # → 以 user/message 进入模型上下文(08 页示例轨迹 08-1 的改写场景) # 与 23-1 的差异:inject 可能错过当前请求(preStep 已 claim 之后到达)
来源:23 页 §3 + 08 页 inject 语义
§1挂载条目
agent-instructions → @deepseek-ai/dsh-agent-instructions(1863 行)——AGENTS.md/CLAUDE.md 指令文件(08 页「subdir AGENTS.md」inject 的来源)skill → @deepseek-ai/dsh-skill——技能注册表skill-filesystem → dsh-skill-filesystem(1071 行)——从磁盘发现 SKILL.mdskill-badge(disabled)——badge 展示tool-skill → dsh-tool-skill(461 行)——模型查询/加载技能的工具commands → @deepseek-ai/dsh-commands——免轮次命令分派command-feedback → dsh-command-feedback——/feedback 命令
§2包文件地图
| 包 | 规模 | 角色 |
|---|---|---|
packages/skill/skill/ | 2 文件 / 898 行 | Service Definition:SkillRegistry extends Service(src/index.ts:357)——技能注册/发现/读取 |
packages/skill/skill-filesystem/ | 2 文件 / 1071 行 | Provider:inject = ['skills'](src/index.ts:46)——从目录树发现 SKILL.md |
packages/skill/tool-skill/ | 2 文件 / 461 行 | Consumer:inject = ['agents', 'tools', 'skills'](src/index.ts:25),ctx.tools.register(skillTool)(161 行) |
packages/context/agent-instructions/ | 7 文件 / 1863 行 | AGENTS.md 扫描与注入——inject 的实际执行者 |
§3机制:注册 → 注入 → 消费
- 发现:skill-filesystem 扫描目录树里的 SKILL.md,注册进
SkillRegistry(名字、描述、正文)。 - 工具暴露:tool-skill 把「查技能列表、读技能正文」做成模型工具——模型需要某项技能时主动调它(拉取式)。
- 指令注入:agent-instructions 扫描工作区/子目录的 AGENTS.md(含父目录向上查找),把内容经
agent.inject()放进 inbox——不唤醒(08 页 inject 语义),等下一次 step 边界被 claim 进上下文(拉取式之外还有推送式)。 - 命令分派:
ctx.commands上的命令由 UI 直接触发,无需模型轮次——它是「旁路」(如 /compact 直接调压缩引擎,21 页)。
§4关键代码
357export class SkillRegistry extends Service {
25export const inject = ['agents', 'tools', 'skills']
161 ctx.tools.register(skillTool) // 拉取式的入口
357
技能域的 Definition。注意它是「注册表」而非「执行器」——技能本身没有运行时,正文就是它的全部。
25
tool-skill 的 inject 里有 agents——因为它需要 agent.inject() 把技能正文注入当前会话(与 agent-instructions 同一通道)。
161
「技能如何变成模型能力」的答案:注册进 tools(14 页 registry),schema 进提示词(12 页),模型调用它读取技能。
§5易错点
技能注入走 inbox 不唤醒(08 页 inject 语义)——一条技能注入若在 preStep 已 claim 之后到达,会错过当前请求,落到下一步。这是「拉取式(工具)优于推送式(注入)」的原因之一:模型主动调 skill 工具的时机是确定的。
命令是旁路不是轮次:commands 不需要模型参与——这就是为什么 command-compact(21 页)能直接调压缩引擎。它和「工具」的区别:工具需要模型决策后调用,命令由用户/UI 直接触发。