ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Agent Skills实战:从零构建大模型技能库与SKILL.md规范指南

Agent Skills实战:从零构建大模型技能库与SKILL.md规范指南 最近大模型圈子里冒出一个高频词agent-skills。我上周刚好在公司内部把一个半残废的内部工具从“一堆零散prompt”重构成了“一套技能库”效果立竿见影——同样一个任务以前Agent经常跑一半犯迷糊现在稳定得多而且新同事接手也不用再读那十几页没人维护的操作文档。如果你正在做AI应用开发或者你手头已经接了Function Calling、MCP却总觉得这些“工具”没被Agent用好那这篇东西就是写给你的。我尽量不讲抽象概念直接把agent-skills是什么、怎么搭、怎么调、怎么避免翻车讲透所有代码和目录结构都是可以直接抄走用的。1. 从“会聊天”到“能干活”Agent Skills到底解决了什么问题1.1 大模型不缺工具缺的是使用说明书先说我踩过的那个坑。之前我在项目里给Agent接了一个内部查询接口想着模型只要会调接口就行。结果用户问“帮我看下上个月华东区的退货率”Agent第一轮调错参数第二轮把时间范围理解错第三轮直接开始编数据。表面上看是模型“笨”实际上问题出在我给了它一把扳手但没告诉它这扳手是用来拧水管还是拧螺丝。这就是agent-skills要解决的核心问题——它不只是一个工具而是一份“会随着上下文被模型读取”的说明书。每个技能本质上是一个文件夹里面放一段结构化文档SKILL.md和可选的辅助脚本。当用户的需求命中技能的描述时模型会把这份说明书加载进来照着里面的步骤、参数约定和边界条件去执行任务。说白了工具是“手”技能是“大脑里那本操作手册”。之前的问题是手已经有了大脑没有手册。1.2 Skills、MCP、Function Calling三者根本不是一回事很多朋友第一次接触agent-skills时都会懵“这不就是MCP Server吗或者不就是Function Calling”还真不是。我把这三者的关系用一个比喻讲清楚Function Calling是模型输出“结构化调用意图”的能力比如它决定“我要调用get_weather(city北京, date今天)”。这是底层机制相当于OS提供的系统调用。MCP是一个“外设接口标准”。你按这个标准写一个服务模型就能以统一格式调用外部工具、读取外部数据相当于USB-C协议谁都可以插。Agent Skills是“外设驱动使用教程”。技能里不仅包含怎么触发底层函数更包含“什么场景下才该用”“参数该怎么填最稳妥”“一系列步骤应按什么顺序做”“做了之后结果怎么解读”这些纯靠MCP和Function Calling是表达不出来的。我实测下来最直观的感受是只挂MCP工具模型经常处于“有工具但不知道该不该用、怎么用”的状态加了技能层之后模型会先判断“这是不是技能管辖的活儿”再决定要不要调度外部工具。这层“判断流程编排”恰恰是技能的核心价值。1.3 技能库让Agent有了“成长档案”还有一个非常实际的好处技能是可复用、可积累的。以前做一个Prompt调优项目经验和教训都存在某个人的脑子里现在每总结出一个稳定可靠的做事流程就可以固化成一个Skill文件夹放进团队共享的技能库。我亲眼看着我们团队从“每个Agent临时拼Prompt”进化成“公共技能库业务技能库”两层结构。上个月做的合同审核Skill这月另一个项目做招投标文件审查时直接拉过去复用稍微改了改边界描述就上线了。这种积累效应比多写几个Prompt模板有价值得多。2. 一张SKILL.md撑起一个技能规范与加载机制拆解2.1 文件夹即技能SKILL.md即说明书不同Agent框架对skills的实现细节略有差异但主流方案的目录结构高度一致。下面这套是我目前在项目中直接使用的兼容性和可读性都不错skills/ ├── daily-report/ │ ├── SKILL.md │ └── scripts/ │ └── collect_commits.py ├── contract-review/ │ ├── SKILL.md │ ├── rules/ │ │ └── clause_dict.txt │ └── scripts/ │ └── parse_pdf.py └──>--- name: daily-report description: 用于生成日报 ---结果是什么用户问“帮我汇总一下这周的工作进展”模型不调用它用户问“把这几个commit整理一下”模型也不调用它。原因很简单描述太模糊模型无法把它和用户的真实意图关联起来。后来我改成这样--- name: daily-report description: 适用于用户要求生成当日或指定日期的日报、工作汇报、进展摘要时。技能会读取用户指定的Git仓库提交记录、仓库目录下的项目日志或用户粘贴的工作记录按“今日完成/进行中/风险与阻塞/明日计划”四个模块输出结构化Markdown日报。不适用于生成周报、月报或对大量历史数据的统计分析。 ---改完之后召回率立刻上来了。总结成一句话描述要回答三个问题——什么情况下用、它会做什么、它不做什么。“不做什么”尤其重要能显著减少模型的误调用。比如我明确写“不适用于生成周报”用户要周报时模型就会自动跳过这个技能不会乱来。3. 手把手做好一个日报技能从描述到脚本的一次完整落地3.1 目标拆解先给技能划好能力边界现在我用一个高频场景——自动生成日报——完整演示一遍从设计到落地的全过程。这个技能不挑领域你只要把后端换成自己公司的数据源就行。第一步不是写代码而是想清楚这技能管什么、不管什么。我的设计思路是管读取今日git提交记录、合并的PR、用户粘贴的零散工作记录汇总成日报。不管分析历史趋势、做绩效评估、生成周报月报。这些交给别的技能或直接由模型处理。这个边界会在SKILL.md里用很直白的话写清楚。很多人写技能喜欢大包大揽最后模型什么都想干什么都干不好。一个技能专注一件事才是正确姿势。3.2 SKILL.md正文给模型可执行的操作步骤接下来是SKILL.md的核心正文。我把这块当成“给刚入职的实习生写操作手册”来写不看别的文档光看这份说明就能把事情做对。--- name: daily-report description: 适用于用户要求生成当日或指定日期的日报、工作汇报、进展摘要时。技能会读取用户指定的Git仓库提交记录、仓库目录下的项目日志或用户粘贴的工作记录按“今日完成/进行中/风险与阻塞/明日计划”四个模块输出结构化Markdown日报。不适用于生成周报、月报或对大量历史数据的统计分析。 --- # 日报生成 ## 目标 生成一份简洁、结构化、不夸大事实的工作日报。 ## 数据来源优先级 1. 用户明确指定的仓库路径或粘贴的工作记录。 2. 当前工作目录及递归子目录中名称包含“log”“memo”“todo”的文件。 3. 如果以上两类数据都不存在直接向用户说明缺少数据禁止编造工作内容。 ## 执行步骤 1. 确定日期范围。用户没指定时默认取今天必须换算成项目所在时区。 2. 若存在git仓库运行 git log --sinceYYYY-MM-DD 00:00 --untilYYYY-MM-DD 23:59:59 --prettyformat:%h %s 拉取提交记录。注意使用 --dateiso 确保时间准确。 3. 借助 scripts/collect_commits.py 拉取当日PR合并情况若脚本因网络或权限失败记录失败原因并继续处理其余数据源。 4. 汇总以上内容按四模块整理。没有内容的模块写“无”不要用“暂无”之类的模糊词。 5. 确保每条事项有具体信息——涉及哪个项目、做了什么、结果如何。拒绝“优化了部分功能”这类空话。注意正文里的几个设计。步骤1强调了时区因为Agent运行在服务器上默认UTC日报按UTC切分日期会直接错一天。步骤2给出了具体命令不给模型发挥空间。步骤4和5约束了输出格式明确告诉模型“无就写无”省得它瞎编。3.3 collect_commits.py让模型有“手”可用SKILL.md写清楚了但模型光读说明还拉不了PR数据这时候需要辅助脚本。我的习惯是凡是模型体面完成不了的事多步git操作、调第三方API、解析结构化数据都写成脚本凡是模型擅长的事归纳总结、判断信息价值都留在SKILL.md里让它自己干。这个日报技能的辅助脚本写得相对简单#!/usr/bin/env python3 收集指定日期范围内合并的PR。用法: python collect_commits.py --repo 路径 --since date --until date import argparse import subprocess import json def main(): parser argparse.ArgumentParser() parser.add_argument(--repo, requiredTrue) parser.add_argument(--since, requiredTrue) parser.add_argument(--until, requiredTrue) args parser.parse_args() try: # 此处根据实际托管平台的CLI或REST API进行调用 result subprocess.run( [gh, pr, list, --repo, args.repo, --state, merged, --search, fmerged:{args.since}..{args.until}], capture_outputTrue, textTrue, checkTrue ) # 输出JSON方便模型解析 print(json.dumps({success: True, prs: result.stdout})) except Exception as e: print(json.dumps({success: False, error: str(e)})) raise if __name__ __main__: main()脚本的约定我说明一下stdout输出要能直接作为模型上下文的输入不是给人看的log而是给模型看的JSON。出错时也要输出结构化信息这样模型能判断是重试还是放弃。还有一个细节脚本开头有完整的usage注释。因为Skill的执行流程是“模型读SKILL.md → 模型决定跑脚本 → 模型可能需要给脚本传参数”脚本参数怎么传必须写清楚否则模型会瞎猜参数名。3.4 注册进技能库并跑通全链路技能建好后只需要把整个文件夹放进Agent配置的技能目录框架会自动扫描注册。在我的项目里是改agent_config.yamlagent: name: daily-helper model: gpt-4o skills: - name: daily-report path: ./skills/daily-report重启框架后技能索引里已经能看到daily-report。接下来就是测试。我先用一条最典型的请求验证全链路“帮我把今天的日报生成了仓库在 /data/projects/billing-service”让我来还原模型实际执行时的思考链路用户要求“生成日报”命中了daily-report技能的description。加载SKILL.md全文。按“确定日期范围”步骤计算出今天的起止时间。按“执行步骤2”先跑git log看提交记录。决定调用辅助脚本collect_commits.py传入repo、since、until三个参数。脚本返回了当日合并的PR列表和对应的标题、作者。模型把所有数据汇总按四个模块输出日报Markdown。全程无需人工干预一次跑通。第一版能跑通就算成功了一半剩下的一半是后面的调优和避坑。4. 技能选型与编排该自己写Skill还是接MCP工具4.1 三条选型原则帮你少走弯路很多人在“要不要把功能做成Skill”这个问题上纠结。我自己的判断标准就三条原则一看处理对象是“数据加工”还是“工具调用”。MCP更适合纯粹的工具暴露——比如给模型一个查询天气、查数据库的通道通道本身没有复杂的业务逻辑。Skill则适合带“流程编排判断规则”的任务——比如合同审核要分五步走每步有不同判断标准。一句话MCP管“能调什么”Skill管“该怎么调、按什么顺序调、调完之后怎么判断”。原则二看逻辑是否会跨多次调用、依赖中间状态。如果一个任务需要“先查AA的结果决定要不要查BB失败后要回退到A”这种多步状态流转用纯工具配置很难表达交给Skill写清楚最合适。原则三看是否有现成可复用的标准工具。如果你要做的功能市场上已经有人写好了标准MCP Server那就直接接别重复造轮子。只有当你需要的是“一套独特的做事流程”而不是“一个通用能力”时才值得写Skill。4.2 技能组合与调用顺序把复杂任务拆成技能流水线建了五六个技能之后你会遇到一个更复杂的问题用户的任务可能需要多个技能配合。比如用户说“基于这几个合同数据给我出个季度经营分析并顺便生成日报”。我目前的做法是维护一个“路由清单”在Agent的主系统提示词里写清楚技能之间的组合关系# 技能组合约定 - daily-report: 用于每日例行汇报。当日数据已由其他技能生成时优先复用已有中间结果。 - contract-review: 用于合同文件审查。输出为结构化条款摘要。 -># eval_set.yaml test_cases: - input: 帮我把今天的日报生成一下仓库在 /data/projects/billing-service expect_skill: daily-report expect_output_contains: [今日完成, 明日计划] - input: 这两个星期的工作总结一下 expect_skill: weekly-report expect_not_skill: daily-report - input: 把这份合同的关键条款提取出来重点是金额、违约金和终止条款 expect_skill: contract-review expect_output_contains: [违约金, 合同金额]跑回归时我会用脚本一次性把评估集里的请求发给Agent然后检查两个层面意图对不对该调的技能是否调用了、不该调的是否没调、输出好不好关键内容是否覆盖。这套方法帮我抓出过好几次“改坏”的情况已经成了团队Agent质量保障的标准动作。5.3 一次典型的描述迭代从召回失败到稳定命中拿我最开始提到的日报技能举个实例。第一版上线后回归集里有个场景挂了“今天没啥进展但明天有个上线”这是用户真实会说的话模型的意图判断却是“不应该调日报技能”——它认为用户说“没进展”就不需要汇报了。这个问题不是技术能解决的得靠语义理解。我在description里补了一句“即使当日进展为空或用户表示没有进展也应当调用本技能并生成无进展日报以便保留工作记录。”这就等于把边界条件的说明写进了技能元数据。改完后该场景立刻通过回归测试。这类“语义边界盲区”不测不知道一测全暴露。所以我强烈建议把你在日常交流中见过的所有用户真实说法都沉淀进技能评估集这是技能越用越准的根本保证。最后分享一个自己换来的教训技能不是越“厚”越好。我早期有个技能SKILL.md写了四千多字流程图、背景知识、参考案例全塞进去结果模型执行时反而决策迟缓还经常抓不住重点。后来我把正文狠狠压缩到以“可直接执行的指令”为主原则、背景、判断逻辑能省则省只围绕“干什么、按什么顺序、遇到什么情况怎么办”来写执行成功率反而提升了。现在我的团队里有一条不成文规则SKILL.md正文超过800字必须做减法。技能是给模型看的“行动指南”不是给人类看的“产品文档”。祝各位都能早日攒出自己的技能库让Agent真正从“嘴替”变成“手替”。
返回列表