☰
AI Skills 实战拆解:从提示词到标准化智能体技能包
2026/10/21 21:27:50 网站建设 项目流程

AI Skills 最近几乎成了智能体开发讨论里出现频率最高的词。可你要是连着刷几篇帖子就会发现,大家说的东西经常不是同一个:有人讲“人怎么用 AI 更熟练”,有人讲“给模型配一份可复用的操作说明书”,还有人直接把技能等同于“会调用 API”。这很容易让人越看越乱。

我的看法很直接:从实际开发者的视角来看,AI Skills 就是一套标准化的任务执行能力包。它不是一段孤零零的提示词,而是把任务拆解、操作步骤、校验规则、输出模板和必要的辅助脚本一起封装进一个可被发现、可复用的结构,让智能体在遇到对应场景时能直接按“说明书”执行。这篇文章我想从概念一路讲到实践,重点把“为什么需要”“技能文件怎么写”“如何从零手写并调试”“怎么沉淀成长期技能库”这几件事讲透。适合正在做智能体应用、或者被大量重复人工调整提示词折腾到精疲力竭的同学参考,也欢迎刚接触这个概念的新手跟着操作一遍。

1. 从“聊天”到“执行”:AI Skills 到底解决什么问题

1.1 一个典型的低效循环

我先描述一个可能不少人都经历过的场景。假设你要让智能体帮你定期梳理一批网页链接,把它们整理成结构化的报告。最开始,你很自然地在对话框里写了一段很长的提示:“请逐个打开这些链接,提取标题、站点简介、平台入口和接口可用性,最后按我给你的模板输出。注意访问不了的页面标注 N/A,不要编造内容。如果页面给出的是外文,用中文总结主要信息。另外不要输出任何多余的话。”

当前的主流模型大概率能按这个要求做一次,而且效果不错。于是你把这个提示存下来,打算下次继续用。可过了一周,你想在另一个项目里复用,发现当时的模板细节已经不全了;又看到好几条相似的提示散落在不同地方,改一个变量就得全文同步一遍。最后你干脆把它写进系统提示里,结果系统提示越来越长,连其他任务的回答都变得啰嗦。这个循环的本质是:我们在用“一次性聊天文本”的形态,去管理一套需要反复执行的业务流程。而流程应该有载体、有版本、能被智能体主动调用——这就是技能模块存在的理由。

1.2 它和提示词、工具、知识库不是一回事

有同学可能会问:这东西不就是换了个马甲的提示词吗?其实区别很大。提示词解决“告诉模型这一次该怎么做”,工具解决“给模型提供一项外部能力”,知识库解决“给模型补充相关背景资料”,而技能解决的是“把一套可重复执行的方法固化下来,并让模型能按需发现和装载”。我把它们的边界整理成表,对比会清楚很多:

能力形态核心解决典型载体由谁触发
提示词/系统提示单次任务的行为约束文本段落使用者写入上下文
工具/函数调用调用外部真实能力API、函数定义模型决策后执行
知识库(RAG)补充具体事实与资料向量检索和文档检索流程自动注入
技能(Skills)固化整套操作流程说明书+示例+脚本智能体智能选择

实际工程中二者常有交叉:技能内部可以调用工具,也可以引用知识库,但它的定位更接近“任务方法论”。这里给一个生活化类比:提示词像“你告诉我今晚想吃什么”,工具像“给你一个可以用起来的厨房”,知识库像“给你一本菜谱资料”,而技能则是一份标准化菜谱——写清楚用什么锅、先放什么后放什么、做到什么程度算熟、出品摆盘长什么样。你需要的不是无限加长的口头吩咐,而是一份可以被翻阅、被执行的操作规程。

1.3 为什么任务越复杂,越需要技能而不是更多提示

随着智能体任务变复杂,模型单次上下文能承载的信息有限,注意力也会被各种冗余词句搅乱。如果所有约束都由一段巨大的系统提示承载,一方面容易出现前后矛盾的指令,另一方面一旦任务版本升级,所有调用方都会被牵动。技能的好处在于给任务做了模块化封装:每个技能负责一个清晰的领域,智能体在需要时装载对应技能,不必每次都把全量规则塞进上下文;同时技能边界足够清楚,模型也能更准确地判断“什么时候该用、什么时候不该用”。这一点在后面写实际技能时会反复碰到。

