首页/Agent 核心/Skill 与渐进式披露
Agent 核心 · 第 10 章

Skill 与渐进式披露

第 9 章的搜索助手打完了“模型 + 工具 + 循环”的组合拳;从这一章起进入第四章「怎么扩展它」——当能力越攒越多,怎么组织?第 7 章末尾说过:工具越多,Agent 越笨——schema 挤占窗口、选择困难。但有些能…

约 9 分钟3,529 字7 个代码示例

第 9 章的搜索助手打完了“模型 + 工具 + 循环”的组合拳;从这一章起进入第四章「怎么扩展它」——当能力越攒越多,怎么组织?第 7 章末尾说过:工具越多,Agent 越笨——schema 挤占窗口、选择困难。但有些能力的“说明书”天生就大(比如“如何做前端设计”要写好几百行规范)。Skill 机制的解法很优雅:平时只给一行索引,用到时才加载全文。这一章讲这个“渐进式披露”的设计哲学和实现。

1. 问题:说明书比工具还大

回顾第 7 章的困境,它有一个更极端的形态:

工具 schema(常驻上下文)        ≈ 100~200 token / 个
一份前端设计规范(完整版)       ≈ 2000+ token
十个领域的操作手册              ≈ 20000+ token  ← 窗口直接爆炸

比如你想要一个“前端设计助手”能力:涉及设计原则、配色规范、组件用法、无障碍要求——写成完整说明书有几千 token。但用户十个任务里只有一个用得上它。常驻加载 = 为 10% 的需求支付 100% 的窗口税。

这就是一组经典矛盾:

方案 问题
全部塞进系统提示词 窗口爆炸、费用爆炸、指令淹没(第 5 章)
拆成多组工具 schema 第 7 章的选择困难 + 窗口税依旧
不提供 能力缺失

2. 解法:渐进式披露(Progressive Disclosure)

Skill 的思路来自一个朴素观察:人也不是把所有手册背下来再干活的——需要时翻手册就行。

三层结构:

第 0 层  索引:一行描述(常驻上下文,~10 token)
         "skill: 前端设计规范——创建高质量网页时使用"
第 1 层  元数据:触发条件、适用范围(按需注入,~100 token)
第 2 层  正文:完整的操作手册(使用时才加载,2000+ token)

工作流变成:

  1. Agent 启动时只加载所有 skill 的索引(10 个 skill 也就 100 token)
  2. 模型遇到匹配的任务,调用 use_skill 工具取出正文
  3. 正文作为工具结果进入上下文,模型按手册执行

代价是多一次工具调用的延迟,收益是窗口的大幅节约。当 skill 数量多、单个体积大时,这笔账非常划算。

3. 实现:给 Agent 装 Skill 系统

沿用第 7 章的封装风格。skill 本体就是一个带元数据的 markdown 文件:

# ---------- skill: 前端设计规范(存为 skills/frontend-design.md) ----------
FRONTEND_SKILL = """# 前端设计规范

## 适用场景
从零创建网页、重构页面视觉、优化 UI 细节时使用本规范。

## 设计原则
1. 布局:移动优先,栅格对齐,留白克制
2. 配色:主色一个、辅色一个、中性色阶,对比度 ≥ 4.5:1
3. 字体:系统字体栈,标题/正文层级不超过 4 级
4. 交互:所有可点击元素有 hover/active 态反馈

## 输出要求
- 交付单文件 HTML,内联 CSS
- 必须通过基本的可访问性检查
"""

然后是 use_skill 工具(伪装成普通工具的“文档加载器”):

from pydantic import BaseModel, Field

SKILLS: dict[str, dict] = {
    "frontend-design": {
        "index": "前端设计规范:创建或重构网页视觉时使用",
        "content": FRONTEND_SKILL,
    },
    # ... 其他 skill
}

class UseSkillArgs(BaseModel):
    name: str = Field(description="要使用的技能名,必须是索引中列出的名称")

def use_skill(name: str) -> str:
    skill = SKILLS.get(name)
    if not skill:
        return f"技能不存在。可用技能:{list(SKILLS)}"
    return skill["content"]

关键设计在系统提示词——只放索引,不放正文:

