如果你最近刷到过那套标题为“从安装到 Skills 实战,再到多 Agent 协作”的 5 小时 Agent Skills 教程,应该会注意到一个现象:真正值钱的内容不是某个框架的 API 怎么调,而是“如何把一个能力做成可复用的 Skill”。评论区最常见的提问不是“这段代码什么意思”,而是“为什么我的 Agent 就是不调用这个 Skill”。
这不是个例。过去一年,AI Agent 的开发模式正在从“堆 Prompt + 堆工具函数”切换到“能力模块化”。模型负责思考,Skill 负责执行,Agent 负责编排。这篇文章就围绕这条主线展开:先讲清楚 Agent、Tool、Skill 的区别,再带你从零搭建一个可用的 Skill 项目,最后用一个多 Agent 协作示例说明 Skill 在生产项目里该怎么组织。
读完你应该能回答三个问题:Agent Skills 到底解决什么问题;一个合格的 Skill 目录结构长什么样;多 Agent 场景下,Skill 的边界应该划在哪里。
1. 为什么 Agent Skills 值得专门花时间研究
1.1 先看一个真实的开发痛点
很多团队把大模型接进业务后,初期效果惊艳,一个月后却陷入维护泥潭:
- 业务规则放在 system prompt 里,改一次规则要重新调一遍所有对话;
- 工具函数写了上百个,模型经常在相似函数之间选错;
- 同一个“代码审查”逻辑,在 A 项目的 Agent 里实现一遍,在 B 项目里又要重写;
- 多 Agent 协作时,每个 Agent 各写一套处理逻辑,换人接手直接看不懂。
这些问题本质上是同一个:能力没有模块化。Agent 的“决策外壳”和“执行能力”绑得太紧。
1.2 Skill 化之后发生了什么
把能力抽成 Skill 之后,变化发生在三个层面:
- 复用层:一个代码审查 Skill,可以被主 Agent、审查 Agent、代码生成 Agent 共用;
- 维护层:修改规则只需要改 Skill 内部文件,不需要动 Agent 的决策逻辑;
- 评测层:Skill 有固定输入和输出,可以单独跑一组测试用例验证质量。
换句话说,Agent Skills 不是某个厂商的专属功能,而是 Agent 工程化的一种组织方式。它把“让模型知道怎么做”和“让系统真正能执行”分开来管理。
1.3 什么样的读者最需要这篇文章
- 已经跑通过一个 Agent Demo,但不知道怎么接真实业务;
- 在多 Agent 项目里发现无法协作,想找一套拆解任务的思路;
- 想系统学习 Agent 开发,但被各种框架术语绕晕。
对完全没有接触过 Agent 的读者,本文也尽量从最小概念讲起,所有代码示例都可以直接复制跑通。
2. 先搞清楚三个概念:Agent、Tool、Skill
写 Agent Skills 最容易踩的第一个坑,是分不清这三个词。网上很多教程把 Tool 和 Skill 混着用,导致模型调用逻辑越来越乱。
2.1 概念对比
| 维度 | Tool(工具) | Skill(技能) | Agent(智能体) |
|---|---|---|---|
| 本质 | 单个可执行函数 | 一组能力包:指令 + 脚本 + 示例 | 具备感知、规划、行动的执行体 |
| 粒度 | 最小 | 中等,跨多个步骤 | 最大,负责完整任务 |
| 是否包含使用说明 | 通常只有函数签名 | 包含描述、步骤和示例 | 不直接包含执行细节 |
| 是否自己决策 | 否 | 否,等待被调用 | 是 |
| 典型示例 | 调用天气查询 API | 代码审查、数据清洗、报表生成 | 需求拆解 Agent、编码 Agent |
2.2 一句话区分
- Tool 是“手”:能执行一个具体动作,但它不知道什么时候该动手;
- Skill 是“一套动作 + 使用手册”:告诉模型在什么场景用、按什么步骤做、用什么脚本执行;
- Agent 是“大脑 + 调度器”:分析任务、选择调用哪个 Skill、决定什么时候停。
用一个现实类比:Agent 是餐厅店长,Skill 是后厨的标准化菜谱,Tool 是单个灶台或一把刀。店长不会直接去切菜,但必须知道哪道菜该交给哪个后厨、按什么菜谱做。
2.3 Skill 和 Function Calling 的区别
很多人在实际开发中会混淆 Skill 与 Function Calling。这两者有联系,但有本质区别:
- Function Calling 是模型输出结构化参数、由系统调用函数的一种机制,更偏向协议层面;
- Skill 是比函数更高一层的“能力封装”,它可能依赖多个函数、可能包含执行步骤、可能还附带示例输入输出;
- 一个 Skill 内部完全可以封装 Function Calling,但反过来不行。
这种分层设计的好处是:即使底层大模型从一个厂商切换到另一个厂商,只要 Skill 的接口不变,Agent 的调度逻辑就基本不需要动。
另外,有的框架把 Agent 周围负责编排、上下文管理的那一层称为 harness 或 orchestrator。它属于 Agent 的“骨架”,负责连接模型与 Skill。理解这个分层,再去看各种框架文档会轻松很多。
3. Skill 的典型应用场景与选型判断
3.1 适合用 Skill 的场景
从实际项目看,以下场景用 Skill 化收益最明显:
- 固定流程类:代码审查、SQL 生成与校验、单元测试生成、数据报表输出;
- 领域知识类:财务税务计算、医疗文本结构化、法律条款核对;
- 多步操作类:先读取文件、再清洗、再建模、最后输出报告;
- 团队协作类:多个 Agent 共享同一套领域规则。
这些场景有一个共同点:步骤相对固定、规则变化频繁、需要统一维护。近期吴恩达在多个 Agent 公开课程里反复强调的也是这个方向——把 agentic workflow 拆成可复用的技能单元,而不是把全部逻辑塞进提示词。
3.2 不适合用 Skill 的场景
反过来,如果任务每次都是全新的、几乎没有重复逻辑,强行 Skill 化只会增加维护成本。例如:
- 一次性数据分析探索;
- 纯闲聊型对话;
- 完全依赖模型临场发挥的头脑风暴。
Skill 的价值在于“重复”,没有重复就没有必要封装。
3.3 选型建议:框架还是自行实现
现在各大厂商和开源社区都提供了 Agent Skills 相关实现:有的以插件形式存在,有的以标准目录结构加脚本的形式存在。对学习阶段,更推荐先自行实现一个最小版本,原因有两个:
- 能理解 Skill 的本质,而不是被框架 API 带偏;
- 最小实现只有几十行代码,出了问题容易排查。
框架带来的收益主要在工程化层面,比如请求重试、上下文管理、并发控制。这些可以等最小版本跑通后再引入。
4. 环境准备与前置条件
本文的示例使用 Python,选择 Python 是因为它在 Agent 生态里资料最全、排错最容易。示例代码不依赖任何特定大模型 API,核心逻辑可以独立运行。
4.1 本地环境要求
- 操作系统:Windows / macOS / Linux 均可;
- Python 版本:建议 3.10 及以上,代码用到了 pathlib 和标准库,不需要额外安装第三方包;
- 命令行:能执行
python或python3。
4.2 创建项目目录
mkdir agent-skills-demo && cd agent-skills-demo python -m venv .venv source .venv/bin/activateWindows 下激活虚拟环境执行.venv\Scripts\activate。
4.3 整体目录规划
agent-skills-demo/ ├── skills/ │ └── code_review/ │ ├── SKILL.md │ ├── review.py │ └── examples/ │ └── bad_demo.py ├── agent_core.py └── main.py说明:
skills/存放所有可复用 Skill,每个 Skill 一个子目录;SKILL.md是 Skill 的“使用手册”,供模型读取;review.py是 Skill 的“执行引擎”;agent_core.py负责加载 Skill;main.py演示多 Agent 协作流程。
5. 从零实现一个代码审查 Skill
为了把概念落到能跑的代码上,我们实现一个“代码审查 Skill”。这个 Skill 解决一个真实场景:多 Agent 协作生成代码后,需要一个统一、可复用、规则可维护的检查环节。
5.1 第一步:编写 SKILL.md
SKILL.md是整个 Skill 的灵魂。它不仅是给人看的文档,更是模型决定“要不要调用这个 Skill”的依据。
# 文件路径:skills/code_review/SKILL.md --- name: code_review description: >- 对一份源代码执行静态审查,输出风险点、风险等级和修复建议。 当用户要求“审查代码”“检查 Bug”“Review 代码”“评估代码质量”时使用。 调用前需要拿到目标文件路径 target_path。 --- # Code Review Skill ## 输入 - target_path: 待审查的源文件路径,可以是绝对路径或相对路径 ## 执行步骤 1. 确认 target_path 存在且为文本文件 2. 调用 review.py 对文件做 AST 静态分析 3. 按 review.py 返回的结果生成 markdown 审查报告 4. 如果发现高风险问题,必须额外给出修复示例 ## 注意事项 - 只分析代码内容,不执行目标代码 - 如果文件无法解析,在报告中说明原因,不中断整个流程关键点在于description字段。模型通过 description 决定是否调用这个 Skill,描述里必须包含触发场景、必要参数,以及调用前需要准备什么。很多 Agent 不调用 Skill,一半以上是 description 写得不像“使用场景说明”,而像“功能简介”。
5.2 第二步:实现执行脚本 review.py
执行脚本负责真正的静态检查。这里用 Python 标准库自带的ast模块解析被审查代码,不执行目标代码,保证安全性。
# 文件路径:skills/code_review/review.py import ast import sys from pathlib import Path def analyze_file(target_path: str) -> dict: """对指定 Python 文件做启发式静态审查""" source_code = Path(target_path).read_text(encoding="utf-8") tree = ast.parse(source_code) risks = [] for node in ast.walk(tree): # 规则 1:裸 try/except 会吞掉异常,风险等级中 if isinstance(node, ast.Try): for handler in node.handlers: if handler.type is None and handler.name is None: risks.append({ "line": node.lineno, "type": "裸 except 吞掉异常", "level": "中", "suggestion": "捕获具体异常类型,并记录 error 日志", }) # 规则 2:函数分支过多,说明可读性差,风险等级低 if isinstance(node, ast.FunctionDef): branch_count = sum( 1 for child in ast.walk(node) if isinstance(child, (ast.If, ast.While, ast.For)) ) if branch_count > 5: risks.append({ "line": node.lineno, "type": "函数分支过多", "level": "低", "suggestion": "拆分为多个小函数", }) return { "file": target_path, "risk_count": len(risks), "risks": risks, } if __name__ == "__main__": if len(sys.argv) != 2: print("用法: python review.py <源文件路径>") sys.exit(1) result = analyze_file(sys.argv[1]) print(result)这段代码展示了 Skill 的一个核心设计:规则集中在脚本里,便于单独测试和维护。想要增加审查规则,只需要在analyze_file中追加ast节点判断逻辑。
这里真正容易踩坑的地方是 AST 输出行号与源文件行号对齐的问题。ast.parse在语法错误时会直接抛异常,所以脚本里建议后续捕获SyntaxError,避免因为一个文件解析失败导致整个 Agent 流程中断。
5.3 第三步:写一个故意有问题的示例
为了验证 Skill 生效,建一个带问题的示例文件。
# 文件路径:skills/code_review/examples/bad_demo.py def divide(a, b): try: return a / b except: return None这个文件有一个明显问题:裸except会吞掉所有异常,包括键盘中断和系统退出。用我们的 Skill 至少能检查出这个问题。
5.4 第四步:实现 Skill 加载器 agent_core.py
Agent 需要一个统一入口加载 Skill。加载器把SKILL.md里的描述和脚本里的函数绑定在一起。
# 文件路径:agent_core.py import importlib.util import re from pathlib import Path class SkillRegistry: """简化版 Skill 注册表:负责发现、加载和缓存 Skill""" def __init__(self, skills_root: Path): self.skills_root = Path(skills_root) self._skills = {} def discover(self): for skill_dir in self.skills_root.iterdir(): if not skill_dir.is_dir(): continue md_path = skill_dir / "SKILL.md" if not md_path.exists(): continue self._load_one(skill_dir, md_path) return self._skills def get(self, name: str) -> dict: if name not in self._skills: raise KeyError(f"Skill 未注册: {name}") return self._skills[name] def _load_one(self, skill_dir: Path, md_path: Path): text = md_path.read_text(encoding="utf-8") name_match = re.search(r"^name:\s*(\S+)", text, re.MULTILINE) if not name_match: raise ValueError(f"{md_path} 缺少 name 字段") name = name_match.group(1) script_path = skill_dir / "review.py" if not script_path.exists(): raise FileNotFoundError(f"{skill_dir} 缺少执行脚本 review.py") spec = importlib.util.spec_from_file_location(f"{name}_impl", script_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) self._skills[name] = { "name": name, "description": self._parse_description(text), "analyze_file": module.analyze_file, } @staticmethod def _parse_description(text: str) -> str: match = re.search( r"^description:\s*>\s*\n(.*?)^---", text, re.MULTILINE | re.DOTALL, ) if not match: return "" return " ".join( line.strip() for line in match.group(1).splitlines() if line.strip() )这个注册表的职责很简单:扫描skills/目录、解析SKILL.md元信息、动态加载脚本。真实项目中,这里会变成框架的插件机制,但核心思想一样。
6. 多 Agent 协作:Skill 如何支撑复杂任务
有了可复用的 Skill,多 Agent 协作才有意义。如果每个 Agent 都自己实现一套审查逻辑,协作就变成了代码复制大赛。
6.1 协作模式:编排者 + 角色 Agent
在真实项目中,多 Agent 协作最常见的模式是:
- 一个编排者(Orchestrator)负责拆解任务、分配子任务;
- 多个角色 Agent(需求 Agent、编码 Agent、审查 Agent)分别处理自己的环节;
- 每个角色 Agent 内部调用对应的 Skill 完成具体执行。
在这种结构里,Skill 是角色 Agent 的“专业能力”。审查 Agent 的决策逻辑只有一小段,真正的专业能力都在code_reviewSkill 里。
6.2 完整协作示例 main.py
下面用一个最小可运行的流程演示:需求拆解 Agent 把任务拆成步骤,编码 Agent 生成代码,审查 Agent 调用code_reviewSkill 检查结果。
# 文件路径:main.py import json from pathlib import Path from agent_core import SkillRegistry def role_decompose(task: str) -> list[str]: """需求拆解 Agent:将主任务拆成子步骤 生产环境这里调用大模型接口,演示环境用固定规则""" return ["编写实现代码", "执行代码审查", "输出修复建议"] def role_coder(task_step: str) -> str: """编码 Agent:生成代码并落盘 生产环境由大模型生成,演示环境写入一段固定样例代码""" code = ( "def divide(a, b):\n" " try:\n" " return a / b\n" " except:\n" " return None\n" ) target = Path("tmp_work/target.py") target.parent.mkdir(exist_ok=True) target.write_text(code, encoding="utf-8") return str(target) def role_reviewer(registry: SkillRegistry, file_path: str) -> dict: """审查 Agent:调用 code_review Skill 执行检查""" skill = registry.get("code_review") return skill["analyze_file"](file_path) def main_flow(task: str) -> dict: registry = SkillRegistry(Path("skills")) registry.discover() steps = role_decompose(task) report = None target = None for step in steps: if "编码" in step or "实现" in step: target = role_coder(step) if "审查" in step or "检查" in step: report = role_reviewer(registry, target) return report if __name__ == "__main__": result = main_flow("实现一个除法函数,并执行代码审查") print(json.dumps(result, ensure_ascii=False, indent=2))注意,演示代码里刻意没有接真实大模型,因为本文的重点是 Skill 的工程结构,而不是某个模型的 API。真实项目中,role_decompose、role_coder都会替换成大模型调用,但role_reviewer这段调用 Skill 的代码基本保持不变。这就是 Skill 化带来的稳定性:模型的输出可以不稳定,但审查规则是确定的。
6.3 分工的边界
在多 Agent 场景里,划分 Skill 边界有三条原则:
- 按能力域划分,不按 Agent 划分:比如“代码审查”是一个能力域,而不是“审查 Agent 的私有逻辑”;
- 一个 Skill 只做一件事:审查就是审查,不要顺手做格式化、部署;
- Skill 之间不要互相调用:协作应该发生在 Agent 层,而不是 Skill 内部。否则会形成难以排查的调用链。
7. 运行验证与结果判断
代码写完不代表结束,Skill 工程化最重要的一步是验证。
7.1 单独验证 Skill
先不启动整个流程,单独运行review.py验证 Skill 本身是否可用。
python skills/code_review/review.py skills/code_review/examples/bad_demo.py预期输出(不同 Python 版本下字典顺序可能有差异,但结构一致):
{'file': 'skills/code_review/examples/bad_demo.py', 'risk_count': 1, 'risks': [{'line': 3, 'type': '裸 except 吞掉异常', 'level': '中', 'suggestion': '捕获具体异常类型,并记录 error 日志'}]}如果能看到risk_count: 1,说明 Skill 的执行脚本工作正常。
7.2 验证 Skill 加载器
python -c "from agent_core import SkillRegistry; from pathlib import Path; r = SkillRegistry(Path('skills')); print(r.discover().keys())"预期输出dict_keys(['code_review'])。如果为空,检查skills/目录结构和SKILL.md的name字段是否拼写正确。
7.3 验证多 Agent 协作流程
python main.py预期输出是一份包含file、risk_count、risks的 JSON。这里最容易出现的错误是agent execution terminated due to error.这类运行时中断。出现时不要先怀疑模型,先检查三层:脚本路径、模块导入、函数名是否匹配。
7.4 判断成功与否的标准
一个 Skill 算不算合格,可以从四个维度判断:
- 能被发现:注册表能扫到它;
- 能被描述:模型读 description 后能理解使用场景;
- 能被调用:执行脚本输出稳定结果;
- 能被复用:在多个 Agent 流程中都能调用同一个函数。
生产级别还要加第五条:能被评测。给 Skill 准备一组固定测试用例,每次修改后跑一遍,防止改出回归问题。
8. 常见问题与排查方法
学习和实战中最常遇到的问题,集中在描述不清、加载失败、流程中断和安全越权四个方面。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| Agent 从不调用某个 Skill | description写得像功能简介,没有触发场景 | 检查 SKILL.md 的描述是否包含关键词和调用条件 | 重写 description,加入触发场景、必要参数、前置条件 |
| SKILL.md 解析失败,注册表为空 | YAML frontmatter 缺少结束符,或name字段写错 | 用命令直接读取前 20 行检查格式 | 确保前后---闭合,name和description严格缩进 |
agent execution terminated due to error. | 脚本路径错误或函数导入失败 | 先单独运行 review.py,再检查 agent_core.py 的导入逻辑 | 确认文件路径存在,函数名和_load_one中调用一致 |
| Skill 输出结果不稳定 | 脚本内部使用了非确定性逻辑,或解析了错误文件 | 对同一输入运行多次,对比输出 | 把规则写成纯函数,输入输出保持确定性 |
| 多 Agent 场景互相干扰 | Skill 内部依赖全局变量或共享文件 | 检查是否有全局状态,观察并发调用现象 | Skill 内只使用局部变量,文件写入使用隔离目录 |
| Skill 执行了危险操作 | 脚本包含删除、执行外部命令等高风险逻辑 | 审查 Skill 脚本的文件操作和系统调用 | 收敛权限,禁止高风险调用,增加沙箱隔离 |
9. 最佳实践与工程建议
9.1 配置文件级守护:SKILL.md 是给模型看的
写 Skill 时,最容易忽略的是description的语义质量。一个合格的描述应该回答三个问题:何时用、怎么用、需要什么输入。可以参考下面的模板:
--- name: 技能名称 description: >- 在[具体业务场景]中,当用户[触发条件]时使用。 需要提供[必要参数],执行[关键动作],输出[产出物]。 ---如果发现模型经常在多个 Skill 之间选错,大概率是 description 里的触发词重叠太多。这时要明确区分边界,比如“审查”与“重构”不要同时出现在两个 Skill 的描述开头。
9.2 保持单一职责
一个 Skill 只负责一个能力域。宁可多建几个 Skill,也不要在一个 Skill 里塞进“审查 + 格式化 + 部署”三件事。单一职责直接决定了 Skill 的可维护性和可复用性。
9.3 规则代码与决策逻辑分离
这一点在本文示例里体现得很明确:审查规则写在review.py,模型决策在main.py的 Agent 层。规则层应该完全确定性,决策层可以接受不确定性。这种分离让测试变得容易,也让非算法工程师也能维护规则。
9.4 安全问题:Skill 就是攻击面
Skill 本质上是把大模型输出的“文本意图”翻译成“系统动作”,因此它天然是攻击面。实际项目中要特别注意:
- 最小权限:Skill 进程只授予完成任务所需的最小文件、网络和系统权限;
- 沙箱隔离:涉及文件写入、命令执行时,在独立沙箱或容器中运行;
- 审计日志:记录谁在什么时候调用了哪个 Skill、传入了什么参数;
- 输入校验:目标文件路径做白名单校验,防止路径穿越;
- 禁止高危操作:默认禁止删除文件、修改全局配置、执行未经验证的 shell 命令。
9.5 版本管理与评测
Skill 的规则会频繁变化,建议像管理代码一样管理 Skill:
- 每个 Skill 目录纳入 Git 版本管理;
- 修改规则必须同步更新示例和测试用例;
- 发布前跑一遍 Skill 的回归用例;
- 在团队中建立“Skill 变更评审”流程,避免规则被悄悄改坏。
9.6 不要过早框架化
很多初学者一上来就引入大型 Agent 框架,结果被配置项淹没。更务实的学习路径是:先用最小实现跑通一个 Skill,理解目录结构、描述加载、脚本调用这三件事;再引入框架的插件机制、并发控制和上下文管理;最后再设计多 Agent 协作方案。
10. 总结与后续学习方向
Agent Skills 的流行,本质上是 Agent 从 Demo 走向生产的必然结果。模型的思考能力再强,如果没有稳定、可复用、可维护的执行能力,Agent 就永远只是聊天机器人。Skill 化把“能力”从“决策”中剥离出来,用一套统一的标准组织复杂任务,这正是多 Agent 协作能够落地的前提。
本文用一个最小可运行的代码审查示例,走完了 Skill 从设计、编写、加载到多 Agent 复用的全过程。下一步你可以做三件事:
- 把
code_review的规则扩展成自己业务里的检查项,比如接口参数校验、SQL 注入风险扫描; - 把
role_decompose和role_coder替换成真实大模型调用,感受模型决策与 Skill 执行分离的稳定性; - 尝试拆分第二个 Skill,然后观察多个 Skill 在同一个 Agent 流程里如何被调度。
建议收藏这套目录结构和验证方法。后续无论切换到哪个框架、哪个模型,这份“规则确定性 + 决策灵活性”的设计思路都不会过时。