做 AI Agent 开发这一年多被问得最多的一个问题不是“Agent 怎么搭”而是“Skill 到底怎么写才算好用”。这问题看着简单实际坑特别多。GitHub 上 Agent 框架选型五花八门但真正拉开体验差距的往往不是模型本身而是挂在 Agent 身上的那些 Skill 写得好不好。这篇我把自己的理解和踩坑经验完整梳理一遍从概念到实操尽量一次讲透。这篇内容适合谁正在做 Agent 应用、想给助手加自定义能力、或者刚接触 Skill 开发不知道从哪下手的开发者。读完你至少能明白三件事Skill 的边界在哪、描述文件怎么写模型才不迷糊、核心代码要注意哪些坑。1. 先搞清楚Skill 在 Agent 体系里到底扮演什么角色1.1 Skill 和 Agent 的关系别搞反了先说结论Agent 是执行者Skill 是能力包两者是“调用”和“被调用”的关系不是平级关系。我用个比较好懂的类比。Agent 就像一个刚入职的新员工脑子聪明大模型学习能力强但没有任何岗位经验。Skill 就是给这个新员工的操作手册和工具包——告诉他“遇到什么情况翻开哪一页按什么步骤操作”。没有 Skill 的 Agent 也能干活但只能干一些通用的事比如闲聊、套模板、简单推理。一旦涉及专业场景比如“解析这份财报并提取关键指标”“把这段音频转成带时间戳的文字稿”没有对应 Skill 的 Agent 就会开始自由发挥结果不可控。这里经常有人把概念搞混把 Skill 当成一个 mini Agent在 Skill 内部写一堆决策逻辑。我的建议是Skill 内部尽量少做“决策”多做“执行”。决策是 Agent 的事Skill 只需要把“怎么做”做到极致。你在一个 Skill 里塞的智能判断越多模型的调用准确率就越低出问题的时候也越难排查。1.2 Skill、Memory、MCP 三者怎么分工现在社区里最火的一组概念就是 agent skill memory mcp很多人搞不清这几个东西的关系甚至觉得它们是同类竞品。其实它们是三个完全不同的层次Skill 管“怎么做”是一段可复用的能力描述加实现代码解决的是“特定任务怎么完成”的问题。Memory 管“记住什么”是 Agent 的长期记忆和短期上下文解决的是“这个用户上次聊到哪、偏好是什么”的问题。MCP 管“怎么连”是标准化的工具接入协议解决的是“Agent 怎么调用外部系统、数据源”的问题。举个例子你就明白了。假设你要做一个“会议纪要助手”。Memory 负责记住每个参会人的部门、项目背景、上次会议遗留事项MCP 负责连接日历系统、会议录制系统把原始材料拉下来Skill 负责把录音转文字、按议程归纳、生成待办清单。三者各管一段缺一不可。如果你把该放 Memory 的东西写进 Skill比如在 Skill 描述里写“用户上次提到过……”那就是把动态信息硬编码进了静态能力里每次还得改文件迟早翻车。同理能通过 MCP 标准协议接入的外部服务也没必要单独包一层 Skill——那等于把标准接口又私有化了一遍维护成本翻倍。记住这个判断顺序能靠 Memory 解决的用 Memory能靠 MCP 连接的用 MCP最后的专业处理逻辑才交给 Skill。2. 好用的 Skill 是设计出来的不是写出来的2.1 先用一句话定义 Skill 的边界我评估一个 Skill 好不好用第一个标准就是能不能用一句话说清楚它干什么。如果一句话说不清那这个 Skill 的边界就有问题。举个反面例子。有人写了个 Skill 叫“数据处理”描述里写“处理各种数据文件包括但不限于 CSV、Excel、JSON、XML、日志文件支持清洗、转换、统计、可视化”。这种 Skill 模型根本不知道怎么用——它面对一个具体任务时要从一大堆“可能”里猜该走哪条路径猜错的概率极高。正确做法是拆。清洗 CSV 是一个 SkillExcel 转 JSON 是另一个 Skill日志统计又是一个 Skill。每个 Skill 只干一件事描述里把“输入是什么、输出是什么、什么情况下用”写死。模型在调用时就不需要做复杂推理直接匹配就行。一句话原则一个 Skill 解决一类问题宁可多写几个不要堆成一个。我在实际项目里见过太多“万能 Skill”最后全都变成了“摆设 Skill”——模型不敢调用调用了也不知道会发生什么。2.2 描述文件是写给模型看的不是写给人看的Skill 的目录里通常有个描述文件比如 SKILL.md这是整个 Skill 的灵魂。很多人把这个文件当成 README 来写写一堆“本 Skill 基于 Python 3.10 开发支持批量处理”这种开发者视角的话。但真相是这个文件的第一读者是模型不是人。模型是通过你的描述来决定“什么时候调用、怎么调用”的。所以描述文件至少要写清楚这几件事触发条件什么场景下应该使用这个 Skill最好给两到三个具体例子。禁用条件什么场景下绝不要用。这一点很多人忽略但恰恰是防止模型乱调用的关键。输入格式每个参数是什么含义、允许的取值、格式要求。输出格式返回什么结构字段怎么定义。注意事项比如依赖外部 API、需要网络、耗时较长等。我给你看一个反例。某 Skill 描述里写着“本工具用于处理日志文件可以实现日志的统计和分析”。模型拿到这个描述面对“帮我看看这个日志里有多少报错”这种任务它会犹豫是调 Skill 还是自己写正则因为描述里没说明输入路径怎么给、输出格式是什么。模型一犹豫就可能做出错误选择。这个问题的根源在于你写的描述是“给自己看的项目说明”不是“给模型的调用指南”。2.3 输入输出设计要给模型留好“抓手”模型调用 Skill 本质上是一个“填参—调用—拿结果”的过程。参数设计得好不好直接影响成功率。我的经验是三个原则。第一参数要扁平。尽量用平铺的独立参数不要搞深层嵌套的 JSON 对象。模型在构造参数时是逐字段生成的层级越深出错率越高。第二输出要稳定。最好定义成结构化的 JSON 或 Markdown让模型能直接消费。第三错误要语义化。Skill 内部报错时返回给模型的不应该是堆栈而是一句人话加一个建议动作。举个参数设计的例子。你做一个“网页正文提取”的 Skill参数设计成{ url: ..., output_format: markdown, max_length: 3000 }就比设计成{ request: { target: { url: ... }, options: { format: markdown, max_length: 3000 } } }稳妥得多。后者在模型眼里就是四个字容易出错。你每多包一层嵌套就是在给模型制造多一分填错的可能性。3. 实操从零写一个可复用的 Agent Skill3.1 目录骨架怎么搭不同 Agent 框架对 Skill 的目录结构要求不完全一样但核心思想是一致的一个 Skill 必须自包含——要么不依赖外部资源要么把依赖明确声明出来。我常用的最小骨架是这样meeting-minutes/ ├── SKILL.md ├── scripts/ │ ├── transcribe.py │ ├── summarize.py │ └── requirements.txt ├── assets/ │ └── prompt_templates/ └── tests/ ├── sample_input.json ├── sample_output.json └── test_skill.py解释一下每个部分的作用。SKILL.md 是给模型看的说明书必须放在最显眼的位置。scripts 目录放实际执行的代码requirements.txt 声明 Python 依赖。assets 目录放辅助资源比如给模型用的提示词模板、预置数据。tests 目录放测试数据和测试脚本这部分很多人嫌麻烦不写但我强烈建议至少放一组样例输入输出——这不仅能让你自己调试方便还能在接入新框架时快速验证。我自己用下来的体会是目录结构这关最忌讳“为了规范而规范”。如果 Skill 本身只需要一个脚本那就只放一个脚本不要硬拆出一堆空目录。骨架是给人看的也是给框架识别用的保持简洁比什么都重要。3.2 SKILL.md 完整示例与逐段拆解下面这个示例我实际项目里用过你可以直接抄来改。它做的是“会议纪要生成”--- name: meeting-minutes description: 生成结构化会议纪要。当用户提供了会议录音文件或会议文字记录并希望得到带决策项、待办事项的会议纪要时使用。 version: 1.0.0 ---注意 frontmatter 里的 description我特意写了“当用户提供了……并希望得到……”这种带条件和目的的话术而不是“本工具用于生成会议纪要”。前者给了模型清晰的触发判断依据后者没有。这是 SKILL.md 里最容易忽视但最关键的细节。正文部分要写清楚用法## 使用方法 输入以下任一形式 - 本地录音文件路径例如 /data/meetings/20250601.mp3 - 会议文字记录纯文本需用双引号包裹 - 同时提供录音文件和已有文字稿文字稿优先 输出 返回 Markdown 格式的会议纪要包含以下字段 - 会议主题 - 参会人如无法识别则标注“未知” - 讨论要点按时间顺序最多 5 条 - 决策项格式编号 描述 负责人负责人未知时留空 - 待办事项格式编号 任务 负责人 截止日期日期未知时标注“待定” ## 使用约束 - 仅处理中文和英文的会议内容 - 如果输入文件超过 100MB拒绝处理并提示用户压缩 - 如果录音中有效人声不足 30 秒返回“录音过短无法生成纪要” - 不要主动修改输入文件不要在纪要中补充原文没有的信息这段描述里“使用约束”部分特别重要。我见过太多 Skill 没有约束段模型就会在边界情况下乱来。你写清楚“不要主动修改输入文件”“不要补充原文没有的信息”模型就会收敛很多。还有一点输出里的字段格式我写得很具体比如“编号 描述 负责人”这种颗粒度正好是模型能直接照做的程度。3.3 核心代码实现有哪些隐藏要点代码本身不复杂但有几个点必须处理好。第一是幂等性同一个输入无论调用多少次输出应该一致。第二是超时控制Skill 可能会被模型反复调用如果某个操作特别慢你得有超时机制不能卡死整个 Agent。第三是依赖隔离尽量把 Skill 的依赖声明清楚不要和主项目的依赖混在一起。我用一个最简单的 Python 片段说明“给模型返回语义化错误”的写法import os def run(file_path: str , text: str ) - dict: try: if not file_path and not text: return { error: 缺少输入请提供录音文件路径或会议文字记录, suggestion: 请提供 file_path 或 text 参数, } if file_path: if os.path.getsize(file_path) 100 * 1024 * 1024: return { error: 文件超过 100MB, suggestion: 请压缩后重试, } # 核心逻辑... minutes_markdown # 会议纪要\n\n## 会议主题\n... return {ok: True, result: minutes_markdown} except Exception as e: # 这里不要把堆栈抛给模型转成人话 return { error: f处理失败{e}, suggestion: 检查输入文件格式是否正确, }看到区别了吗每个错误分支都返回了error加suggestion。模型拿到这个结果后可以自己判断下一步怎么补救甚至直接根据 suggestion 主动向用户询问缺失信息。如果你直接抛一个 Python 堆栈模型大概率会一脸懵然后开始瞎编。这里再补充一个容易被忽略的点Skill 的入口函数最好统一签名。无论内部逻辑多复杂对外只暴露一个run函数入参是平铺的字符串参数出参是字典。这样不管接到哪个 Agent 框架里适配成本都极低。你可以在项目里定一个通用模板所有新 Skill 都套这个模板生成维护起来会轻松很多。3.4 调试 Skill 的“可观测性”做法调试 Skill 最痛苦的点在于你看不到模型是怎么理解你的描述文件的。同一个 Skill换个模型可能调用逻辑就变了。我的做法是给 Skill 加一个 dry-run 模式。具体操作是在 Skill 入口处加一个环境变量或参数控制当开启 dry-run 时不真正执行核心逻辑只输出模型传入的参数、以及你对这些参数的解析结果。这样你就能快速验证两个问题模型有没有传对参数你的参数解析逻辑有没有 bug我经常发现模型把max_length传成了字符串“三千”这种问题在 dry-run 模式下一眼就能暴露。另外强烈建议在实际运行日志里记录每次调用的触发理由。你可以在 SKILL.md 里要求模型在调用时附带一句“调用原因”比如“用户提供了录音文件路径符合触发条件”。这看起来多此一举但实际调试时极其有用——你能立刻知道模型是“正确地调用了”还是“乱调用”。我自己排查线上问题时有相当一部分就是靠日志里那句调用原因快速定位到是描述文件写得不清楚而不是代码有 bug。4. 常见问题与排查技巧实录4.1 高频翻车点速查表我把项目里见过的高频问题整理成了一张表你可以直接对照排查问题现象根本原因解决办法模型该调用 Skill 时不调用描述文件触发条件写得太抽象在 description 里加具体场景例子模型不该调用时乱调用缺少禁用条件negative prompt增加“使用约束”段落明确什么情况不要用参数传错或传不全参数层级太深、字段命名有歧义扁平化参数字段名用通俗词汇补充参数示例输出格式不稳定代码没有强制结构化输出代码层固定 JSON 结构不要依赖模型整理Skill 跑得很慢拖垮 Agent缺少超时和重试机制加超时控制把耗时操作拆成异步或分步换一个模型后行为变化大描述文件依赖了特定模型的表达习惯用更通用的自然语言重写描述减少“潜台词”这里我重点说一下第一行。模型不调用 Skill很多时候不是模型笨而是你的描述文件太“哲学”。你写“本工具用于数据处理”模型不知道你的数据处理和它自己用代码处理有什么区别。你写“当用户提供 CSV 文件且要求筛选、统计、可视化时使用输出 JSON 格式图表配置”模型就知道该调用了。触发条件一定要具体到“什么输入 什么意图”缺一不可。4.2 我自己踩过的三个坑第一个坑把多个动作塞进一个 Skill。早期我做了一个“综合办公助手”Skill既能查天气又能算 Excel还能写周报。结果模型每次调用都在猜我要干什么猜错率极高。后来拆成了三个独立 Skill准确率直接上来了。这个教训让我彻底认同了“单一职责”原则——在 Agent Skill 的开发里这个原则比在普通软件工程里还要重要因为你的调用方是一个会“猜”的模型它猜的难度直接决定了成功率。第二个坑描述文件里写太多“可以”。比如“本 Skill 可以用 Python 处理数据也可以生成图表还可以导出报告”。模型面对这种描述会把“可以”理解成“可选”导致它经常只做其中一部分就交差。后来我把每个能力拆成独立的调用接口在描述里明确“每次调用只执行一个函数不自动串联多个函数”问题才解决。第三个坑输出格式没在代码层兜底。我之前有个 Skill 让模型自己组织输出格式结果一次线上运行同一个任务拿到了三种不同结构的返回结果下游解析代码直接被搞崩。后来所有 Skill 的输出我都改成代码层强制的 JSON 结构模型只提供数据字段不再让模型自由发挥格式。从那以后输出稳定性提升了一个量级。这事的教训就是能交给代码保证的东西绝不要交给模型“自觉”。4.3 几个提高 Skill 成功率的细节最后分享几个我实测对提升成功率特别有用的细节。一是 SKILL.md 里加一个“快速示例”段落用一个具体的输入输出对演示完整调用过程模型看过例子之后照着做的概率远高于只读抽象描述。人看说明书也是一样给个成品样例比讲十句规则都管用。二是在参数说明里给每个字段加上必填/选填和取值范围比如“max_length可选默认 3000范围 500-10000”模型传参时就不容易越界。我在调试时见过模型给max_length传了-1如果你没有取值范围约束这种错误参数会一路传进代码里产生莫名其妙的结果。三是建议在 Skill 里对“部分成功”的情况做明确返回。比如会议纪要生成时录音转了文字但参会人没识别出来这时候返回结果里标注“参会人识别失败已置为未知”而不是直接报错。模型知道哪些信息缺失后会主动向用户确认体验比“硬报错”好很多。这个思路本质上就是我前面说的语义化错误的延伸——让模型始终知道自己“拿到了什么、缺了什么、下一步能做什么”。写 Skill 这件事做到最后还是回到两个关键原则让模型少猜让代码多扛。描述文件把触发条件、输入输出、边界约束写清楚模型就不需要瞎猜代码层把结构化输出、错误处理、超时控制做好系统就不会因为模型的一点点理解偏差而崩溃。把这个思路贯彻下去你写出来的 Skill 大概率不会难用。我个人实际操作中的体会是Skill 开发是一个反复迭代的过程别指望第一版就完美。先用最简单的骨架跑通一个场景再根据日志里模型的调用行为不断打磨描述文件最后再补全边界处理和测试。这种节奏看起来慢但每一步都在积累对“模型怎么理解你的代码”的直觉写到第三个第四个 Skill 的时候你会明显感觉到顺手很多。
企业数字化 ERP 产品动态
相关推荐
MySQL深分页优化实战:从OFFSET慢查询到延迟关联与书签分页 每次聊到 MySQL 性能优化,"深分页"几乎是必被点名的那个题。后端面试、日常巡检、线上故障排查,撞上它的概率实在太高了。我也记不清有多少次,一边看着慢查询日志里LIMIT 100000, 20这种 SQL,一边跟同事叹气:… · 2026/9/24 20:10:06
DataX MySQL批量同步:灵活配置与实战调优指南 年初接到一个数据迁移需求:几十张业务表要从一套MySQL迁到另一套MySQL,数据量不算变态,单表几万到几百万行都有,但要求能批量处理、可重复执行、中途失败了好定位。我第一反应是写个Java程序循环读再写,但想想断点续传… · 2026/9/24 20:10:06
从阅文到B站,为什么内容平台都在做“一番赏“生意 如果你最近逛过B站的活动页面,或者刷到过阅文旗下IP的周边预售,可能会发现一个共同点:越来越多内容平台,正在把"一番赏"作为衍生品变现的主要形式之一。这不是偶然的选择,而是一整套已经在日本被验证过几十年… · 2026/9/24 20:10:06
GitLab + Arbess + OSS:构建可追溯的 Java 制品流水线 1. 为什么要用 Arbess 把 GitLab 和 OSS 串起来1.1 从“构建靠人盯”到“流水线自动跑”的转变先交代背景。我们团队内部有大量 Java 服务,代码都放在自建的 GitLab 上,但很长一段时间里,构建、打包、传服务器这些环节都靠开发自己手动执行。… · 2026/9/24 21:43:02
鸿蒙PC包管理器生态探索:apt/dpkg迁移避坑指南 “你这套apt/dpkg的Linux思维,在鸿蒙PC上怕是要推倒重来。”这是我第一次在HarmonyOS NEXT PC开发机上敲下apt update时收到的内心警告。熟悉Linux生态的开发者迁移到鸿蒙PC,最大的冲击往往不是IDE变了、语言从C变成了ArkTS,而是最基础的“软… · 2026/9/24 21:43:02
SpringBoot+Vue实验室管理系统:从需求拆解到部署全流程实战 实验室管理系统这个东西,我在毕业设计阶段接触过不少同学的版本,自己也完整带过几个项目。说实话,SpringBoot Vue 的前后端分离架构,放在实验室管理这个场景里,属于非常典型的“管理系统类”毕业设计选题。它的好处在… · 2026/9/24 21:43:02
HashMap 深度解析:从数组链表到红黑树,彻底讲透 put、get、扩容与线程安全 HashMap 是 Java 集合框架里出镜率最高的类,也是面试八股里的常青树。但说句实话,能把它讲到“面试官点头”的人真不多。我面过不少候选人,十个里八个能背出“数组加链表,JDK 1.8 引入红黑树”,可再追问一句“get 的时… · 2026/9/24 21:43:02
PaddleOCR 3.0实战指南:PP-OCRv5与PP-StructureV3深度解析 1. 这不是一次普通升级:PaddleOCR 3.0背后的真实战场“百度飞桨PaddleOCR 3.0开源发布 OCR精度跃升13%”——这行标题在技术社区刷屏时,我正蹲在客户现场调试一套票据识别系统。客户指着屏幕上把“8,650.00”识别成“8,650.0O”的结果,皱着眉… · 2026/9/24 21:42:55
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44