第6章 三分架构——Tool、Skill、Capability
2026.07.29Tool、Skill、Capability——三种不同的能力增长机制。不是一种,不是四种,恰好三种。
模式层
6.1 三种基本模式
Agent 的能力增长不是一维的。一个 agent 可以学习新的知识,可以掌握新的方法,可以长出新的执行能力。但三种不同的"增长"需要三种不同的机制——不能用一个机制覆盖所有场景。
三种模式之间的关系和交互流程如下:
graph TB
subgraph "Tool(编译时固定)"
T_RF[read_file]
T_WF[write_file]
T_RC[run_command]
T_GB[glob / grep]
T_CT[commit]
T_PL[plan / milestone]
T_RV[review]
T_GN[generate_*]
T_AG[agent]
end
subgraph "Skill(注入式知识)"
SK_DIR[skills/ 目录]
SK_SCAN[Registry 扫描]
SK_INJ[注入 system prompt]
SK_USE[use_skill<br/>按需激活]
SK_PR[prompts/ 草稿层]
end
subgraph "Capability(可执行产物)"
CA_DIR[capabilities/ 目录]
CA_MAN[manifest<br/>Environment × Lifecycle]
CA_GEN[generate_capability<br/>write_file 级]
CA_RUN[run_capability<br/>权限检查]
CA_SHL[Shell 执行]
CA_WASM[Wasm 执行]
CA_DOCK[Docker 执行]
end
T_RF -->|Permission::None| EXEC[工具执行]
T_WF -->|Permission::Ask| PERM[权限检查]
T_RC -->|Permission::Ask| PERM
T_CT -->|Permission::Ask| PERM
SK_DIR --> SK_SCAN
SK_SCAN --> SK_INJ
SK_USE --> SK_INJ
SK_PR -->|promote_prompt| SK_DIR
CA_DIR --> CA_RUN
CA_GEN -->|写文件| CA_DIR
CA_RUN --> PERM
PERM -->|通过| CA_SHL
PERM -->|通过| CA_WASM
PERM -->|通过| CA_DOCK
style T_RF fill:#e8f5e9
style T_WF fill:#e8f5e9
style T_RC fill:#e8f5e9
style SK_DIR fill:#fff3e0
style SK_INJ fill:#fff3e0
style CA_DIR fill:#f3e5f5
style CA_RUN fill:#f3e5f5
style PERM fill:#fce4ec
Tool:编译时固定。
Tool 是 agent 天生就会的东西——代码写死的、编译进二进制的、运行时不可增删的原语。read_file、write_file、run_command、glob——这些是 agent 能力的原子操作。
Tool 的关键特性是不可伪造性。你不能通过对话注入一个假工具。不能通过写一个 .md 文件就创造一个新的 run_command。Agent 手里的工具集是确定的、可枚举的、可审计的。你可以在二进制中数出 26 个工具,每一个都有完整的实现和测试。
Tool 的安全隐含是:信任来自编译时。 编译器和类型系统保证了工具的实现不会在运行时被篡改。你不用担心 agent 突然多了一个不该有的工具。
Tool 的局限是:它们不学习。 工具的数量和功能在编译时确定,运行时不能增删。要给 agent 增加新的原子操作,必须改代码、编译、部署。
Skill:注入式知识。
Skill 是 agent 的程序性知识——存在 skills/ 目录下的纯文本 Markdown 文件。每个文件是一套方法论:代码审查步骤、调试流程、工作计划方法。
Skill 的关键特性是注入式。它不是 agent 天生的知识——它是从文件读进来的。Agent 在启动时通过 Registry 加载 skills/ 目录下的所有文件,内容拼入 system prompt。新增一个 Skill 文件,agent 下次 turn 就多了一份方法论。
Skill 的安全隐含是:信任来自文件系统。 Skill 的内容是纯文本,不包含可执行代码。写入 skills/ 目录的文件最多改变 agent 的推理路径,不能改变 agent 的实际操作能力。
Skill 的局限是:它们不执行。 Skill 只能告诉 agent "怎么做",不能给它"做什么新的事"的执行能力。一个 Skill 可以规定代码审查的步骤,但不能执行审查——执行需要 Capability。
Capability:可执行产物。
Capability 是 agent 写的可执行代码——存在 capabilities/ 目录下,附带一个 manifest 声明环境和生命周期。
Capability 的关键特性是可执行性。它不是知识,是代码。agent 用 generate_capability 写一段代码和 manifest,用 run_capability 执行它。执行环境根据 manifest 的声明路由到 Shell / Wasm / Docker 后端。
Capability 的安全隐含是:信任来自执行闸门。 generate_capability 只是写文件(write_file 级权限),真正的闸门在 run_capability(触发权限检查)。写廉价、执行昂贵——这个原则贯穿了整个三分架构。
Capability 的局限是:它们需要环境。 Capability 的执行依赖声明环境是否可用。如果 Docker 不可用,声明 Docker 的 Capability 无法执行。
| 维度 | Tool | Skill | Capability |
|---|---|---|---|
| 修改时机 | 编译时 | 运行时 | 运行时 |
| 内容形式 | Rust 代码 | Markdown | 代码 + manifest |
| 安全隐含 | 不可伪造 | 改变推理路径 | 改变执行能力 |
| 审计追踪 | 看二进制 | 看 git log | 看 git log + 执行记录 |
6.2 为什么恰好三分
三分不是架构师的设计洁癖——它是三个不同的安全边界催生的自然分类。
从安全边界推导:
- 编译时安全需要一个不可伪造的原语层 → Tool
- 注入安全需要一个不执行代码的知识层 → Skill
- 执行安全需要一个带权限闸门的执行层 → Capability
每一层对应一个不同的"信任如何建立"的问题。Tool 的信任来自编译器和类型系统。Skill 的信任来自文件系统的只读性(文件不会自己变成代码)。Capability 的信任来自执行闸门(写文件不触发权限检查、执行文件触发)。
少于三分:
- 只有 Tool:agent 无法学习新知识。每次遇到同样的问题,它都要从头思考。没有地方存放"这个项目的编码偏好"、"这个团队的首选方案"
- 只有 Tool + Skill:agent 可以学习和思考,但学到的知识不能变成可执行的能力。如果 agent 发现"每次部署都需要这几步",它不能把它写成脚本然后复用
多于三分:
理论上可以增加第四类——比如"可配置的 Tool"(运行时加载的插件)、"动态 Skill"(从网络远程加载的知识)等。但每增加一个分类,就增加了一个"这个新能力应该归哪一类"的判断边界。三分恰好是"一个人能用手跟踪所有类别"的上限。当一个新的能力增长需求出现时,绝大多数情况下可以用三分框架找到归属:
- 需要新的原子操作 → 加 Tool(需要编译)
- 需要新的决策方法 → 写 Skill(需要注入)
- 需要新的可执行能力 → 生成 Capability(需要闸门)
如果不在三分中——那说明这个能力可能不应该由 agent 自己管理。
6.3 三分之外的草稿层
三分之外还有一个"准分类":Prompt 草稿层。
prompts/ 目录存放 Skill 的草稿态。它的存在是因为从"知识是 agent 临时生成的"到"知识成为正式 Skill"之间需要中间状态。
成熟度模型:
消息(临时) → Prompt 草稿(一次使用,prompts/) → Skill(正式化,skills/) → 常驻(注入 system prompt)
- 消息:agent 在对话中生成的知识,一次使用,不持久
- Prompt 草稿:agent 用
generate_prompt写入prompts/的草稿。通过use_skill按需激活一次,不会随启动自动注入 - Skill:通过
promote_prompt从草稿晋升为正式 Skill。从prompts/移动到skills/,启动时自动注入 - 常驻(注入 system prompt):Skill 被标记为"高频使用",在 system prompt 中永久存在
每个晋升步骤都有明确的工具操作。generate_prompt → promote_prompt → 自动注入。没有"随口说了一句话就变成永久行为"的隐式升级。
草稿层不是第四类——它是 Skill 的"未成熟状态"。草稿和正式 Skill 共享同一个工具路径(use_skill),区别在于加载时机(按需 vs 自动)。
案例层
6.4 Registry 扫描与激活流程
Registry 是三分架构的文件系统接口。它负责扫描、索引和注入三类能力。
struct Registry {
skills: HashMap<Name, SkillEntry>, // skills/ 下的正式 Skill
prompts: HashMap<Name, PromptEntry>, // prompts/ 下的草稿
capabilities: HashMap<Name, CapabilityEntry>, // capabilities/ 下的 Capability
}
enum RegistrySource {
Skill { path: PathBuf, promoted: bool },
Prompt { path: PathBuf, created_at: Instant },
Capability { path: PathBuf, manifest: Manifest },
}
Registry 的启动流程:
- 扫描
skills/目录,收集所有.md文件 → skills HashMap - 扫描
prompts/目录,收集所有.md文件 → prompts HashMap - 扫描
capabilities/目录,收集各子目录中的 manifest 文件 → capabilities HashMap - 构建常驻目录表:skills 的内容 → 摘要列表 → 注入 system prompt
- prompts 和 capabilities 的内容不注入 system prompt,仅在 agent 按需调用时加载
/reload 命令重新执行步骤 1-5,但不重启 daemon。
6.5 目录 → 常驻目录 → system prompt 注入路径
skills/ 目录的文件进入 system prompt 的路径如下:
skills/security-review.md
↓
Registry 扫描 → 读取文件内容
↓
构建常驻目录表:
- name: security-review
- source: Skill { path: skills/security-review.md, promoted: true }
- content: "审查代码时按这个顺序:1) 输入验证 2) …"
↓
注入 system prompt 的尾部:
"你有以下可用 Skill:\nsecurity-review: 审查代码时按这个顺序:…"
↓
agent 在 turn 中可以直接引用"按 security-review 的步骤做"
capabilities/ 的路径不同——它的内容不注入 system prompt,只注入可用性提示:
capabilities/daily-report/
├── manifest.yaml
└── main.sh
↓
Registry 扫描 → 读取 manifest
↓
构建可用能力列表(只列名称,不注内容):
"你有以下可用 Capability:daily-report (Shell/OnDemand)"
↓
agent 只有调用 run_capability daily-report 时,才读取 manifest 和代码
这种"只注名称、不注内容"的设计避免了 Capability 的代码占用 system prompt 的 token 预算。
6.6 完整的自我进化循环示例
以下是一个 agent 从发现问题到沉淀为 Skill 的完整循环:
步骤 1: agent 在代码审查中发现一个重复出现的模式
→ "每次审查 Python 代码,都需要检查 import 顺序"
步骤 2: agent 用 generate_prompt 写草稿
→ generate_prompt(name: "python-import-review", content: ...)
→ 文件写入 prompts/python-import-review.md
步骤 3: agent 在下一次审查中试用草稿
→ use_skill("python-import-review")
→ 草稿内容注入当前上下文
步骤 4: 经过几次试用,确认这个 Skill 值得正式化
→ promote_prompt("python-import-review")
→ 文件从 prompts/ 移动到 skills/
→ Registry 更新,下次启动自动加载
步骤 5: agent 在后续审查中自动使用这个 Skill
→ skills/python-import-review.md 在 system prompt 中
→ agent 每次审查 Python 代码时都会检查 import 顺序
这个循环的关键是步骤 3 和步骤 4 之间的间隔。草稿不是一次生成就自动转正的。agent 需要在实际使用中验证这个 Skill 的价值,然后显式决定是否晋升。晋升是一个独立的 agent 操作——不是自动的、不是隐式的。
如果 agent 生成的 Skill 质量不高,或者适用场景太窄,它可以在草稿阶段被废弃——prompts/ 中的文件可以被删除,不会影响 skills/ 的正式知识库。
ADR 深度阅读
Prompt 草稿层的引入动机(ADR 0025)
ADR 0025 记录了一个从实践暴露的问题:agent 生成的 Skill 质量不稳定。
在草稿层出现之前,agent 用 generate_skill 直接写文件到 skills/。问题在于:agent 第一次生成的 Skill 几乎总是需要修改的。 术语不一致、步骤顺序不合理、验收标准模糊。
最初的做法是让 agent 重复生成——生成 → 审查 → 发现问题 → 修改 → 重新生成。但 agent 在修改时可能引入新的问题,而且"修改 Skill"和"使用 Skill"的界限在 agent 的上下文中模糊。
解决方案是引入中间态:prompts/ 草稿目录。agent 的首先生成物进入 prompts/,只有经过 promote_prompt 显式晋升后才进入 skills/。这个变化的核心不是新增了一个目录——是在"写"和"用"之间加了一道晋升门。
晋升门的意义在于:它不是人肉审批,但也不是自动通过。Agent 做了生的动作(generate_prompt),做了晋升决策(promote_prompt),中间还有试用验证(use_skill 从草稿加载)。每一次独立操作都是 agent 自主决策的——但每一步都可以被用户审计。
这条 ADR 的另一个动机是:防止 skills/ 中出现大量未经验证的 Skill。如果每个 agent 生成的粗稿都直接进入正式知识库,skills/ 会很快膨胀到难以管理。草稿层是一个"缓冲池"——高质量的内容晋升,低质量的内容随时间被清理。
下一章深入 Skill 系统的设计——程序性知识的注入时机、溯源机制、草稿晋升的完整实现。