最近在给项目接 AI Agent 时,总有一种“模型懂很多,但干不了细活”的感觉。让它生成代码可以,让它批量处理表格、调用本地脚本、按业务规则做判断,结果往往不稳定。后来接触到 Agent Skills 这个概念,才意识到问题出在“能力边界”上——模型本身具备的是推理能力,而真正要落地到具体任务,还需要一套明确的“工作技能包”。
这篇文章我们彻底拆解 Agent Skills 的完整链路:它是什么、和 AI Skills 有什么区别、怎么把现成技能装进自己的 Agent、以及最关键的一步——如何从零造一个能用、好维护的 Agent Skills。全文采用小白友好的讲解方式,尽量不用难懂的黑话,最终目标是让你 1 小时内理解原理、能操作、能自己动手开发一个小技能。
如果你之前对 Agent、Function Calling 这些概念似懂非懂,这篇文章刚好适合你。
1. Agent Skills 是什么:先建立一个直观印象
1.1 一个能听懂人话的“工具箱”
如果你用过各类 AI Agent,大概率遇到过这种尴尬:
- 大模型聊天很流畅,论文、代码都能写;
- 但让它去统计本地文件夹里的 Markdown 标题数、批量给文件重命名、把 CSV 转成 JSON,它经常“避而不答”,或者生成一段不完整的内容让你自己动手。
为什么?因为模型本身的知识和推理能力再强,也“触碰不到”你本地的文件、数据库、命令行工具。它需要一种机制,把“模型会推理”和“程序能执行”这两件事连起来。
Agent Skills 解决的正是这个问题。你可以把它理解为“给 AI 助手额外安装的插件包”:
- 每个 Skills 对应一个具体能力,比如“批量处理 Markdown 文档”“生成接口文档”“查询数据库表结构”。
- 每个 Skills 都自带了“说明书”,告诉模型:我这个能力是干什么的、什么时候该调用、怎么调用。
- 每个 Skills 还自带了可执行脚本,模型不需要重写代码,直接调用这个脚本就能完成任务。
这样,Agent 就从一个“只会聊天的助手”,变成“装备齐全的团队”。
1.2 更严谨一点的定义
如果要用专业一点的话来描述,Agent Skills 可以定义为:
一段可复用的能力封装,通常由描述文件、可选依赖清单和可执行脚本组成,能够被 AI Agent 在推理过程中自动识别、加载和调用。
它和传统的 API、SDK 有一个本质区别:API 需要开发者通过写代码来调用,而 Agent Skills 的调用者不是人,是模型本身。模型根据用户的任务描述,自行判断“该使用哪个 Skills”,然后按 Skills 里的使用说明来执行。
这也决定了 Agent Skills 的设计重点:
| 设计重点 | 说明 |
|---|---|
| 明确描述 | 模型要靠描述判断是否调用,含糊等于没用 |
| 接口简单 | 脚本的入参、出参要简单可控 |
| 输出规范 | 模型需要根据标准输出来回答用户 |
| 最小依赖 | 依赖越多,Agent 环境越容易崩 |
1.3 它解决了哪些实际问题
在真实项目中,我们使用 Agent Skills 通常是为了解决下面几类问题:
- 操作本地资源:读取文件、批量修改、整理目录结构等。
- 访问外部数据:调用内部接口、查询数据库、抓取公开网页等(需要授权)。
- 完成确定性的计算:比如格式转换、数据清洗、数据校验,这类任务用模型硬写容易翻车,用脚本一次搞定。
- 复用团队经验:一个团队沉淀好的 Skill,可以被多个 Agent、多个项目反复使用。
2. Agent Skills 与 AI Skills、Function Calling 的区别
2.1 AI Skills 与 Agent Skills 的关系
“AI Skills”和“Agent Skills”经常被混着用,但严格来说,它们不完全是一个层次的概念。
- AI Skills 是一个更宽泛的说法,指“大模型具备的某种能力”,可以是通过提示词实现,也可以是通过工具实现。
- Agent Skills 更强调“面向 Agent 的可调用技能”,它必须满足三个特征:描述化、模块化、可执行。
换句话说,Agent Skills 是一种具体实现形式,而 AI Skills 更像一个能力总称。当网上很多文章讨论“Agent Skills 赋能人文社科混合研究方法论文写作”时,本质上是在说:研究者把文献整理、数据清洗、摘要提取等步骤封装成可复用的 Skills,让 Agent 在论文写作流程中自动调用。它让跨学科的研究方法不再停留在“提问-回答”层面,而是真正变成一套可执行、可复现的分析流程。
2.2 Agent Skills 与 Function Calling 的区别
Function Calling(函数调用)是很多 Agent 框架的基础能力,模型按照协议输出一个结构化调用指令,然后由程序执行对应函数。
两者最直观的区别:
| 对比项 | Function Calling | Agent Skills |
|---|---|---|
| 定位 | 一次函数调用 | 一个完整技能包 |
| 包含内容 | 函数定义 + 参数 | 描述文件 + 脚本 + 依赖 + 示例 |
| 复用程度 | 往往需要逐个注册 | 可整体复制、分发、安装 |
| 开发成本 | 低 | 中等 |
| 适合场景 | 简单、单个功能 | 复杂、可沉淀、可复用 |
举一个例子:
- Function Calling:Agent 调用
get_weather(city="北京")。 - Agent Skills:包含一个
SKILL.md描述文件,说明何时使用、入参规则,还带一个scripts/get_weather.py,实现天气查询、结果格式化、异常兜底。
Skills 不只是“一段函数”,它是一个自包含的、携带说明的能力包。
2.3 Agent Skills 与 Prompt 工程的边界
还有一部分人会把 Agent Skills 理解成“更长的提示词”。实际上,两者也有明显差别:
- Prompt 只能引导模型“怎么回答”。
- Skills 可以让 Agent“真正去执行”。
例如,你可以在提示词里写“请帮我统计文件里有多少个标题”,但如果文件不在模型上下文中,它无法完成。而一个负责读取文件的 Skills 可以主动读取一个文件夹,统计完再把结果返回给模型。
所以,在复杂 Agent 应用中,推荐组合使用:Prompt 负责定义 Agent 的人设、决策边界;Agent Skills 负责具体执行、计算、访问数据。
3. 环境准备与版本说明
3.1 本地开发环境
开发一个 Agent Skills 本身并不需要特别复杂的工具链。本文示例以 Python 为主,推荐环境如下:
- 操作系统:Windows 10/11、macOS、Linux 均可;
- Python 版本:建议 3.9 及以上;
- 依赖管理:
pip,后面会用requirements.txt; - 文本编辑器:VS Code、PyCharm 或者其他你顺手的编辑器;
- 支持 Agent Skills 的 Agent 客户端或平台。
关于 Agent 客户端,目前不同产品对 Skills 的规范和支持程度还有差异,建议先确认你使用的 Agent 是否支持“加载本地 Skills 目录”的能力。本文会把重点放在技能本身的设计和编写上,平台差异不会影响你理解核心逻辑。如果你在某个平台上的具体配置有差异,以官方文档为准。
3.2 本文目录规划
为了演示清晰,我们约定一个工作目录:
agent-skills-demo/ ├── skills/ │ ├── text_assistant/ │ │ ├── SKILL.md │ │ ├── requirements.txt │ │ ├── scripts/ │ │ │ └── process_markdown.py │ │ └── examples/ │ │ └── demo.md └── playground/ └── test.mdskills/:放所有技能的地方;playground/:用来放测试文件,模拟用户要处理的数据。
4. 拆解 Agent Skills 的标准结构
4.1 描述文件:SKILL.md
每个 Skills 里最关键的文件是SKILL.md。它有两个作用:
- 给 Agent 看:模型通过读取这个文件,决定“这个技能适不适合当前任务”;
- 给人看:开发者也能快速了解技能用途。
一个典型的SKILL.md可以这样写:
--- name: markdown_text_assistant description: 提供 Markdown 文档的统计与整理能力,例如统计标题数量、生成长度摘要、检查重复标题。 --- # Markdown 文本助手 ## 使用时机 当用户希望分析 Markdown 文档,或者需要对 Markdown 文档做基础体检时使用。 ## 输入参数 - file_path: Markdown 文件路径,必填。 - action: 要执行的动作,可选值包括 summary、headings、check_duplicates。 ## 输出格式 脚本输出 JSON 格式结果,字段包括 action、file_path、result。 ## 示例 ```bash python scripts/process_markdown.py --file_path playground/test.md --action summary注意几点: - `description` 越具体,Agent 越容易判断何时调用; - 参数说明要写清楚类型和是否必填; - 建议附带一个可运行的示例命令,帮助 Agent 理解调用方式。 ### 4.2 依赖文件 requirements.txt 如果脚本里用到了第三方库,需要把依赖写进 `requirements.txt`。让 Agent 或平台在安装 Skills 时自动安装。 ```txt # 本文示例没有任何第三方依赖,保留作为依赖管理示例示例脚本只用 Python 标准库就够了,所以依赖文件可以为空。但保留这个文件仍然有价值,后续新增第三方库时不用调整结构。
4.3 主体脚本 scripts/process_markdown.py
脚本是 Skills 的执行核心。你需要保证:
- 输入参数能通过命令行解析,推荐用
argparse; - 输出格式稳定,推荐 JSON;
- 要做好异常处理,避免因为文件名不对、文件不存在直接崩溃;
- 加上必要的日志,方便排查。
4.4 examples 示例目录
examples/不是强制要求,但在真实项目中非常推荐。示例文件的作用是:
- 方便开发者快速测试;
- 帮助 Agent 理解“这个技能跑起来的输出长什么样”。
5. 实战一:先把一个现成的 Skills 用起来
5.1 准备测试数据
在playground/test.md下创建一个简单的 Markdown 文件:
# 项目周报 本周主要完成了三个任务。 ## 任务一:完成接口开发 接口已上线,待联调。 ## 任务二:修复登录 Bug 已修复超时问题。 ## 任务三:补充单元测试 覆盖率提升到 80%。 ## 待办事项 - 联调 - 回归测试5.2 编写 Skills 描述文件
现在我们在skills/text_assistant/下建立文件。先写SKILL.md:
--- name: markdown_text_assistant description: 分析 Markdown 文档,支持统计标题数量、生成摘要、检查重复标题。当用户给出 Markdown 文件并要求分析时使用。 --- # Markdown 文本助手 ## 使用时机 当用户希望分析 Markdown 文档,或者需要对 Markdown 文档做基础体检时使用。 ## 输入参数 - file_path: Markdown 文件路径,必填。 - action: 要执行的动作,可选值包括 summary、headings、check_duplicates。 ## 输出格式 脚本输出 JSON 格式结果,字段包括 action、file_path、result。 ## 示例 ```bash python scripts/process_markdown.py --file_path playground/test.md --action summary### 5.3 编写核心脚本 创建 `scripts/process_markdown.py`: ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Markdown 文档处理脚本: - summary: 统计文档总行数、标题数、估算字数 - headings: 提取文档标题结构 - check_duplicates: 检查重复标题 """ import argparse import json import re import sys from pathlib import Path def read_markdown(file_path: Path) -> str: if not file_path.exists(): raise FileNotFoundError(f"文件不存在: {file_path}") return file_path.read_text(encoding="utf-8", errors="ignore") def parse_headings(content: str): """ 提取所有标题及其级别。 返回 (level, title) 列表。 """ headings = [] lines = content.splitlines() for line in lines: line = line.strip() match = re.match(r"^(#{1,6})\s+(.*)", line) if match: level = len(match.group(1)) title = match.group(2).strip() headings.append({"level": level, "title": title}) return headings def action_summary(content: str): headings = parse_headings(content) total_chars = len(re.sub(r"\s", "", content)) return { "total_lines": len(content.splitlines()), "headings_count": len(headings), "estimated_chars": total_chars, } def action_headings(content: str): return {"headings": parse_headings(content)} def action_check_duplicates(content: str): headings = parse_headings(content) seen = {} for item in headings: key = item["title"] seen.setdefault(key, []).append(item["level"]) duplicates = {k: v for k, v in seen.items() if len(v) > 1} return {"duplicates": duplicates} def main(): parser = argparse.ArgumentParser(description="Markdown 文本助手") parser.add_argument("--file_path", required=True, help="Markdown 文件路径") parser.add_argument( "--action", required=True, choices=["summary", "headings", "check_duplicates"], help="要执行的动作" ) args = parser.parse_args() file_path = Path(args.file_path) output = {"action": args.action, "file_path": str(file_path.resolve())} try: content = read_markdown(file_path) if args.action == "summary": output["result"] = action_summary(content) elif args.action == "headings": output["result"] = action_headings(content) else: output["result"] = action_check_duplicates(content) print(json.dumps(output, ensure_ascii=False, indent=2)) except Exception as exc: output["error"] = str(exc) print(json.dumps(output, ensure_ascii=False, indent=2)) sys.exit(1) if __name__ == "__main__": main()5.4 命令行验证
在项目根目录执行:
python skills/text_assistant/scripts/process_markdown.py \ --file_path playground/test.md \ --action summary预期输出:
{ "action": "summary", "file_path": ".../playground/test.md", "result": { "total_lines": 24, "headings_count": 5, "estimated_chars": 72 } }这说明一个 Skills 已经可以被直接执行。接下来就是把这样一个包含描述文件和脚本的目录告诉 Agent,让它学会在合适的时机调用。
5.5 让 Agent 调用这个 Skills
不同 Agent 平台的加载方式不太一样,但底层逻辑基本一致:把skills/text_assistant/整个目录注册到 Agent 的技能列表中。通常只需要两步:
- 在 Agent 配置里指定 Skills 存放路径,并启动扫描;
- 给 Agent 发一条指令,例如“分析 playground/test.md 这份 Markdown 文档,帮我提取标题结构”。
此时 Agent 会先读取SKILL.md,理解技能用途;然后根据用户需求构造命令,执行脚本;最后把脚本返回的 JSON 以自然语言总结给用户。
记得先单独测试脚本能不能跑通,再接入 Agent。脚本本身稳定,Agent 端排查问题会简单很多。
6. 实战二:从零开发一个自己的 Agent Skills
6.1 选主题与需求分析
软件开发里最忌讳一上来就写代码。开发 Agent Skills 也一样,先想清楚三件事:
- 这个技能解决什么问题?
- 模型什么时候该调用它?
- 它的输入和输出是什么?
下面我们给这个例子定义需求:
技能名称:csv_to_json_converter
解决什么问题:把 CSV 文件转换为 JSON 文件,并支持字段筛选。
调用时机:当用户上传或指定了一个 CSV 文件,希望转成 JSON,或提取部分列时。
输入:
input_file: CSV 文件路径output_file: 输出 JSON 文件路径(可选,默认同目录生成)selected_columns: 逗号分隔的字段名列表(可选)
输出:标准 JSON 统计信息,例如转换成功、行数、列名。
6.2 创建目录结构
skills/csv_to_json_converter/ ├── SKILL.md ├── requirements.txt └── scripts/ └── convert_csv.py6.3 编写 SKILL.md
--- name: csv_to_json_converter description: 将 CSV 文件转换为 JSON 文件,支持按列筛选。当用户希望处理 CSV 数据格式转换时使用。 --- # CSV 转 JSON 转换器 ## 使用时机 当用户提供 CSV 文件路径,希望转换为 JSON 或提取部分字段时使用。 ## 输入参数 - input_file: 必填,CSV 文件路径。 - output_file: 可选,输出 JSON 文件路径。不填则默认在输入文件同目录生成同名 .json 文件。 - selected_columns: 可选,逗号分隔的字段名列表,只保留指定列。 ## 输出格式 返回 JSON 统计信息,包括 success、row_count、columns、output_file。 ## 示例 ```bash python scripts/convert_csv.py \ --input_file data.csv \ --output_file data.json \ --selected_columns name,age,email### 6.4 编写转换脚本 ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ CSV 转 JSON 转换器: - 读取 CSV 文件 - 可指定输出路径 - 可筛选指定列 - 输出转换统计结果 """ import argparse import csv import json from pathlib import Path def load_csv(file_path: Path, selected_columns=None): if not file_path.exists(): raise FileNotFoundError(f"输入文件不存在: {file_path}") with open(file_path, "r", encoding="utf-8-sig", newline="") as f: reader = csv.DictReader(f) if reader.fieldnames is None: raise ValueError("CSV 文件为空或格式不正确") all_columns = list(reader.fieldnames) # 校验用户选择的列是否都存在 if selected_columns: missing = set(selected_columns) - set(all_columns) if missing: raise ValueError(f"以下列不存在: {', '.join(sorted(missing))}") data = [] for row in reader: if selected_columns: row = {col: row.get(col, "") for col in selected_columns} data.append(row) return data, all_columns def save_json(data, output_file: Path): output_file.parent.mkdir(parents=True, exist_ok=True) with open(output_file, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) def main(): parser = argparse.ArgumentParser(description="CSV 转 JSON 转换器") parser.add_argument("--input_file", required=True, help="CSV 输入文件路径") parser.add_argument("--output_file", help="JSON 输出文件路径") parser.add_argument("--selected_columns", help="逗号分隔的列名列表,可选") args = parser.parse_args() input_path = Path(args.input_file) selected = None if args.selected_columns: selected = [col.strip() for col in args.selected_columns.split(",") if col.strip()] if args.output_file: output_path = Path(args.output_file) else: output_path = input_path.with_suffix(".json") try: data, all_columns = load_csv(input_path, selected) save_json(data, output_path) result = { "success": True, "row_count": len(data), "columns": list(data[0].keys()) if data else all_columns, "output_file": str(output_path.resolve()), } print(json.dumps(result, ensure_ascii=False, indent=2)) except Exception as exc: result = { "success": False, "error": str(exc), } print(json.dumps(result, ensure_ascii=False, indent=2)) raise SystemExit(1) if __name__ == "__main__": main()6.5 准备测试数据与运行
创建playground/sample.csv:
name,age,email,department 张三,28,zhangsan@example.com,研发部 李四,31,lisi@example.com,产品部 王五,25,wangwu@example.com,市场部运行转换:
python skills/csv_to_json_converter/scripts/convert_csv.py \ --input_file playground/sample.csv \ --output_file playground/sample.json \ --selected_columns name,age,department预期输出:
{ "success": true, "row_count": 3, "columns": ["name", "age", "department"], "output_file": ".../playground/sample.json" }打开playground/sample.json:
[ { "name": "张三", "age": "28", "department": "研发部" }, { "name": "李四", "age": "31", "department": "产品部" }, { "name": "王五", "age": "25", "department": "市场部" } ]这样一个完整可用的 Agent Skills 就做出来了。从“会用到会造”的整个过程,其实只涉及描述文件、脚本、依赖管理、测试数据这几个要素。
7. 常见问题与排查思路
即使是一个简单的 Agent Skills,在真实环境中也可能遇到各种问题。下面按优先级整理一份排查清单。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| Agent 从不调用这个技能 | SKILL.md 里的描述太模糊,Agent 无法判断何时使用 | 打开描述文件,补充“使用时机”和“示例” |
| 脚本在终端能跑,但 Agent 调用时报错 | Agent 工作目录与脚本预期目录不一致 | 脚本内统一使用相对路径,并先打印当前工作目录 |
| 中文内容输出乱码 | 控制台编码问题 | 脚本输出统一使用 UTF-8,Windows 可设置PYTHONIOENCODING=utf-8 |
| 文件路径找不到 | 传入的是相对路径,或路径中包含特殊字符 | 在SKILL.md里写明路径要求,脚本层做resolve() |
| 依赖安装失败 | 版本冲突或网络超时 | 锁关键依赖版本,减少第三方依赖数量 |
| 输出格式不稳定 | 脚本内直接print中文描述,没有统一 JSON | 全部改成 JSON 输出,字段固定 |
| 大量数据内存溢出 | 一次性读取完整大文件 | 改为分批读取或流式处理 |
下面挑两个高频问题详细说。
7.1 Agent 不调用 Skills
这是最容易遇到,也最让人头疼的问题。排查顺序建议如下:
- 检查
SKILL.md的description是否写清楚了适用场景; - 确认 Agent 配置里 Skills 目录路径是否正确;
- 确认用户指令与技能描述有较高相关性,比如你写的是“Markdown 分析”,用户说“帮我看看这个文件”,Agent 确实很难判断;
- 在描述文件中增加典型示例,模型看到示例后,识别准确率会明显提升。
7.2 脚本工作目录不对
很多脚本在命令行直接执行没问题,但被 Agent 调用后,运行目录是 Agent 进程的工作目录,不是脚本所在目录。这时候就会触发“找不到文件”的报错。
在脚本里最好加一个调试信息:
import os import sys print(os.getcwd(), file=sys.stderr)先确认实际运行目录,再决定路径如何拼接。更稳妥的做法是,在SKILL.md中传入绝对路径,或者让脚本基于入参路径的父目录推导文件位置。
8. 最佳实践与工程建议
8.1 描述文件要“把事情说清楚”
写SKILL.md时,不要只写“这是一个文本处理工具”,要具体到:
- 什么时候使用;
- 什么时候不要使用;
- 参数怎么传;
- 输出长什么样。
模型没有耐心去猜测一个模糊的描述。很多时候,Agent 调用不准就是因为描述文件写得太抽象。
8.2 脚本做到单一职责、稳定输出
一个技能只解决一个问题。如果脚本又负责解析、又负责发送网络请求、又负责写数据库,一旦出错很难定位。
强烈建议脚本统一输出 JSON,并且包含固定字段。这样无论脚本怎么改,Agent 都能稳定解析结果。至少包含:
success:是否成功;result或error:结果或者错误信息。
8.3 加入日志与异常处理
脚本要记录足够的日志:
- 输入参数;
- 关键步骤;
- 异常堆栈。
日志建议写到stderr,标准输出只保留供 Agent 读取的结果,避免日志和结果混在一起。
8.4 安全与权限边界要提前设计
Agent Skills 能够帮 Agent 执行真实操作,意味着它可能带来安全风险。需要注意:
- 最小权限原则:技能只授予完成当前任务所需的最小权限,比如只允许读取指定目录,不允许删除文件;
- 操作前确认:涉及删除、覆盖、修改生产数据时,脚本应该先输出影响范围,并确认后再执行;
- 路径校验:对传入路径做白名单或前缀校验,避免任意文件访问;
- 敏感信息保护:不要在技能脚本中硬编码数据库密码、Token;
- 日志脱敏:打印日志时不要输出完整密钥、手机号、身份证号等敏感字段。
8.5 版本管理与可维护性
把 Skills 当成代码工程来维护:
- 使用 Git 管理每个技能的独立仓库或目录;
- 在
SKILL.md中维护变更记录; - 每个技能都带上
requirements.txt,锁定关键依赖版本; - 提供基本测试用例,至少要有一个最小可运行示例。
8.6 从使用到创造的成长路径
学习 Agent Skills 时,不要只停留在“会调用现成技能”。一个比较有效的路径是:
- 第一周:克隆别人的 Skills,逐行读懂脚本;
- 第二周:给现有技能增加一个新参数、新动作;
- 第三周:结合自己工作里的重复任务,写一个 50 行以内的技能;
- 第四周:尝试把多个小而简单的技能组合成一套更复杂的流程。
9. 总结与学习路线
这篇文章从零拆解了 Agent Skills 的完整链路,重点包括:
- Agent Skills 的定义,以及它和 AI Skills、Function Calling 的区别;
- 一个标准技能包的基本结构:
SKILL.md、依赖文件、核心脚本、示例目录; - 如何引入并验证现成技能;
- 如何从需求分析、目录搭建、代码编写、测试验证四个步骤,完成自己的第一个技能开发;
- 常见调用问题的排查思路,以及工程化落地时的安全与维护建议。
如果你是第一次接触 Agent Skills,建议先不要急着写复杂技能。把本章的两个示例复制到本地,分别跑一遍,观察脚本输出格式的变化,再尝试修改描述文件和参数。这个过程会帮你建立对“模型如何理解技能”的直觉。
接下来可以继续学习的方向包括:Agent 多技能编排、技能间的依赖传递、本地工具与外部 API 的混合调用、技能测试自动化,以及如何在团队内部建立统一的技能仓库。实战中优先关注技能描述质量和异常处理能力,它们往往决定 Agent 在实际任务中的可用性。
如果这篇文章对你有帮助,可以收藏备用,后续遇到 Agent 调用技能不准、脚本写好了却无法被识别这些问题时,翻出排查清单对照一遍,通常能省下不少时间。动手才是最好的学习方式,建议现在就找一个小任务试试。