
搞 Agent 开发的朋友最近应该经常听到 agent-skills 这个词各种框架和社区里都在聊。我自己的理解很简单它就是把一个智能体能做的事拆成一个个可以单独定义、单独维护、单独复用的“技能单元”比如网页检索、代码执行、数据分析、文件整理每个技能就像工具箱里的一把专用工具Agent 接到任务时按需调用而不是每次开工都从零攒一堆提示词。这篇文章不聊概念包装就讲我实际搭建 agent-skills 体系时踩过的坑、摸索出来的落地方法。从设计思路、技能包结构、路由匹配到评估和排查完整过一遍。适合正在做 Agent 应用、想给智能体做能力扩展的工程师参考也适合刚接触这个方向、想搞明白它到底解决什么问题的朋友。我会尽量把每个决策背后的理由讲清楚让看完的人能直接照着搭一套。1. 先搞清楚 Agent Skills 到底在解决什么问题1.1 从“会聊天”到“会干活”的能力跃迁先往回看一步。早期的 LLM 应用基本就是聊天机器人模型只负责生成文本能力边界在对话窗口里。后来出现了函数调用function calling模型可以决定“我需要执行一个外部操作”于是系统里有了工具的概念。再到 Agent 循环模型不再只是调一次工具而是可以多轮规划、执行、观察结果、调整计划直到完成任务。这一步跃迁带来的变化很多人低估了系统的复杂度从“提示词管理”转移到了“能力管理”。以前你维护的是一个 prompt 文件现在你要维护的是几十个工具、几十段工具描述、不同任务场景下的调用策略。提示词膨胀的问题还没解决工具膨胀的问题就来了。我见过一个项目工具列表加到四十多个模型每次选择工具时光是把工具描述读完就已经消耗大量上下文而且经常选错。agent-skills 就是在这个背景下被反复提及的它把“工具”从单纯的执行函数升级成带有教学说明、使用示例、校验规则、输出规范的能力包让模型在调用时不仅知道“有这个工具”还知道“这个工具应该在什么场景用、怎么用、输出长什么样”。1.2 Skill、Tool、Workflow 三者的边界很多刚开始接触的人会把 skill、tool、workflow 混为一谈这三者的边界如果不清后面设计一定会乱。**Tool工具**是系统提供给模型的最小可执行单元通常是一个函数、一个 API、一段命令。它只负责“执行动作”不负责“教模型怎么用”。比如search_web(query)就是一个工具输入关键词返回搜索结果。**Skill技能**是一个能力包包含一个或多个工具同时携带自然语言的使用说明、典型示例、边界约束、输出格式要求。可以理解为“教模型正确使用工具的说明书 工具本体”。同一个search_web工具放在“学术文献调研技能”里和放在“电商竞品分析技能”里用法完全不同skill 就是解决这个“用法”问题的。**Workflow工作流**是固定化的流程编排定义的是步骤之间的前后顺序和依赖关系适合那些“每次都要按照同样流程走”的场景。用一个类比来区分Tool 是给厨师准备的炉子和锅Skill 是菜谱告诉厨师这道菜该用什么火、先放什么、做到什么程度算好了Workflow 是餐厅的后厨动线冷菜间、热菜间、出菜口的顺序不能乱。这三者可以组合使用一个 skill 内部可能调用多个 tool一个 workflow 可能编排多个 skill。我在实际设计时有一条原则凡是“模型需要学习才能用好”的能力就放进 skill 里凡是“固定不变、不需要模型决策”的步骤就放进 workflow 里。1.3 我总结的 agent-skills 真正解决的问题做了几轮之后我发现 agent-skills 解决的痛点非常具体不是概念炒作痛点一提示词膨胀。过去我们为了让模型正确使用工具会在 system prompt 里写大段说明工具一多说明越来越长模型注意力被稀释。skills 把说明拆分到每个技能包里模型只在实际选中某个技能时才读取对应的教学文档system prompt 可以保持精简。痛点二能力难以测试。工具是扁平的测试时只能测“输入参数对不对、返回值合不合法”。skill 是带上下文的你可以针对一个完整场景做测试比如“用户让你调研某个行业模型是否选择了正确的调研技能、是否按技能要求执行了检索、摘要和分析三步”。这种测试粒度直接决定了系统能不能持续迭代。痛点三上下文失控。工具数量多时工具描述本身就会吃掉上下文。skill 采用按需加载模型先根据简短描述决定用哪个技能再注入完整的技能说明上下文消耗大大降低。2. agent-skills 设计的核心思路2.1 技能包采用“教学文档 可执行体”的双轨结构我见过不少实现方案最后稳定下来用的是双轨结构每个技能由两部分组成一部分是给人和给模型读的说明文档一部分是真正可执行的代码或脚本。说明文档我通常叫SKILL.md它承担“教学”职责。内容包括技能的目标、适用场景、不适用场景、使用步骤、每个步骤的关键细节、输出格式要求、常见错误规避。这份文档不是摆设它会被注入到模型上下文中所以必须写得极其结构化。模型自己也是靠这份文档学会“什么时候用、怎么用”这个技能的。可执行体则是具体的代码文件比如search.py、summarize.py。它承载真正的逻辑负责调 API、处理数据、返回结构化结果。为什么要这么设计因为模型本身不是一个稳定的程序执行器它擅长的是“理解意图、制定计划、解析结果”而不是“稳定地跑完一段复杂逻辑”。把不稳定的人类语言教学和稳定的程序逻辑分开各取所长。文档负责让模型做对决策代码负责让执行不出错。这个分离是 agent-skills 最核心的思想后面所有的设计都是围绕它展开的。2.2 技能路由Agent 怎么知道该用哪个技能技能多了之后最现实的问题就是模型怎么在几十个技能里挑出正确的那一个答案藏在技能包的元信息里。每个技能都需要一个name技能名和description技能描述这两个字段就是模型做路由选择的检索依据。模型其实是在做一次“根据用户意图匹配技能描述”的语义匹配。所以描述写得干不干净直接决定命中率。我自己写技能描述时有三条硬性要求开头写清楚“这个技能做什么”一句话不超过 15 个字。写明白触发条件用户提出什么类型的问题、处于什么场景时应该用我。写明白非触发条件反例什么情况下不要用我。这个很多人会忽略但反例对消除误选非常有效。举例一个“周报生成技能”的描述可以这样写name: weekly_report description: 根据用户提供的本周工作记录生成周报。 当用户提到周报本周总结本周工作汇报时使用。 若用户只是询问上周内容或尚未提供任何工作记录不应使用本技能。注意最后一句“不应使用”这就在模型脑子里划了一道边界。实测下来加了反例之后技能误选率能下降不少。2.3 一个最小可用技能包长什么样我习惯用一个轻量的 YAML 作为技能包的元信息文件再配一个 Markdown 教学文档和一个 Python 实现脚本。骨架大概是这样的skills/ └── weekly_report/ ├── SKILL.md # 教学文档 ├── generate.py # 可执行脚本 └── skill.yaml # 元信息name、description、dependencies其中skill.yaml只负责描述“这个技能是什么”不写长篇大论name: weekly_report description: 根据用户提供的工作记录生成结构化周报。 触发条件用户提到周报本周总结工作汇报。 不触发用户没有提供工作记录或询问往年数据。 dependencies: - python3 - jinja2SKILL.md才是给模型看的核心教学文档# 周报生成技能 ## 目标 将用户散乱的工作记录整理为结构清晰的周报包含本周完成、未完成、风险、下周计划四个部分。 ## 使用步骤 1. 解析用户提供的工作记录识别每一条的完成状态。 2. 将记录归类到本周完成或未完成提炼关键成果和数字。 3. 对照项目风险清单识别潜在风险。 4. 生成 markdown 格式周报。 ## 输出要求 - 使用 markdown 二级标题分节。 - 每个本周完成条目必须包含做了什么 结果量化如有 对应项目。 - 不要虚构用户未提供的细节。 ## 常见错误 - 不要把进行中的工作写成已完成。 - 不要在周报中加入个人评价和情绪表达。这种结构的好处是模型在需要时读一次文档就能学会而代码实现可以专注在“字符串格式化、模板渲染”这类稳定逻辑上。3. 实操从零搭建一套可用的 agent-skills3.1 选型什么时候自研什么时候用现成框架动手之前先回答选型问题。现在社区里已经有几类现成的实现比如 LangChain 的 Tool 体系、OpenAI 的 function calling、部分框架内置的 Agent Skill 机制。我的建议是分场景看方案适合场景局限现成框架的 Tool 体系快速验证、依赖框架已有生态往往只有工具层缺少教学文档和技能生命周期管理直接使用大模型平台提供的 Agent 能力不想维护底层链路接受平台绑定技能格式和调度策略受平台限制自研轻量 skill 层需要精细控制上下文注入、技能路由、评估体系初期工作量较大需要自己设计文档结构和调度逻辑我自己最终选择了“自研轻量 skill 层 底层调用框架工具”的组合。原因很简单我需要精细控制 SKILL.md 的注入时机和上下文长度也希望技能包是纯文本、纯文件、可 Git 管理的这样测试和 CI 都好做。自研的部分其实不重核心就是一个技能注册表和一段调度逻辑大概几百行代码的事但灵活性提升非常大。如果你只是做原型验证我强烈建议先用现成框架跑通端到端再决定要不要抽出自己的 skill 层。先看到效果再谈优化这个顺序别反。3.2 手把手实现第一个技能合同核心条款提取我拿一个实际会高频用到的场景来演示完整流程从合同 PDF 里提取核心条款。这个技能在企业内部场景非常常见而且它足够复杂能展示出 skill 设计的完整思路。第一步明确技能边界。这个技能只负责“从用户提供的合同文件中提取指定条款并输出结构化结果”它不做合同审核、不做风险评分也不做多文件对比。边界越清晰SKILL.md 越好写模型越不容易在调用时跑偏。第二步写 SKILL.md 教学文档。核心要写清楚提取的条款清单、每一条的判定标准、输出格式。比如“付款条款”要提取哪些字段、遇到“预付款 30%货到付 70%”这种表达如何处理。第三步写可执行脚本。我会用 PDF 解析库提取文本然后调用大模型做结构化抽取。注意这里有一个重要设计不要把“解析 PDF”和“条款抽取”耦合在同一个脚本里拆成两个脚本或者两个函数这样单独测试解析、单独测试抽取逻辑都好排查问题。第四步注册技能并配置路由。在技能注册表里登记 name 和 description确保模型能通过简短描述命中它。第五步端到端测试。给模型一个模糊的用户请求比如“帮我看看这份合同付款怎么安排的”看它是否能自动选中该技能、是否按 SKILL.md 的步骤执行、输出是否合规。我实际写技能的时候会把脚本设计成从标准输入读入文件路径从标准输出吐出 JSON这样既方便手动测试也方便被上层执行框架调用。下面是一个脚本骨架示例#!/usr/bin/env python3 合同条款提取技能的执行体 import json import sys from pathlib import Path def extract_text_from_pdf(path: Path) - str: # 这里调用 PDF 解析库提取全文 # 注意处理扫描件需要 OCR否则结果为空 pass def extract_clauses(text: str, clause_names: list[str]) - dict: # 调用 LLM 做结构化抽取 # 把 clause_names 和 text 一起交给模型返回 JSON pass def main(): pdf_path Path(sys.argv[1]) raw_text extract_text_from_pdf(pdf_path) clauses extract_clauses(raw_text, [payment, liability, termination]) print(json.dumps(clauses, ensure_asciiFalse, indent2)) if __name__ __main__: main()这里有个容易踩的坑PDF 解析出来的文本经常是带着换行符和表格碎片化的直接扔给模型抽取时模型可能把跨页的表格内容搞混。我后来在脚本里加了一个文本清洗函数把行内换行替换成空格再按段落重新组织抽取准确率明显上去了。3.3 技能的完整生命周期管理技能不是写完就结束了。随着业务变化技能需要更新、下架、灰度。我实践下来技能生命周期至少要关注下面几件事版本管理。技能包整个目录纳入 Git每次改动都留 commit。我给每个技能包维护一个version字段修改教学文档或实现脚本时都要提升版本。为什么连文档都要管版本因为模型行为直接受 SKILL.md 内容影响文档一旦改了技能的表现就可能变化。如果你的系统有线上会话在跑改文档之前一定要想清楚。依赖隔离。每个技能尽量使用独立的运行环境或独立的依赖声明。我见过最难受的场景两个技能都需要用 Python 的 HTTP 库一个要求 requests 2.x一个要求 3.x装完互相打架。我的处理办法是技能包声明自己的依赖执行时按技能包维度做环境隔离依赖冲突问题就彻底没有了。灰度发布。对于会直接影响业务的技能我不会直接全量更新。先把新版本技能跑在一部分测试请求上和旧版本的结果做对比确认没有回归再放量。下架和废弃。技能废弃时不要直接删目录我习惯在描述里加一行“该技能已废弃请勿使用”同时把路由权重降为 0。直接删除可能导致正在运行的 agent 因为引用了不存在的技能而报错。4. 常见问题与排查技巧实录4.1 一份能救命的排查速查表我把实操中遇到的问题和排查思路整理成一张表遇到类似现象可以直接对着查现象可能原因排查方法与解决方案模型死活不选某个技能描述写得模糊或与用户意图不对齐检查 skill 的 description简化触发条件补上反例模型选错技能选了 A 但应该用 B两个技能描述太相似路由区分度不够重写描述制造差异A 强调场景 XB 强调场景 Y技能执行成功但结果不对SKILL.md 的教学步骤和实现脚本逻辑不一致对比文档与脚本确认文档描述的每一步都对应脚本的真实行为调用技能后上下文迅速膨胀技能输出太长或 SKILL.md 被重复注入限制技能输出长度要求结构化摘要检查是否因技能内部步骤循环导致多次读取文档同一技能在不同会话表现差异大SKILL.md 中示例太少模型没有足够参照增加典型示例和反例并在示例中标出易错点技能更新后效果反而变差新版文档破坏了原有指令结构回滚版本用 diff 分析文档改动点小步迭代而非大改这张表是真实反复被问到的场景我自己几乎每条都踩过一遍尤其是“描述相似导致误选”几乎每个技能库膨胀到一定程度都会遇到。4.2 “说会了但做不对”才是最大的坑很多人在技能上遇到的不是“模型不会选”而是“模型选了也做了但结果根本不对”。我称这个问题为“说会了但做不对”它的根因多半在 SKILL.md 的教学质量上。SKILL.md 写得太抽象模型就只会“照着感觉”执行写得太笼统没有具体的判定标准和输出样例模型就会自由发挥。我自己的经验是教学文档里要提供至少一个“完整示例”包含输入、过程、输出三部分。而且要明确给出“什么算对”的判定标准比如“当合同中金额同时出现小写数字和大写中文数字时以大写中文数字为准并在结果中保留两者原始值”。这种具体规则模型是可以稳定遵循的。还有一点容易被忽略SKILL.md 的措辞会影响模型的执行严谨度。如果你写“请尽力提取所有条款”模型就会表现得比较松散如果你写“提取合同中出现的全部付款相关句子按条款出现顺序输出”模型就会更严格地检索。指令里每个限定词都有分量。4.3 上下文失控技能输出把对话窗口撑爆技能返回的东西如果又长又杂一轮下来整个对话上下文就爆了。这个坑是我在并行处理多合同对比时遇到的三个合同分别调用技能每个技能输出几千字的完整条款原文第二轮回合还没开始上下文已经要用完了。后来我做了两个调整问题基本解决第一技能输出改为两级结构。第一级是极简摘要只有关键字段和结论用于 agent 的后续推理第二级才是详细内容默认情况下保留在文件或外部存储中只有用户明确要求时才被拿出来展示。二级结构参数化设计如下{ summary: { payment_terms: 预付30%货到后30天内付70%, liability_cap: 不超过合同总额的20% }, details: 完整条款文本相当长默认不放入上下文 }第二技能支持“只返回摘要”的调用模式。在 SKILL.md 里写明调用参数detail_levelsummary时只输出摘要detail_levelfull时才输出全文。上层 agent 默认用 summary 模式只有用户追问细节时再重新调用技能取详情。这套设计让我的长链路任务稳定了很多。4.4 安全与副作用控制技能权限不可忽视技能是有副作用的。一个搜索技能会消耗外部 API 额度一个文件操作技能可能直接改动服务器上的文件一个数据库技能可能执行带风险的查询。我在技能层做了两件事来控制风险一是技能描述中明确声明副作用。比如“本技能会调用第三方搜索服务消耗 API 额度”“本技能会修改指定目录下的文件执行前请与用户确认”。模型在规划时会读到这些说明遇到高风险的技能组合时会更谨慎必要时会停下来询问用户。二是执行层的权限控制。我在技能执行接口里加了权限校验按技能类型分类为“只读”“可控写入”“高危险操作”高危险的技能默认要求二次确认。这个确认动作是由上层 agent 完成的比如在调用 DELETE 类型操作前agent 要先输出一段确认文案给用户用户批准后才真正执行。这层保护在真实业务里非常必要。5. 技能评估与持续迭代的实操建议5.1 给每个技能建一套专属测试集技能能不能用、改了之后有没有退化不能靠感觉判断要有测试集。我的做法是为每个技能准备一个“黄金样本集”包含以下几类典型样本最常见的用户请求和对应的理想输出。边界样本比如输入数据缺失、格式异常、内容超长的情况。混淆样本容易被误路由到其他技能的相似请求用来检验路由区分度。反例样本明确不该触发该技能的用户请求检验是否会误触发。每次技能更新后我会把这批样本跑一遍对比输出是否符合预期。这个测试集不但能保住技能质量还能作为新同学接手时的参考材料。5.2 用“失败复盘”驱动迭代我养成了一个习惯让每个技能在返回结果时附带一个trace字段记录自己是如何决策的包括模型读取的 SKILL.md 片段、走的步骤、在哪一步结果不符合预期。当技能表现差时第一件事不是改代码而是看 trace 找问题出在文档还是实现。有一段我印象很深一个数据分析技能老是漏掉部分关键指标看 trace 发现模型在读取 SKILL.md 时把“指标清单”和“输出格式”两节混在一起理解了导致步骤顺序错乱。后来我把 SKILL.md 的章节顺序调整并在指标清单前加了一行“这是输入指标不是输出格式”问题立刻消失。5.3 控制技能库规模避免“能力过载”技能不是越多越好。我见过一个团队把技能做到八十多个结果模型几乎每次路由都要纠结而且技能描述之间的互相干扰越来越严重。技能库规模的控制和代码库一样优先考虑复用和抽象而不是堆数量。我给自己定了几个量化标准同一领域内技能之间描述相似度不能过高如果两个技能的触发场景高度重叠就该合并成一个技能并用参数区分技能总数超过二十个时开始做分组和路由分层。分组很重要我可以先按领域分大类模型先在大类里选再在类内选技能路由准确率会显著提升。6. 最后分享一点我的个人体会做 agent-skills 这段时间我最大的感受是Agent 工程的复杂度正在从“模型能力”转移到“能力组织和能力治理”。你在 skill 上花的心思其实是在给模型搭建一套越来越完善的“职业培训体系”——技能包是教案路由是分诊台测试集是考核标准。这套体系搭得越扎实后面加再多的能力都不会乱。如果你正准备开始我的建议是别一上来就铺十几个技能。先挑两三个业务价值最高、使用频率最高的场景把 SKILL.md 和测试集打磨透再逐步扩展。技能包的文件结构从一开始就按“教学文档 可执行体 元信息 测试集”的方式组织后面维护成本会低很多。再提醒一句SKILL.md 的每一次改动都要像改生产代码一样对待因为它直接决定了模型的行为边界。