def build_system_with_skills() -> str:
    lines = ["你是一个通用助手,具备以下技能:"]
    for name, s in SKILLS.items():
        lines.append(f"- {name}: {s['index']}")
    lines.append("任务匹配某个技能时,必须先调用 use_skill 加载其完整规范再执行。")
    return "\n".join(lines)

运行效果(第 8 章的 Agent 原样复用):

用户: 帮我做一个个人主页
  ⚙ use_skill({"name": "frontend-design"})       ← 模型主动加载规范
  ↳ # 前端设计规范 ...(2000 token 进入上下文)
  ⚙ write_file({"path": "index.html", ...})       ← 按规范干活
  ✔ 完成

窗口对比:常驻方案每次请求都带 2000+ token;skill 方案只在用到的会话里花这 2000。十个 skill 常驻 2 万 token 的场景,skill 机制把日常开销压到 100 token 以内。

4. 和普通工具的本质区别

值得停下来想清楚:use_skill 和普通工具差在哪?

维度 工具(Tool) 技能(Skill)
本质 一个可执行的函数 一段给模型看的文档
执行者 你的代码 模型自己(按文档行事)
结果 外部世界的改变(文件/请求) 上下文的扩充
类比 锤子 使用锤子的教程

一句话:工具给模型“手”,技能给模型“方法论”。工具改变世界,技能改变模型的行事方式。两者正交,可组合——skill 正文里可以指示模型“先调用 read_file 再动手”。

也正因如此,skill 有个天然限制:它约束的是统计行为(第 5 章的老话题)。规范写“对比度 ≥ 4.5:1”,模型大概率遵守但不保证——需要硬约束时得配合工具层校验(第 6 章)或代码检查。

5. Skill 的工程形态

真实的 skill 生态(如 Anthropic 的 Agent Skills、Trae 的技能系统)比上面的玩具版多几层工程:

skills/
├── frontend-design/
│   ├── SKILL.md          # 正文:规范/方法论
│   ├── scripts/          # 可执行脚本(工具与技能的混合体)
│   └── assets/           # 模板、参考文件
└── code-review/
    └── SKILL.md

三个进阶模式:

  1. 带资源的 skill:SKILL.md 引用目录里的脚本/模板。模型读文档后可以决定执行其中的脚本——此时 skill 成了“工具的打包发行版”
  2. lock 文件:skills-lock.json 记录每个 skill 的来源和版本,保证团队环境一致(和 pnpm-lock 同一思想)
  3. 三级渐进:索引 → SKILL.md 的目录 → 具体小节。超大手册可以再拆,模型按需翻到“第 3 节”

6. 什么时候该做成 Skill

决策清单(对照第 7 章的工具设计):

做成 Skill,当内容是“知识/规范/流程”—— - ✅ 前端设计规范、代码评审标准、写作风格指南 - ✅ 某业务的操作 SOP(先查表、再核对、后回填) - ✅ 大而全但低频使用(10% 的任务才用)

做成 Tool,当内容是“动作”—— - ✅ 读文件、调 API、执行计算 - ✅ 需要确定性结果(校验、转换) - ✅ 高频核心路径

混合形态最常见:skill 文档里指导模型按什么顺序调用哪些工具。比如“发布技能” = 文档(发布流程)+ 对工具既有能力的编排。

本章小结

  • 渐进式披露:索引常驻、元数据按需、正文用时加载——用一次调用延迟换大幅窗口节约
  • use_skill 伪装成工具,本质是“文档加载器”:工具给模型手,技能给模型方法论
  • skill 约束的是统计行为,硬约束仍需工具层校验兜底
  • 工程形态:SKILL.md + 资源目录 + lock 文件 + 三级渐进
  • 决策标准:知识/规范/低频 → Skill;动作/确定性/高频 → Tool

Skill 解决了“自家能力怎么组织”的问题。但生态里有大量别人做好的服务(天气、数据库、GitHub)——每个都手写工具太蠢。需要的是一个标准协议,让所有 Agent 都能即插即用地接入所有工具。这就是 MCP。

下一篇:11 · MCP 全景 —— Model Context Protocol:Anthropic 发起的开放标准,正在成为“Agent 界的 USB-C”。解剖它的通信角色、传输方式和 JSON-RPC 报文。