news 2026/9/8 3:18:28

Agent Skills实战:从概念到代码,打造大模型智能体技能包

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent Skills实战:从概念到代码,打造大模型智能体技能包

现在的大模型应用开发,已经慢慢从“单次问答”走向“多工具协同”和“智能体自主完成任务”。不少同学在看完各种 Agent 科普后,仍然会有一个困惑:模型能力再强,怎么让它真正帮我执行一个复杂任务?比如“帮我整理一个目录下的所有图片,按拍摄时间重命名并生成一份 Markdown 索引”,如果只靠提示词,大模型做不到,但如果你给它写好一个 Skill(技能),它就能非常稳定地完成。

这就是 Agent Skills 存在的意义。

这篇文章会从概念入手,讲清楚它和 Function Calling、Tools、MCP 之间的关系,然后带你在本地搭建一个最小可运行的 Agent Skill 项目,最后通过一个完整实战代码,走通“定义技能 → 注册技能 → 让 Agent 调用技能 → 输出结果”的闭环。文章较长,建议先收藏再慢慢看。

1. 为什么 Agent 需要 Skills

1.1 Agent 的“手”和“脑”

大模型本身擅长的是“思考”,也就是根据上下文生成文本。但它有几个天然短板:

  • 不知道实时数据,比如今天的天气、最新股价。
  • 不能调用外部系统,比如发邮件、操作数据库、调用支付接口。
  • 执行过程不稳定,同一个任务换一种问法,可能流程就乱了。

为了解决这些问题,业界慢慢形成了“模型 + 工具”的架构。模型负责拆解任务、决定调用哪个工具,工具负责具体执行。

早期大家管这些工具叫 Function Calling 或者 Plugins,后来随着智能体框架的发展,出现了更细分的概念:Agent Skills。

1.2 Skills 是什么

Agent Skills 可以理解为“给 Agent 预装的一项专项能力包”。它不仅仅是一个 API 接口,而是一套完整的“技能描述 + 执行脚本 + 使用说明”。

典型结构如下:

skills/ └── image-sorter/ ├── SKILL.md # 技能说明文档 └── sort_images.py # 实际执行脚本

SKILL.md 告诉模型“这个技能是干什么的、什么时候该用、怎么用”,脚本负责真正干活。模型读 SKILL.md 后,决定要不要调用这个技能;一旦调用,就执行对应脚本。

用一句话概括:Tools 是单个动作,Skills 是完成一类任务的方法包。

1.3 Skills 与传统 Tools 的区别

很多同学容易把 Skills 和 Tools 混在一起。这里做一个简单区分:

维度ToolsAgent Skills
粒度单个函数/接口一组脚本+说明文档
触发方式模型根据函数描述调用模型理解技能说明后触发
学习成本需要写清楚函数入参出参需要写清楚使用场景和步骤
可复用性一般只能复用函数本身整个方法包可复制到其他项目
典型例子查询天气接口完整的数据清洗方法包

Skills 更接近“教模型一套方法”,而不是“给模型一把螺丝刀”。

1.4 本文实战目标

接下来我们会做一个完整的 Agent Skill 实战案例,目标是让 Agent 具备一个自定义技能:“文件归档助手”。

需求场景:

  • 用户告诉 Agent:把某个目录下的文件按扩展名分类。
  • Agent 调用 file-archiver 技能。
  • 技能脚本扫描目录,按扩展名创建子文件夹并移动文件。
  • 技能脚本生成一份归档报告。

整个项目不需要额外的大模型服务也能运行,核心是为了讲清楚 Skills 的机制。最后我们还会接入一个大模型客户端,演示“用户自然语言 → Agent 决策 → 调用 Skill”的完整流程。

2. 环境准备与项目结构

2.1 运行环境说明

本文示例代码使用 Python 编写,依赖很少,重点在于理解 Skills 的组织方式。

推荐环境:

  • Python 3.10+(3.8 及以上应该也能运行,但本文示例用 3.10 语法)。
  • 操作系统:Windows / macOS / Linux 均可。
  • 编辑器:VS Code 或者任意你习惯的 IDE。
  • 可选依赖:OpenAI SDK 或 Anthropic SDK(用于最后的大模型联动示例)。

版本提示:大模型 SDK 更新速度很快,文中涉及的 SDK 库以常见稳定版本为例,如果你安装的版本更新,调用方式可能略不同,建议以官方文档为准。

