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 文件,每个文件对应一个业务模块,再给它加上元数据(namedescription、关联的 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 里 namedescription 是仅有的两个必需字段——模型就是靠这两个字段来决定要不要激活这个 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 的 namedescription。这让模型知道”我有哪些能力可用”,但不消耗详细指令的上下文空间。就像你知道团队里有个”税务专家”,但你不会在每次开会时都让他把税法全文念一遍。
Level 2:指令(Instructions)—— 按需加载
当模型判断某个 Skill 与当前任务相关时,才通过 bash 命令读取 SKILL.md 的完整正文。如果正文引用了其他文件(如 FORMS.mdREFERENCE.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...