skills这个词放在一年前还是简历上的职场词汇放在今天的技术社区里却成了一个相当具体的工程概念。我这几个月一直在给团队内部搭建基于大模型的AI助手做得最多的事情就是在Agent框架里写技能文件——英文叫Skills本质是把一套提示词处理步骤工具调用打包成AI能稳定执行的能力单元。很多朋友问我Skills到底是什么、和普通Prompt有什么区别、自己团队要不要上这一套。这篇就把我这段时间的实践从概念到代码、从踩坑到编排完整梳理一遍适合正在折腾Agent开发、或者准备把日常事务性工作交给AI的读者。1. Skills为什么突然变成了技术圈的热词1.1 一个词的两副面孔从人的技能到AI的技能过去我们说skills通常指的是人所掌握的能力比如沟通能力、编程能力、项目管理能力。它强调经验和熟练度很难被直接拷贝和迁移。做AI应用之后我发现这个词的含义变了Skills开始变成Agent系统里一个明确的文件单位——一段可以被反复加载、执行、测试、共享的指令集。我最初看到这个概念时也怀疑过这不就是改良版的Prompt吗后来把一个技能文件写进Agent系统并跑通之后我才意识到区别在哪。Prompt解决的是单次对话的引导而Skill解决的是一类任务的标准操作流程。换句话说Prompt是临时记住怎么干活Skills是让AI真正掌握一类任务并且在不同场景下都能按同一套标准稳定执行。提示如果已经熟悉了Prompt工程可以把Skills理解成被结构化的Prompt工程。它把提示词、参数声明、执行步骤、参考示例、工具权限打包在一起变成一个能被系统调度、能跨会话复用的组件。1.2 Skills与Prompt、插件、工作流的本质区别形态核心定位典型特点普通Prompt单次对话引导即用即弃不关心谁来调用不跨会话复用Skills可复用的任务能力单元有参数协议、有示例、有依赖声明能被调度器按语义加载插件/工具运行时外部能力强调能做什么不负责怎么决定做什么工作流编排固定步骤流程顺序和分支通常由人设计机器按流程执行Skills恰好处在中间位置它可以完全不接工具只靠模型推理完成文本处理也可以调用一个或多个工具并让Agent自己决定执行节奏。这也是为什么主流Agent框架都在往这个方向靠拢——思路其实差不多把能力拆开、文档化、让模型按需加载。1.3 为什么各家Agent方案都在推技能化本质上是真实业务里一个Agent只干一件事的情况太罕见。以最常见的客服场景为例一个Agent可能要处理售前咨询、订单查询、退换货、投诉升级每个场景的应答逻辑完全不同。如果全部塞进系统提示词上下文很快被塞爆各个场景的指令还会互相干扰。技能化的思路是小文件、高内聚、按需加载。每个技能只管好自己的边界Agent碰到什么场景就临时把对应技能加载进来。它还顺带解决了行为可维护性的问题传统Prompt写在代码里改一句话就要重新部署一轮技能文件是独立文本产品经理也可以打开看、改、评审。说白了技能化是AI应用从做Demo走向做产品时自然长出来的一种工程化组织方式。2. 一个技能模块的骨架从技能文件到参数协议2.1 技能目录长什么样入口文件与辅助资源一个技能通常以目录为单位存在目录名是技能的唯一标识里面放一个入口文件SKILL.md以及若干辅助目录。我自己习惯的结构是这样skills/ └── generate-weekly-report/ ├── SKILL.md ├── examples/ │ ├── input_sample_1.md │ ├── input_sample_2.md │ └── output_sample_1.md └── references/ ├── feishu_style_guide.md └── metric_definitions.json入口文件SKILL.md是必须存在的它承担了这个技能是什么、什么时候用、怎么执行、输出什么的全部定义。辅助目录里的examples放输入输出示例references放长上下文背景资料。这两个目录不是装饰它们专门用来控制上下文长度把不一定每次都查的细节从入口文件里挪走只有AI真正需要时才会去检索加载。2.2 参数协议让AI学会按格式接收输入很多人写技能文件只写你是一个助手帮我生成周报这是不够的。一个合格的技能必须具备参数协议——告诉AI这个技能应该接收哪些字段、字段格式是什么、哪些必填、哪些可选。我习惯用YAML frontmatter写在SKILL.md最顶部--- name: generate-weekly-report description: 根据本周工作记录生成结构化的周报支持 Markdown / 飞书文档 / PPT大纲 三种输出格式。 when_to_use: 用户需要提交周报、生成周总结、整理本周产出时 version: 1.2.0 parameters: work_logs: type: string description: 本周的原始工作记录可以是散乱笔记、聊天记录摘录 required: true report_format: type: string enum: [markdown, feishu, ppt] default: markdown focus_areas: type: array description: 需要重点展开的方向或项目名称 required: false include_next_plan: type: boolean default: true description: 是否输出下周计划板块 ---注意参数协议里的enum和default。enum让AI不再自由发挥输出格式default让调用方不传参数时也有确定行为。当Agent调度器解析用户请求后它需要把原始输入映射成这些结构化参数再传给技能去执行。参数协议写得越明确解析准确率就越高后面出错的概率就越小。这也是为什么我推荐用YAML而不是JSON写frontmatter——可读性更好能写注释大多数框架都原生支持。2.3 写Description的真正意义调度器靠它认人在SKILL.md里最容易被低估的是description和when_to_use这两个字段。很多技能在真实环境里被漏调十有八九是这两个字段没写好。Agent运行时会同时挂载几十上百个技能它不可能每个都加载一遍那样上下文早爆了。它会在收到用户请求后优先用每个技能的description做一次语义匹配选出最可能相关的几个再实际加载正文。这就像图书馆的检索系统你给每本书写的简介决定了读者能不能通过目录找到它。所以description不要当成文档定位来写而要当成触发条件来写。比如根据本周工作记录生成结构化周报支持三种输出格式就比周报生成工具更容易被调度。when_to_use里最好写清楚用户什么话术属于适用范围甚至写上一两个反例当用户只是闲聊本周感受时不要使用本技能。限制条件越明确误调用越少。组成部分作用容易被忽视的细节SKILL.md定义技能整体行为不要把长文档全塞进来parameters定义输入协议enum/default能显著提高稳定性description供调度器语义匹配写触发条件不写功能罗列examples提供few-shot参考要和真实业务场景贴合references存储长尾背景资料按需加载控制上下文长度3. 手写第一个技能周报生成器从设计到落地3.1 为什么拿周报开刀刚接触Skills时最常犯的错误是拿一个特别复杂的业务场景练手比如全自动客服系统结果又依赖CRM又依赖知识库还要处理多轮对话最后什么都救不了。我的建议是第一个技能选一个边界清晰、输入输出明确、每周都要重复的事务性工作——周报生成器几乎是完美的练手对象。它的输入是散乱工作记录输出是结构化文本不需要额外接任何工具却足够让你体会到散乱输入到结构化输出的对比感。3.2 需求拆解与技能目录搭建动手前先花十分钟把需求拆清楚输入可能是直接粘贴的一周笔记也可能是一段聊天记录。输出分成本周成果、数据与进展、下周计划三块。格式默认Markdown但也能输出飞书文档、PPT大纲。风格简洁、面向管理者不写流水账。然后在技能目录里创建generate-weekly-report/搭好examples和references两个辅助目录。references里放一份协作工具的格式规范文档examples里放3组输入输出示例。这组示例特别重要AI写作时会模仿示例里的语气和颗粒度。3.3 核心文件实现SKILL.md正文部分我会把处理流程、输出模板、约束项全写清楚# 周报生成助手 你是一位协助互联网团队整理周报的助理目标是把用户输入的散乱工作记录整理成可读性高、层次清晰的结构化周报。 ## 处理流程 1. 通读全部工作记录先剔除闲聊、无效信息。 2. 将剩余内容按重要事项归类判断所属项目或协作方向。 3. 对每一类事项提炼做了什么 结果/进展 下一步三个要素。 4. 按输出模板组织成文模板见 examples/。 ## 输出模板 ### 本周成果 - 按重要程度排序不超过5条 ### 数据与进展 - 有具体数字时保留数字没有数字写待补充 ### 下周计划 - 结合记录中出现的待办事项整理没有则写暂无 ## 约束 - 不要编造记录中不存在的工作内容。 - 不要把内部沟通语气带入周报保持客观书面化。 - 如果记录缺乏信息不要强行展开写记录信息不足即可。 - 当 report_formatfeishu 时按 references/feishu_style_guide.md 调整标题层级。我把约束项写得很细因为对大模型来说不编造不啰嗦按模板来这类要求必须显式声明它默认的写作风格往往过于自由。examples里的参考输出也得认真准备AI会不自觉模仿示例的句式长度和用词习惯。3.4 三组测试输入跑一遍写完别急着部署拿三组不同风格的输入试高信息量输入包含项目、数字、阻塞、联调协作验证信息归类能力。低信息量输入只有三条简短笔记看会不会强行扩充编造。带审阅意见的输入用户吐槽某些事项没进展验证能否保留关键状态。我实测下来第一组通常稳定通过第二组偶尔出现脑补细节的毛病——这正是需要在约束里强调不要编造的原因。第三组最容易翻车模型倾向于把用户吐槽这种口语化表达直接搬进周报。这时候需要在处理流程里加一步把吐槽转换成客观状态描述比如把联调进度太慢了改写成用户反馈联调进度偏慢需持续跟进。3.5 迭代调优解决格式漂移与数据编造技能文件不可能一次写对迭代就是靠反复跑测试输入逼近预期行为。我遇到最多的两个共性问题一个是格式漂移同样的输出格式AI每次生成的标题层级、列表符号偶尔不一致。解决方法是把输出模板和示例钉死示例里怎么分段模板里就怎么要求。另一个是数据编造输入里没有的数据AI会为了结构完整自动补全。解决方法是加一句缺失字段一律写待补充禁止推测并在示例输出里保留一个待补充样例让模型知道这样写是允许的。这两个问题如果不专门测试很难在真实使用中提前发现。我一般把测试用例放在技能目录下的tests/里每次改完SKILL.md就全量跑一遍避免改掉一个坑又引入一个新坑。4. 技能调用的暗坑上下文污染、参数歧义与权限边界技能从能跑到跑得稳中间隔着一串暗坑。线下调试时一切正常一旦挂到Agent上被真实用户调用各种诡异问题就冒出来了。我把这段时间踩得最深的四个坑拆开讲。4.1 暗坑一描述太宽泛技能被乱加载现象用户问今天天气怎么样Agent却把周报技能加载进去了生成了一堆毫无关联的输出。排查思路去翻Agent的调度日志发现加载技能的理由是用户话里出现了今天这个词而技能description里写了根据本周工作记录调度器把本周和今天的语义混淆了。修复把description改成触发条件更严格的说法在when_to_use里明确写仅当用户提供了本周工作记录或要求生成周报时使用日常询问天气、日期等不需要周报能力。同时把周报、周总结、周产出、本周工作记录设为强触发词。验证用一组包含边缘话术的测试对话跑一遍确认不再误加载。4.2 暗坑二参数歧义导致输出张冠李戴现象用户一次性给了上周的记录和本周的记录希望分别生成两份AI却把它们混在一起输出。根因参数协议里只有一个work_logs字段模型无法区分两组数据各自的归属。修复把参数改成支持多条记录的数组结构或者新增time_period参数让用户输入时显式标注上周/本周time_period: type: string enum: [last_week, this_week, custom] default: this_week修复后模型会主动识别记录的时间标签并且生成两份独立的周报。遇到AI把两件事混为一谈优先怀疑参数设计而不是怀疑模型能力。4.3 暗坑三上下文被长文本塞满Agent变笨现象技能上线后整体回答质量下降不只是技能相关的问题连简单闲聊都开始答非所问。根因某位同学把一份几十页的协作规范文档直接写进了SKILL.md导致每次加载技能都带来大量上下文token挤占了Agent可用的注意力空间。修复把长文档移到references目录技能正文里只写当需要飞书格式时查阅references/feishu_style_guide.md。模型只有在真正需要格式规范时才会主动读取文件平时不占上下文。这个坑我直接写进了团队规范SKILL.md正文控制在600行以内超出的部分一律放references或拆成多个技能。4.4 暗坑四权限边界模糊引发误操作现象技能文件里声明了一个多余的数据库写入权限用户在对话中请求把名单里所有用户标记为已处理时Agent直接执行了实际上该技能只需要读取权限。根因技能在申请工具权限时抱着多申请点总没错的心态而Agent对权限描述的理解并不严格。修复在技能声明里明确scope只暴露该技能运行所必需的最小工具权限对写操作增加确认话术对可能的回滚方案做说明。技能化真正落地时权限边界和视图边界同样重要宁可先少申请权限再按需放权。这四个坑的共性其实都是假设太强假设调度器能理解意图假设参数不会歧义假设上下文无限大假设权限系统会自动兜底。而真实Agent并没有那么多脑补能力。所以任何一次技能改动都要拿着一组边缘用例去测试而不是只测happy path。5. 把多个技能拼成一套工作流组合、依赖与编排5.1 单一技能的极限在哪里单个技能能解决边界清晰的任务但真实业务流程很少只有一个环节。比如给管理层输出每周经营周报实际上包含从数据平台拉取指标、从项目群聊聚合事实、生成结构化周报、标记风险事项。如果把它做成一个技能这个技能会异常庞大既难维护也难调试。更合理的做法是拆成多个小技能再让它们协同工作。5.2 串行编排让一个技能的输出成为另一个技能的输入我目前用得最多的编排方式是串行——技能A的产出喂给技能B。实际配置时我在技能B的文件里声明依赖depends_on: - fetch-metrics - aggregate-project-notes这个声明有两层作用一是让调度器知道执行B之前要先准备A二是让B在拿到A的输出时可以按约定好的字段做解析。关键是固定中间传递的数据格式比如约定fetch-metrics的输出永远是JSON字段名统一、单位统一这样下游技能才不会拆错。用固定数据契约做串联只要每个环节的输出都明确整条链路就相对好调。这也是为什么前面强调参数协议要写清楚——单独看很基础一旦涉及编排协议就是接口契约不完整就会链路断裂。5.3 并行策略与状态隔离有些场景不需要串行。比如客服同时收到订单查询和投诉建议两个技能可以并行处理最后合并返回。并行能省时间但要注意状态隔离技能A在上下文里产生的中间变量不要让技能B意外读取到。我的做法是把每个技能的输出封装成独立数据块在汇总阶段由调度器统一合并而不是让技能们都去写同一个共享缓冲区。简单说技能之间只通过明确的接口交换数据不共享隐式状态。5.4 实际案例周报 指标拉取 风险识别拿开头那个管理层周报需求举一个完整例子fetch-metrics从数据平台拉取本周核心指标输出JSON。aggregate-project-notes把项目群聊、会议纪要聚合为关键事实列表输出Markdown。generate-weekly-report读取上述两个输出结合模板生成周报。identify-risks检查周报中的数据和事实标出风险项输出风险清单。这四个技能各自只有单一职责任何一环出问题都能单独替换而不影响其他环。上线当天它们在我的Agent里先串行跑完事实采集与报告生成再追加一轮风险识别输出质量稳定。这也是我推荐的做法先拆到不能再拆为止再用接口组合起来。6. 团队技能库的管理命名、版本与评审机制等技能数量超过十几个以后真正的瓶颈不再是写技能而是管理技能。6.1 目录结构按业务域而不是按类型组织有人习惯按技术类型建目录prompt_skills/、tool_skills/结果找起来非常痛苦。建议按业务域组织skills/ ├── product/ ├── customer-service/ ├──>