2.2 安装 Python 依赖

创建项目目录并进入:

mkdir agent-skills-demo cd agent-skills-demo

建议先创建虚拟环境:

python -m venv venv source venv/bin/activate # Windows 下使用 venv\Scripts\activate

安装后续可能用到的依赖:

pip install openai

如果只是先跑通文件归档技能本身,不需要任何第三方库,Python 标准库的osshutilpathlib就够了。

2.3 项目结构规划

我们要在一个小项目中体现 Skills 的完整生命周期,建议按下面的目录组织:

agent-skills-demo/ ├── skills/ │ └── file-archiver/ │ ├── SKILL.md │ └── archive_files.py ├── data/ │ └── sample_files/ # 测试目录 │ ├── readme.md │ ├── notes.txt │ ├── photo.jpg │ ├── report.pdf │ └── script.py ├── agent/ │ └── skill_runner.py # 技能加载与执行器 ├── demo_manual.py # 手动调用技能示例 └── demo_with_model.py # 接入大模型的完整 DEMO

这个结构不算复杂,但已经能体现出“技能包”和“执行器”分开的思想。后面每个文件都会给出详细代码。

3. Agent Skills 的核心概念拆解

3.1 SKILL.md 规范

在 Anthropic 的 Claude Skills 文档中,一个 Skill 目录的核心是SKILL.md文件,它使用 Markdown 编写,描述技能的使用场景、输入参数、输出格式和注意事项。

一个规范的 SKILL.md 通常包含:

  • name:技能名称。
  • description:技能作用描述,模型会根据这段文字判断是否调用。
  • when_to_use:什么情况下应该使用这个技能。
  • inputs:需要哪些输入参数。
  • outputs:会返回什么结果。
  • examples:使用示例。
  • notes:注意事项。

这样设计的本质是:让模型在没有执行脚本的情况下,也能准确判断“什么时候该调用、调用了会得到什么”。

3.2 技能脚本的调用方式

技能脚本是真正干活的代码。它和普通 Python 脚本没有本质区别,但有几个设计上的要求:

  • 支持命令行参数输入。
  • 结果尽量输出为结构化文本(JSON 或纯文本)。
  • 失败时要返回清晰的错误信息。
  • 不要硬编码路径,路径从参数传入。

这样设计是为了让 Agent 可以通过“构造命令”的方式灵活调用技能,而不是把逻辑写死。

3.3 技能发现与加载机制

所谓技能发现,就是让 Agent 在运行前知道“我有哪些技能可以用”。常见实现方式有两种:

  1. 约定目录扫描:Agent 启动时扫描skills/目录下的所有SKILL.md,把技能说明注入系统提示词。
  2. 工具注册表:通过代码显式注册技能,把技能名称、描述、调用函数放入一个注册表。

本文采用方式一,因为更贴近“Skills 作为独立包”的设计理念。

3.4 Skills 和 Function Calling 的关系

这里再补充一个容易被问到的点:Skills 和 Function Calling 有重叠,但定位不同。

Function Calling 是模型接口层面的能力,它让模型输出一个结构化调用请求。 Skills 是应用层面的封装,它包含说明文档和执行脚本。实际开发中,经常是“Skills 里的脚本被封装成 Function Calling 接口暴露给模型”。

你可以把 Skills 看成“技能的仓库”,把 Function Calling 看成“技能暴露给模型的通道”。

4. 从零实现一个 Agent Skill:文件归档助手

4.1 编写技能说明文档 SKILL.md

首先创建技能目录和说明文件。

文件路径:skills/file-archiver/SKILL.md

--- name: file-archiver description: 将指定目录下的文件按扩展名分类归档,并生成一份归档报告。适合整理下载目录、项目文档目录等场景。 --- # File Archiver Skill 将指定目录下的所有文件按扩展名移动到对应子目录中,并在目录下生成 archive_report.json 报告文件。 ## When to Use - 用户希望整理某个目录下的文件时。 - 需要按文件类型分类存放时。 - 希望生成文件清单报告时。 ## Inputs - directory: 要归档的目录路径,必填。 - dry_run: 是否只预览不实际移动,可选,默认 false。 ## Outputs - 归档后的目录结构描述。 - archive_report.json 文件内容,包含处理文件数和分类统计。 ## Examples 输入: python archive_files.py --directory /tmp/test_dir 输出: 归档完成。共处理 5 个文件,分为 3 类。 报告文件:/tmp/test_dir/archive_report.json ## Notes - 脚本不会处理子目录内的文件,只处理目标目录下的一层文件。 - 如果目标文件已存在,会重命名为 filename_1.ext 避免覆盖。 - 建议先使用 dry_run 模式预览效果。