2. 解剖一份 SKILL.md:目录、元信息、指令区、示例模板

2.1 一份技能文件的标准骨架

目前主流智能体框架里,技能通常会以一个目录为单位组织。我给一个比较通用的结构:

my-skill/ ├── SKILL.md # 技能说明书,必须放在根目录 ├── assets/ # 参考资料、模板文件 │ └── report_template.md ├── scripts/ # 必要时放辅助脚本 │ └── check_url.py └── examples/ # 输入输出样例,方便模型对齐格式 ├── example_input.json └── example_output.md

其中 SKILL.md 是灵魂,也是模型和这套技能之间的“接口契约”。它通常分成两部分:文件头部的元信息和正文的操作规程。下面我拿一个实际技能来拆解,技能目标暂定叫“链接信息梳理”。

2.2 description 写不好,技能等于不存在

先看文件头部:

--- name: url-description-report description: > 当用户需要把一批网页链接整理为结构化报告时使用。 适合处理链接列表、开放平台信息汇总、接口可用性检查等场景。 如果你只是需要访问一个页面查点资料,不要用这个技能。 ---

为什么这部分重要?因为大多数智能体框架在决策要不要调用某个技能时,会先把所有技能的 name 和 description 做简要汇总,交给模型选择。description 本质上是一段“被模型阅读的搜索索引”,需要说清楚技能解决什么、不解决什么。我见过不少人把 description 写成“用于整理链接报告”,结果模型在遇到“帮我看看这个网站能做什么”这种输入时,根本不会想到调用它。更有效的写法是“触发条件描述 + 典型输入形态 + 明确排除项”。如果空间充足,可以补上可能出现的输入字段示例,比如“常见会传入的字段包括 url、备注、分类”。

2.3 指令区、边界与示例的配合逻辑

文件正文是真正会被模型当作指令来读的部分。我通常分成几块:任务目标、输入格式、执行步骤、输出模板、守则与错误兜底。下面是一个示范片段:

# 任务目标 将输入的链接列表逐条核实,并输出统一 markdown 报告。 # 输入格式 用户可能提供多种来源的输入: - 纯链接列表,每行一条 - 链接带备注,例如“链接+空格+备注文本” - 直接粘贴一整段包含链接的聊天文本,此时需要先抽取链接 # 执行步骤 1. 从用户输入中抽取所有链接,保留附带备注。 2. 对每个链接做存活性和可访问性检查;无法确认时标记为 UNKNOWN。 3. 尝试获取页面标题与站点简介;抓不到就用链接自身域名做基本推断。 4. 按报告模板逐条输出,不输出链接之外的主观评价。 5. 所有无法核实的字段填 N/A,严禁编造。 # 输出模板 ## {序号}. {页面标题} - 来源链接:{原始链接} - 站点简介:{概览} - 可访问性:{可用/不可用/UNKNOWN} - 备注:{用户的原始备注或“无”} # 守则 - 如果输入与链接整理完全无关,直接拒绝执行。 - 一次只处理一个任务,不自动扩大范围。

最后再放两三组输入输出样例,比任何长篇解释都管用。模型的少样本学习能力很强,样例等于“标准答案示意”,尤其适合格式要求严格的任务。但示例不要太多,避免技能体积膨胀,后面我会专门聊体积控制。

3. 手写一个“链接信息梳理技能”:需求拆解、文件编写与实测迭代

3.1 需求拆解:先明确输入、输出和“不做的事”

动手写 SKILL.md 之前,我先把自己的需求写在草稿纸上,通常只列三项:输入范围、输出模板、不做清单。以链接梳理为例:

项内容
用户会输入什么链接列表、带备注的链接、混在段落里的链接
我要产出什么固定格式的 Markdown 信息卡片,每条链接一张
明确不做的事不爬取页面全部正文、不做价值评估、不该用链接分析时不要触发

有人觉得这一步啰嗦,但实际执行下来,多数二次修改成本都出在这里。尤其是“不做的事”,相当于给模型划出安全边界,可以大幅减少模型自作主张的行为。比如你不加“不做 SEO 评估”,模型很可能在报告里擅自加一段“该站点 SEO 表现中等”的废话,打乱格式。

