Skills 技能体系:从单步工具到可复用的能力包
系列:ToyAgent 智能体知识库 10/26
一句话核心:工具解决"一步"的问题,技能解决"一类"的问题。L0 提示词、L1 工具组合、L2 子流程,三层沉淀把验证过的流程固化成资产。
为什么需要
工具(Function Calling)是原子操作:查一次天气、读一个文件。但用户的要求往往是复合的——"做一份杭州旅行攻略"实际需要:查天气 + 看时间 + 结合日期给建议 + 按格式排版。
让模型每次现场思考这个流程,有两个代价:慢(每步都要模型决策)和不稳定(同一请求今天走三步明天走四步,输出格式飘忽)。把验证过的流程封装起来,就是技能(Skill)——模型只负责"选哪个技能",执行走确定性编排。
核心机制:三层抽象
| 层级 | 构成 | 例子 |
|---|---|---|
| L0 | 提示词技能:纯 Prompt 模板 | 「翻译腔修正器」「周报生成器」 |
| L1 | 工具组合:固定调用一组工具 + 拼装 | 旅行攻略 = 天气 + 时间 + 模板 |
| L2 | 子流程:一个完整 ReAct 循环封成技能 | 「代码审查技能」内部跑多轮工具链 |
技能的执行分两段:先选技能(模型按语义匹配,这是唯一交给模型的决策),再执行技能(确定性编排):
// 1. 技能选择:模型输出结构化决策
String skill = Json.str(model.chat(routeMessages(input)), "skill");
// 2. 技能执行:switch 确定性分发,而非现场发挥
return switch (skill) {
case "travel_plan" -> travelPlan(input); // L1:组合两个工具
case "weather_report" -> weatherReport(input); // L1:单工具
default -> freeChat(input); // L0:纯提示词兜底
};
// L1 技能内部:调几次工具、什么顺序,全是预先设计好的
String weather = WeatherApi.query(city);
String time = LocalDateTime.now().format(FMT);
String answer = model.chat(List.of(
Message.system("你是旅行顾问。基于天气与时间信息输出攻略……"),
Message.user(input + "\n天气: " + weather + "\n时间: " + time)));
编排哲学:注意 L1 技能内部没有循环、没有不确定性。能确定的流程绝不交给模型现场决策——把不确定性留给真正需要它的环节(如攻略文案本身)。这是智能体工程里"编排重于自主"原则的最小体现。
先路由后执行的完整链路:
graph TD
IN["用户请求"] --> R["技能路由:模型语义匹配"]
R -->|travel_plan| T["L1 旅行攻略技能"]
R -->|weather_report| W["L1 天气播报技能"]
R -->|未命中| F["L0 自由对话兜底"]
T --> T1["查天气 API"]
T --> T2["取当前时间"]
T1 --> T3["拼装提示词生成攻略"]
T2 --> T3
W --> OUT["确定性输出"]
T3 --> OUT
F --> OUT
图示:模型只做一次技能选择决策,命中 L1 技能后走预先设计好的确定性编排,未命中则落到 L0 提示词兜底。
举例
模拟对话轨迹——同一个请求,走技能与不走技能的差别:
用户:帮我做一份杭州的旅行攻略
[无技能版] 模型自由发挥:
思考:也许该查天气?也许不用?先直接写吧……
→ 输出泛泛的景点列表,可能漏掉天气因素,格式每次不一样
→ 3 轮模型决策,token 开销大,质量随机
[技能版]
第 1 轮(路由):模型输出 {"skill": "travel_plan"}
第 2 轮(执行,确定性):
weather = "晴,18-26℃,东南风 3 级"
time = "2026-10-13 周二 14:30"
→ 注入提示词:"你是旅行顾问。基于天气与时间信息输出攻略…"
模型输出:
「今明两天杭州晴好、昼夜温差大(18-26℃),建议:
今天下午:西湖环湖(紫外线强,备防晒)……
明日:灵隐寺早行(午后转热),晚归前查返程」
技能版只花 2 轮模型调用,输出结构稳定、引用了真实天气与时间——因为"要不要查天气、怎么用时间"这些流程决策已经从模型手里拿走了。
L2 技能的例子:「博客发布官」技能——内部是一个完整循环:读草稿 → 生成摘要/分类/标签 → 自查规范 → 提交人工确认 → 确认后落库。用户看到的是"一个技能",里面跑着多轮工具链与 HITL 节点。
沉淀视角:Claude Skills、OpenAI GPTs、企业插件市场,本质是同一件事——把个人/组织经验固化为可复用资产。一个好的技能包 = 描述文档(供路由匹配)+ 执行逻辑(工具编排)+ 示例(Few-shot)。技能库越厚,智能体越强,而模型不用换。
三层怎么选
| 场景特征 | 选层 | 理由 |
|---|---|---|
| 只需要改说话风格/格式 | L0 | 无外部依赖,成本最低 |
| 步骤固定、工具已知 | L1 | 确定性编排,稳定省 token |
| 步骤数随输入变化、需多轮探索 | L2 | 必须留自主循环,但循环边界由技能框定 |
面试考点
- 技能和工具的区别? 工具是原子能力(一步),技能是流程封装(一类问题);技能内部可以组合工具,技能向外暴露的是"能力"而不是"接口"。
- "编排重于自主"是什么意思? 流程中能确定的环节(调哪些工具、什么顺序、怎么拼装)用人写死,模型只在语义匹配与内容生成两处发挥作用——稳定性、成本、可测试性全部受益。
- 技能包由哪三部分组成? 描述文档(供路由语义匹配)、执行逻辑(确定性编排/子流程)、Few-shot 示例。三者缺一:没描述选不中,没逻辑不稳定,没示例质量飘。
生产化路径
- 技能路由用向量匹配兜底:技能多了以后,纯靠模型读全量技能清单选会超预算——先 Embedding 粗筛 Top-K 技能,再让模型精选。
- 技能跨轮生效:注意会话态实现里"绑定技能只在当轮有效"的坑——技能注册要进持久的会话上下文,否则用户第二轮说"继续"时技能已失效。
- 参数白名单:技能可配置的工具集做白名单校验,防止技能被诱导调用越权工具(幻觉工具问题)。
- 技能市场与版本化:技能按语义化版本管理,改编排逻辑 = 发新版本;线上问题可回滚到旧版技能而不是改提示词热修。
- 观测:每个技能记录选中率、执行成功率、平均轮次——路由选错的技能是质量问题的头号来源。