这份文档是给模型读的,所以要写清楚触发条件和输入输出格式。

4.2 编写技能执行脚本

文件路径:skills/file-archiver/archive_files.py

这个脚本接受命令行参数,完成三个动作:

  1. 扫描目录。
  2. 按扩展名归档。
  3. 生成报告。

完整代码如下:

#!/usr/bin/env python3 """ 文件归档技能脚本。 用法示例: python archive_files.py --directory /path/to/dir python archive_files.py --directory /path/to/dir --dry_run """ import argparse import json import shutil from collections import defaultdict from pathlib import Path def get_file_category(ext: str) -> str: """根据扩展名返回分类名。""" ext = ext.lower() if ext in {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".svg"}: return "images" if ext in {".md", ".txt", ".doc", ".docx", ".pdf"}: return "documents" if ext in {".py", ".js", ".java", ".go", ".ts"}: return "code" if ext in {".zip", ".rar", ".7z", ".tar", ".gz"}: return "archives" return "others" def archive_directory(directory: Path, dry_run: bool = False) -> dict: """ 按扩展名归档目录文件。 返回包含处理统计的字典。 """ if not directory.exists() or not directory.is_dir(): raise ValueError(f"目录不存在: {directory}") # 分类统计 category_map = defaultdict(list) moved_count = 0 for item in directory.iterdir(): # 只处理文件,跳过子目录和报告文件本身 if not item.is_file(): continue if item.name == "archive_report.json": continue category = get_file_category(item.suffix) category_map[category].append(item.name) # 创建分类子目录 target_dir = directory / category if not dry_run: target_dir.mkdir(exist_ok=True) # 目标路径:避免重名覆盖 target_path = target_dir / item.name if target_path.exists(): stem = item.stem suffix = item.suffix counter = 1 while target_path.exists(): target_path = target_dir / f"{stem}_{counter}{suffix}" counter += 1 shutil.move(str(item), str(target_path)) moved_count += 1 # 生成报告 report = { "directory": str(directory), "dry_run": dry_run, "file_count": sum(len(files) for files in category_map.values()), "moved_count": moved_count if not dry_run else 0, "categories": {k: len(v) for k, v in category_map.items()}, "files": dict(category_map), } if not dry_run: report_path = directory / "archive_report.json" report_path.write_text( json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8", ) return report def main(): parser = argparse.ArgumentParser(description="文件归档技能") parser.add_argument("--directory", required=True, help="要归档的目录路径") parser.add_argument("--dry_run", action="store_true", help="只预览不实际移动") args = parser.parse_args() try: report = archive_directory(Path(args.directory), dry_run=args.dry_run) print(json.dumps(report, ensure_ascii=False, indent=2)) except Exception as exc: print(f"归档失败: {exc}") raise SystemExit(1) if __name__ == "__main__": main()

这里有几个细节值得说明:

  • get_file_category函数把常见扩展名归为五类,映射关系可以按实际需求调整。
  • 重名文件使用_1_2后缀避免覆盖,防止数据丢失。
  • dry_run模式只统计不移动,便于模型先向用户确认。
  • 报告统一输出为 JSON,方便上层解析。

4.3 测试技能脚本

先创建测试数据目录和几个文件:

mkdir -p data/sample_files cd data/sample_files echo "# 测试文档" > readme.md echo "一些笔记" > notes.txt touch photo.jpg echo "测试PDF" > report.pdf echo "print('hello')" > script.py cd ../..

先以 dry_run 模式运行,确认分类结果:

python skills/file-archiver/archive_files.py \ --directory data/sample_files \ --dry_run

预期输出类似:

{ "directory": "data/sample_files", "dry_run": true, "file_count": 5, "moved_count": 0, "categories": { "images": 1, "documents": 3, "code": 1 }, "files": { "images": ["photo.jpg"], "documents": ["readme.md", "notes.txt", "report.pdf"], "code": ["script.py"] } }

确认没有异常后,正式归档:

python skills/file-archiver/archive_files.py \ --directory data/sample_files

运行后查看目录结构:

tree data/sample_files

预期结果:

