Agent Skills
type
Post
status
Published
date
Mar 26, 2026
slug
skills
summary
tags
category
LLM
icon
password
Place
一、为什么要 Skills?没有 Skills 会有什么问题?
在 Agent Skills 出现之前,我们让大模型”干活”的方式几乎全部依赖于 System Prompt——把业务逻辑、操作流程、输出格式、Tool 调用规则全部写在一段长长的提示词里,塞进对话上下文。
这种方式在简单场景下够用,但随着 Agent 需要对接的 Tool 越来越多、业务流程越来越复杂,三个核心问题逐渐暴露:
1. 能力选择问题:模型怎么知道该激活哪套规则?
一个企业级 Agent 可能要处理”退换货”、“投诉处理”、“VIP 服务”等多种业务场景,每个场景对应不同的 Tool 调用组合和业务规则。在 Skills 出来之前,这个”选择”问题通常靠 Router 模式 解决,常见有两条路径:
- 基于向量相似度的代码匹配:对每个场景的描述文本做 Embedding,用户请求进来后同样向量化,通过余弦相似度在代码层面直接定位最匹配的 prompt 模板。这是纯工程化的方案,不依赖额外模型,但你需要自己维护向量索引和相似度阈值。
- 小模型分类 + 大模型执行:先用一个轻量级模型(或微调后的小模型)判断用户意图,将请求路由到对应的 Tool,再在 Tool 内部调用大模型来完成实际的推理和生成。这种方案意图识别更准,但你需要维护分类模型的训练和更新,还要管理”小模型选路、大模型干活”的两层调用链路。
两条路径殊途同归——都是在手动实现能力匹配,只是一个靠代码计算,一个靠模型判断。但无论哪种,你都需要自己维护分类器/向量索引、路由逻辑和 prompt 模板之间的映射关系。
Skills 把这个过程内化到了模型的工作流中:每个 Skill 只暴露
name + description 作为元数据,模型自动匹配激活相关的 Skill。 不需要你手写分类器和路由逻辑,模型自己就能做选择。2. Tool 编排的管理问题:业务规则散落在提示词中
当 Agent 需要调用多个 Tool 完成一个复杂任务时(比如投资分析要依次调数据库、行情 API、风险评估工具),“按什么顺序调、传什么参数、什么条件下走哪个分支”这些编排规则,以前全部散写在 System Prompt 里。一个巨型 prompt 既难跨项目复用(只能复制粘贴逐一适配),也难维护(改一条规则要担心影响其他规则)。
说白了,Skills 在这里做的事情并不复杂——本质就是改造了 prompt 的存储结构。把原来一整坨 System Prompt 拆成独立的 Skill 文件,每个文件对应一个业务模块,再给它加上元数据(
name、description、关联的 Tool 列表等)。这样每个 Skill 就变成了一个可寻址、可复用、可独立版本管理的单元,而不是淹没在 2000 行 prompt 里的一段文字。3. Token 消耗问题:从全量加载到按需加载
传统做法下,所有规则全量进入 context window,无论本次对话是否用到。这不只是”浪费 token”的成本问题——context window 是有限的认知资源,塞得越多,模型的注意力越分散,输出质量越差。
Skills 引入了三级渐进式加载机制(后面第二节会详细展开):
- Level 1:只加载元数据(name + description),让模型知道有哪些能力可用
- Level 2:匹配到相关 Skill 后,才加载完整指令
- Level 3:执行脚本时,脚本代码本身不进入 context,,只是调用,所以不占token
从”全量加载”到”按需加载”,这个转变让 context window 的利用效率大幅提升。
Agent Skills 的出发点,就是解决这三个问题。 它将模型的”业务知识”从对话级的一次性指令,升级为文件系统级的可复用模块——自动匹配、统一管理、按需加载。
二、Skills 的结构
一个 Skill 就是一个目录,核心是
SKILL.md 文件(YAML frontmatter 做元数据 + Markdown 正文写指令)。多个 Skill 并列存放:每个
SKILL.md 长这样:frontmatter 里
name 和 description 是仅有的两个必需字段——模型就是靠这两个字段来决定要不要激活这个 Skill 的REFERENCE.md:补充参考资料
REFERENCE.md 是 Skill 目录下的可选文件,充当当前 Skill 的知识附录——存放术语表、格式规范、字段说明、Schema 定义等事实性参考材料。它不是另一个 Skill,也不是独立的 SOP,而是当前 Skill 自身的补充文档。SKILL.md 正文中通过引用触发加载,例如:模型在读取
SKILL.md 正文时看到这个引用,才会按需去读取 REFERENCE.md 的内容。如果本次任务用不到,它就不会被加载——这属于 Level 2 按需加载的一部分。scripts/:本地可执行脚本
scripts/ 目录存放 Skill 自带的可执行脚本(Python、Shell 等),用于处理确定性的、可本地完成的操作——数据验证、文件格式转换、模板渲染、报告生成等。关键设计原则是 “脚本代码不进 context,执行输出进 context”。一个 200 行的 Python 验证脚本,作为文本塞进 prompt 会消耗大量 token;但作为可执行脚本,模型只需看到 “验证通过” 或 “第 3 行格式错误” 这样的输出结果。
scripts 和 MCP Tool 的区别
scripts 和 MCP Tool 都是模型可以”调用”的能力,但它们属于完全不同的层面:
- scripts(Skill 内嵌脚本):跟随 Skill 目录分发,由模型通过 bash 直接在本地执行,不需要外部服务。它是 Skill 自带的一部分,适合封装与该 Skill 业务逻辑强绑定的确定性操作。比如一个 PDF 表单填写 Skill 自带的
fill_form.py,脱离这个 Skill 就没有独立使用的意义。
- MCP Tool(外部工具):通过 MCP 协议连接的外部服务能力(数据库查询、API 调用、文件系统操作等),在 Agent 层面统一注册和管理,不属于任何一个 Skill。它是通用的能力通道,多个 Skill 都可以调用同一个 MCP Tool。
Skill 的
SKILL.md 正文中可以用自然语言引用 MCP Tool,但不负责管理它们。例如:简单来说:scripts 是 Skill 自带的”手边工具”,MCP Tool 是 Agent 层面的”公共基础设施”。 Skill 只说”第一步该查数据库”,至于数据库怎么连、用什么协议,那是 MCP 的事。
三级渐进式加载(Progressive Disclosure)
这是 Skills 架构设计中最精妙的部分。传统 Prompt 是”一股脑全塞进去”,而 Skills 采用三级渐进式加载,只在需要时才加载相应内容:
Level 1:元数据(Metadata)—— 始终加载
模型启动时,只加载每个 Skill 的
name 和 description。这让模型知道”我有哪些能力可用”,但不消耗详细指令的上下文空间。就像你知道团队里有个”税务专家”,但你不会在每次开会时都让他把税法全文念一遍。Level 2:指令(Instructions)—— 按需加载
当模型判断某个 Skill 与当前任务相关时,才通过 bash 命令读取
SKILL.md 的完整正文。如果正文引用了其他文件(如 FORMS.md、REFERENCE.md),也按需读取。Level 3:代码与资源(Code & Resources)—— 执行时加载
当指令中提到可执行脚本时,模型通过 bash 执行脚本,但脚本代码本身不会进入 context window——只有执行输出会进入。
这是一个很关键的设计:一个 200 行的 Python 数据验证脚本,如果作为文本塞进 prompt,会占用大量 token;但作为可执行脚本,模型只需要看到”验证通过”或”第 3 行格式错误”这样的输出结果。代码提供了确定性的执行能力,输出提供了最小化的上下文信息。
用一张图概括这个加载流程:
综合来看,一个 Skill 目录中的三类文件各司其职:指令(.md)处理模糊的判断,脚本(scripts/)处理精确的操作,资源(REFERENCE.md 等)提供事实性参考。 三者的分工让 Skills 同时具备了灵活性和可靠性。
三、Skills 和 MCP 的关系
Skill 的指令中可以调用 Tool,而 MCP(Model Context Protocol)就是 Agent 生态中 Tool 的标准提供方式——通过 JSON-RPC 协议让模型发现和调用外部工具(数据库、API、文件系统等)。
两者的关系很简单:Skills 定义”该做什么”,MCP Tool 提供”用什么做”。 Skill 在
SKILL.md 里写”第一步查询财务数据”,模型就会去调用 MCP 注册的 query_financial_data 工具。数据从 MCP 来,流程和判断逻辑从 Skill 来。四、Skills 和提示词工程的关系
Skills 和提示词工程(Prompt Engineering)的关系,可以概括为一句话:Skills 是提示词工程的工程化升级。
从”手工作坊”到”工业化生产”
传统提示词工程就像手工作坊——每次对话都是一次性的手工活。你精心调好一段 prompt,它只活在这一次对话中。下次遇到类似需求,你得重新写,或者从某个笔记里复制粘贴。
Skills 做的事情,是把提示词工程从”对话级”提升到”文件系统级”:
维度 | 传统 Prompt | Skills |
生命周期 | 对话级(用完即弃) | 持久化(文件系统存储) |
复用方式 | 复制粘贴 | 自动加载、自动匹配 |
上下文占用 | 全量加载 | 按需加载(三级渐进式) |
模块化 | 无(所有规则混在一起) | 有(每个 Skill 独立封装) |
能力边界 | 仅文本生成 | 文本 + 代码执行 + 文件操作 |
可维护性 | 低(牵一发动全身) | 高(独立修改、独立测试) |
Skills 没有取代 Prompt
Skills 并不是要”取代”提示词工程。Prompt 依然是与模型交互的基本方式——你依然要写 System Prompt、用户消息,使用思维链、Few-shot 等技巧。两者的边界在于是否可复用:
- 适合写成 Skill 的:会反复出现的业务流程、团队规范、领域知识。比如代码审查标准、报告生成模板、客户投诉处理 SOP——这些规则跨对话、跨用户都通用,值得沉淀为独立模块。
- 适合留在 Prompt 里的:一次性的、跟当前对话上下文强绑定的指令。比如”帮我把这段话翻译成英文”、“用更口语化的风格重写”——这类指令用完即弃,没有复用价值,做成 Skill 反而是过度工程。
用一个公式表达:
Prompt 不需要声明 Skill
一个常见的疑问是:使用 Skills 之后,是不是每次写 Prompt 都要手动指定”这次用哪个 Skill”?
不需要。Skill 一旦注册,就已经是模型能力的一部分了。 Agent 启动时,所有 Skill 的
name + description 会自动加载到上下文中(Level 1)。当用户请求进来,模型根据元数据自行判断该激活哪个 Skill——这个过程对 Prompt 编写者是透明的。这也是 Skills 相比传统 Router 模式的核心改进:你不需要手写分类器、路由逻辑或 if-else 分支来决定”什么请求走什么规则”。模型自己就能做这个选择,就像一个熟练员工不需要每次都被告知”这个问题该翻 SOP 第几页”——他已经知道了。
Prompt、Memory、RAG、Skills 共同构成了 Agent 的能力体系:
- Prompt:基础交互方式,一次性的对话指令
- Memory:记忆系统,记住用户偏好和交互历史
- RAG:知识检索,从外部数据源获取实时信息
- Skills:技能系统,封装可复用的业务流程和操作规范
当任务越复杂、越关键,后三者的系统化工程价值就越凸显。从”怎么写好一个 Prompt”到”怎么设计一套 Skills 体系”,这是从提示词工程到技能工程(Skill Engineering)的范式迁移。
五、SpringAI集成Skills
目标:把 Spring AI 的 Generic Agent Skills 跑起来:能从.claude/skills发现并按需加载SKILL.md。
1)加依赖(pom.xml)
2)注册 SkillsTool(最小可跑)
3)可选:允许 skill 读文件 / 跑脚本
4)创建 skill 文件
目录结构(放在项目根目录):
SKILL.md 最小模板:上一篇
JVM
下一篇
MCP
Loading...