最近 AI Agent 圈子里“Skill”几乎成了和“Tool”一样高频的词。你看社区里到处是“Cursor 有哪些 Skill 推荐”“Claude 怎么写一个完善的 Skill”“Codex 的绘图 Skill 怎么配”但你要是追问一句“Skill 和 Tool 到底有什么区别”大部分人是答不上来的。我自己从年初开始给 Agent 项目引入技能库中间把这两个概念来回揉了好几遍踩了不少坑才真正理清楚。今天这篇就聊聊这个看似基础、实际卡住很多人的问题Skill 为什么不同于 Tool以及在此基础上Agent 技能库的自演进和动态加载机制到底该怎么设计。先说结论Tool 是一个函数Skill 是一套方法论。很多人把 Skill 当成“更复杂的 Tool”或者干脆当成“Tool 的另一个名字”这个误解会在你做技能库的时候带来连锁问题——技能设计得不像技能加载策略也用不上最后系统变成一堆工具的堆砌谈不上任何演进能力。1. 先搞清楚Skill 和 Tool 到底差在哪1.1 从一次失败的功能调用说起我先描述一个很典型的场景。你写 Agent 时最早接触的概念大概率是 ToolOpenAI Function Calling 出来之后大家都习惯了给模型注册几个 JSON Schema让它自己去决定调用。你注册了search_on_web、write_file、run_code模型看着用户的问题选一个执行。这套逻辑理解成本极低用起来也不容易出大错但它的上限非常明显你的 Agent 永远只会做这三件事不会多也不会少。Skill 的思路不一样。Claude Code 引入 skill、Cursor 现在也有类似的目录结构它们核心逻辑是一致的把“一件完整的事应该怎么做”描述清楚而不只是提供一个孤立动作。一个 Tool 解决“怎么打开网页”一个 Skill 解决“怎么完成一次靠谱的竞品调研”——后者包含了检索词的构造方法、信息来源的选择、交叉验证的步骤、报告输出的结构甚至常见坑的规避方式。我见过不少项目把 Skill 写成“把五个 Tool 塞进一个 JSON”然后告诉模型“这几个函数你看着用”。这不叫 Skill这叫函数分组。真正的 Skill 必须有过程性知识而 Tool 只有原子能力。1.2 粒度不同Tool 是螺丝刀Skill 是拆机流程我常用一个生活类比来解释粒度差异。Tool 是工具箱里的一把螺丝刀它只负责“拧”这一个动作输入是螺丝型号输出是扭矩。Skill 则是你用螺丝刀拆一块显卡的整套流程先断电、判断哪几颗螺丝、按什么顺序拧、用多大力道、拧下来的螺丝放哪个格子、遇到滑丝怎么处理。这个类比能引出 Skill 和 Tool 最核心的三个分界线维度ToolSkill粒度原子操作单一动作复合能力包包含多步流程和决策规则状态无状态每次调用相互独立可以有状态记录进度、中间结论、已排除的错误分支描述方式JSON Schema 结构化参数自然语言工作流 脚本 参考资料能力边界固定写死就是写死可演进可从失败中增补步骤触发方式模型按需直接调用先检索、再加载、再执行这幅表格里的最后两行其实就是标题里“自演进”和“动态加载”的伏笔。Tool 是固定的所以它不需要演进也没法演进Tool 数量有限所以它也不需要动态加载一次性全注册给模型就行。但 Skill 不一样它的数量和复杂度会增长而且它需要在实践中不断调整自己。1.3 本质分水岭Skill 是有状态、可演进的我再展开说说状态性。一个 Tool 调用web_search(query)发出去就结束了不需要记住“我刚才搜过什么”。但一个 Skill“分析用户反馈”执行到一半它必须要知道已经读完了哪三个文件、情感分类做到哪一步、目前发现的主题有哪些、下一步该调用哪个聚类脚本。这些状态如果每次都要模型从零开始推理token 消耗大还容易错。所以我设计 Skill 的时候会把“工作记忆”作为一等公民。Skill 的元信息里带一个current_progress字段每当执行完一个阶段就更新一次。这样 Agent 哪怕中途被打断、或者上下文被压缩恢复之后还能接着干。这个设计 Tool 是做不到的因为 Tool 没有“阶段”的概念。可演进就更关键了。Tool 的 bug 修一次就完了逻辑是内存里写死的Skill 则是一个可以持续修改的文档加脚本组合。你今天发现这个 Skill 的流程漏了一个“数据去重”步骤第二天就可以把这一步补进 SKILL.md之后所有加载这个 Skill 的 Agent 行为都会跟着更新。这种“行为会变”的特性就是后面讲自演进机制的地基。2. 代码层面的差异从 JSON Schema 到技能描述2.1 Tool 的接口长什么样先看一段最常见的 Tool 定义这是 Function Calling 里一个标准 Web 搜索工具的写法tools [ { type: function, function: { name: web_search, description: 执行一次 Web 搜索返回前10条结果, parameters: { type: object, properties: { query: {type: string, description: 搜索关键词}, max_results: {type: integer, default: 10} }, required: [query] } } } ]这套结构的本质是给模型一份“可调用函数清单”。模型读到的信息只有函数名、一句话描述、参数约束。它不知道这个函数内部怎么工作也不知道什么时候该优先用它更不知道用了之后结果该怎么解读。这些高层决策目前还是靠模型的通用推理能力硬扛的。当你的项目只有三五个 Tool 时这种做法完全够用。但当你开始积累几十个 Tool问题马上来了模型的选择准确率开始往下掉经常在参数上传错、或者调了 A 工具其实应该调 B 工具。这时候你就需要一个中间层把“选哪个工具”的决策变成“用哪套流程”的决策。2.2 Skill 的目录结构长什么样我现在项目里的 Skill 组织方式参考了 Claude Code 的 skill 写法又加了点自己的约束。一个典型的 Skill 长这样user-feedback-analysis/ ├── SKILL.md ├── scripts/ │ ├── sentiment.py │ └── cluster_topics.py └── references/ └── report_template.mdSKILL.md 是核心它用自然语言描述完整工作流。我一般要求它必须包含以下几个字段--- name: user_feedback_analysis description: 对用户反馈文本执行结构化分析输出情感分布、主题聚类和改进建议 triggers: - 分析用户反馈 - analyze user comments - 用户评价聚类 --- ## When to use 当用户要求分析评论、反馈、工单或需要从非结构化文本中提取洞察时。 ## Workflow 1. 读取原始反馈数据使用 read_file 或 fetch_data 2. 调用 scripts/sentiment.py 对每条反馈做情感分类 3. 调用 scripts/cluster_topics.py 做主题聚类 4. 汇总成表格报告输出到 write_file ## Error handling - 数据文件不存在先搜索本地目录不要直接报错 - 情感分类置信度低于 0.6标记为 uncertain归入待复核列表你可以对比一下Tool 的 JSON Schema 里只有“输入输出”而 SKILL.md 里有触发条件、执行顺序、错误处理、产出格式。模型加载这个 Skill 之后它不只是多了一个函数而是知道了“做这件事的标准流程”。这种描述驱动的好处在于把不可见的推理过程变成了可见的流程文档。你可以直接审视这个 Skill 写得对不对可以在失败之后精准地修改某一处步骤而不用翻代码。2.3 为什么是“SKILL.md scripts references”三段式我解释一下这个结构为什么值得参考。SKILL.md 承担叙事层负责让模型理解整体流程和决策逻辑scripts 承担确定层比如聚类算法、情感打分这类稳定的逻辑不应该让模型每次临时自由发挥references 承担知识层提供特定领域的背景资料或产出模板。模型是语言模型不是代码解释器所以叙事层的质量直接决定它执行得有没有章法脚本可以把容易出错的数值计算固定下来避免模型幻觉参考资料则可以控制知识注入的时机——不是一开始就全塞进去而是流程走到某一步需要时再读。这三个层次互相配合Skill 才有灵魂。3. Agent 技能库为什么要“自演进”3.1 静态技能库的三个痛点先说自演进之前静态技能库到底痛在哪里。第一个痛点是长尾能力永远覆盖不全。你不可能在上线前把所有任务场景枚举完真实世界里用户的问题总会在某个角落超出你预设的范围。第二个痛点是冷启动阶段技能是抄来的——社区里一堆人做的“推荐 Skill 包”本质上都是别人方法论适合别人场景不代表适合你必须跑起来后针对自己领域修正。第三个痛点最实际上下文窗口和 token 成本不允许你塞下满满的技能文档。当技能库超过二三十个你就已经被迫开始做取舍了而这个取舍不该靠手工完成。这几个痛点指向同一个答案技能库必须能在运行中自己“长出”新技能、修订旧技能、淘汰过时技能。这就是自演进的价值。3.2 自演进的基本循环观察、反思、生成、验证、入库我给自己的 Agent 设计了一套五个阶段的演进循环跑下来小半年效果还不错观察Observation每个任务执行完把完整的执行日志留存下来包括任务目标、实际动作序列、每步的结果、最终是否成功、失败时的错误信息。反思Reflection用反思模型判断失败根因。是“缺少某个步骤”“步骤顺序不对”“领域知识不足”还是“模型本身幻觉”。这个分类很关键因为只有根因是前三类时才适合通过修改 Skill 解决。生成Generation根据根因生成补丁。缺步骤就往 Workflow 里加一步顺序不对就调整 Workflow 的步骤编号知识不足就补 references 里的资料。验证Verification拿历史成功任务当回归集跑一遍修改后的 Skill确认没有破坏原本能跑通的场景。入库Registration通过验证后更新 SKILL.md 或 references同时更新技能库索引。这里最关键的一条经验是自演进的关键不是“生成”而是“评估”。大模型生成一个新 Skill 太容易了难的是判断这个 Skill 到底该不该存在。我看有的朋友做的 Agent 跑一天就多出两三百个 Skill每个描述都写着“处理各种问题”最后检索时全是噪音根本没法用。我后来给自己的库定了几条硬门槛提示新 Skill 必须让某类任务的成功率相对提升10%以上才允许入库连续10次执行无失败记录的旧 Skill可以降低它在前置检索中的权重连续20次未被加载的 Skill自动进入待清理名单。这套规则让技能库保持克制进化出来的都是真正经历过实战检验的能力而不是反思模型的胡思乱想。3.3 一次失败记录长什么样自演进依赖结构化日志我记录失败事件的格式大致如下{ task: 分析某产品的用户反馈, action_sequence: [read_file, fetch_data, write_file], failure: 产出报告未覆盖负面情绪条目, root_cause: 缺少情感分类步骤, patch: 在 SKILL.md Workflow 第2步后插入 sentiment.py 调用 }有了这种记录演进就变成了一个可追溯的过程。你能清楚知道哪个 Skill 在哪次任务上跌倒过、补了什么内容、补完之后效果如何。这套日志也是后面动态加载优化的重要数据来源。4. 动态加载机制怎么让几百个技能不撑爆上下文4.1 为什么必须动态加载技能库一旦超过三五十个把所有技能的描述一次性塞进系统提示词就不现实。一个中等规模的 SKILL.md 约 2000 token50 个就是 10 万 token这还不算脚本和参考资料。每轮对话都支付这么大的成本速度慢、费用高而且模型注意力被大量不相关内容稀释选择准确率反而下降。所以动态加载不是“高级功能”而是技能库规模化的必然选择。核心思路就一句话每次只往上下文里注入最可能解决当前任务的 Skill任务结束或不再相关时再撤下。4.2 一个可落地的五段式加载流程我自己的实现是这样的索引层Index每个 Skill 维护一份 profile包含标识、功能描述、触发关键词、依赖的工具列表、embedding 向量。加载时只读 profile不读 SKILL.md 全文这样索引层可以做到非常轻量。意图解析Intent Parsing从用户请求和当前 Agent 状态抽取任务描述生成检索 query。召回Recall组合三种策略——向量检索算相似度拿 top-N、关键词来自 profile 里的触发词精确命中、规则匹配看当前阶段适合哪些技能。精排Ranking对候选技能打分综合向量相似度、历史成功次数、被加载后的任务完成率最终选 top-K 注入我一般设 K 为 3 到 5。执行与回收Execute Recycle加载后交给模型执行任务完成后把完整技能描述撤出上下文只保留必要的记忆摘要。这个流程的一句话版本是把技能库当知识库用不是把全部文档发给模型而是先检索出最相关的几份再让模型精读。这和 RAG 的哲学完全一致区别在注入的内容不是纯知识文本而是一整套带工作流的方法论。4.3 依赖关系和常用技能的缓存优化动态加载里最容易忽视的是 Skill 之间的依赖。有些 Skill 执行到中间需要调用某个公共工具如果这个工具没有同时加载流程就会卡住。我的做法是每个 Skill 的 profile 里显式声明dependencies字段加载时先递归把依赖一起加载确保整套流程能跑通。另外一个优化策略是把高置信度常用技能做成常驻缓存。比如“需求分析”和“报告生成”这类几乎每个任务都会用到的 Skill不需要每次动态检索直接压在系统提示词里。剩下的长尾技能才走动态加载检索压力会小很多。这个“常驻 动态”的混合模式是我实测下来性价比最高的组合。4.4 动态加载的动态回溯动态加载不只是静态的“检索一次、加载一次”。我后来加了一层基于反馈的自我修正某个 Skill 被加载后如果任务成功给它一个正向权重加成如果失败权重降低。这个权重直接影响下次检索排序。时间一长技能库本身就会形成一种“好用的技能靠前、不好用的技能靠后”的状态这算是一种微观层面的自演进。用一段 Python 伪代码可以概括完整流程def dynamic_load(user_input, library_index, k5): candidates semantic_search(user_input, library_index, top_kk*3) keyword_hits keyword_trigger(user_input, library_index) merged merge_score(candidates, keyword_hits) selected top_n(merged, max_numk, weight_boostTrue) injected [lib[skill_id].compile_for_prompt() for skill_id in selected] return injected这个 70 分的基础实现已经能解决 80% 的问题剩下的 20% 都是边界情况和工程细节下面专门讲。5. 从设计到落地我踩过的四个典型坑5.1 工具注入太多触发 tool-call flooding有一个坑我印象特别深技能库上线第二周系统突然频繁报“tool call cancelled because tool-call flooding was detected”。排查了半天才发现某个 Skill 的依赖声明写得太宽泛一次加载带了 15 个工具进来。模型一下子看到太多可选工具一次请求里发了几十个 tool calls直接把框架的保护机制打爆了。解决办法有两层。第一层是把同时注入的工具数量限制在 5 到 8 个宁可让 Skill 内部多步串行调用同一个工具也不要一次性开放所有权限。第二层是要求 Skill 内部步骤设计成顺序依赖——第 1 步完成并写入状态之后第 2 步才可见对应的工具从机制上逼着模型按流程走。5.2 Skill 描述与用户问法对不上检索召回率低第二坑是“写了 SKILL.md 但检索不到”。有一次我写了个“数学建模 Skill”profile 里用的全是数学术语结果用户在 Cursor 里问“帮我建个模型预测销量”向量检索出来的 top-5 根本不含这个 Skill。原因很纯粹profile 的关键词和 embedding 描述没有覆盖用户可能用的日常表达。解法是在 profile 里维护一个synonyms字段把领域术语、口语说法、中英文表达都写进去。现在我的规则是写 profile 时至少列 5 个同义触发表达并且用真实用户问题做过一轮测试确保能召回。这一步看着不起眼实际上对动态加载的命中率影响最大。5.3 自演进失控技能库从 8 个膨胀到 150 个这个坑前面提到过我再细化一下。我的一个实验 Agent 跑了 48 小时技能库从 8 个涨到 150 个中间大量技能功能重叠甚至有 20 多个技能描述都是“处理各类任务”。复盘后发现反思模型太“积极”遇到一点小失败就生成新 Skill而不是先尝试修订现有 Skill。我后来加了三条硬约束才止住膨胀一候选 Skill 在生成时必须和现有库做相似度对比阈值过高直接拒绝入库二设置单库上限比如 60 个超出的必须淘汰库里已有 Skill 才能放新的进来三每个新 Skill 入库前用 5 个历史真实任务做回归测试跑不过就重写。这三条加上之后技能库的规模就平稳下来了质量和有效加载率反而上去了。5.4 “需要立即结果”的调用被动态加载的延迟拖垮还有一个很隐蔽的坑群体热词里有个常见报错叫“messages tool calls need immediate results”大意是模型发出了某个工具调用但框架要求它立即返回结果而技能库动态加载本身有延迟导致调用被判定为超时或取消。这类问题本质上是加载时机设计失误。我自己的修正方案是把高置信度常用技能做成常驻缓存避免每次从磁盘读取和 embedding 检索同时在意图解析阶段就预加载候选技能而不是等模型生成 tool call 时再临时加载。也就是说把动态加载从“模型决策后”提前到”意图明确后“把延迟从关键路径上挪走。这个调整之后类似的“调用无法立即满足”的问题基本绝迹。6. 最后的一点经验沉淀Skill 和 Tool 的区别本质上是“能力”和“方法论”的区别。Tool 在解决“能做什么”Skill 在解决“该怎么做得靠谱”。一个只有 Tool 的 Agent 像一个什么都会一点但没条理的新手一个有成熟 Skill 库的 Agent 像一个有标准操作程序的老工程师。如果你现在正在做 Agent我的建议是先别急着收藏一堆网上推荐的 Skill 包先把手头能稳定执行的几类任务沉淀成 Skill跑一周看看哪些步骤容易出错、哪些决策需要人工介入再动手优化。技能库的自演进和动态加载不是一开始就要做得很复杂的东西——它是你的库长到一定规模之后自然产生的需求。真到了那一步你会发现前面聊的这些机制每一条都是从实际问题里长出来的一个都不会白做。
企业数字化 ERP 产品动态
相关推荐
Pi Agent vs Claude Code:智能体编排如何重构开发范式 1. 从“代码助手”到“智能体编排平台”:一次开发范式的悄然迁移 最近在几个技术社区里刷到一个高频问题:“Claude Code用着挺顺,怎么突然发现团队里一半人换成了Pi?”起初我以为是某个新出的轻量级IDE插件,结果点开链… · 2026/11/3 8:56:44
免费音视频字幕工具:自动转写与时间轴同步技术解析 1. 项目概述 作为一名长期与音视频打交道的创作者,我深知字幕制作这个环节有多折磨人。传统字幕制作要么需要反复暂停视频手动输入,要么依赖收费软件,效率低且成本高。今天要分享的这个工具彻底改变了我的工作流——它不仅能自动将音视频转为… · 2026/11/3 8:56:44
百度地图Map Skills:自然语言生成地图API代码实践 1. 项目背景与技术定位去年夏天我在参与一个物流路径优化项目时,曾花费整整两周时间手工标注了几百个特殊路况点。当时就在想:如果能用自然语言描述需求,让AI自动生成地图标注代码该多好?百度地图最新推出的Map Skills功能&#x… · 2026/11/3 8:56:44
SenseNova-Vision-7B-MoT进阶技巧:处理复杂视觉推理任务的完整解决方案 SenseNova-Vision-7B-MoT进阶技巧:处理复杂视觉推理任务的完整解决方案
SenseNova-Vision-7B-MoT是一款强大的视觉推理模型,专为处理复杂视觉任务设计。本文将分享一系列实用进阶技巧,帮助您充分发挥该模型的潜力,轻松应对各类视觉… · 2026/11/3 9:27:16
(最新)基于Springboot知识产权管理系统【附源码+文档】 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:27:16
【系统架构设计(35)】TCP/IP协议族详解 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:27:16
BFS-Best-Face-Swap:革命性AI换脸工具,5分钟掌握高质量面部交换技术 BFS-Best-Face-Swap:革命性AI换脸工具,5分钟掌握高质量面部交换技术
想要体验专业级的AI换脸效果却不知从何入手?BFS-Best-Face-Swap为你提供了终极解决方案!这个基于先进AI技术的面部交换工具,能够在短短几分钟内完成… · 2026/11/3 9:26:15
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46