ARTICLE DETAIL

资讯详情

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

Agent Skills 实战指南:从原理到编写可复用技能包

Agent Skills 实战指南:从原理到编写可复用技能包 1. 从“skills”这个热词说起它到底是什么最近半年不管是在技术社区、开发者群聊还是各种工具链的讨论帖里“skills”这个词出现的频率高得离谱。很多人第一次看到“skills”这个词脑子里浮现的是招聘网站上的“技能要求”但在当下的语境里它指的是一套全新的能力封装机制——Agent Skills。简单说就是把一段可复用的指令、流程、工具调用逻辑打包成一个标准化的“技能包”让 AI agent 能够按需加载、按需执行。你可能会问这不就是插件吗不完全是。插件更多是给宿主程序增加功能而 skills 的核心在于“教会 agent 怎么做一件事”。它更像是一份写给 AI 看的操作手册里面包含了触发条件、执行步骤、依赖工具、输出格式甚至还有失败重试的逻辑。一个写得好的 skill能让 agent 从“能聊天”变成“能干活”。这套机制最早在 Claude 的生态里被大规模讨论后来 Codex、Google Cloud 的 agent 体系也陆续跟进。现在你在 GitHub 上搜 “skills”能翻出成百上千个仓库有做代码审查的、有做论文写作的、有做分镜脚本的甚至还有专门用来“自动挖洞”的安全类 skill。热词里提到的 “claude agent skills: a first principles deep dive”、“codex skills”、“agent skills 测试”这些都是这个生态里的典型话题。这篇文章适合谁看如果你是刚接触 agent 开发的工程师想搞清楚 skills 的目录结构、加载机制和调试方法那这篇就是写给你的。如果你已经在用 Claude 或 Codex 做日常开发想把自己重复性的工作流封装成 skill那更好我会把实操步骤拆到你能直接抄作业的程度。如果你只是好奇“skills 大全”里到底有什么、值不值得花时间折腾我也会给你一个务实的判断。2. 核心机制拆解skills 为什么这样设计2.1 从“提示词工程”到“技能封装”的演进逻辑早期我们用 AI 写代码靠的是在对话框里反复调提示词。今天写一个“帮我审查这段 Python 代码”的提示明天写一个“帮我生成单元测试”的提示每次都要重新描述一遍上下文。这种做法的问题很明显不可复用、不可版本管理、不可组合。你调好了一个提示词换一个会话就没了想分享给同事只能复制粘贴。skills 的出现本质上是对“提示词工程”的一次工程化改造。它把提示词从“一次性对话内容”变成了“可持久化的文件资产”。一个 skill 通常是一个目录里面至少有一个SKILL.md文件用 YAML frontmatter 声明元信息用 Markdown 正文描述执行逻辑。agent 在启动时会扫描 skills 目录根据当前任务匹配对应的 skill然后加载它的内容作为系统提示的一部分。这个设计的好处在于第一可版本控制skill 文件可以提交到 Git谁改了什么一目了然第二可组合一个任务可以同时加载多个 skill比如“代码审查”加“安全扫描”加“性能分析”第三可测试你可以写测试用例来验证 skill 在给定输入下是否产生预期输出。2.2 SKILL.md 的结构与字段含义一个标准的 skill 目录长这样my-skill/ ├── SKILL.md ├── scripts/ │ └── helper.py ├── references/ │ └── checklist.md └── assets/ └── template.json核心是SKILL.md它的开头必须是 YAML frontmatter--- name: code-review description: 对指定代码文件进行结构化审查输出问题清单和改进建议 version: 1.2.0 author: your-name tags: - code-quality - review ---name是 skill 的唯一标识agent 在匹配时会用它来索引。description最关键它决定了 agent 在什么场景下会触发这个 skill。写得太宽泛比如“帮助处理代码”会导致误触发写得太窄比如“审查 Python 3.11 中 asyncio 的异常处理”又会导致该触发的时候不触发。我的经验是description 里要包含动作、对象和输出三个要素比如“审查 Python 代码文件输出按严重程度排序的问题列表”。正文部分就是写给 agent 的指令。这里有个常见的误区很多人把正文写成给人看的文档用了大量“本文将介绍”“首先我们需要”这种叙述性语言。实际上 agent 不需要这些过渡它需要的是明确的步骤、判断条件和输出格式。我一般会按这个结构来写## 执行步骤 1. 读取用户指定的文件路径如果路径不存在返回错误信息并终止。 2. 按以下维度逐行检查 - 变量命名是否符合 snake_case - 是否有未处理的异常分支 - 是否存在硬编码的密钥或令牌 3. 对每个发现的问题记录行号、问题类型、严重程度高/中/低。 4. 按严重程度降序排列输出 Markdown 表格。 ## 输出格式 | 行号 | 问题类型 | 严重程度 | 建议 | |------|----------|----------|------| | 12 | 命名不规范 | 低 | 改为 user_name |2.3 加载机制agent 怎么找到并执行 skill不同平台的加载机制略有差异但核心逻辑大同小异。以 Claude 的 agent 体系为例skills 通常放在项目根目录的.claude/skills/下或者用户主目录的~/.claude/skills/下。agent 启动时会递归扫描这些目录读取每个SKILL.md的 frontmatter建立一个“技能索引”。当用户发起一个任务时agent 会先做一次意图匹配把用户输入和所有 skill 的 description 做语义相似度计算选出 top-k 个候选 skill。然后根据任务的复杂度决定是加载一个还是多个。加载之后skill 的正文内容会被拼接到系统提示里agent 就“学会”了这个技能。这里有个细节值得注意skill 的加载是有 token 成本的。一个写得啰嗦的 skill 可能占用几千个 token加载三四个就把上下文窗口吃掉一大半。所以我在写 skill 时会尽量把通用知识放到references/目录里正文只保留执行逻辑需要时再让 agent 去读参考文件。这样既保证了灵活性又控制了上下文开销。3. 实操从零写一个可用的 skill3.1 环境准备与目录初始化假设你要写一个“自动生成单元测试”的 skill。第一步是确定存放位置。如果你用的是 Claude Code推荐放在项目根目录的.claude/skills/下这样团队里每个人拉取代码后都能直接用。如果是个人常用技能放在~/.claude/skills/下更合适。初始化命令很简单mkdir -p .claude/skills/unit-test-gen/scripts cd .claude/skills/unit-test-gen touch SKILL.md如果你用的是 Codex 体系目录名可能是.codex/skills/具体以你所用工具的文档为准。热词里提到的 “claude 国内安装 skills 官方市场” 和 “skills 下载平台有哪些”其实指的就是从社区仓库克隆现成的 skill 目录放到对应的 skills 路径下即可。我一般会先建一个vendor/目录来存放第三方 skill方便后续更新和替换。3.2 编写 SKILL.md 的完整示例下面是我实际在用的一个单元测试生成 skill 的完整内容你可以直接复制修改--- name: unit-test-gen description: 为指定的 Python 函数或类生成 pytest 单元测试覆盖正常路径、边界条件和异常分支 version: 1.0.0 tags: - testing - python - pytest ---正文部分## 前置检查 1. 确认用户提供了目标文件路径和函数名。如果缺少任一信息询问用户补充。 2. 读取目标文件定位到指定函数或类。如果找不到返回“未找到目标符号”并终止。 ## 生成规则 1. 为每个公开方法生成至少三个测试用例 - 正常输入下的预期输出 - 边界值如空列表、零、最大整数 - 异常输入如 None、类型错误 2. 使用 pytest 风格测试函数命名格式为 test_函数名_场景。 3. 如果目标函数依赖外部服务使用 unittest.mock 进行打桩不要发起真实网络请求。 4. 生成的测试文件放在与被测文件同级的 tests/ 目录下文件名格式为 test_原文件名.py。 ## 输出要求 - 只输出测试代码不要输出解释性文字。 - 代码块语言标注为 python。 - 如果目标函数已有测试文件追加新用例而不是覆盖。写完这个文件后你可以用npx来快速验证 skill 是否被正确加载。热词里提到的 “claude mcpservers npx” 和 “npx playwright install 失败”其实反映了一个常见场景很多 skill 依赖外部工具链比如 Playwright 用于浏览器自动化。如果你的 skill 里调用了npx playwright而本地没有安装浏览器二进制就会报错。解决办法是先手动执行npx playwright install chromium把依赖装好再让 agent 去调用。3.3 调试与验证怎么知道 skill 生效了写完 skill 后不要直接扔给 agent 跑复杂任务。我习惯先用一个最小可复现的输入来验证。比如对于上面的单元测试 skill我会准备一个简单的 Python 文件def add(a, b): if not isinstance(a, (int, float)) or not isinstance(b, (int, float)): raise TypeError(参数必须是数字) return a b然后对 agent 说“用 unit-test-gen 技能为 add 函数生成测试。” 如果 agent 正确加载了 skill它应该输出三个测试用例分别覆盖正常相加、边界值比如 0 和负数、以及类型错误。如果它只是泛泛地写了一个测试说明 skill 的 description 没有匹配上或者加载路径不对。排查加载问题的顺序是第一确认SKILL.md的 frontmatter 格式正确YAML 对缩进敏感一个 tab 就能让解析失败第二确认目录层级没有多一层或少一层有些工具要求 skill 目录直接放在 skills 根目录下不能再嵌套第三查看 agent 的启动日志通常会打印“loaded N skills”之类的信息如果数量不对说明扫描路径有问题。4. 进阶玩法组合、测试与性能优化4.1 多 skill 组合与优先级管理单个 skill 能做的事有限真正强大的是组合。比如你可以同时加载“代码审查”“安全扫描”“性能分析”三个 skill让 agent 对同一个文件做多维度检查。但这里有个坑不同 skill 的指令可能冲突。比如 A skill 要求输出 JSONB skill 要求输出 Markdownagent 就会懵。我的做法是在每个 skill 的 frontmatter 里加一个priority字段数值越小优先级越高。当冲突发生时agent 按优先级决定听谁的。另外我会在项目根目录放一个skills.config.json显式声明哪些 skill 可以同时加载、哪些互斥{ combinations: [ { skills: [code-review, security-scan], mode: sequential }, { skills: [unit-test-gen, coverage-report], mode: parallel } ], exclusive: [ [format-json, format-markdown] ] }这个配置文件不是所有平台都支持但你可以把它作为团队约定写在 README 里让每个人手动遵守。4.2 为 skill 写测试用例热词里有个词叫 “agent skills 测试”这说明大家已经意识到 skill 也需要测试。我通常用两种方式单元测试和端到端测试。单元测试针对 skill 里的脚本。比如你的 skill 包含一个scripts/parse_ast.py那就用 pytest 给它写测试验证输入输出是否符合预期。这部分和普通 Python 测试没区别。端到端测试更关键准备一组输入样本让 agent 加载 skill 后执行检查输出是否包含预期关键词。比如对于代码审查 skill我会准备一个故意包含漏洞的文件然后断言 agent 的输出里必须出现“硬编码密钥”和“未处理异常”这两个词。如果没出现说明 skill 的指令不够明确需要调整。我一般会把端到端测试写成 shell 脚本放在tests/e2e/下#!/bin/bash output$(agent run --skill code-review --input tests/fixtures/vulnerable.py) if echo $output | grep -q 硬编码密钥; then echo PASS else echo FAIL: 未检测到硬编码密钥 exit 1 fi4.3 控制 token 开销的实用技巧前面提到 skill 加载会消耗 token这里展开说几个我实测有效的优化手段。第一把长文档拆到 references 目录。正文只保留“什么时候读哪个文件”的指令比如“如果用户要求检查安全合规性读取 references/security-checklist.md”。这样 agent 只在需要时才加载大文件。第二用表格代替段落。同样的信息表格比段落节省 30% 到 50% 的 token。比如检查项列表用表格写“检查项 | 判断条件 | 严重程度”比用三段话描述要紧凑得多。第三避免重复描述。如果你有多个 skill 都需要“读取文件”这个步骤不要在每个 skill 里都写一遍而是抽出一个公共 skill让其他 skill 通过depends_on字段引用它。这样公共部分只加载一次。第四定期清理未使用的 skill。我见过一个项目里堆了四十多个 skillagent 每次启动都要扫描一遍光索引就吃掉不少 token。后来我按季度做一次清理把三个月没触发过的 skill 归档到skills-archive/目录启动速度明显提升。5. 常见问题与排查速查表5.1 skill 不触发或误触发怎么办这是最高频的问题。表现是你明明写了 skillagent 却不用或者你只是随便聊一句agent 却加载了一堆无关 skill。排查思路分三步。第一步检查 description 的语义覆盖范围。你可以把 description 和用户输入分别做 embedding算一下余弦相似度。如果低于 0.7基本不会触发如果高于 0.9可能误触发。第二步检查是否有多个 skill 的 description 高度相似导致 agent 选择困难。解决办法是给每个 skill 加一个exclusive_group字段同一组内只允许一个被加载。第三步检查 agent 的匹配阈值配置有些平台允许你调整触发灵敏度默认值可能偏保守。我自己的经验是description 里最好包含一个否定条件。比如“审查 Python 代码但不处理 Jupyter Notebook 文件”。这样能有效减少误触发。5.2 依赖工具安装失败的典型场景热词里 “npx playwright install 失败” 是个典型。很多 skill 依赖外部命令行工具比如 Playwright、FFmpeg、ImageMagick。如果这些工具没装好skill 执行到一半就会报错。我的做法是在 skill 目录下放一个setup.sh把所有依赖安装命令写进去#!/bin/bash set -e npm install -g playwright npx playwright install chromium --with-deps pip install -r requirements.txt然后在SKILL.md的前置检查里加一条“如果检测到依赖缺失提示用户先运行bash setup.sh。” 这样比让 agent 自己猜要可靠得多。另外网络环境不稳定时npx下载可能超时。可以配置镜像源或者提前把包缓存到本地。具体方法因环境而异核心思路是把不确定性前置解决不要让 agent 在运行时去处理网络问题。5.3 输出格式不稳定的修正方法同一个 skill有时候输出 Markdown 表格有时候输出 JSON有时候又变成纯文本。这种不稳定性通常是因为指令不够具体。修正方法是在SKILL.md里给出完整的输出模板而不是只描述格式要求。比如不要写“输出一个表格”而是写## 输出模板 严格按以下格式输出不要添加额外说明 | 行号 | 问题 | 严重程度 | |------|------|----------| | {line} | {issue} | {severity} |把占位符写清楚agent 的发挥空间就小了一致性自然就上来了。如果还是不稳定可以在 skill 里加一句“如果输出不符合模板重新生成一次”。5.4 速查表问题现象可能原因排查动作解决方式skill 不触发description 太窄检查语义相似度放宽 description加入同义词skill 误触发description 太宽检查是否有否定条件加入排除场景设置 exclusive_group加载报错YAML 格式错误用 yamllint 检查修正缩进避免 tab依赖缺失未安装外部工具查看错误日志编写 setup.sh 并前置执行输出格式乱指令不具体对比多次输出提供完整输出模板token 超限skill 太冗长统计 token 数拆分到 references用表格替代段落6. 我对 skills 生态的一些个人判断折腾了几个月 skills 之后我最大的体会是写 skill 的难度不在于技术而在于“把隐性知识显性化”。你脑子里知道怎么审查代码、怎么生成测试、怎么做安全扫描但要把这些步骤拆成 agent 能执行的指令需要你对流程有非常清晰的认识。很多 skill 写得不好不是因为作者不懂技术而是因为作者默认了很多前提条件没有写出来。另一个感受是skills 的复用价值被低估了。热词里 “skills 大全”“skills 推荐”“codex 好用的 skills” 这些搜索词说明大家有很强的“找现成”需求。但现成的 skill 往往和你的项目上下文不匹配直接拿来用效果一般。我的建议是先找几个高质量的 skill 作为参考理解它们的结构然后基于自己的实际工作流改写。改上三五个之后你就能形成自己的 skill 模板库了。最后分享一个小技巧我会在~/.claude/skills/下放一个_template/目录里面是空的SKILL.md骨架包含 frontmatter 和常用的章节标题。每次要写新 skill直接复制这个模板改改 name 和 description十分钟就能出一个初版。这个习惯让我从“想写 skill”到“写完 skill”的周期缩短了一大半。
返回列表