ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI技能(Skills)设计与实践:从零构建可复用的智能体能力

AI技能(Skills)设计与实践:从零构建可复用的智能体能力 1. 从“skills”聊起为什么这个词突然成了技术圈的热词如果你最近泡在开发者社区或者关注AI应用落地会发现“skills”这个词出现的频率越来越高。它不是一个新概念但在大模型应用爆发之后被重新赋予了非常具体的含义——指的是给AI助手或智能体定义的一组可复用、可组合的能力单元。简单来说就是让AI不只会“聊天”而是会“干活”并且干活的规则、步骤、边界都被明确写下来。在我接触过的不少项目里团队早期都陷入过同一个误区把所有的业务逻辑一股脑塞进系统提示词里结果模型输出时好时坏改一次需求就要动一整段prompt维护成本极高。后来切换到“技能化”的思路——把每个独立任务封装成一个带描述、带参数、带执行逻辑的模块——整个系统的稳定性上了一个台阶。这个思路不仅仅适用于AI应用开发它背后其实是一种通用的问题拆解方法论把复杂能力拆成标准化的小单元再像搭积木一样组装出更复杂的行为。这篇文章我打算围绕“skills”展开聊聊它到底是什么、为什么值得重视、以及我实际踩过坑之后总结出来的设计、编写和测试方法。无论你是正在做智能体应用的产品经理还是自己写代码的独立开发者或者只是对AI工具玩法感兴趣这篇文章都能给你一套可以直接上手的框架。2. 技能Skills到底是什么一个AI时代的能力单元2.1 从“工具调用”到“技能”一字之差逻辑却完全不同很多人会把skills和function calling函数调用混为一谈但这两者在设计思路上有本质区别。Function calling解决的是一次性的、确定性的操作——比如调用天气API、查询数据库而skills强调的是“完成一个完整任务的能力”它内部可能包含多个步骤、多次判断甚至可以调用多个底层工具。我打个比方如果function是螺丝刀那skill就是一套家具组装方案。螺丝刀只负责拧螺丝这一个动作而组装方案会告诉你先装哪块板、用哪种螺丝、什么时候需要用到螺丝刀、什么时候需要改用扳手。同样道理一个“生成周报”的skill内部可能需要先收集数据、再判断重点、然后排版输出——这已经超出了简单函数调用的范畴。这个区别带来的直接变化是你把“怎么做”的判断逻辑从用户手里、从模型的不确定性里转移到了你定义的技能规则里。模型不再需要临场发挥琢磨怎么组织一份周报它只需要按照skill里写好的步骤执行。输出质量的上限被拉高下限也被稳稳兜住。2.2 一套好技能的核心构成要素我在实际项目中沉淀下来一个完整可用的skill通常需要包含六个部分少了哪个都会在真实场景中出问题。第一个是触发描述。这决定了模型在什么情况下应该调用这个技能。描述写得含糊模型就会在错误的场景里频繁误唤或者该用的时候死活不用。第二个是参数定义。每个技能需要哪些输入、参数类型是什么、是必填还是可选必须定义得清清楚楚。第三个是执行指令这是技能的核心部分告诉模型拿到输入之后按什么顺序、用什么标准来完成整个任务。第四个是约束条件包括边界和禁忌——哪些事绝对不能做哪些情况要停止执行。第五个是参考示例给模型一两个优质的输入输出样例能显著提升它理解规则的准确度。第六个也是很多人会忽略的是失败处理逻辑——技能执行不顺利时模型应该怎么响应、怎么报错而不是硬着头皮给一个错误结果。这套结构看起来不复杂但真正写好每一部分都需要反复打磨。尤其是执行指令和约束条件写得太概括会执行不到位写得太死板又会失去灵活性需要找一个微妙的平衡。2.3 为什么说“技能化”是AI应用从demo走向生产的必经之路做过AI应用的人大概都有这种体验搭建一个原型很简单让模型在十次里八九次表现不错也不难难的是那剩下的一两次失误。而真正投入生产环境哪怕百分之一的概率出问题都可能变成不可接受的风险。技能化在这个过程中扮演的角色就是把“概率性”的执行压缩成“接近确定性”的流程。你可以把技能当作一个防止模型自由发挥的笼子——在笼子内部它仍然有灵活性但笼子的边界是你画好的不可越界。对于企业级应用这种可控性几乎等于一切。另外技能化还有一个配套的好处就是组合性。当你的技能库里有“文档解析”“数据提取”“表格生成”这些基础技能后你再做一个“合同分析报告”的新功能就不需要从零写逻辑了——把三个已有技能串起来就完成了一个新技能。这种复用机制直接改变了AI应用的开发方式从“每次写一个prompt”变成“持续积累能力资产”。3. 设计一个高质量技能的四步法从需求分析到规则编写3.1 第一步把任务拆到“一个技能只做一件事”我见过最多的失败案例都是因为想把技能设计成“全能选手”。一个技能既要做信息收集又要做数据分析还要负责生成图表结果往往是哪一步都差强人意。大模型的注意力是有限的技能职责范围越宽规则就会越复杂模型就越容易在某个环节上跑偏。正确做法是先做任务分解。比如你最终想要一个“市场竞品分析报告”那可以先拆成“竞品信息搜索技能”“竞品数据整理技能”“报告结构生成技能”“报告美化排版技能”这几个子任务。每个子任务单独封装成技能分别进行测试和优化最后再组合调用。拆分的颗粒度怎么判断我的经验是如果一个技能的核心逻辑用三到五个步骤描述不完或者调用完成后输出内容明显包含了好几个不同性质的结果那就说明拆得太粗了。反过来如果一个技能还需要依赖大量外部参数才能独立干活那可能拆得太细使用时反而增加调用复杂度。3.2 第二步为每个技能写好“使用说明书”这一步是整个设计过程中最容易被低估的。很多人喜欢直接写执行步骤跳过了触发场景描述结果模型根本不知道什么时候该调用这个技能。写触发描述有一个实用技巧正面描述加反面描述结合。正面描述告诉模型“当用户提出什么类型的需求时使用本技能”反面描述则明确“当用户只是想简单了解概念时不要使用本技能直接回答即可”。这两种描述放在一起能大幅减少误唤和漏唤。参数定义也需要仔细推敲。参数数量尽量精简能少则少。每个参数不仅要有类型定义还必须有清晰含义说明。比如一个“生成周报”的技能参数可能包括“时间段”“工作内容概述”“本周重点成果”这三个每个参数都要写明格式要求和示例值。参数太多会加重使用者的填写负担参数太粗又会导致输出缺乏针对性需要在具体设计时反复权衡。3.3 第三步编写执行指令时把自己当成一个“带新人的老员工”这可能是最重要的一条经验你在写执行指令时的心态决定了技能的上限。如果只是机械地罗列出步骤那写出来的规则一定生硬且不耐用但如果你想象自己是在手把手带一个聪明但没经验的新人就会自然地补充很多必要的背景解释和判断标准。比如你写“总结会议纪要”这个技能机械写法是1. 阅读会议记录2. 提取关键信息3. 按格式输出。但带过新人的写法会是这样先说明一份好的会议纪要应该包含哪些模块决议、待办、风险项再解释提取“关键信息”的判断标准比如反复出现的话题、有明显时间节点的任务、关联到具体责任人的内容再补充输出格式的详细模板最后加一句“如果会议讨论内容有明显冲突或含糊不清的信息保留原文表述并在备注栏标明”。同样的逻辑不同的表达深度技能效果可能差出好几倍。模型和新人一样不怕你啰嗦就怕你没把判断标准说透。3.4 第四步设计约束条件与失败兜底约束条件不是用来限制模型“不犯错”的而是用于定义“错误的边界”。你要明确告诉模型哪些类型的操作即使看起来合理也不要执行。比如做问答类技能时涉及医疗建议的场景需要明确要求输出“建议咨询专业医生”的免责声明做企业数据分析技能时对涉及机密信息的内容要设置“拒绝回答并提醒权限问题”的兜底逻辑。失败处理是我见过被忽略得最严重的一个部分。很多技能根本没有处理异常情况的指令一旦模型遇到它无法理解或无法执行的请求就开始胡说八道。一个及格的技能必须有自己的“认怂策略”识别到超出能力范围时如何向用户说明识别到输入信息不足时如何引导用户补充信息。这比让模型硬生生编一个答案对用户的影响要好得多。4. 实战演练从零编写一个可复用的“会议纪要生成”技能4.1 需求场景与参数设计理论讲再多不如动手写一个。我拿“会议纪要生成”这个应用频率极高的场景来走一遍完整流程。这个技能的目标是输入一段会议录音转文字或者人工整理的会议速记输出一份结构化、可直接分发给参会人员的会议纪要。参数设计我选了三个第一个是meeting_text必填字符串类型接收会议原始文本第二个是meeting_duration选填数字类型代表会议时长可帮助模型推断详略程度第三个是output_style选填预设两个值concise表示精简版detailed表示详细版默认使用detailed。三个参数基本覆盖了大多数使用场景又不会给调用者太多负担。4.2 我实际的技能规则文件长什么样规则文件我偏向使用YAML格式因为可读性强后续维护时一眼就能看懂结构。下面这个版本是我在多个项目中迭代后沉淀下来的去掉了我自己项目的敏感业务字段保留了一套通用的框架。name: meeting_minutes_generator description: 将会议原始文本转换为结构化会议纪要。 当用户提供会议录音的转写文本、人工速记或非结构化的会议讨论内容 并希望生成正式的会议纪要、行动项清单或会议总结时使用本技能。 如果用户只是询问会议相关的一般性建议不包含需要整理的原始文本则不使用本技能。 parameters: meeting_text: type: string required: true description: 会议录音转写文本或速记内容可以包含口语化表达和重复内容。 meeting_duration: type: number required: false description: 会议总时长单位分钟用于调整输出详略。 output_style: type: string required: false enum: [concise, detailed] default: detailed description: 输出风格concise为快速要点版detailed为完整会议纪要。 instructions: | 你是一位资深的会议记录专员。请按以下步骤处理会议文本 第一步通读全文识别会议的基本信息。包括参会角色如主持人、决策人、执行人、核心讨论主题。 第二步提炼关键决策。重点关注带有结论性的语句例如“我们决定”“最终确定”“就按照”等引导词。 第三步提取待办事项。标准包括出现了具体时间节点、明确指派了责任人、涉及需要交付的成果。三者至少满足两个才可作为待办事项列出。 第四步识别风险与遗留问题。会议中提到但尚未解决的疑问、潜在风险和未达成一致的话题单独归类列出。 第五步按模板输出。详细版模板如下 【会议主题】 【会议时间与参会人】若原文未说明标注“未提供” 【关键决议】编号列表每条包含决议内容和决议背景 【待办事项】编号列表每条包含事项描述、负责人、截止时间未说明时写“待确认” 【风险与遗留问题】编号列表 【备注】其他值得记录但不在上述类别内的信息 constraints: | 1. 待办事项必须基于原文不得凭空补充责任人和时间。 2. 若原文内容不足以支撑某一模块该模块标注“原文未提供相关信息”不要自行编造。 3. 会议文本含大量口语化内容时保留原意的前提下进行书面化改写不改动事实信息。 4. 若参会人明确提出“此事需要保密”整体输出中不得以任何方式复述该部分内容。 5. 当output_style为concise时以上述模板为基础每个模块仅保留最重要的三条。 examples: - input: | 我们今天聊了一下系统升级的事情最后决定下个月开始分阶段推进。老王负责运维那边的对接月底前要出一个风险评估报告。客户端兼容性的事情还得再确认一下暂时没有结论。 时间的话这次会大概开了一个小时。参会人有李总、老王、陈晨。 output: | 【会议主题】系统升级推进方案讨论 【会议时间与参会人】时长约1小时参会人李总、老王、陈晨 【关键决议】 1. 系统升级计划确定分阶段推进下月开始执行。 【待办事项】 1. 风险评估报告 - 负责人老王 - 截止时间本月底 【风险与遗留问题】 1. 客户端兼容性方案尚未确认待进一步讨论。 【备注】原文未提供更多信息。4.3 我在编写时踩过的几个关键坑先说说参数设计上的一个教训。最早一版我加了target_audience目标读者参数结果调用时每次都得多填一个字段但实际产出效果并没有明显差异后来直接删了。参数不是越多越好每多一个参数调用成本和使用门槛都在增加。只有确定能让技能输出产生质变的参数才值得保留。还有instructions的编写顺序我吃过一次大亏。第一次我把“输出模板”放在了步骤一导致模型从第一步开始就纠结于格式反而没有耐心去理解会议内容。后来我把模板移到第五步让模型先分析和提炼最后再套格式输出质量立刻有了改善。这背后的逻辑是让模型先把注意力放在理解内容上格式只是最后一层约束。关于约束条件中的“保密”处理这里也分享一个经验。如果你只是写“不要输出保密内容”模型其实很难判断什么算保密。更好的方式是给一个可操作的判断标准——比如“当原文中出现‘不要外传’‘注意保密’等明确提示时对应段落内容完全跳过”。这样模型执行起来才有明确的依据。4.4 测试技能时我建议你跑完这几组用例很多人测试技能只跑一两个happy path正常路径觉得输出不错就算过关了。但真实场景远没有这么简单。我自己的习惯是至少跑四组用例第一组是标准会议文本验证核心功能是否正常第二组是极其口语化、信息支离破碎的会议记录测试模型的容错和信息提取能力第三组是故意包含明显冲突信息的文本比如“决定做A方案”和后面又说“A方案先别动”验证模型能否识别不确定性并写进风险项第四组是引发约束条件的用例比如原文含“暂不公开”等内容测试保密逻辑是否生效。前两组决定技能是否可用后两组决定是否可信。很多技能死在后面这两组上——不是因为主流程跑不通而是遇到异常输入时暴露出各种边界漏洞。5. 如何把零散技能变成你自己的“技能资产库”5.1 技能的分类组织与命名规范当技能只有三五个的时候怎么命名都无所谓。但技能数量到了几十个之后如果命名毫无规律你一定会后悔当初没有认真设计规范。我自己的习惯是采用“动词_对象”的结构比如generate_report、parse_document、extract_entity。这种结构一眼就能看出技能的功能边界和适用范围后续做自动调用时也容易匹配。分类方面我建议按“能力类型”而不是“业务场景”来分组。因为业务场景会变但底层的处理能力相对稳定。比如“合同审核”“论文审阅”“简历评估”这些业务场景本质都属于document_analysis这个能力域。分组按能力走沉淀下来的分类体系会稳定很多反过来也能帮助你发现当前技能库里的空白地带。5.2 为技能建立“版本档案”与更新日志我在独立开发的前期也犯过一个懒技能文件改完就覆盖完全不记得以前版本为什么这么写。结果就是某个技能某天突然表现大幅下降但根本不知道是改哪句话改坏的。后来我养成了一个习惯每个技能文件头部加一个简单的变更记录字段哪怕只是寥寥几笔也能省下后面大量的排查时间。版本档案不一定要用复杂的工具在技能文件的末尾追加一个changelog列表就够用。每次修改时记录日期、修改人、修改内容和修改原因。这样做的好处是当你回顾一段时间的修改历史往往能发现某些反复回退的问题那通常意味着最开始的设计方向就有偏差而不是细节调校的问题。5.3 技能评估体系不要凭感觉判断技能“好不好”判断一个技能好不好用不能只看一两次的运气。我建议为每个关键技能建立一套简单的评估集固定10到20组测试用例每次修改后在整组用例上跑一遍记录通过率和失败模式。通过率的定义也要提前统一比如“输出内容是否完整包含所有必填模块”“是否存在明显的错误事实”。这个评估集一个季度更新一次日常修改用现有集做回归测试。这个方法看起来笨但省心的程度超乎想象。尤其当你同时维护多个技能时没有这套评估机制你根本不知道哪次改动影响到了哪些下游组合调用。有了它能让你从“每次凭感觉修”变成“每次改完跑一遍心里有底”。6. 误用与滥用Skills不是银弹这些场景它帮倒忙在我接触过的技能滥用案例中最高频的错误就是把技能当成一切问题的答案。很多团队把“技能化”当作一个口号遇到任务就封装成技能结果技能的数量上来了系统整体效果反而下降。原因是技能调用本身对模型是有消耗的——使用技能意味着模型需要先理解触发条件、查阅参数、遵循内部步骤这比直接自由回答要“重”得多。哪些情况下不适合使用技能我总结了几条经验。第一个是开放性极强、没有标准流程的任务。比如“帮我想一个营销创意”这种任务的价值恰恰在于模型的发散能力套上技能反而束缚了思维。第二个是一次性任务做完就不用再做了。技能的本质是“可复用”没有复用价值的一次性规则写在系统提示里更直接。第三个是为非常小的子步骤建立技能比如“判断一句话的情感极性”这种粒度用简单的规则或提示就解决了封装成技能属于过度设计。我见过最典型的反面案例是一个人把“写邮件”做成了三个技能一个写主题行、一个写正文、一个写结尾。看起来拆分得很细但实际调用时需要串三次对话每次模型都要重新理解上下文效率反而远不如一个完整的邮件生成技能。这个例子的教训是技能化的核心是“边界清晰”不是“拆得越碎越好”。正面案例则是另一个极端我维护的一个客服系统把“多轮信息收集—订单查询—退款规则判断—售后话术生成”拆成四个技能配合一个简单的调度逻辑处理长尾售后问题的成功率提升了很多而且每个技能都可以独立测试和优化不会牵一发动全身。好的技能化体系一定是既有清晰的单元边界又能灵活组合这才是这个思路真正的价值所在。7. 最后分享一点我的真实体会做技能设计这一路下来我最大的感受是它考验的其实不是你对大模型有多了解而是你对自己业务的拆解能力。同样一个任务能不能找到正确的切分维度能不能提炼出稳定的处理步骤才是技能质量的分水岭。技术工具会不停迭代但这种“把复杂问题拆成可执行模块”的思维方式在任何技术浪潮里都不会过时。如果你现在正准备开始建立自己的技能库我建议你从小处着手——挑一个你每周都会重复做两三次的任务先把它写成一个完整技能跑通、打磨、用起来。等真的用上一个月你再回头看会发现自己对业务的理解和之前完全不在一个层面上。这个过程本身就是最大的收获。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进