data/sample_files/ ├── archive_report.json ├── code/ │ └── script.py ├── documents/ │ ├── notes.txt │ ├── readme.md │ └── report.pdf └── images/ └── photo.jpg

到这一步,技能本身的逻辑已经完整了。

5. 实现技能加载器:让 Agent 能发现技能

5.1 技能加载器的作用

前面我们写了技能脚本,但 Agent 还不会自动发现它。现在写一个小型技能加载器,模拟 Agent 框架的“技能发现”机制。

它的职责:

  1. 扫描skills/目录下的所有子目录。
  2. 读取每个目录中的SKILL.md文件。
  3. 解析技能名称和描述。
  4. 提供执行技能的统一入口。

文件路径:agent/skill_runner.py

""" 技能加载器:扫描 skills 目录,提供技能发现与执行能力。 """ import json import subprocess from pathlib import Path class SkillRunner: def __init__(self, skills_root: str = "skills"): self.skills_root = Path(skills_root) self.skills = {} self._scan_skills() def _scan_skills(self): """扫描技能目录,读取每个技能的 SKILL.md 基本信息。""" if not self.skills_root.exists(): return for skill_dir in self.skills_root.iterdir(): if not skill_dir.is_dir(): continue skill_md = skill_dir / "SKILL.md" if not skill_md.exists(): continue # 简单解析 name 和 description name = skill_dir.name description = "" in_front_matter = False for line in skill_md.read_text(encoding="utf-8").splitlines(): if line.strip() == "---" and not in_front_matter: in_front_matter = True continue if line.strip() == "---" and in_front_matter: break if in_front_matter and line.startswith("description:"): description = line.split(":", 1)[1].strip() self.skills[name] = { "name": name, "description": description, "path": str(skill_dir), "script": str(skill_dir / (name + ".py")), } def list_skills(self) -> list: """返回所有技能的基本信息。""" return list(self.skills.values()) def get_skill_prompt_block(self) -> str: """生成一段可供注入系统提示词的技能描述文本。""" lines = ["可用技能列表:"] for skill in self.skills.values(): lines.append(f"- {skill['name']}: {skill['description']}") return "\n".join(lines) def run_skill(self, skill_name: str, args: list) -> dict: """ 执行指定技能。 参数: skill_name: 技能名称,例如 file-archiver args: 命令行参数列表,例如 ["--directory", "data/sample_files", "--dry_run"] 返回: stdout、stderr 和返回码。 """ if skill_name not in self.skills: raise ValueError(f"未找到技能: {skill_name}") script = self.skills[skill_name]["script"] cmd = ["python", script] + args result = subprocess.run( cmd, capture_output=True, text=True, encoding="utf-8", ) return { "stdout": result.stdout, "stderr": result.stderr, "returncode": result.returncode, } def run_skill_with_json(self, skill_name: str, args: list) -> dict: """执行技能并将 stdout 解析为 JSON。""" result = self.run_skill(skill_name, args) if result["returncode"] != 0: return { "success": False, "error": result["stderr"], } try: data = json.loads(result["stdout"]) return { "success": True, "data": data, } except json.JSONDecodeError: return { "success": True, "raw": result["stdout"], }

这个加载器的核心是subprocess.run,它通过命令行调用技能脚本。这样的好处是技能脚本可以用任何语言编写,不一定非得是 Python,只要支持命令行参数即可。

5.2 手动调用技能测试

文件路径:demo_manual.py

from agent.skill_runner import SkillRunner def main(): runner = SkillRunner(skills_root="skills") print("=== 可用技能 ===") for skill in runner.list_skills(): print(f"- {skill['name']}: {skill['description'][:50]}...") print("\n=== 注入系统提示词的文本 ===") print(runner.get_skill_prompt_block()) print("\n=== 以 dry_run 方式调用 file-archiver ===") result = runner.run_skill_with_json( "file-archiver", ["--directory", "data/sample_files", "--dry_run"], ) print(result) if __name__ == "__main__": main()

运行:

python demo_manual.py

如果输出中包含“归档失败”或者 JSON 报错,先检查技能脚本路径是否与skills/file-archiver/file-archiver.py一致。这里要说明一个问题:我们的技能脚本起名是archive_files.py,但加载器默认脚本名是技能目录名.py,所以这里要么把脚本改名,要么修改加载器逻辑。

为了让项目一致,推荐把脚本名改为file-archiver.py

修改命令:

