这两年做AI Agent落地跑过不少真实项目之后我发现一个特别突出的瓶颈不是模型能力不够而是Agent的手太少了。你让大模型聊天、写文案、做总结它表现得很好但一旦牵扯到实际操作——查数据库、调接口、处理文件、执行一套多步骤任务——就会暴露出各种问题工具函数写得又多又杂模型经常选错上下文里塞了几十个工具定义token开销大得离谱更别提换一个项目之前沉淀的能力几乎全废得从头再来。agent-skills这个概念解决的就是这个问题。我自己的理解是**把高频、可复用的能力封装成一个个独立、自描述、可验证的技能模块让Agent按需调用、自由组合。**它比function calling更完整比workflow更灵活是目前做Agent工程化时性价比最高的能力扩展方式。这篇文章我会把我自己从0到1搭建技能层的完整思路写出来包括技能的结构设计、描述怎么写才触发得准、多技能怎么编排、实际踩过的坑以及哪些业务场景最值得优先落地。适合正在做Agent开发、AI应用落地或者想把大模型能力真正接到业务里的人参考。我不会讲太多纸上谈兵的理论尽量用能直接抄作业的方式来说。1. 为什么工具调用不够用需要单独的技能层1.1 从function calling到技能层到底解决了什么问题早期大家做Agent能力扩展最朴素的做法就是堆function calling把业务接口一个个声明成函数塞给模型。项目小的时候没什么问题但一旦函数超过20个你会发现三个很现实的问题。第一是选择困难。大模型本质上是在做概率匹配当候选函数太多、函数描述又写得不清楚时选错函数的概率会直线上升。我见过最夸张的情况是明明有专门的天气查询接口模型偏偏调了一个新闻接口然后把返回的标题文字硬生生当天气念给用户听。这种错误不是模型笨而是你给它的选择空间太大了缺乏约束。第二是上下文膨胀。每个函数的声明都有函数名、参数说明、返回值结构动辄几百token。塞上三四十个函数定义对话还没开始光工具定义就吃掉大半上下文窗口。而且更麻烦的是越到后面轮次模型越容易忘记前面函数的确切用法这时候你再额外加强调用说明上下文就更挤了。第三是复用彻底失效。工具函数和具体业务接口强绑定换个项目换个数据源你就得重新写一套。没有人会去沉淀一套可以被多个项目共享的工具层因为每个项目的接口都不一样。结果就是每个团队都在重复发明轮子做了大量同质化的工作。技能层解决的是这三件事。它把函数提升到技能的颗粒度不再是调这个API查天气而是获取某地区未来三天的天气预报并生成出行建议。技能内部可以是一个函数也可以是多个函数的组合还可以是一段精心调教过的Prompt加上后处理逻辑。对Agent来说它不需要关心技能内部怎么实现只需要知道什么场景下该用这个技能、传什么参数、拿什么结果。1.2 技能与工具、插件、工作流的边界怎么划很多人会问那技能和插件、工作流有什么区别我的划分方式是这样的用一张表说清楚维度工具调用 (Function)插件 (Plugin)Agent技能 (Skill)工作流 (Workflow)粒度最小单接口偏外部集成中等面向能力最大面向流程决策方式模型选函数模型选工具模型按时机触发流程引擎固定执行内部复杂度低中等中高含Prompt逻辑高多节点编排可复用性弱中强弱绑定场景核心价值让模型能操作生态接入让Agent具备完整能力让流程稳定可靠我举个例子帮助理解。工具调用是一把螺丝刀插件是工具箱里的一套电动工具而技能是一个熟练工人会怎么把螺丝拧好——包含了选什么工具、用什么手法、拧到什么程度才算紧、拧滑丝了怎么处理。技能是工具和经验的组合体这也是它和单纯工具调用最本质的区别。工作流则更像一条流水线每个环节固定、顺序固定、异常处理也固定。技能层落地得好的话工作流其实是构建在技能之上的你定义好每一步做什么每一步调用的就是技能这样工作流既是稳定的又因为技能的存在保持了灵活性。我自己做项目时通常先搭技能库再基于技能库编排流程而不是一上来就画流程图。2. 一个能跑起来的技能最少要有这五个部分2.1 技能描述写的是触发条件不是功能说明很多人在定义技能时犯的最大错误是把技能描述写成了功能介绍。比如本技能可以对CSV文件进行数据清洗——这句话模型看了等于没看因为任何数据处理类技能都能套上这个描述模型根本不知道什么时候该用你、什么时候该用另一个。正确的做法是**描述里必须写清楚触发场景、前置条件和边界。**什么情况下用户的需求应该命中这个技能什么情况下不应该命中。我常用的描述模板是这样的name: csv_cleaner description: 当用户上传CSV/Excel文件并要求对数据进行去重、缺失值处理、 格式统一等清洗操作时使用本技能。如果用户只是问文件内容、 做简单查看不要使用本技能直接读取文件回答即可。 parameters: file_path: type: string description: 待清洗文件的路径 rules: type: object description: 清洗规则支持 dedupe / fillna / strip你会发现这段描述里最关键的不是清洗这个词而是**如果用户只是问文件内容不要使用本技能**这一句。这是在给模型划边界。模型判断是否调用技能时描述里显式的正反例越多命中率越高。我后来总结了一句话技能描述要用当...时使用和如果...不要使用两种句式反复框定触发条件。2.2 参数设计越扁平越好越限定越好技能的参数设计直接决定模型能不能一次传对。我有几条实践经验都是踩坑踩出来的。第一**尽量只用扁平结构不要嵌套。**嵌套的JSON对象会让模型在多轮对话中拼参数时非常容易出错经常出现漏掉内层字段或者把字段放错层级的情况。能拍平就拍平。第二能用枚举就枚举能用布尔就布尔。cleaning_type: string这种写法就是给自己挖坑模型会给你传乱七八糟的清洗这种值。你要做的是给出固定选项cleaning_type: { enum: [dedupe, fillna, strip, standardize], default: dedupe }第三**参数必须有默认值。**模型不是每次都能拿到所有信息。用户说把文件里重复的数据去掉它知道要用dedupe但不知道文件路径——这时候如果路径是必填的调用就失败了。我的习惯是核心业务参数必填其余全部给默认值模型实在没信息时就用默认值顶上而不是直接报错。第四在技能内部做参数校验不要全信模型传来的值。模型传参错位是常态你要在技能入口做一层防护比如检查文件是否存在、枚举值是否合法、数值范围是否合理。这一层可以让技能的报错率大幅下降。2.3 返回值设计统一封装让Agent能看懂结果技能返回什么直接决定Agent下一步能不能做出正确判断。很多早期项目技能返回的是原始数据比如直接把数据库查询结果丢给模型结果模型面对一堆字段不知道重点在哪里就开始胡说。我建议所有技能都返回到一个统一的结构里{ code: 0, message: success, data: { cleaned_rows: 152, removed_duplicates: 37, preview: 各行前100字符预览... }, usage_notes: 清洗完成数据集中有12行日期格式异常已统一为YYYY-MM-DD }注意最后这个usage_notes字段这是我自己加的习惯。它用自然语言告诉Agent这个技能执行完之后的关键结论和需要留意的情况。为什么不直接让Agent自己看data因为data里的信息太多太杂模型自己判断容易遗漏重点。你把重点提炼好写清楚Agent的下一步决策就会稳很多。这个字段的设计思路其实就是把信息抽取的工作提前到技能内部完成而不是丢给模型现场分析。关于返回值还有一个建议**技能的返回尽量结论化不要数据化。**比如一个做财务分析的技能返回里直接写毛利率从32%下降到28%主要原因是XXXX而不是丢一堆财务数字让模型自己算。Agent的算术能力和总结能力没有你想象中那么可靠能算的你在技能内部算完给它结论就好。2.4 样例与验证给模型抄作业的机会给测试留抓手每个技能定义里我还会附上2到3个使用样例。这个做法参考的是few-shot prompting的思路模型在决定是否调用技能时会把当前对话和技能样例做相似度匹配样例越贴近真实场景触发就越准。样例的格式我一般写成用户输入 → 技能调用参数的映射samples: - user_input: 把这销量的CSV去个重 params: file_path: uploads/sales_data.csv rules: [dedupe] - user_input: 数据里有好多空着的格子帮我补一下 params: file_path: uploads/sales_data.csv rules: [fillna]这些样例有两个用途一个是帮模型更准确地触发技能另一个是给你自己做回归测试用。把样例积累起来就是一个技能的评测集。我后面会专门讲评测怎么做这里先提一句不要等到技能做完了才去补样例而是边写技能边补每加一个实际场景就往samples里加一条。3. 多技能编排从单个技能到一套组合拳3.1 技能编排的五种基本模式单个技能只是积木真正发挥价值的是编排。我在实际项目里总结出五种常见的技能编排模式几乎覆盖了绝大多数业务场景。第一种是线性流水线。比如读取合同→抽取关键条款→生成摘要→归档文件每个环节调用一个技能前一个的输出直接作为后一个的输入。这种模式最简单也最常用适合业务流程清晰、步骤固定的场景。第二种是条件分支。比如用户提交的工单先调用分类技能判断工单类型然后根据类型走不同处理路径技术问题调故障排查技能费用问题调计费查询技能投诉问题调升级流程技能。分支的关键在于分类技能的输出必须足够可靠每个分支入口的信号要明确。第三种是并行分解。一个大任务可以拆成多个独立子任务时同时调用多个技能。比如做市场分析报告竞品信息收集行业趋势分析内部销售数据统计三个技能互不依赖可以同时跑最后在汇总节点合并结果。这种模式对延迟敏感的项目特别重要能大幅缩短整体响应时间。第四种是递归自省。Agent调用一个技能之后根据返回结果判断是否还需要调用别的技能循环往复直到任务完成。比如网页抓取技能发现页面需要登录返回一个需要凭证的状态Agent看到这个状态后自动触发登录技能然后再继续抓取。这种模式最接近人类的做事方式但对技能的返回设计和Agent的决策能力要求最高。第五种是人机确认。涉及重要操作删除数据、发送邮件、修改配置时技能并不直接执行而是先输出一个待确认的操作预览让用户确认后再真正执行。这个模式在生产环境里几乎是必须的它不是一个具体的技能而是所有高危操作类技能都应该遵守的一个外层约束。3.2 编排器怎么做编码式还是模型式编排模式有了谁来决定走哪种模式这就要说到编排器的设计了。我见过两种路线。第一种是编码式编排流程是工程师写死的。代码里明确写着第一步调技能A第二步判断输出第三步调技能B。这种做法的优点是稳定可控完全不会有模型乱选流程的问题缺点是死板面对需求外的场景就无能为力。适合那些流程极其稳定、容不得差错的场景比如自动对账、定时报表。第二种是模型式编排把编排决策权交给大模型。模型看到用户需求后自己决定先调哪个技能、再调哪个技能。这种做法灵活能应对各种新场景但风险也在这儿——模型可能调错顺序可能漏掉步骤可能在一个死胡同里反复调用同一个技能。我自己的做法是混合式业务主干用编码式固定下来确保核心路径不出错在每个主干节点上节点内部的具体实现用模型式让模型在子技能里自主选择。比如客户咨询处理流程的第三步固定是生成解决方案但方案是用售后知识库技能、还是用故障排查技能让模型根据咨询内容自己判断。这样既保证了主干流程的稳定又保留了分支上的灵活度。3.3 技能之间的数据传递别搞全局共享编排过程中最容易踩的坑是技能之间的数据传递设计。我早期犯过的错误是搞了一个全局上下文对象所有技能都能往里面写数据、读数据。看起来很方便实际跑起来就是一场灾难技能A写进去的字段技能B不知道什么时候会读到技能C改了技能D依赖的数据排查问题时完全不知道从哪里入手。整个系统变成一个大泥球互相信任又互相干扰。后来我确立了一个原则**技能之间不共享全局状态只能通过显式的输入输出契约通信。**技能A的输出必须是技能B的输入这种关系必须在编排定义中显式写出来A不知道B的存在B也不关心数据从哪来只看自己拿到的东西符不符合要求。这样做有几个明显的好处。一个是可测试性上来了每个技能可以独立测试不依赖其他技能的状态一个是可排查性上来了数据流向是明确的调用链出了问题顺着链找就行还有一个是可替换性上来了技能B的实现换了只要输入输出契约不变编排完全不用动。实际落地时我会为每个技能维护一份输入契约和输出契约跑编排前先做一次静态检查确认技能串联是匹配的。这个检查看起来笨但对那些技能多、调用链长的大项目来说能提前拦住大量低级错误。3.4 技能的版本与生命周期管理技能做多了以后自然会发生版本迭代。今天优化了描述明天改了参数结构后天换了内部实现如果不管控很快就会出问题旧流程还在用旧版本的技能行为新技能又上线了两边行为不一致排查起来欲哭无泪。我的做法不是很复杂但很管用。给每个技能加一个语义化版本号major.minor.patch然后约定三条规则参数结构或返回结构发生变化时必须升major版本因为涉及契约变更新增功能但兼容旧契约时升minor版本只修改内部实现、外部行为不变时升patch版本。每次升级samples和评测集也必须同步升级并在变更记录里写明本次升级改了什么、防线是什么。这样即使有人误用了旧版本也能快速定位到历史行为差异。另外一个实操建议是技能上线时不要一刀切替换而是新旧版本并存一段时间让线上流量慢慢迁移。特别是那些被编排链路依赖的技能你永远不知道下游哪个环节对某个细节输出有隐性依赖。先并存观察确认安全了再彻底下线这是最稳妥的办法。4. 实操中的五个大坑与排查思路4.1 技能重叠导致的触发混乱这是技能库膨胀到一定规模后最常遇到的问题。技能A是生成产品介绍文案技能B是生成产品推广文案描述里都提到产品文案——模型一看这两个好像都能用于是随机挑一个输出风格大相径庭。我排查这个问题的思路是**给技能库做定期审查把描述相似的技能标记出来确认它们触发边界的差异是否足够清晰。**如果两个技能的差异在描述上体现不出来就要么合并要么在描述里互相写排除条款。举个实际的例子我做过两个技能周报生成和项目进度汇总。它们的输入都是项目信息列表但前者输出是有叙述性的段落型周报后者输出是结构化的进度字段。最初两个技能经常被模型搞混。我的解决办法是在周报生成的描述里加了一句话如果用户需要的是项目进度字段列表而非周报正文请使用项目进度汇总技能。在另一个技能的描述里也加了对应的反向指引。实践下来这种双向排除指引比单纯让描述更详细要有效得多。还有个辅助手段是给技能加路由前缀在统一的技能路由列表中按领域分组模型先走到领域组再在组内选择具体技能相当于做了一次粗粒度过滤减少了不同领域技能之间的误触。4.2 上下文膨胀技能本身的token成本失控技能定义塞太多、描述写太长会导致上下文被技能定义占据真正留给对话和处理的空问越来越少。这个问题在技能数超过20个之后会特别明显尤其是每次对话都要把所有技能定义全部注入的系统。我的解决方案是分级加载。默认情况下只给Agent注入高频核心技能的精简描述每个描述控制在100token以内而完整版技能描述、样例、详细参数说明存在一个技能注册中心里等模型确定要调用某个技能时再动态加载它的详情给模型。这有点像操作系统的虚拟内存不是所有东西都常驻内存用到才换入。具体效果我做过一个统计精简前系统里36个技能的全量定义加起来约4200token精简后常驻描述压到大约900token其余通过延迟加载按需注入。对多轮对话来说这个差距意味着上下文空间扩大了近4倍效果非常明显。关于技能描述节省token我还有一个习惯**每个技能描述里最多保留一条正例一条反例。**很多人会在描述里写三五个样例每一行都要占token加乘起来开销不小。样例放两三个典型就够了重点在于典型而不是多。4.3 技能效果评估没有评测集等于裸奔很多团队做完技能就直接上线然后靠线上用户反馈来发现各种问题。这种做法太被动了。技能触发的准不准、参数传得对不对、返回结果模型看不看得懂这些问题应该在上线之前就用评测集暴露出来。我给每个技能都配了一个迷你评测集大概5到10个测试用例每个用例记录用户输入→期望触发的技能→期望传入的参数→期望返回的结果特征。做技能迭代时跑一遍评测集看命中率、参数准确率、返回结构合格率。用一个很简单的打分表评测项权重说明触发命中率40%该触发时是否触发不该触发时是否误触参数完整率25%调用参数是否完整且取值正确返回结构合格率20%返回的code/message/data结构是否规范多轮交互稳定率15%连续多轮调用同一技能是否稳定有了这张表每次改完技能描述或内部逻辑跑一遍评测分数不降才能上线。这不是形式主义是在留住你花很长时间调出来的一手好状态。一个小技巧**评测集至少有一半用例来自真实线上对话日志。**自己编的用例再怎么全面都没有真实用户五花八门的说法来得接地气。4.4 冷启动技能太多做不动从抄作业起步搭建技能库这件事最难的不是技术而是起步阶段。虽然理论上能做的技能有很多但一次性铺开做所有人都会被拖垮。我自己的建议是第一个月只专心把2到3个使用频率最高、边界最清晰的技能打磨出来比如你们业务里最常见的信息抽取格式转换数据查询把它们做到极致——评测分数高、内部逻辑稳、描述触发准。高频使用场景的判断标准有两个。一个是翻翻你们的对话日志哪些操作反反复复出现哪些处理逻辑每次都是同样的几行代码另一个是问自己哪个能力如果Agent做不好对业务影响最大这两个问题一交叉答案就明确了。我当时就是从一段把非结构化文本里的联系人信息提取成结构化字段的需求开始做第一个技能的。这个操作在我之前的所有项目里都反复出现过每次换项目都要重新写一遍解析逻辑风格还不统一。把它技能化之后后续所有项目都能直接复用这才是技能库冷启动该有的节奏。4.5 工具选型不要为了智能牺牲可控最后一个好多人会问我的问题这些技能要不要用某个特定框架来做我个人的看法是**技能层是一个工程架构概念不是某一家特定工具的专属能力。**你用任何大模型框架、甚至裸调用API都能实现技能层区别只是封装的便利程度。我建议按团队情况来选型如果团队里都是工程师用代码来定义技能灵活度和可控性最高如果团队里有懂业务的非工程师可以考虑用配置文件YAML/JSON定义技能描述和参数再配合一个可视化管理后台。不管选哪种核心衡量标准只有三条**技能定义能不能版本化技能效果能不能评测技能入口能不能审计留痕**这三条有一项做不到工具再花哨也只能是玩具。如果你是从零开始不要急着找框架。先用最基本的方式把2个技能做出来跑通再考虑上工具、上管理后台。道理很简单技能层的价值在于沉淀和复用你连沉淀的对象都还不清楚上再强的管理工具都是空的。5. 哪些业务场景最值得优先把能力技能化5.1 数据类技能最稳妥的切入点数据相关的操作天然适合做成技能。原因有三第一数据处理的输入输出边界清晰容易定义契约第二处理逻辑可以用代码精确控制不像文本生成那样发挥不稳定第三高频率使用是必然的几乎每个Agent项目都会遇到数据读取、清洗、格式转换的需求。我推荐从三个具体动作开始做表格类文件的读取与清洗、非结构化文本的字段提取、不同数据格式之间的转换JSON转CSV、CSV转Excel、Markdown转PDF等等。这三个动作覆盖了大部分客服、运营、财务等非技术人员日常会用Agent来做的数据工作。5.2 文档操作类技能看得见的价值感让Agent帮你读文档、写文档、改文档是见效最快的技能方向。一个做得好的文档类技能效果是非常直观的合同审阅技能能自动识别重点条款和风险项报告生成技能能根据数据生成结构完整的周报格式转换技能能把零散笔记变成规范的会议纪要。文档类技能有个额外的优势**用户的感知度特别高。**数据清洗做得好用户看不到内部细节但一份排版漂亮、内容完整的分析报告摆在用户面前价值感是即时可见的。这在项目初期争取资源、争取业务方配合时特别有用所以我通常建议团队把文档类技能放在优先级清单的前面。实际操作时有一个细节要留意文档操作技能和纯文本生成技能不一样它往往需要处理真实的文件读写所以技能的输入参数里要包含文件路径、保存路径这类信息这就涉及到和文件存储系统的对接。不要在技能里硬编码路径把存储系统的访问方式做成可配置的技能的可复用性会大大提升。5.3 垂直领域的知识问答让技能充当专家外脑通用大模型在垂直领域的深度问答上经常翻车本质是因为缺少领域知识。技能层可以在知识接入上扮演桥梁角色把领域知识库的检索、融合、回答链路封装成技能Agent遇到相关问题时自动调用这个技能而不是自己在脑子里凭空想。这类技能的设计核心是检索质量。我在实操中把知识问答技能分成两个子技能一个负责召回根据问题检索知识库返回相关片段一个负责生成基于召回的片段组织最终回答。分开做的好处是召回质量可以独立评测——你不需要看最终的答案好不好只看召回的内容是不是真和问题相关问题定位就快得多。不管你做的是哪个垂直领域知识问答技能都是最值得投入的方向因为它的替代价值最明显原本需要一个人天天盯着社群、邮件、工单来回答各种重复问题现在一个高质量的问答技能就能扛住大部分标准场景。5.4 自动化流程中的多技能串联当你手头的技能积累到一定程度自然而然就会开始做跨技能的流程编排。比如客服场景里用户来了一个问题 → 先调分词理解技能 → 再调知识库检索技能 → 然后调工单处理技能 → 最后调消息回复技能这就是一个完整的技能编排链路。我建议在做了3到5个独立技能之后就主动设计一条旗舰流程把其中几个技能串起来做一个完整的业务闭环。原因有两个。一个是验证架构多技能串联能暴露数据契约、编排器决策、上下文管理这些单技能状态下发现不了的问题早暴露早修复。另一个是验收价值一个完整的流程比单个技能更容易向业务方展示成果有了能跑通全链路的Demo后续争取资源会顺利得多。串流程时把握一个原则**每个环节只做一件事且对这件事有清晰的输入输出定义。**如果某个环节的内部还要拆成好几步就要考虑它是不是也配得上拆成多个技能。技能拆分的颗粒度和一个函数只做一件事是同一个道理粒度太粗会让复用难粒度太细会让编排乱找到平衡点是门手艺多试几次就能摸到感觉。我自己的体会是技能层最大的价值不是让Agent变聪明而是让Agent变得可控和可积累。聪明是模型带来的不可控可控才是你做工程的人该操心的事。技能把一次次的模型调用变成了一个个标准化的能力资产让团队的每一次调优、每一个踩坑经验都能沉淀下来而不是随风飘散。最后再分享一个小技巧**从你复制粘贴最多的那一段处理逻辑开始做你的第一个技能。**找到那个让你每次写项目都重复一遍、还每次都会出点小问题的工作把它包装成技能。做完之后你大概就能直观感受到什么叫技能层的威力了。