十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Agent Skills 实战指南:从 SKILL.md 到技能调度引擎

Agent Skills 实战指南:从 SKILL.md 到技能调度引擎 如果你最近在关注大模型应用开发一定躲不开一个词Agent Skills。吴恩达在公开教程和分享里反复提到它Anthropic 又把它做成了 Claude 的原生能力各种教程从视频平台一路铺到知识社群标题一个比一个响。但说实话大部分内容要么停在概念层反复讲“Agent 是大势所趋”要么只教某一个工具的操作步骤看完之后你还是不知道这东西在自己的项目里该怎么落地。这篇文章想做一件事把 Agent Skills 从概念到代码实战完整串一遍。我会先讲清楚它到底解决了什么问题再拆解 SKILL.md 这种技能文件的底层设计然后带你手写一个真正能用的技能最后用 Python 实现一个最小可运行的 Skill 调度引擎。这样无论你是用 Claude 这类现成产品还是在自建 Agent都能把“技能”这一层真正用起来。先给一个明确判断Agent Skills 不是 Prompt 工程的换皮也不是 MCP 工具的替代品而是“如何组织模型能力”这个层面上的新抽象。它的核心价值是把散落在系统提示词里的知识、步骤和脚本沉淀成可复用、可组合、可测试的能力单元。2026 年再回头看这很可能是 Agent 开发从“小作坊”走向“工程化”的关键一环。1. Agent Skills 为什么突然值得所有开发者学习1.1 所有 Agent 项目都会撞上的同一堵墙先回忆一个场景。你做了一个能写 SQL 的 Agent最初效果很好因为系统提示词里只写了“你是 SQL 专家根据需求生成 SQL”。然而业务方很快提了新需求还要能解释 SQL、能优化慢查询、能生成建表语句、能检查数据质量。于是你开始往系统提示词里追加规则。三个月后系统提示词膨胀到一两万 token模型变慢成本变高最要命的是规则之间开始互相打架——这条说“优先使用索引”那条说“不要假设索引存在”。这不是个例。几乎所有 Agent 项目都会在同一个位置撞墙能力增长之后管理成本指数级上升。你每新增一个功能都得考虑它会不会与旧功能冲突会不会污染每次请求的上下文会不会让调试变成灾难。过去一年我见过太多团队把精力浪费在“给巨型提示词打补丁”上。Agent Skills 提供了一个完全不同的解法把每种能力封装成独立的“技能包”平时不占用上下文需要时才被加载。这就像一支团队不会让每个人都把全部门的手册背在脑子里而是遇到对应任务时去书架拿对应的那一本。这个转变看起来简单实际上改变的是 Agent 能力的组织方式。1.2 从“巨型提示词”到“能力库”吴恩达在关于 Agent 的课程和分享中反复强调一个判断Agent 应用开发的瓶颈已经不是模型能力本身而是开发者能否把模型能力模块化、可控地组织起来。他提到 Agent 通常可以拆成配置、工具、记忆、技能等几个模块其中“技能”解决的是“模型知道怎么做”的问题——把做一件事的步骤、经验、禁忌和示例固化下来而不是每次临时写在提示词里。Anthropic 则把这一概念产品化了。它推出的 Claude Skills 允许开发者用文件夹和 Markdown 文件定义技能放在指定目录Claude 会在任务相关时自动加载。两个动作叠加在一起结果就是 Agent Skills 从一个学术概念快速变成了普通开发者也能用的工程工具。网上流传的“吴恩达 Agent Skills 教程 PDF”版本很多内容质量参差不齐。更稳妥的做法是直接看官方课程、官方文档和官方示例仓库避免被旧版本内容误导。理解这个趋势时也要注意提示词技巧并没有过时它仍然是基础能力只是真正能支撑复杂业务的已经变成可维护、可复用、可测试的能力单元。1.3 谁最适合读这篇文章如果你满足下面任意一条这篇文章值得完整读完你在用 LangChain、Claude、OpenAI 等搭建 Agent但系统提示词已经严重失控你希望让同一个能力比如代码审查、数据清洗、SQL 优化在多个 Agent 项目中复用你想知道 SKILL.md 这种文件格式到底怎么设计为什么说 description 是灵魂字段你需要自建 Agent想在代码层面理解“技能加载”的完整链路。读完你会发现Agent Skills 没有想象中神秘但细节里的坑也不少。下面我们从概念开始逐步走到代码实战。2. Agent Skills 的核心概念与设计原理2.1 Skill 的本质是什么Skill技能本质上是一个自包含的能力包它包含一段对任务的描述、一段指导模型完成任务的说明以及可能用到的辅助脚本、模板和参考资料。它与系统提示词最大的区别是“懒加载”。系统提示词每一轮都会完整进入模型上下文而技能只有当用户请求与之相关时才被取出并注入。这个设计直接改变了两件事第一上下文窗口不再被无关指令占满第二能力之间可以物理隔离互不干扰。理解 Skill 有一个很好的类比它像是给模型一本“操作手册”。模型不需要背下所有手册但遇到对应场景时它能查到并调用正确的那一本。手册里既有步骤说明也有“不要这么做”的提醒还可以附带专用工具。这样一来模型的知识不再全部塞在“人设”里而是按需取用。2.2 SKILL.md一个技能文件长什么样在 Claude Skills 的实现里每个技能是一个文件夹必须包含一个 SKILL.md 文件。这个文件分为两部分YAML frontmatter 和 Markdown 正文。frontmatter 里有核心的 name 和 description 两个字段。name 是技能的唯一标识description 的作用是让模型判断“用户当前的任务是否和这个技能相关”因此它必须写清楚“什么时候该用”和“什么时候不该用”。正文则描述技能的工作流程、规则、示例和注意事项模型加载技能后会依据正文执行任务。除了 SKILL.md技能文件夹还可以包含scripts辅助脚本例如数据清洗脚本、代码分析脚本references参考资料例如行业规范、模板、示例输出assets图片、配置文件等静态资源。这种“说明书 工具 资料”的结构让一个技能既能指导模型思考也能赋予模型实际的执行能力。2.3 动态加载为什么 description 是最重要的字段很多第一次接触 SKILL.md 的开发者会低估 description 的重要性这是最常见的一个误区。有人随便写一句“用于清洗数据”结果模型该触发时不触发不该触发时乱触发。动态加载机制是这样的当收到用户请求时模型把所有可用技能的 description 与当前请求做语义匹配选中一个或多个相关技能然后只加载这些技能的内容进上下文。也就是说description 是技能的唯一“索引”。索引写得不准确技能内容再完备也白搭。好的 description 应该包含三类信息任务领域词、常见用户表述、明确排除的场景。例如description: 清洗 CSV 数据文件。当用户提到 CSV、去重、去除重复行、处理缺失值、空值、数据清洗时使用。不适合需要对数据进行复杂统计分析的场景。这句话同时给了触发信号和边界信号模型就比较容易做对。而“用于清理表格数据”这种写法既缺少明确的触发词也没有排除条件命中率基本靠运气。2.4 Agent Skills 与相近概念的边界先给结论Agent Skills 与系统提示词、RAG、MCP 工具、微调是互补关系不是替代关系。它们在“给模型增加能力”这件事上位于不同的层次。系统提示词是常驻上下文的行为设定适合写身份、底线和固定规则RAG 解决“模型不知道”的问题检索的是事实性知识MCP 工具解决“模型做不到”的问题通过函数调用与外部系统交互微调解决“模型学不会”的问题修改的是模型权重Agent Skills 解决“模型不会按最佳方式做”的问题提供的是程序性知识——做一件事的步骤、经验和禁忌。用表格对比更直观能力类型解决什么问题修改的层次是否常驻上下文系统提示词控制模型角色与固定规则每轮输入是RAG补充事实知识每轮输入检索后否MCP 工具连接外部系统执行能力否微调改变模型内在行为模型权重不占上下文Agent Skills传授做任务的方法论按需注入否理解了这条边界你就知道为什么在真实架构里它们会同时存在用系统提示词定身份用技能给方法论用工具给执行力必要时用 RAG 补知识。这也是 2026 年主流 Agent 架构的基本形态。3. 环境准备与前置条件3.1 使用 Claude Skills 的环境要求如果你要直接体验 Claude 的技能能力需要满足以下条件一个 Claude 账号能访问 Claude Code、Claude Desktop 或支持 Skills 的 API 接入方式在本地创建技能目录。macOS/Linux 的默认全局路径是~/.claude/skills/Windows 路径请参考官方文档准备技能文件夹里面至少包含一个 SKILL.md以及可选的辅助脚本和参考资料。不同接入方式对技能目录的支持细节可能不同版本请以实际官方文档为准。本文重点演示通用的技能文件结构和设计思路这些思路在大多数实现里都成立。3.2 自建 Skill 引擎的环境要求如果你想在自建 Agent 里实现一套技能调度环境要求很低Python 3.9 或更高版本PyYAML用于解析 SKILL.md 的 frontmatter 部分可选 pandas用于演示技能辅助脚本的依赖一个可用的 LLM API用于把技能内容注入上下文后完成任务。如果暂时没有 LLM API 也没关系本文第 5 节的调度引擎会把“技能命中”和“模型执行”分开演示你可以先跑通调度链路后续再接模型。4. 手把手编写第一个可用 Skill这一节我们写一个非常实用的技能CSV 数据清洗。需求是当用户给出一个 CSV 文件要求去重、删除空值时Agent 能自动完成清洗并向用户报告结果。4.1 先定义清楚技能边界写 Skill 之前先回答三个问题这个技能负责什么CSV 基础清洗包括整行去重和删空这个技能不负责什么复杂统计分析、列级别数据填充用户会怎么描述任务可能说“去重”“清洗”“有脏数据”“有空值”。边界越清楚后续 description 越好写模型误用概率越低。这一步很多人会跳过直接写正文结果后面反复调整 description反而更浪费时间。4.2 编写 SKILL.md创建目录my-skills/csv-cleaner/在里面新建 SKILL.md--- name: csv-cleaner description: 清洗 CSV 数据文件。当用户提到 CSV、去重、去除重复行、处理缺失值、空值、数据清洗时使用。不适合需要对数据进行复杂统计分析的场景。 --- # CSV 数据清洗 当用户需要对 CSV 文件进行基础清洗时使用本技能。 ## 适用场景 - 去掉 CSV 中的重复行 - 删除包含空值的行 - 输出清洗后的新文件 ## 执行步骤 1. 确认输入文件路径和输出文件路径 2. 检查输入文件是否存在读取前 20 行了解表头和数据格式 3. 调用 python scripts/clean_csv.py input output 执行清洗 4. 检查输出文件向用户报告原始行数、去重后行数和删除空值后的行数 5. 如果脚本报错先检查文件编码和列名不要擅自修改数据 ## 注意事项 - 默认采用整行去重和整行删空不做列级别的填充 - 如果用户指定了其他清洗规则以用户规则为准 - 输出文件不要覆盖输入文件避免误操作这段文件里的关键点是“执行步骤”写得足够具体模型照着做不会产生歧义同时“注意事项”给出了安全边界避免脚本覆盖原文件。SKILL.md 本身不需要太长重点是“可执行”和“无歧义”。4.3 编写辅助脚本在my-skills/csv-cleaner/scripts/下创建 clean_csv.py# 文件路径my-skills/csv-cleaner/scripts/clean_csv.py import sys import pandas as pd def clean_csv(input_path: str, output_path: str) - dict: df pd.read_csv(input_path) original_len len(df) df df.drop_duplicates() dedup_len len(df) df df.dropna() dropna_len len(df) df.to_csv(output_path, indexFalse) return { 原始行数: original_len, 去重后行数: dedup_len, 删除空值后行数: dropna_len, } if __name__ __main__: input_file sys.argv[1] output_file sys.argv[2] result clean_csv(input_file, output_file) print(result)脚本先做整行去重再做整行删除空值最后把清洗结果以字典形式打印出来。模型读取打印结果就知道该向用户汇报什么。为了让技能环境可复现可以在技能目录里加一个 requirements.txt内容写pandas即可。4.4 注册技能并触发测试把技能目录复制到 Claude 的全局技能目录下mkdir -p ~/.claude/skills cp -r my-skills/csv-cleaner ~/.claude/skills/然后在支持 Skills 的客户端里输入类似这样的请求请帮我清洗桌面上的 sales_data.csv去掉重复行和空值输出到 clean_sales.csv。正常情况下模型会先根据 description 判断命中 csv-cleaner 技能然后读取 SKILL.md 的步骤调用辅助脚本完成清洗最后汇报行数变化。如果模型没有触发技能最先应该检查的就是 description 是否覆盖了用户话里的关键词和场景描述。5. 代码实战用 Python 实现最小 Skill 调度引擎如果你不使用 Claude 产品而是自建 Agent那么最需要理解的就是“技能加载链路”。这一节我们实现一个最小可运行的 Skill 调度引擎包含三个能力从目录加载技能、根据用户请求匹配技能、把技能内容注入 Agent 上下文。5.1 设计思路整个引擎分为两层Skill 类负责解析单个 SKILL.md把 frontmatter 和正文变成结构化对象SkillRegistry 类负责扫描技能目录、加载全部技能、根据用户请求做匹配。匹配算法这里用最简单的关键词重合度生产环境建议换成向量检索但整体调度链路是同一个。先跑通链路再优化匹配质量这是比较稳的工程顺序。5.2 完整实现技能加载与匹配引擎# 文件路径skill_engine.py from dataclasses import dataclass from pathlib import Path from typing import Optional import yaml dataclass class Skill: 一个技能解析 SKILL.md保存 name、description、正文和脚本目录 name: str description: str body: str scripts_dir: Optional[Path] None classmethod def load(cls, skill_dir: Path) - Skill: skill_file skill_dir / SKILL.md if not skill_file.exists(): raise FileNotFoundError(f{skill_dir} 中找不到 SKILL.md) text skill_file.read_text(encodingutf-8) if not text.startswith(---): raise ValueError(SKILL.md 必须以 YAML frontmatter 开头) parts text.split(---, 2) if len(parts) 3: raise ValueError(SKILL.md frontmatter 格式不完整) meta yaml.safe_load(parts[1]) return cls( namemeta.get(name, skill_dir.name), descriptionmeta.get(description, ), bodyparts[2].strip(), scripts_dirskill_dir / scripts if (skill_dir / scripts).exists() else None, ) def to_prompt(self) - str: return f[Skill: {self.name}]\n{self.description}\n\n{self.body} class SkillRegistry: 技能注册表从目录加载全部技能并按简单相似度匹配最合适的技能 def __init__(self, skills_dir: str): self.skills_dir Path(skills_dir) self.skills [] for directory in self.skills_dir.iterdir(): if directory.is_dir(): try: self.skills.append(Skill.load(directory)) except Exception as exc: print(f加载技能 {directory.name} 失败: {exc}) def list_skills(self) - list: return [skill.name for skill in self.skills] def match(self, user_input: str) - Optional[Skill]: 基于关键词重合度做匹配生产环境建议换成向量检索 user_input user_input.lower() best_skill None best_score 0 for skill in self.skills: score 0 desc_text ( skill.description.lower() .replace(, ) .replace(。, ) .replace(,, ) ) for word in desc_text.split(): if word and word in user_input: score 1 if skill.name.lower() in user_input: score 5 if score best_score: best_score score best_skill skill return best_skill if best_score 0 else None def build_agent_messages(user_input: str, registry: SkillRegistry) - list: 把匹配到的技能注入 Agent 的 messages 列表 messages [ { role: system, content: 你是一个支持技能调度的 AI 助手。如果命中了技能请严格遵循技能中的步骤完成任务。, } ] skill registry.match(user_input) if skill: messages.append({role: system, content: skill.to_prompt()}) messages.append({role: user, content: user_input}) return messages这段代码里有三个关键设计。第一Skill.load 方法把“技能就是文件夹”这个约定落了地。解析 frontmatter 得到 name 和 description把正文保存到 body如果存在 scripts 目录就记住路径。任何一步出错都能被外层捕获并打印不会让整个引擎崩溃。第二SkillRegistry.match 是“按需加载”的核心。它遍历所有已加载技能把 description 分词后与用户输入做重合度打分技能名命中则加权。这个算法只用于演示链路真正的生产环境里用户请求往往不会和 description 用词完全一致所以更建议用向量数据库或模型语义判断来替代。第三build_agent_messages 把技能作为一条动态附加的 system 消息放在固定系统消息之后、用户消息之前。这比把技能塞进固定 system prompt 更符合“按需加载”的设计也方便你统计每次请求到底注入了哪些技能。5.3 准备测试数据先在本地准备一个技能目录和一个待清洗的 CSV 文件mkdir -p skills/csv-cleaner/scripts cp my-skills/csv-cleaner/SKILL.md skills/csv-cleaner/ cp my-skills/csv-cleaner/scripts/clean_csv.py skills/csv-cleaner/scripts/ pip install pyyaml pandas为了验证调度结果可以准备一个简单的sample.csv里面故意放几行重复数据和空值数据。这不是必须的因为本节主要验证“技能是否被命中并注入”脚本本身的清洗逻辑已经在上一步验证过。5.4 运行与验证创建演示脚本 demo.py# 文件路径demo.py from skill_engine import SkillRegistry, build_agent_messages if __name__ __main__: registry SkillRegistry(skills) print(已加载技能:, registry.list_skills()) for request in [ 帮我清洗这个 CSV 文件去掉重复行和空值, 帮我写一首关于秋天的诗, ]: messages build_agent_messages(request, registry) matched_skill 无 for msg in messages: if msg[role] system and msg[content].startswith([Skill:): first_line msg[content].split(\n)[0] matched_skill first_line.replace([Skill: , ).replace(], ) break print(f请求: {request}) print(f注入技能: {matched_skill}) print( * 50)运行命令python demo.py预期输出大致是已加载技能: [csv-cleaner] 请求: 帮我清洗这个 CSV 文件去掉重复行和空值 注入技能: csv-cleaner 请求: 帮我写一首关于秋天的诗 注入技能: 无 第一类请求的文本里包含“CSV”“清洗”等 description 中的触发词所以命中第二类请求完全不相关所以返回空Agent 只能依赖基础能力回答。这就是“按需加载”的雏形。如果运行失败优先检查是否安装了 PyYAML以及 SKILL.md 的 frontmatter 是不是标准 YAML最常见的坑是 frontmatter 结束符没有顶格写。5.5 如何接入真实的 LLM在上面基础上接入真实模型只需要把 build_agent_messages 返回的 messages 直接传给 LLM 的 chat 接口即可。当你把技能正文注入上下文后模型会像读到一条临时系统指令一样遵循其中的步骤。如果技能正文里写了“调用某个脚本”模型通常会尝试执行这时你的 Agent 还需要一个“代码执行器”组件把脚本调用安全和结果解析做起来。这是整条链路里最容易出问题的部分也恰恰是 Agent Skills 从“玩具”走向“生产”的分水岭。6. Skill 的组合与编排从单技能到多技能 Agent单个技能只能解决单一问题真正工程化的问题是多个技能如何协作。比如一个数据分析 Agent可能会经历“清洗数据 → 生成统计画像 → 绘制图表”三个环节每个环节都可以是一个独立技能。编排方式有两种常见思路。第一种是“模型主导式”模型在一次回答中根据任务需要依次命中并调用多个技能。这种方式的优点是灵活缺点是结果不稳定模型可能跳过某个必要步骤或者把技能 A 的规则错误套用到技能 B 的场景。解决方法是把每个技能的边界写清楚并在 SKILL.md 里注明“本技能不负责后续环节”。第二种是“工作流主导式”用代码预先定义任务链路每个节点指定使用哪个技能。这种方式的优点是稳定可控缺点是灵活度降低。实际项目中更推荐先用工作流把主链路固定住再用技能给每个节点增加弹性。这与“先跑通再优化最后控制质量”的工程节奏是一致的。技能组合有一个设计原则每个技能保持单一职责。一个技能既清洗数据又生成图表看起来方便实际上会让 description 的匹配和目标任务的完成度都下降。更好的做法是拆成两个技能让编排层决定谁先谁后。7. 常见问题与排查思路技能本身不复杂但落地过程中问题很多。下面这张表列出的都是高频问题问题现象可能原因排查方式解决方案Agent 该用技能时没触发description 里缺少用户常用表达对比用户请求与 description 的重合词重写 description加入同义表达和典型请求示例不该触发时频繁误触发description 边界描述模糊记录哪些词导致误判在 description 中写明“不适合……场景”技能内容没有进入上下文frontmatter 解析失败查看是否报错单独解析 YAML用yaml.safe_load验证 frontmatter 合法性辅助脚本报错依赖未安装或路径不对单独运行脚本看完整异常添加 requirements.txt并在 SKILL.md 中声明运行环境多个技能同时命中且指令冲突技能职责重叠打印每个技能的命中得分拆分职责或提高匹配精度必要时使用互斥描述模型不遵守技能中的注意事项正文步骤不够明确检查步骤是否可执行、是否有反例使用“必须/禁止”这类强约束语句并补充反例排查这类问题有个通用顺序先看加载再看注入最后看执行。也就是先确认技能有没有被正确解析和命中再确认它的内容是否真的出现在发给模型的上下文里最后才怀疑脚本和模型执行层面的问题。这一步顺序反了很容易在一个无关环节浪费大量时间。8. 最佳实践与工程建议8.1 命名与描述规范目录名和 name 字段统一使用 kebab-case例如csv-cleaner、sql-optimizer方便脚本扫描和日志排查。description 控制在两到三句话第一句说这个技能负责什么第二句给出常见触发词和用户表述第三句说明不适用于什么场景。不要把 description 写成“这个技能很强大”这种没有信息量的话。8.2 技能内容设计规范正文用步骤式写法每一步都以动词开头如“确认路径”“调用脚本”“检查输出”。至少给一个完整的输入输出示例模型对示例的遵循度远高于抽象描述。写明边界和注意事项尤其是“不要覆盖原文件”“不要假设索引存在”这类容易导致事故的规则。辅助脚本只做一件事输入输出都要简单明确避免在脚本里写死业务参数。8.3 上下文与成本优化技能正文保持精简长时间运行的 Agent 或上下文窗口受限的模型经不起每个技能都写成几千字。详细参考资料放到 references 目录按需读取。匹配时只加载最相关的 1 到 2 个技能不要把所有技能都注入。监控每次请求的输入 token如果一个技能频繁被命中且没有带来效果提升要么优化它要么删除它。8.4 安全边界这是必须强调的一点技能可以包含任意脚本这意味着它拥有执行能力。生产环境必须对技能脚本做沙箱隔离和最小权限控制禁止技能无授权读取或修改敏感文件。任何涉及覆盖、删除、生产环境变更的操作都要在 SKILL.md 中明确要求先备份、先确认。团队协作时技能目录要纳入代码评审流程和普通代码变更同等对待。8.5 版本管理与测试技能目录应该纳入 Git每次修改记录变更原因。每个技能准备 3 到 5 个测试用例包括命中测试和任务完成测试。修改 description 之后必须做回归测试因为 description 是匹配入口改动影响面最大。技能升级建议采用“目录切换”而不是原地修改比如csv-cleaner-v1和csv-cleaner-v2这样可以随时回滚。8.6 评估指标衡量一套技能体系是否健康不只靠“能不能跑通”。至少关注三个指标命中率该触发时是否触发正确率任务完成后结果是否正确成本平均每次任务注入的技能 token 数。三个指标一起看才能判断技能是真正在帮 Agent还是在给 Agent 拖后腿。9. 总结与后续学习方向Agent Skills 的价值不在于概念有多新而在于它把一个工程上一直很难做好的事——如何组织模型能力——变成了可落地的文件结构和调度逻辑。你不再需要把几十条规则硬塞进系统提示词而是可以把每一种能力沉淀成一个技能文件按需加载、独立维护、单独测试。如果你今天就想动手推荐一条最小实践路径先把你现有系统提示词里最大的一段能力描述拆出来写成第一个 SKILL.md放到技能目录里测试然后在自建 Agent 里跑一遍本文第 5 节的调度引擎观察上下文 token 下降了百分之多少。这一步做完你会对“按需加载”有非常直观的体感。后续值得深入的方向有三个一是把关键词匹配升级成向量检索让技能命中更准确二是把单技能扩展成多技能编排配合工作流引擎控制流程三是建立技能评测集让每一次技能改动都有数据可依。至于 MCP 工具、RAG 和微调它们和 Agent Skills 是互补关系最终你会需要根据业务场景把它们组合在一起。建议收藏这篇文章按着第 4 节和第 5 节的内容亲手跑一遍。技能目录里多一个 SKILL.md 不难难的是把“能力模块化”变成你设计 Agent 时的默认思维。从第一个小技能开始这个思维就能慢慢建立起来。
返回列表