mv skills/file-archiver/archive_files.py skills/file-archiver/file-archiver.py

如果保持原脚本名不变,也可以修改SkillRunner中的逻辑,让每个技能在 SKILL.md 中声明脚本文件名。这更像真实框架的做法。这里为了简单,统一使用“技能目录名.py”作为脚本名。

再次运行,确认技能加载器正常工作。

6. 接入大模型:用自然语言触发 Skill

6.1 整体思路

现在到了最关键的一步:让大模型根据用户输入,自动决定是否调用 file-archiver 技能。

流程如下:

  1. 用户输入:“帮我把 data/sample_files 整理一下”。
  2. 系统把技能描述注入系统提示词。
  3. 模型返回一个结构化 JSON 调用请求,比如{"skill": "file-archiver", "args": ["--directory", "data/sample_files"]}
  4. 系统解析 JSON,调用 SkillRunner 执行技能。
  5. 把执行结果返回给模型,模型生成人类可读的总结。

6.2 使用 OpenAI SDK 实现

先安装依赖:

pip install openai

然后编写demo_with_model.py

这里需要说明,OpenAI SDK 不同版本调用方式略有差异,本文以 1.x 版本为例。如果你用的是 0.x 老版本,API 调用方式需要相应调整。

""" 接入 OpenAI 的 Agent Skill 演示。 流程: 1. 调用模型,把技能描述和用户请求一起发送。 2. 模型返回结构化 JSON,指定要调用的技能和参数。 3. 执行技能。 4. 将结果再次交给模型总结。 """ import json import os from openai import OpenAI from agent.skill_runner import SkillRunner client = OpenAI(api_key=os.getenv("OPENAI_API_KEY", "your-api-key")) SYSTEM_PROMPT_TEMPLATE = """你是一个智能助手。你有以下技能可以调用: {skill_prompt} 如果用户请求涉及可用的技能,你必须返回如下 JSON(不要返回其他文字): {{ "skill": "技能名称", "args": ["参数1", "参数2"] }} 如果用户请求不涉及任何技能,请直接回复普通文本。 """ def build_messages(user_input: str, skill_prompt: str): system_prompt = SYSTEM_PROMPT_TEMPLATE.format(skill_prompt=skill_prompt) return [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_input}, ] def extract_skill_call(content: str): """解析模型返回内容。如果包含技能调用 JSON,则返回对应结构。""" try: data = json.loads(content) if "skill" in data and "args" in data: return data except json.JSONDecodeError: pass return None def main(): runner = SkillRunner(skills_root="skills") skill_prompt = runner.get_skill_prompt_block() user_input = "请把 data/sample_files 目录按类型整理一下,先预览不要真移动" messages = build_messages(user_input, skill_prompt) response = client.chat.completions.create( model="gpt-4o-mini", # 或你账号可用的其他模型 messages=messages, temperature=0, ) model_content = response.choices[0].message.content print("模型返回:", model_content) skill_call = extract_skill_call(model_content) if skill_call is None: print("模型未调用技能,直接回复:", model_content) return skill_name = skill_call["skill"] args = skill_call["args"] print(f"\n执行技能:{skill_name}") print("参数:", args) # 这里注意:如果模型没有传 --dry_run,我们可以补上,防止误操作 if "--directory" in args and "--dry_run" not in args: args.append("--dry_run") print("已自动追加 --dry_run,安全预览。") result = runner.run_skill_with_json(skill_name, args) print("技能执行结果:") print(json.dumps(result, ensure_ascii=False, indent=2)) # 把执行结果交给模型总结 summarize_messages = [ {"role": "system", "content": "你是一个助手,请用简洁的中文总结技能执行结果。"}, {"role": "user", "content": f"技能执行结果如下:\n{json.dumps(result, ensure_ascii=False)}"}, ] summary_response = client.chat.completions.create( model="gpt-4o-mini", messages=summarize_messages, temperature=0, ) print("\n总结:", summary_response.choices[0].message.content) if __name__ == "__main__": main()

6.3 安全说明

上面代码中,我先强制加入了--dry_run,这是很重要的一个工程习惯。

文件移动、删除、覆盖这类操作,在生产环境中风险很高。如果你让 Agent 直接操作真实目录,建议遵循以下原则:

  • 默认先 dry-run。
  • 需要用户二次确认后再真正执行。
  • 操作前备份关键文件。
  • 尽量使用测试目录验证。

6.4 没有 OpenAI Key 怎么办

如果你暂时没有 OpenAI API Key,也可以不运行这一段,前面第 4、5 章的本地技能本身已经能说明 Skills 的核心机制。

如果想要一个完全离线、不依赖外部 API 的演示方式,可以写一个“伪模型决策”函数,用关键词规则模拟模型判断:

def mock_skill_call(user_input: str): """模拟模型决策过程,不使用外部 API。""" if "整理" in user_input or "归档" in user_input: return { "skill": "file-archiver", "args": ["--directory", "data/sample_files"], } return None

这种设计在学习阶段非常实用,能让你在没有 API 的情况下先跑通整个调用链。

7. 常见问题与排查思路

在实际开发和运行中,下面几个问题出现频率最高。

问题现象常见原因解决思路
技能脚本无法导入项目根目录不在 sys.path在项目根目录运行,或用python -m agent.skill_runner
技能脚本名称与目录名不一致加载器默认拼接脚本路径统一脚本名,或在 SKILL.md 中声明脚本名
模型返回的不是 JSON提示词约束不够强增加 few-shot 示例,使用更低 temperature
dry_run 模式下仍然移动了文件参数解析逻辑有误检查脚本中 dry_run 分支,确保移动代码在 if 内
Windows 下 subprocess 中文乱码编码未指定在 subprocess.run 中设置 encoding="utf-8"
技能目录被当成普通文件处理扫描逻辑判断错误检查是否使用 is_dir() 过滤
模型调用了不存在的技能SKILL.md 描述不清楚重新检查技能描述,降低描述歧义
文件重名导致覆盖没有做重名处理使用带序号的新文件名,避免覆盖

这里特别要说一下编码问题。在 Windows 下,Python 默认编码可能是 GBK,如果你在执行脚本时遇到中文乱码或编码异常,可以在调用脚本前设置环境变量:

# Windows PowerShell $env:PYTHONIOENCODING="utf-8"

或者在 Python 代码里,在main()开头加:

import sys sys.stdout.reconfigure(encoding="utf-8")

另外,排查任何 Agent Skill 问题时,建议先脱离大模型,手动运行技能脚本。如果脚本本身能正常工作,那问题基本出在模型提示词或参数解析环节。

8. 最佳实践与工程建议

8.1 Skill 命名与目录规范

  • 技能目录名使用短横线分隔,例如file-archiverdb-backup
  • 脚本名与目录名保持一致,减少加载器复杂度。
  • 每个技能目录必须包含 SKILL.md,否则加载器应跳过并告警。
  • 同一个技能目录里如果有多个脚本,确保只有一个入口脚本,其他作为辅助模块。

8.2 提示词与技能描述设计

SKILL.md 里的 description 是模型判断是否调用的关键,不要写得太模糊。

反面示例:

description: 整理文件的技能。

正面示例:

description: 将指定目录下的文件按扩展名分类归档,并生成归档报告。适合整理下载目录、项目文档目录等场景。

关键词是“什么时候用”和“效果是什么”。

8.3 参数安全与权限控制

Agent Skill 落地到生产环境时,一定要关注参数注入问题。

比如你的技能脚本接收目录参数,那用户可以让 Agent 访问服务器任意目录。建议:

  • 配置白名单目录,只允许技能操作允许范围内路径。
  • 对参数做路径标准化检查,避免../穿越。
  • 敏感操作增加确认机制。
  • 对执行用户做最小权限控制,不要用 root 运行 Agent。
  • 涉及数据库变更、删除操作时,先备份,再执行,最后验证。

8.4 结果输出与可观测性

技能执行结果不要只输出一句“完成”。建议:

  • 输出结构化 JSON。
  • 记录执行耗时。
  • 记录操作前后的状态变化。
  • 写入执行日志。

这样上层 Agent 才能更好地判断“这次执行到底成功没有”。

8.5 Skill 的测试方法

一个成熟的 Skill 应该配套测试:

  • 单元测试:测试核心函数。
  • 集成测试:模拟命令行调用。
  • 干跑测试:在测试目录中完整执行一次。

建议为每个 Skill 维护一个tests/目录。学习阶段也许觉得麻烦,但一旦技能数量多了以后,回归测试能帮你省下大量时间。

9. 学习路线与进阶方向

9.1 本文掌握要点

到这里,你已经完成了 Agent Skills 从概念到实战的闭环:

  • 理解了 Skills 和 Tools、Function Calling 的区别。
  • 掌握了 SKILL.md 的结构和编写规范。
  • 用 Python 实现了一个文件归档技能。
  • 写了一个技能加载器,实现了技能自动发现。
  • 通过大模型接口实现了自然语言触发技能调用。
  • 了解了生产环境下的安全和排错思路。

这套流程并不只适用于某一个框架。无论你以后使用 Claude Skills、OpenAI 的 Assistant 工具,还是 Dify、AgentScope 等国产框架,底层思想都很接近。

9.2 下一步可以学什么

  1. 学习 Anthropic 官方 Claude Skills 格式,它和本文结构非常接近。
  2. 研究主流 Agent 框架,比如 LangChain、CrewAI、Dify,看它们的 Tools 和 Skills 是怎么注册的。
  3. 尝试写一个“多技能协作”案例,比如一个技能负责收集数据,另一个技能负责生成报告。
  4. 学习 MCP(Model Context Protocol),理解 Agent 如何通过标准化协议访问外部数据源。

9.3 项目落地时的风险提示

最后,给你一个真实项目中的实用建议:先跑通最小闭环,再扩展技能数量。

很多开发者在学习 Agent 时会犯一个错误——一开始就追求技能数量,今天加一个天气查询,明天加一个数据库操作,最后发现模型经常选错工具。更好的做法是先把 1 到 2 个高质量技能打磨好,让模型的调用率稳定在较高水平,再逐步扩展。

存储、目录、文件操作类技能是练手首选,因为它们逻辑清晰、容易验证结果。等这一类技能稳定了,再去挑战数据库操作、外部 API 集成这些更复杂的技能。

希望这篇教程能帮你迈过 Agent Skills 的入门门槛。如果觉得有用,可以收藏备用;有任何问题,也欢迎在评论区交流。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 3:18:10

猜数字游戏:从C语言基础到工程实践的最佳入门项目

说到C语言入门,有一个项目几乎每个人都绕不开,那就是猜数字游戏。不管是初学者刚上手,还是准备计算机二级考试,甚至很多嵌入式方向的朋友第一次写小工具,都会拿它练手。我见过至少几十个从这十几行代码起步的人&#x…

作者头像 李华
网站建设 2026/9/8 3:18:03

Prisma3D作品发布安全指南:从建模到原创申诉的工程化流程

深夜一点,你把 Prisma3D 里的角色动画终于调好了,导出渲染视频,传到短视频平台,配上一段节奏感很强的 BGM。第二天醒来,打开消息栏,看到的不是播放量上涨,而是一条“作品疑似搬运或非原创&#…

作者头像 李华
网站建设 2026/9/8 3:17:16

小语文稿免费替代Typora,本地离线Markdown写作工具实操指南

之前被 Typora 右下角弹窗提示搞到心态崩溃的应该不止我一个:要么找激活码,要么花 89 元买授权。网上搜出来的序列号要么失效,要么来源不明,点进去还怕附带安全问题。后来我干脆换了一种思路:Markdown 编辑器本来就不是…

作者头像 李华
网站建设 2026/9/8 3:16:18

从“新地图发布”到“新系统上线”:僵尸模式地图的工程全貌

从“新地图发布”到“新系统上线”:一个僵尸模式地图的工程全貌很多人看到“亡者再临 v1.2.0 正式发布!!!”这类公告,第一反应是“又有新地图可以玩了”。但如果你真在一线做过游戏开发,看到这行字的第一反…

作者头像 李华
网站建设 2026/9/8 3:16:15

Nessus Essentials免费漏洞扫描工具安装与实战教程

Nessus 是目前使用范围很广的漏洞扫描工具,无论是在安全团队做渗透测试、在运维部门做基线核查,还是在服务器上线前做安全自查,基本都会用到它。很多新手第一次搜教程,看到的却是“破解版”“一键激活”这一类内容。我的建议是&am…

作者头像 李华
网站建设 2026/9/8 3:15:41

PTP高精度对时源码解析:从NTP到微秒级同步的工程实践

简介:这是一份基于IEEE 1588标准的PTP高精度对时C语言源代码库,面向电信、电力、金融交易及工业控制等需要微秒级时间同步的开发者,提供协议解析、时间戳处理、同步算法、网络收发及守护进程等核心实现,便于构建自研PTP客户端或服…

作者头像 李华