3.2 编写 SKILL.md:从骨架到可运行版本

把上面拆解的内容整理成正式文件,再补充它需要调用哪些辅助脚本,就能得到一个基本可用的版本。这里的关键原则是:能由脚本完成的确定性步骤,不要让模型凭能力去猜。例如链接可访问性检查本质是一次网络请求,模型自己很难稳定拿到真实结果,那就应该让技能调用脚本,并在 SKILL.md 里写清“检查时请执行 scripts/check_url.py,并以它的输出为准”。

技能不一定是纯文本,它可以是“文本说明书 + 辅助工具”的组合。文本说明书负责流程与方法,脚本负责解决模型不擅长或无法完成的确定性计算。比如步骤 2 完全可以写成:

2. 对每个链接执行: python scripts/check_url.py --url {链接} 根据输出中的 OK/UNKNOWN 填写可访问性字段。

这样模型在处理时就有了明确工具路径,而不是在自己内部进行一次没有实际网络数据的推理。

3.3 辅助脚本:把模型不擅长的事交给代码

下面给一个非常简化的检查脚本示意:

# scripts/check_url.py import sys, requests for url in [u.strip() for u in sys.stdin.read().splitlines()]: if not url: continue try: r = requests.head(url, timeout=5, allow_redirects=True) print(f"{url}\tOK\t{r.status_code}") except Exception: print(f"{url}\tUNKNOWN\t无法访问")

实际项目里你会把超时、重试策略、证书错误处理都完善起来,但思路是一样的:让脚本做模型不擅长的事,模型集中精力做流程编排、信息总结和格式控制。这里特别提醒一点:技能里的脚本输出最好保持“简明、稳定、解析成本低”的文本格式,比如一行一条、用 tab 分隔。不要输出大段富文本,否则模型提取关键字段时很容易出错。

3.4 实测迭代:第一次失败是正常的

第一次把技能配上智能体时,我通常拿三类输入做冒烟测试:最典型的输入、带杂音的输入、完全不应该触发技能的输入。

典型问题很快会暴露。比如我初版技能要求“对每个链接做可访问性检查”,模型根本不调用脚本,反而在脑海里假设这些链接都可以访问,导致报告里出现一堆其实没有验证过的“正常”。模型不调用脚本,通常不是模型笨,而是技能文件里没有把“必须调用脚本”变成强约束。于是我把第二步改成“必须执行脚本,并把输出映射到可访问性字段”,加上“必须”两个字后,行为就稳定很多。

同样值得记录的问题还有:模型在第二步执行完脚本后,并没有按照脚本输出里的状态码填写报告,而是自己另写了一段描述。原因是我没有在步骤里写明“状态码只用 OK 或 UNKNOWN 表达,不要额外解释”。这位初版问题总结成一条经验:技能文件里的命令越具体、越接近代码逻辑,模型的执行越稳定。少给判断题,多给选择题或明确顺序指令。

3.5 版本迭代日志示例

技能不是一次性写完就结束的。我习惯在技能目录里放一个简短迭代记录,例如:

版本改动原因
v0.1初版,纯文本梳理验证格式
v0.2增加 check_url.py 强约束模型不调用脚本,臆测可访问性
v0.3调整输出模板,去掉无关字段报告格式被模型擅自扩写
v0.4description 增加反例说明无关输入频繁误触技能

每次改完都跑一遍之前的最小测试集,防止修复一个问题带出另一个问题。

4. 技能在智能体里是如何被调起来的:选择、注入、执行

4.1 一个技能在运行时要经历三个环节

如果你正在调技能为什么始终不被触发,这部分会很有帮助。主流智能体框架对一个技能的使用大体分为三步:

  • 候选发现:框架根据当前环境、用户请求和各个技能的 description,先筛选出一批匹配的技能。这个过程可能是关键词匹配、语义检索,也可能直接由模型自己在有限列表里选择。
  • 内容注入:被选中的技能会以文本形式写入当前对话上下文,通常包含 SKILL.md 的全部或摘要内容,辅助脚本以工具形式暴露。
  • 执行编排:模型根据技能说明书开始组织任务,需要脚本就运行脚本,需要检索就去调检索,最后按模板输出。

