为什么我给智能体做了一套“技能库”而不是写一堆Prompt做AI Agent开发这段时间我踩过最深的坑就是看着模型一本正经地“表演”干活最后却给我返回一堆毫无用处的文本。你问它今天天气它能给你写一篇80字的作文你让它查个数据库它能编出一个不存在的表结构。问题的根源不在于模型本身笨而在于我们根本没有给它一套“能动手”的技能。这也是为什么我最终把项目的核心收敛到agent-skills这个方向上不再追求让模型“理解一切”而是把能被验证、可被重复调用的能力打包成插件式的技能库塞给Agent去用。这事听起来不难实际操作里坑很多。今天把这套思路和落地过程整理出来分享给那些正在做智能体、或者在纠结“为什么我的Agent像个嘴强王者”的朋友。尤其是当你发现光靠堆Prompt描述工具怎么用根本不靠谱的时候这套技能库的方案基本能帮你省掉大半的调试时间。1. 技能库到底是什么为什么强调“可执行”先聊个基础问题Agent和普通聊天机器人最大的差异在哪普通聊天机器人只需要“说”Agent必须去“做”。而“做”就要求Agent底层的模型不仅仅是在生成文本它需要有能力调用外部函数、读取返回结果、再基于结果继续决策形成一个闭环。这个闭环里面最关键的一环就是把“模型想做的事”翻译成“系统能执行的指令”。agent-skills做的事情就是把这一环标准化。1.1 技能不等同于API封装很多人听到技能库第一反应是这不就是封装一堆API给模型调用嘛。这个理解对了一半但远远不够。API封装只解决了“能调用”的问题而技能库要解决的是“会使用”“用得好”的问题。举个实际例子。你给模型开放一个“获取用户订单列表”的API模型确实能调但模型怎么知道什么情况下该调这个API而不是去猜怎么知道调用之前要确认用户身份怎么知道拿到数据之后是该用表格展示还是总结成几句话这些知识写在Prompt里容易糊写在代码里又不够灵活最优雅的载体其实就是“技能”。一个合格的技能至少要包含三部分一段让模型理解的“何时用、怎么用”的说明。一段让系统执行的代码或命令。一套用于校验输入、兜底异常的机制。第一点是给模型看的第二点才是真正干活的第三点则是保证稳定性的护城河。而且这三部分最好是独立成文件、按目录结构组织而不是一股脑扔到Prompt字符串里。1.2 为什么不是让模型“自由发挥”坦率讲现在的模型能力已经很强了尤其是代码生成能力你给它一个任务它确实能直接写代码去实现。那还要技能库干什么我的观点是确定性。模型自由发挥意味着每次生成的代码都可能不一样哪怕功能相同写法、参数、边界处理都可能千差万别。这在生产环境是致命的。你没法测试、没法审计、没法在出问题时兜底。而技能库是把“不确定性”压缩到最小执行体是固定的模型只在“选择哪个技能”和“填入什么参数”这两个环节做决策。这相当于把模型从“全栈工程师”降级为“调度员”听起来好像能力变弱了但实际上整个系统的可靠性、可维护性都大幅提升。打个比方你请一个实习生干活你不放心他直接上手写业务代码而是把一套封装好的工具函数给他告诉他“你要做数据分析就调这个函数把参数填对就行。”这个实习生只要做选择、填参数出错的概率自然就低很多——你要的核心就是这个。1.3 这套方案想要解决的问题清单项目定位搞清楚之后我把agent-skills的目标明确为下面这张问题清单模型不会正确选择工具干脆把“选择逻辑”固化为场景描述让模型按匹配度判断。模型填的参数不规范用JSON Schema约束校验不通过直接返回重试不让脏数据进入执行层。技能无法复用把技能做字节码级独立一个技能装在多个Agent里共享外部不感知。执行结果无法反馈每次执行明确返回结构化结果供模型继续推理或直接呈现给用户。新增技能成本高新增一个技能只需新写一个目录、两个文件无需改Agent主框架代码。这五条基本就是宽泛的Agent项目里最常踩的坑。把这些问题解决掉Agent的可用性会上一个台阶。2. 技能库的整体设计与技能格式接下来是干货部分。项目的核心目录结构设计其实不复杂难的是想清楚每一层的边界到底在哪里。2.1 技能的长相目录即技能在agent-skills里一个技能就是一个独立的目录目录下面有几个约定好的文件。我目前用的结构是skills/ json-to-table/ SKILL.md skill.py schema.json test.jsonSKILL.md描述这个技能是干什么的、什么时候用、参数怎么写这段内容是会完整暴露给模型的所以语言要精准、结构化。skill.py真正的执行逻辑也就是技能落地时跑的代码。schema.json对外部传入参数做校验的JSON Schema定义。test.json一组自动化测试用例用于在技能发布前校验执行逻辑没有跑偏。这套结构受到社区里一些开源方案的启发比如Claude官方文档里推荐的Project Skills结构。我实测下来按这个模板来组织确实足够清晰既照顾了模型的阅读理解也方便工程师维护代码。更关键的是每个技能自带test.json这件事帮我排掉了大量低级错误“技能能跑”和“技能能正确执行”之间就差这一组测试。2.2 SKILL.md写给模型看的说明书这是整个技能库里最容易糊弄、也最值得花心思的文件。我见过不少人写SKILL.md就是把接口文档复制一遍扔进去这是不对的。模型读技能描述就像面试官看简历你写得再详细都没用关键在于信息密度和匹配效率。我总结了一套写法开头一句话说明技能用途包含动作和对象例如“将JSON数组转换为Markdown表格”。参数说明列出每个参数的类型、必填性、默认值、取值范围。使用场景写清楚“当用户提到X时使用本技能当Y时不要使用”这一步能大幅降低模型乱选技能的概率。注意事项执行边界、权限限制、耗时情况等该说的提前说。举个例子正在开发的一个查天气的技能SKILL.md里面会写明“本技能仅支持查询中国城市天气参数city需要是城市中文名省市区不需要查询失败时返回error_code而非抛出异常”。这样模型在决定是否调用时就有了足够的判断依据。2.3 schema.json给参数上个保险模型填参数很多时候是“看着对实际错”。比如用户说“帮我查一下北京和上海的天气”模型可能把参数填成[北京, 上海]但接口只需要单个城市名这时候就需要服务端循环调用而不是一次性传入数组。如果不在Schema层卡住脏数据就会一路穿透到业务代码里面。schema.json基于JSON Schema标准我用的是draft-07版本兼容性和社区支持都比较好。举一个实际例子{ type: object, properties: { city: { type: string, description: 城市中文名例如北京、上海, minLength: 2 }, days: { type: integer, description: 预报天数, minimum: 1, maximum: 7, default: 3 } }, required: [city], additionalProperties: false }注意两点。第一additionalProperties必须设成false否则模型填一个Schema里不存在的字段你也不好拦。第二default要显式给出模型有时候会在可选项上偷懒不填有默认值可以减少一次往返纠错。2.4 执行体怎么写执行体是技能的核心建议保持纯粹只做一件事情输入参数进来输出结果回去不要在技能内部掺杂复杂的业务编排。凡是涉及多个步骤的业务流程应该由Agent主逻辑去编排多个技能而不是在一个技能内部做长流程。还有个细节——超时控制。每个技能的execute方法必须带 timeout避免某个外部服务卡死拖垮整个Agent响应。我一般设置10秒就够超过就抛超时异常由上层决定重试还是降级返回。3. 实操记录从零手写一个json-to-table技能空谈概念没意思拿一个已经实现并跑通的技能来做例子json-to-table。这个技能解决一个很痛的问题——模型直接输出JSON数据给用户人类看得眼花缭乱如果转成Markdown表格体验会好很多。3.1 声明文件先让模型知道有这个东西我在SKILL.md里的完整描述是这样的# 技能JSON转Markdown表格 将JSON数组或对象数据转换为美观的Markdown表格。 适用场景 - 用户提供JSON数据并要求生成表格 - 查询数据库后结果以JSON数组返回需要展示为表格 - 用户要求对比多个方案、产品参数时数据以结构化JSON传入 不适用场景 - 数据本身是文本描述而非数组或对象 - 用户要求生成图表而非表格 参数 - data: 必填JSON字符串或对象表示要转换的数据 - headers: 可选字符串数组指定展示列的顺序和名称 - emptyCellPlaceholder: 可选默认 -用空格替换空单元格的填充值这一段写完之后我不是一次性定稿的而是在实际跑通十几个不同形态的用例之后回填修改的。尤其是“不适用场景”那一行是我后来才发现必须加上去的——不加的话模型会把任何带点数据的请求都往这个技能里塞。3.2 执行逻辑Python实现执行代码本身不复杂但有几个细节值得注意。核心函数是接收data参数如果是字符串就json.loads成Python对象然后根据类型分情况处理。数组就遍历对象就取它所有键做成表头值统一转字符串。最终输出是Markdown格式用|分隔列---分隔表头和数据行。实现得很朴素大约40行代码但加上typing、异常捕获和类型保护就有将近80行了这80行换来的是不同数据形态下都不崩。3.3 校验与测试上线前必须过一遍test.json我要重点说一下。一个没有测试的技能就像一个没有测试的PR合并上线全凭信仰。我的测试联通方式是写三个用例正常场景合法JSON数组断言输出包含表头和数据行。边界场景空数组断言返回“无数据”的提示文本而不报错。异常场景传入非法JSON字符串断言返回包含“解析失败”的错误码。然后跑一个简单的pytest命令把这几个用例过一遍。这个过程看似多花了5分钟但实际省下了我大量后期联调时间。技能挂到Agent上之后模型调用出问题我第一件事就是跑测试文件确认执行逻辑没毛病再去排查模型理解的问题——这种分层排查效率特别高。3.4 技能发布把文件路径登记到库里写完了不等于接入成功了还需要在技能库的注册表里面登记。我用的是一个很轻量的方式在skills/registry.json里面维护一个技能名到目录路径的映射{ json-to-table: { path: skills/json-to-table, description: 将JSON数据转换为Markdown表格, version: 1.0.0 } }这样Agent在启动时读取注册表加载所有技能描述到上下文里模型在需要时点名某个技能框架再从对应目录动态导入执行模块。整个过程下来新增一个技能的边际成本压到了大概30分钟——20分钟写代码5分钟写描述5分钟跑测试。4. Agent内核如何把技能调度起来技能本身做得再漂亮Agent不知道怎么调度也白搭。这块的架构设计是agent-skills真正花心思的地方。4.1 从“会调用”到“会编排”早期版本的Agent内核我给模型暴露的是一个大而全的函数列表。每轮对话模型都在一堆函数描述里挑看着理想实际上模型很容易被无关函数的描述干扰尤其是函数数量超过20个的时候选错函数的概率显著上升。切换到技能库思路之后我调整了策略模型看到的不是“函数列表”而是“技能卡片列表”每个卡片对应一个技能卡片上的文字要像工具操作手册里的章节标题摘要一样短而有力。模型根据当前用户意图挑选匹配的技能卡再通过一个统一的入口execute_skill(skill_name, params)来执行。这一步改动带来的提升是非常直观的函数调用的准确率从之前的约82%提升到94%以上。原因也很简单模型做选择题比做阅读理解要稳得多。4.2 调用协议全程JSON所有技能都通过JSON来交换数据包括请求参数和返回结果。这个设计一开始有点“为了统一而统一”的意思但用久了发现它带来的收益非常大调试方便、日志可读、链路追踪简单。调用协议长这样{ request_id: b3c8a1f2e5d6483a, skill: json-to-table, params: { data: [{name: 张三, age: 28}, {name: 李四, age: 35}] } }返回协议{ request_id: b3c8a1f2e5d6483a, success: true, output: | name | age |\n| --- | --- |\n| 张三 | 28 |\n| 李四 | 35 |, elapsed_ms: 12 }success、output、elapsed_ms这三个字段是必要的。success让模型知道这次调用是否成功决定下一步是继续、换方案还是告知用户失败。output是给模型阅读的结果文本elapsed_ms则是给工程师的性能参考。4.3 参数错误时的兜底策略技能执行发现参数校验不通过应该怎么做很多方案是直接报错返回把错误堆栈丢给模型让模型“看着办”。这个做法不太稳定模型可能反复用错误的参数重试浪费时间。我的方案是在校验不通过时返回一个结构化的fix_hint字段比如{ success: false, error_code: PARAM_VALIDATION_FAILED, fix_hint: 参数city必填当前为nulldays取值范围1-7当前为10 }实测下来模型看到fix_hint之后修正参数的正确率可以到九成以上。这相当于给模型配了一个“实时导师”比让它自己反思靠谱得多。4.4 多技能组合的编排策略实际使用中一个复杂的用户请求往往要跨多个技能。比如“帮我把这周的销售数据拉出来按产品汇总做成表格”——这个请求至少涉及“查询数据库”和“JSON转表格”两个技能。顺序怎么排谁先谁后我的实现策略是第一阶段模型先在技能库里选出可能的技能集合第二阶段模型给出执行顺序形如[query_database, json-to-table]第三阶段框架按顺序逐个执行并把前一个技能的结构化输出注入到后一个技能的params里。这套策略虽然简单但成功解决了“长任务编排”需求里80%的情况。剩下20%的复杂流程靠的是人工预先写好流程模板把“技能执行顺序”固话下来而不是让模型每次临场发挥。5. 常见问题与排查技巧实录做这套系统的过程中我记录下了大家问得最多的几个问题这里整理成速查表。5.1 模型总是不按技能卡来乱选技能这是最常见的问题。排查思路按照优先级来首先看SKILL.md的描述是否足够区分度。比如两个技能都涉及“查询”一个查天气一个查库存描述里如果都写“查询数据”模型自然分不清。我踩过一次坑查询天气的技能因为描述里带了“实时数据”四个字模型在用户问“帮我查一下最新库存”时也选中了它。后来我把描述改成了“查询城市天气预报数据参数city为城市中文名”区分度立刻上来了。其次看技能总数。技能库超过15个之后模型的选择难度会显著增加建议做一层“技能分组”先让模型选组再在组内选技能。相当于从一次选择题降为两次每次选项变少准确率自然提高。还有一种情况是模型压根看不到技能描述。检查一下你的SKILL.md是否真的被加载进了Prompt有些时候因为token限制描述被截断了模型只看到了半截话这也会导致乱选。5.2 技能能跑但结果不理想执行成功不等于结果正确。这类问题建议直接看测试用例覆盖是否充分。我在test.json里除了写正常用例还会专门写一些刁钻用例比如输入数据包含嵌套对象表格怎么展示输入数据里中文字段名和英文字段名混着来表头是否正常数据数组里有100条记录输出会不会爆token这些都是实际场景里真实出现过的。当你发现技能执行结果不对时第一件事是回到测试用例去补一个复现用例修复后跑回归再挂回Agent上验证。5.3 模型知道用技能但参数填不准这个问题的根源多半在schema.json写得不够清楚。尤其是参数描述你写“city: string”模型可能填“北京上海”你写“city: 城市中文名单城市例如北京”模型就能给对。别嫌啰嗦模型不是在读代码它是在读“人话”说清楚一点没坏处。另外如果你发现某个参数模型反复填错可以先在scheme.json里收紧约束比如枚举允许值、设置pattern正则从物理上堵住错误的可能而不是期望模型自我修正。5.4 技能之间的并发冲突当多个用户会话同时使用同一个技能而技能执行体里含有共享状态比如全局变量、临时文件就可能出现数据串扰。我遇到过最典型的问题是一个技能把中间结果写到一个固定名字的临时文件里两个会话同时跑的时候互相覆盖导致结果错乱。解法很简单技能执行体要做到无状态一切中间数据通过参数传递不在技能内部保留全局可变数据。如果确实需要临时文件文件名必须带上request_id这样每个请求都是独立的。5.5 Agent响应太慢技能执行耗时高逐技能计时用协议里的elapsed_ms字段做分析看耗时都花在哪里。我遇到过两类典型一是外呼API的响应慢二是技能内部做了不必要的重试。对于前者建议给外部调用加短超时并增加缓存对于后者检查重试逻辑的退避策略别一失败就秒级重试很容易雪崩。如果Agent整体还是慢可以考虑做技能预热在服务启动时提前执行一次技能内部的初始化逻辑把需要加载的模型、缓存、连接池都准备好首次调用就不会再冷启动卡顿。6. 从“能用”到“好用”的进阶技能库的动态维护最后分享一下自己用了很久才悟出来的一个体会技能库不是一次性建完就完事的东西它更像一个产品需要持续迭代和维护。我在项目里建立了两个机制一个叫“技能命中率周报”另一个叫“技能异常自动上报”。前者统计每个技能一周内被调用的次数、调用成功率、修正率后者在技能执行失败时自动记录错误码和上下文方便后续复盘优化。这两个机制跑起来之后我明显感觉系统的稳定性在往上走。比如有一个技能叫“PDF转文本”上线第一周命中率很高但成功率只有86%查日志发现是某些扫描版PDF没有内嵌文本层用常规库提取出来全是乱码。后来我在SKILL.md里补了一句“如果提取结果包含大量乱码可能为扫描件需要提示用户使用OCR技能”模型的成功率立刻提升到95%以上。这种迭代光靠人工测试是覆盖不到的只有线上数据才会告诉你。另外技能库的扩张也要有节制。我见过有人把技能库做到上百个结果模型选择成本极高系统响应速度也变慢。我更推荐一个比较克制的策略技能数量控制在20个以内把高频、高确定性的能力沉淀为技能低频的长尾需求就让模型用代码解释器临时跑或者干脆接一个人工兜底。让技能库保持精简、高质才符合这套方案的设计初衷。如果你现在也在做Agent还被“模型不好好干活”折磨不妨试试把技能和模型解耦把能固化的能力都固化成技能。这套模式帮我摆脱了“与Prompt搏斗”的泥潭也希望能在你的项目里派上用场。码字不易有问题评论区聊能回的都会回。
企业数字化 ERP 产品动态
相关推荐
Atlas 300V 24G实战:用NPU加速卡部署YOLO推理的全流程指南 前阵子项目做边缘侧视频流目标检测,手里原本用的是GPU,但客户指定设备时偏偏是一块Atlas 300V 24G。拿到卡的第一反应其实和很多人一样:这东西到底算不算运算加速卡?能不能直接把YOLO塞进去跑?后来折腾了几天ÿ… · 2026/9/25 22:25:55
【无标题】27届软件工程找实习总结 很多同学并不是能力不够,而是准备方向和现在企业真正需要的能力出现了偏差。很多计算机学生到了大三、大四,准备秋招的时候,依然把大量时间投入在传统Java项目上,比如SpringBoot商城系统、校园二手交易平台、博客管理系统、后台管… · 2026/9/25 22:25:55
Atlas 300V实战:昇腾AI加速卡上部署YOLO模型全攻略 先回答那个被搜了很多次的问题:Atlas 300V 24G,确实是一块运算加速卡,而且是一块专门为AI推理设计的加速卡。但它和你熟悉的英伟达GPU有本质区别——它不是拿来跑CUDA的,底层走的是完全不同的计算架构和软件栈。很多人第一次接触A… · 2026/9/25 22:25:55
基于PHP的H5转APP在线封装打包平台实现与避坑指南 简介:面向需要把H5手机网站快速封装成安卓和苹果安装包的开发者,这套PHP源码以在线打包方式提供免签绿色封装方案,支持Android与iOS平台。可自行上传安卓证书和启动图,并针对iOS 14全屏兼容问题做了专门修复;同时去除多… · 2026/9/25 23:06:21
GEOFlow API v1开发者完整指南:用REST接口全自动驱动GEO运营工作流 GEOFlow API v1开发者完整指南:用REST接口全自动驱动GEO运营工作流 【免费下载链接】GEOFlow Open-source GEO content engineering and multi-site distribution platform with AI quality inspection, illustrated admin help, hosted sites, browser-assisted pu… · 2026/9/25 23:05:48
8B模型LoRA微调营销文案:数据准备、训练参数与Ollama部署 简介:面向具备机器学习基础的技术人员与市场营销从业者,一套围绕AI模型高效训练的实战指南,核心思路是先借助大型模型生成多样化营销训练数据,再通过Unsloth微调8B小模型,使其在广告文案、社交话题等营销内容生成上接近… · 2026/9/25 23:05:36
基于私有知识库的LLM智能客服问答系统:从RAG到私有化部署实战 简介:这套资源是基于企业私有知识库的大语言模型智能客服问答系统,支持私有化部署,主要面向企业技术团队、AI应用开发者以及需要搭建内部智能问答平台的管理者,尤其适合对数据安全有较高要求的场景。资源包共1302个文件࿰… · 2026/9/25 23:05:29
MaaEnd节点测试教程:如何用测试用例验证识别稳定命中 MaaEnd节点测试教程:如何用测试用例验证识别稳定命中 【免费下载链接】MaaEnd MaaEnd 终末地小助手:基于视觉 AI 的「明日方舟:终末地」自动化工具 项目地址: https://gitcode.com/gh_mirrors/maa/MaaEnd
MaaEnd 是基于视觉 AI 的《明… · 2026/9/25 23:05:29
Apache Pulsar Functions 快速入门实战:从本地运行到集群部署 消息队列后端流处理 【免费下载链接】pulsar Apache Pulsar - distributed pub-sub messaging system 项目地址: https://gitcode.com/gh_mirrors/pulsar28/pulsar 点击查看 免费下载 本指南以 Apache Pulsar 的 Pulsar Functions 轻量级流处理模型为主题ÿ… · 2026/9/25 23:05:29
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37