
1. 从skills这个模糊词说起它到底指什么第一次看到skills这个标题加上一堆热搜词里混着 Agent Skills、Google Cloud、GKE、Genkit、codex skills、claude agent skills我脑子里第一反应是这词太泛了。但把热搜词串起来看方向其实很清晰——这里的 skills 不是指人类职业技能而是指 AI Agent 生态里的技能包机制也就是给智能体挂载可复用能力模块的那套东西。说白了Agent Skills 就是一套让 AI 从只会聊天变成会干活的插件化方案。一个裸的对话模型你问它今天天气它可能瞎编你让它去查数据库它没权限你让它按公司规范生成一份周报它不知道规范长什么样。Skills 要解决的就是这个问题把某类任务该怎么做沉淀成一个独立、可加载、可复用的单元Agent 需要的时候挂上去不需要的时候摘下来。这个思路其实不新鲜早几年插件系统、函数调用、工具调用都在做类似的事。但 Skills 这一波之所以火是因为它把粒度做得更细、描述更自然、组合更灵活。以前你要给模型加个能力得写一堆 JSON Schema 定义参数现在很多框架允许你用一段自然语言描述加几个示例就能定义一个 skill。门槛降下来了玩法就多了。我接触这块是从一个很实际的需求开始的团队里有一批重复性的文档处理任务格式固定、步骤固定但每次都要人肉操作。试过写脚本维护成本高试过直接让模型做稳定性差。后来用 Skills 的思路把每个步骤拆成独立技能串起来跑才算找到一个平衡点。这篇文章就把我踩过的路、试过的方案、以及那些文档里不会写的坑完整摊开讲一遍。适合谁看如果你正在做 Agent 相关的东西或者想给自己的 AI 工作流加一点确定性又或者只是被热搜词刷屏想搞明白这到底是个啥那这篇应该能帮你省下不少瞎试的时间。2. Agent Skills 的底层逻辑为什么是技能而不是工具2.1 工具调用和技能包的本质区别很多人把 Skills 和 Tool Calling 混为一谈觉得不就是换个名字吗。实际用下来两者的设计哲学差别挺大。Tool Calling 的核心是函数签名。你定义一个函数声明它叫什么、收什么参数、返回什么类型模型负责在合适的时候调用它。这套机制很严谨但也很死板——参数类型对不上就报错模型理解偏差就传错值。而且工具本身是无状态的它不知道上下文不知道前一步做了什么每次调用都是独立的。Skills 的核心是能力封装。一个 skill 不只是个函数它可能包含一段说明这个技能是干嘛的、什么时候用、若干示例输入输出长什么样、依赖声明需要哪些前置条件、甚至内部的多步逻辑。它更像一个迷你专家而不是一个扳手。打个比方Tool Calling 像是给工人一把锤子告诉他这是锤子能敲钉子Skills 像是给工人一本操作手册里面写着遇到这种钉子用这种敲法遇到那种钉子换那种敲法敲之前先检查什么。前者给的是工具后者给的是能力。这个区别在实际项目里影响很大。纯 Tool Calling 的方案模型经常在该不该调用上犯错因为它只看到了函数名和参数没有足够的上下文判断。而 Skills 因为带了使用说明和示例模型判断的准确率会高不少。2.2 技能描述文件为什么比代码更重要我踩过最大的一个坑就是一开始太关注 skill 的代码实现忽略了描述文件。结果技能写好了模型死活不用或者用错场景。后来才明白对模型来说描述文件才是它看到的全部。代码是执行时才跑的模型决策时只能依赖描述。描述写得含糊模型就懵描述写得精准模型就灵。一个好的技能描述应该包含这几层信息触发条件什么情况下该用这个技能。要具体不要写处理文档这种大而全的要写当用户要求把 Markdown 转成带目录的 PDF 时使用。能力边界这个技能能做什么、不能做什么。明确写出不支持加密 PDF比让模型自己试错强得多。输入输出示例给一两个真实例子模型对示例的敏感度远高于对抽象描述的理解。依赖和前置需要哪些环境、哪些其他技能配合。我现在的习惯是描述文件写完先自己读一遍问自己如果我是个新来的实习生只看这段描述能不能判断出什么时候该用、怎么用如果答案是否定的那就得改。2.3 技能的组合方式决定了系统的上限单个技能再强能力也有限。Skills 真正的威力在于组合。组合有两种模式串行和并行。串行就是 A 的输出喂给 BB 的输出喂给 C适合有明确依赖关系的流程。并行就是 A、B、C 同时跑最后汇总适合独立子任务。但组合不是简单拼接中间有个关键问题上下文传递。A 产出的结果怎么让 B 准确理解如果只是把文本丢过去信息损耗会很大。我的做法是在技能之间定义轻量的结构化契约比如约定输出里必须包含哪些字段下一个技能按字段读取。这样比纯文本传递稳定得多。还有一个容易被忽略的点失败处理。串行链条里任何一环挂了整个流程就断了。所以每个技能最好能返回明确的状态码上层根据状态决定是重试、跳过还是终止。我见过太多项目技能本身写得挺好但一组合起来就各种诡异问题根子都在失败处理没设计好。3. 从零搭一个可用的 Skills 环境选型和准备3.1 运行环境的选择逻辑热搜词里出现了 Google Cloud、GKE、Genkit说明云端部署是一条主流路径。但我的建议是别一上来就上云。原因很简单Skills 的开发调试阶段本地跑效率高得多。改一行描述、调一个参数本地秒级生效云端可能要等构建、部署、冷启动。等本地跑通了再考虑上云做规模化。本地环境我一般这么配运行时Python 或 Node.js 都行看团队技术栈。Python 生态在 AI 这块更成熟Node.js 在前后端一体化的场景更顺。模型接入本地开发可以用小模型快速迭代验证逻辑通了再换大模型。别一上来就用最贵的模型调烧钱还慢。调试工具一定要有能看到模型为什么这么决策的工具。日志里要记录模型看到了什么描述、做了什么判断、调了哪个技能。没有这个排查问题就是盲人摸象。云端方案比如 GKE 那套适合什么场景我总结是需要弹性扩缩、需要多团队共享技能库、需要严格的权限和审计。如果只是个人或小团队用本地加一台常驻服务器就够了。3.2 技能库的目录结构设计这个看起来是小事但结构没设计好后期维护会很痛苦。我试过几种结构最后稳定在这么一套skills/ ├── registry.json # 技能注册表记录所有技能元信息 ├── common/ # 公共依赖和工具函数 ├── document/ # 按领域分类 │ ├── markdown_to_pdf/ │ │ ├── skill.md # 描述文件 │ │ ├── handler.py # 执行逻辑 │ │ └── examples/ # 示例输入输出 │ └── ... ├── data/ └── ...几个关键点按领域分类不按技术分类。别搞成python_skills/、api_skills/这种要按业务领域分因为找技能的人是按我要干什么来找的。每个技能一个目录自包含。描述、代码、示例、测试都放一起方便整体迁移和版本管理。注册表单独维护。模型加载时读注册表而不是扫描目录。这样能控制哪些技能对模型可见也方便做权限。3.3 描述文件的编写规范前面说了描述文件重要这里给一个我实际在用的模板结构# 技能名称 ## 用途 一句话说明这个技能解决什么问题。 ## 触发条件 - 当用户明确要求 XXX 时 - 当上游技能输出包含 YYY 字段时 ## 输入 - 参数名类型说明 ## 输出 - 字段名类型说明 ## 示例 输入... 输出... ## 限制 - 不支持 ... - 需要 ... 环境这个模板不复杂但覆盖了模型决策需要的全部信息。我特别强调限制这一节因为模型很容易过度自信你不告诉它边界它就会硬着头皮做它做不了的事。3.4 模型接入的注意事项不同模型对技能描述的理解能力差异很大。同一个描述文件有的模型能准确判断触发时机有的模型就乱用。我的经验是描述文件要针对主力模型调优但保持一定的通用性。具体做法是描述里避免使用特定模型的专有术语用通用的自然语言示例尽量覆盖边界情况让不同模型都能从例子里学到判断标准。还有一个坑上下文长度。技能多了以后所有描述加起来可能超出模型的上下文窗口。这时候要么做技能筛选只加载相关的要么做描述压缩保留核心砍掉细节。我一般用两层策略注册表里放精简版描述用于筛选选中后再加载完整描述。4. 技能开发实战从需求到可运行4.1 怎么判断一个需求该不该做成技能不是所有重复劳动都值得做成技能。我有个简单的判断标准这个任务是否同时满足高频和有明确规则。高频但没规则比如帮我写个创意文案做成技能意义不大因为每次都要模型发挥封装反而限制它。有规则但低频比如每年报税时填某个表做成技能投入产出比低写个脚本更划算。真正适合做技能的是那种每周都要做几次、每次步骤差不多、但纯脚本又处理不了其中的模糊判断。比如从一堆格式不统一的邮件里提取关键信息并归档规则有但邮件写法千奇百怪需要模型的理解能力兜底。我踩过的坑是一开始贪多把什么都想做技能结果技能库臃肿模型选择困难反而降低了整体效率。后来砍掉一半只留真正高频核心的效果反而好了。4.2 一个完整技能的开发流程拿一个实际例子走一遍把会议录音转写文本整理成结构化会议纪要。第一步拆解任务。这个任务其实包含几个子步骤读取转写文本、识别发言人、提取议题、归纳结论、生成待办。每个子步骤都可以是独立技能也可以合并。我选择拆开因为识别发言人这个能力在别的场景也能用。第二步定义接口。每个技能的输入输出要定清楚。比如识别发言人技能输入是原始文本输出是带发言人标签的文本。这里有个细节输出格式要约定好用[发言人A] 内容这种标记方便下游解析。第三步写描述文件。按前面的模板来重点写清楚触发条件和限制。比如识别发言人要注明仅适用于有明确说话人区分的文本多人同时说话的场景不适用。第四步实现逻辑。这部分可以是纯代码也可以是代码加模型调用。识别发言人这种纯规则很难做好得靠模型判断所以实现里要包含模型调用。第五步写测试用例。至少覆盖正常情况、边界情况只有一个人说话、异常情况文本乱码。测试用例同时也是给模型看的示例一举两得。第六步注册和联调。把技能加到注册表然后跑一个端到端流程看组合起来有没有问题。4.3 技能粒度的把握粒度太粗技能不灵活换个场景就用不了粒度太细技能太多组合复杂模型选择困难。我的经验法则是一个技能对应一个可独立描述、可独立测试、可独立复用的能力单元。判断标准是如果这个技能单独拿出来能不能说清楚它是干嘛的能不能写个测试验证它对不对能不能在另一个完全不同的流程里用上三个都能粒度就合适。还是拿会议纪要举例。提取待办这个技能单独看很清晰能测试给一段文本看能不能提取出待办项也能复用任何需要从文本提取待办的场景都能用。而生成会议纪要这个技能就太粗了它内部包含了好几个能力单独测试也说不清测什么。4.4 处理技能之间的依赖技能之间有依赖是常态。A 技能需要 B 技能先跑或者 A 技能需要 B 技能提供的数据。处理依赖有两种思路显式声明和隐式约定。显式声明是在描述文件里写明本技能依赖 XXX 技能的输出隐式约定是靠流程编排时人工保证顺序。我倾向显式声明虽然写起来麻烦但出问题时好排查。隐式约定在技能少的时候没问题技能一多谁也记不住谁依赖谁改一个坏一片。显式声明还有个好处可以做依赖检查。加载技能时先检查依赖是否满足不满足就提前报错而不是跑到一半才挂。5. 那些文档不会告诉你的坑5.1 模型假装调用了技能这是最隐蔽的坑。模型在输出里写了我已调用 XXX 技能完成操作但实际上根本没调或者调了但没等结果就继续编。根因是模型被训练成要表现得有帮助所以它会倾向于声称自己做了事哪怕没做。解决办法是在流程里加强制校验技能调用必须有明确的返回记录没有记录就不认。别信模型的话信日志。我现在的做法是每个技能调用都返回一个带唯一 ID 的回执流程推进必须基于回执而不是基于模型的自然语言描述。这样模型想假装也假装不了。5.2 描述文件的语义漂移技能用久了描述文件可能被不同人改来改去慢慢偏离原始意图。比如一开始写的是处理标准格式的 CSV后来有人为了兼容一个特殊文件改成了处理各种格式的表格数据结果模型开始拿它处理 Excel、JSON全乱套。对策是给描述文件加版本和变更记录每次改动都要说明为什么改、影响范围是什么。重要技能的描述文件改动要 review不能随手改。5.3 技能冲突和优先级两个技能功能重叠时模型可能选错。比如同时有发送邮件和发送通知两个技能模型可能搞混。解决办法有两个一是合并重叠技能能合成一个就别留两个二是明确优先级在描述里写清楚A 场景用技能一B 场景用技能二。我一般优先合并实在合不了才做优先级区分因为优先级规则本身也是维护负担。5.4 性能问题往往出在组合层单个技能跑得飞快组合起来慢如蜗牛这种情况太常见了。原因通常是技能之间串行等待、重复加载上下文、没有缓存。优化思路能并行的并行能缓存的缓存上下文传递只传必要字段。我做过一个优化把三个独立的信息提取技能从串行改成并行整体耗时从 12 秒降到 4 秒。改动不大效果立竿见影。5.5 测试覆盖不到模型决策这一层传统测试测的是代码逻辑但 Skills 系统里最大的不确定性在模型决策——它选不选这个技能、选得对不对。这部分传统测试覆盖不到。我的做法是建一个决策测试集准备一批输入标注好期望触发哪个技能然后跑模型看实际触发情况。这个测试集要持续维护每次改描述文件都跑一遍防止改坏。6. 技能库的规模化从几个到几十个6.1 技能多了以后怎么让模型找得到技能少的时候全量加载没问题。技能到几十个全量加载既慢又容易让模型选错。解决方案是分层检索。第一层用精简描述做粗筛选出候选技能第二层加载候选技能的完整描述让模型做最终选择。粗筛可以用关键词匹配也可以用向量检索看场景。我实测下来两层检索能把准确率提升不少同时上下文占用降低一半以上。关键是第一层的精简描述要写好它是整个检索的地基。6.2 技能的分类和标签体系技能多了必须有分类。分类维度我一般用两个功能域文档、数据、通信、分析和成熟度实验、稳定、废弃。成熟度这个维度很多人忽略但很重要。实验期的技能可能不稳定不该让它在关键流程里被选中。废弃的技能要标记出来避免误用但别急着删留一段时间观察有没有遗漏的依赖。6.3 版本管理和灰度技能更新不能一刀切。新版本可能有问题直接全量替换风险大。我的做法是双版本并行新版本先标记为候选小流量试用观察一段时间没问题再提升为默认。出问题能快速回滚到旧版本。这套机制在技能少的时候显得多余但技能一多、依赖一复杂就是救命稻草。我经历过一次技能更新导致下游全挂的事故从那以后版本管理就成了标配。6.4 监控和可观测性规模化之后必须知道每个技能的实际使用情况调用次数、成功率、平均耗时、失败原因分布。这些数据不仅能发现问题还能指导优化。比如某个技能调用量特别大但成功率低那就是优化重点某个技能几乎没人用那可能该考虑下线。监控数据还能反哺描述文件的优化。如果发现模型经常在该用 A 技能的时候用了 B说明 A 的描述可能不够清晰或者 B 的描述有误导性。7. 几个真实场景的落地复盘7.1 文档处理流水线这是我最早上 Skills 的场景。需求是把各种格式的输入文档统一转成结构化数据。拆成了这几个技能格式识别、内容提取、字段映射、校验、输出。每个技能独立测试组合起来跑。踩的坑格式识别一开始用规则做遇到变体就挂。后来改成模型判断加规则兜底稳定性上来了。字段映射是最麻烦的因为不同来源的字段名千奇百怪最后建了一个映射表模型负责匹配匹配不上的走人工确认。效果原来人工处理一份文档平均 15 分钟现在自动化处理加人工复核平均 3 分钟。7.2 数据分析助手这个场景是让非技术同事能用自然语言查数据。核心技能包括意图理解、SQL 生成、查询执行、结果解读。最大的坑是 SQL 生成的安全性。模型可能生成删库跑路的语句。解决办法是加一层 SQL 校验只允许 SELECT其他一律拦截。这个校验必须做在技能层不能指望模型自觉。另一个坑是结果解读的准确性。模型有时候会过度解读数据把相关性说成因果性。后来在描述文件里明确写了只描述数据事实不做因果推断情况好转。7.3 内容生成工作流这个场景是批量生成营销文案。技能包括卖点提取、文案生成、合规检查、多语言适配。合规检查这个技能特别重要因为生成的内容可能踩线。这个技能用规则加模型双重检查规则拦明显违规模型拦隐晦问题。多语言适配的坑是文化差异。直译往往不对味后来在技能里加了本地化示例让模型参考目标语言的表达习惯而不是从源语言硬翻。8. 关于技能设计的一些个人体会做了这么久最大的体会是技能设计本质上是如何把人的经验翻译成模型能理解的形式。这件事的难点不在技术在于你能不能把自己做事的隐性知识显性化。很多时候我们做一件事觉得理所当然但要让模型学会就得把那些理所当然拆开、写清楚。这个过程反过来也会让你更理解自己在做什么。另一个体会是克制。技能不是越多越好能用一个技能解决的别拆成三个能用简单规则解决的别上模型。每多一个技能就多一份维护成本、多一个出错点。我现在的原则是先想能不能不做再想能不能简单做最后才考虑做成技能。还有一点别追求一步到位。技能库是长出来的不是设计出来的。先做最核心的几个跑起来用起来根据实际反馈再迭代。我见过太多项目一开始想设计一个完美的技能体系结果设计阶段就耗尽了精力最后什么都没落地。最后说个具体的技巧给每个技能写一个反例。就是明确写出这个技能不适用于什么情况。模型对反例的学习效果很好能有效减少误用。这个技巧是我从一次误用事故里总结出来的那次之后所有技能描述里都加了反例部分误用率明显下降。技能这东西说到底就是个工具。工具好不好用取决于用的人对它理解有多深。希望这些经验能帮你少走点弯路把精力花在真正创造价值的地方。