理解这三个环节之后,“技能调不起来”的排查就清楚多了。如果候选发现阶段没选中技能,问题多半出在 description 写得不像索引;如果选中了但执行不对,问题多半出在 SKILL.md 指令不够明确;如果执行途中格式丢失,问题多半是上下文里有其他指令和技能冲突。

我现在对技能调不起来时的排查顺序是:

问题优先检查
技能根本没触发description 是否包含足够多的触发词和排除词
技能触发了但执行路径不对SKILL.md 的步骤是否按顺序写清、是否允许分支
输出格式总是跑偏是否缺少输出模板,或存在和全局提示冲突的指令
每次结果不稳定是否缺少固定脚本约束,是否示例太少

4.2 一个技能吃多少 Token,怎么控制预算

技能文件体积需要精打细算。假设一个技能 SKILL.md 写了 1500 token,辅助脚本说明又占 500 token,那么每次技能被激活,上下文就要多出 2000 token 的开销。如果智能体同时维护几十个技能,每次激活好几个,上下文很容易被技能说明占满,反而挤压真正干活的窗口。

我常用的控制策略包括:

  • 技能说明控制在 800 到 2000 token 之间,除非任务本身需要非常细致的规则。
  • 大段参考模板尽量放到 assets 目录,由技能在需要时按模板生成,而不是整份模板写死在 SKILL.md。
  • 技能需要引用多个脚本时,SKILL.md 只写接口和输出解析方式,不贴全部源码。
  • 不需要每次对话都启用的技能,应在 description 里明确“不要随意使用”,降低误触发概率。

4.3 当全局提示和技能打起来时

技能执行偏差还有一个常被忽略的原因:全局系统提示和技能指令冲突。比如全局提示写“回答尽量简洁”,而技能里写“必须输出完整 Markdown 报告”,模型面对冲突时经常会选择折中方案,结果两边都不满意。解决方式是在全局提示里加一句“当技能中定义了输出模板时,优先遵循技能模板”。这一点很小,但对长流程任务影响巨大。

5. 从“临时提示”到“技能库”的重构:拆、改、验三段式

5.1 先承认:提示不是技能

很多人的第一个技能库,是从“我收藏的 20 条好提示”开始的。这也能用,但很快会遇到问题:提示往往针对一次具体问答,里面有大量场景假设,复用性远没有想象中高。所以我的建议是,先别把所有收藏都改成技能,先挑那些已经重复用过三次以上、并且你对输出结果已经满意的提示来重构。这些才是真正经历过验证的流程,值得被固化。

5.2 拆:把一条提示拆成任务单元

以“整理自动化测试工具清单”为例。原始提示可能是“请帮我整理一批适合做接口测试的开源工具,列清楚名称、适用场景、GitHub 星标、最近更新时间,按表格输出,并给我的项目推荐 3 个”。这条提示里其实包含三个可复用单元:检索与筛选标准、信息字段定义、推荐链路。

重构时,先把它拆开,逐个问自己三个问题:

  • 这个单元是否稳定?
  • 它需要哪些输入才能完成?
  • 它的输出如何被下一个单元使用?

“筛选标准”是相对固定的,“项目背景”是每次不同的参数;“输出字段”是固定的,“推荐 3 个”可以被抽成可选步骤。这样拆出来的任务单元,才能帮你决定技能里哪些是固定步骤、哪些是可变参数。

5.3 改:垂直化、规则化、参数化

重构最关键的一步,是把原来的口语提示改写成“规则文本 + 参数占位”。我会做三件事:

  • 垂直化:把提示限制在一个明确的领域内,不要让一个技能什么都干。
  • 规则化:每个步骤用强制语气写清楚,添加“必须”“优先”“禁止”这类词,并写明边界条件。
  • 参数化:把每次任务不同的部分标记为输入参数,比如{项目介绍}、{目标平台},在文件开头说明用户常见的表达方式。

我还会刻意删掉那些礼貌用语和模糊修饰词。模型不会因为“请尽量”就更听话,反而会因为指令不够坚定而输出得更自由。技能文本应该像 API 文档,而不是一封商洽邮件。

下面给一个小例子,展示原始提示和技能指令的对比:

原始提示风格技能指令风格
“麻烦看看这些工具行不行,列几个主要的就行”第一步必须输出名称;第二步必须说明适用场景;若信息缺失写 N/A
“最好能提到星标数,没有也没关系”星标数缺失时写 N/A,禁止用“未知”“大概”这类词

5.4 验:最小测试集与回归习惯

技能改造完,一定要有一个最小测试集。哪怕只有五组输入,也要覆盖五类情况:标准输入、边界输入、错误输入、无关输入、格式要求严格的输入。

每次改动技能文件之后都跑一遍这五组,对比输出是否符合预期。很多人说技能“越改越不稳定”,其实往往是因为只拿一两组用例测试,结果修好了 A 又弄坏了 B。有了回归测试的习惯,这个坑就能避开。

6. 技能库规模化的现实问题:颗粒度、上下文预算、维护

6.1 每个技能只负责一件事

技能颗粒度是实践中最常出现的分歧。有人喜欢把很多步骤塞进一个超厚技能,觉得这样触发率高;也有人把特别小的动作单独做成技能,结果技能数量爆炸,智能体每次选技能都变成高成本的匹配任务。

我的经验是一句话:一个技能描述的任务,应该能在“一段说明书”里说清楚。如果一个技能的 SKILL.md 需要超过 3000 token 才能说清楚,那它大概率不是太粗,而是被塞进了多个相关但不同的任务。

拆分的判断标准也简单:问自己“结束条件是什么”。如果技能内部有明显不同的结束条件,比如“先提取链接,再生成报告”和“做可访问性检查”就不该合在一起。智能体可能只需要检查场景,却被流程带进了完整报告输出。这时候把可访问性检查抽成一个独立小技能,让链接梳理技能按需调用它,结构会更健康。

6.2 上下文预算与按需加载

技能库规模变大以后,我强烈建议:别把所有技能一次性挂载到智能体上。除非场景非常简单,否则一定做“按需加载”。

实现上,可以选择只把技能清单(名称加一句话描述)放进模型可见配置,等模型确定要执行某项流程后,再真正加载对应 SKILL.md 文件的完整内容。这等于把技能的“索引”和“全文”分开,既能保证候选发现覆盖足够广的技能,又能避免上下文被没有用到的技能说明白白吃掉。

算一笔账:如果挂载 20 个技能,平均每个技能 1200 token,全量加载就是 24000 token。按当前主流模型的价格,既费钱也占窗口。如果只加载技能清单,token 可能只需要 2000 左右,真正命中后只加载那一个技能的全文,整体成本会明显下降。

6.3 维护一个自带版本感的技能库

最后说说长期维护。技能是一种会“腐烂”的资产:页面结构变化了,脚本要更新;模型能力升级了,原来很绕的指令可以简化;业务场景变化了,技能边界要调整。所以技能库不能只往回堆文件。

我个人的维护习惯有三个:

  • 每个技能文件头部保留版本号和最近修改日期,改动时在迭代记录区追加一行,写清改了哪里、因为什么改。
  • 所有技能共用一份索引文件,记录技能名称、职责、大概 token 成本、依赖脚本。新技能入库或大改后,顺手更新索引。
  • 把“最少必要技能数”当作治理目标。每隔一段时间看一遍哪些技能超过三个月没被真正触发,如果没有可靠计划要用它,就果断归档到_archive/。

我在实际维护中还有一个体会:技能说明不是写得越全越好,而是“刚好够用”。每次往 SKILL.md 里加句子前,先问自己一句,这行话是处理任务所必需的吗?如果不是,就删掉。因为技能文本最终会成为模型上下文的一部分,句子越多,模型真正执行时注意力越分散。保持每份技能短小、明确、可测试,比堆砌一长串看起来周到的命令更可靠。

以上这些,是我这段时间做技能改造时最想提醒后来者的内容。如果你手头正有一批反复手工调整的提示词,不妨先挑一条用满三次以上的,按拆、改、验的流程走一遍。做完第一个技能之后,你大概率会重新理解为什么大家都在强调“技能而不是提示”这个方向。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询