☰
Agent Skills实战:从设计到实现,打造高效AI智能体技能
2026/10/7 11:23:36 网站建设 项目流程

最近在折腾 AI agent 项目,"agent-skills" 这个关键词几乎天天都要碰。圈子里聊得最多的就是:到底什么样的技能才叫一个合格的 skill?为什么同样的模型,有人调出来像个得力的实习生,有人调出来就像个只会复读的聊天机器人?差异往往就藏在 skills 的设计与实现上。

如果你正准备入坑 agent 开发,或者已经在用 Claude、Codex 这类编码智能体,想给它们装上更顺手的"手脚",这篇文章应该能帮你少走不少弯路。我会从第一性原理出发,拆解 agent skills 到底是什么、怎么设计、怎么实现,再附上完整实操案例和排坑记录,内容偏实战,尽量说人话。

1. agent skills 的本质:先搞清楚它解决了什么问题

1.1 从"工具"到"技能"的认知升级

很多人第一次接触 agent 时,最先听到的概念是 tool(工具),比如"搜索工具""计算器工具""数据库查询工具"。工具解决的是"单次、确定性"的操作——输入几个参数,返回一个结果。但真实世界的任务远没有这么简单。比如"帮我把这个项目的依赖升级到最新版本",这背后是一连串动作:先读 package.json、查当前版本、了解 breaking changes、改代码、跑测试、解决冲突、再跑测试……如果每一步都要 agent 自己临场发挥、现场拼接,结果往往很随机,今天能用明天就翻车。

这就是 skills 存在的意义。一个 skill 不是单个动作,而是把"完成某类任务的方法论"封装成一个可复用、可版本管理、可分享的单元。它包含了触发场景、执行步骤、避坑指南、示例代码,甚至允许 agent 在执行过程中动态调整策略。

我的理解是:tools 是乐高积木块,skills 是说明书加成套积木的组合包。积木块再多,没有图纸,新手也拼不出像样的东西;而 skills 就是那张图纸。

1.2 为什么现在 skills 这么火

最近"Claude agent skills"相关的讨论热度很高,GitHub 上各种 skill 仓库如雨后春笋。核心原因有三点,我逐一拆开讲。

第一,模型能力变强之后,瓶颈从"能不能理解"转移到了"有没有好的工作方法"。大模型的推理能力已经相当能打,但你给它一套混乱的执行框架,它也发挥不出应有水平。相反,一个精心设计的 skill 相当于把资深工程师的"肌肉记忆"喂给了 agent,质量和稳定性都会有明显提升。

第二,agent 的应用场景在快速拓宽。从写代码、改 bug 到数据分析、运维排查、内容创作,每个场景都有自己的专业套路。skills 提供了一种标准化的封装方式,让不同场景的 know-how 可以被沉淀、被分享、被复用。

第三,生态在快速形成。现在除了 Claude 官方的 skills 机制,Codex 有 codex skills,GitHub 有 skills 市场,国内也有不少第三方工作台在推自己的 skills 平台。这种生态效应让"会写 skills"逐渐变成 agent 开发者的基本功。

1.3 skills 和 tools、prompts 的边界在哪

这是新手最容易混淆的地方。我直接给一个对比表,看完基本就清楚了。

维度ToolsPromptsSkills
粒度单个动作指令文本方法集合
状态无状态,每次独立无状态可以有阶段、有记忆
复用性低,需要编排中,复制粘贴高,可安装可分发
触发方式显式调用上下文引导按需自动加载
包含内容函数+Schema提示词说明+脚本+示例+校验

写到这我要强调一个观点:不要试图用 skills 替代一切。简单、稳定、单一职责的操作,用 tools 反而更干净;跨步骤、多决策点、需要专业经验的任务,才值得封装成 skill。拿生活类比,开灯用开关(tool),但装修一套房子得靠施工方案和验收标准(skill),后者才需要沉淀成文档和流程。

2. skill 的架构拆解:一个合格技能的内部结构

2.1 SKILL.md:一切的核心入口

目前主流 agent 框架对 skill 的抽象高度一致:一个目录,里面至少有一个 SKILL.md 文件,负责让 agent"读懂"这个技能是干什么的、什么时候该用、怎么用。

SKILL.md 不是传统意义上写给人类看的 README,它更像是 agent 的"任务简报"。我见过写得好的 SKILL.md,几乎都有这几个特征:

  • 开篇用两三句话讲清楚这个 skill 适用的任务类型,以及不适用的情况,避免 agent 误触发。
  • 用清晰的层级标题组织"执行步骤",不是让人读着舒服,而是让 agent 的注意力能快速定位到当前阶段。
  • 包含具体的质量标准和完成定义,比如"测试覆盖率不得低于 80%""所有构造函数必须显式声明"。
  • 嵌入失败回退策略,告诉 agent 当步骤 A 失败时,是重试、降级还是向用户求助。

有一个常见误区是:把 SKILL.md 写成一本操作手册,翻到第三屏才能看到核心指令。agent 的上下文窗口虽然越来越大,但注意力永远是稀缺资源,信息密度低、通篇废话的 SKILL.md 会显著拉低执行质量。我在实际项目中的经验是,一份优秀的 SKILL.md 控制在 150~300 行以内,能用列表绝不用长段落,每一步都对应一个可验证的结果。

2.2 辅助脚本和资源:让技能真正"能干活"

光有说明文档还不够,真正落地的 skill 通常还包含:

  • 脚本文件,比如 Python、Shell 脚本,负责自动化执行具体步骤。
  • 模板文件,比如代码脚手架模板、汇报文档模板。
  • 配置文件,用于声明依赖、权限、执行环境。
  • 测试用例,供 agent 在完成实现后自行验证。

为什么需要这些"实体文件"?因为 agent 在推理过程中最大的短板是执行效率。一个生成 commit message 的 skill,如果每一步都靠模型现场推理,生成 100 条 commit message 的时间和 token 成本都很可观。但如果 skill 里内置一个脚本,先把 diff 抓出来,再批量调用模型或规则引擎处理,效率和稳定性都会上一个量级。

当然,辅助脚本不是越多越好。脚本越复杂,维护成本越高,出问题时排查难度也越大。我个人的原则是:能用十行 shell 解决的,不写五十行 Python;能用单个脚本搞定的,不拆成四个文件。

2.3 触发与加载机制:让技能在恰当的时机出现

skills 和传统工具最大的使用体验差异在于触发方式。传统工具是 agent 在每一步主动去"检索工具列表";而现代 skill 机制(尤其在 Claude 和 Codex 的实现里)倾向于把 skill 的元信息注入系统提示词或采用"按需加载"策略。

按需加载意味着:agent 在运行过程中遇到一个任务,先判断"这像不像某个 skill 擅长处理的问题",如果匹配,再读取完整的 SKILL.md 和资源文件,然后开始执行。这种方式大幅节约了上下文窗口,但也给 skill 的"元信息描述"提出了更高要求——描述写得模糊,agent 就无法建立匹配;描述写得过于宽泛,又容易误触发。

这里有一个非常实际的调试技巧:每次测试 skill 的时候,留意 agent 到底读取了哪些文件、在哪个环节决定启用这个 skill。如果每次都差一步才触发,问题大概率出在 SKILL.md 的"适用场景"描述上,而不是执行逻辑本身。

2.4 版本与依赖管理:skills 也是要长期维护的代码

我在团队里经常说一句话:skill 写得出来是一回事,养得活是另一回事。很多 skill 刚开始效果惊艳,跑两周就越来越笨,原因往往是:

  • 内部脚本依赖了外部服务,但 API 升级了没人同步。
  • SKILL.md 里的示例代码和当前项目的最佳实践脱节了。
  • skill 针对的框架版本变了大版本,但说明文档没更新。

所以,如果你有多个项目共用一套 skills,强烈建议用 Git 仓储管理,给每个 skill 打上版本号,在 SKILL.md 里声明适用的依赖版本范围。这个动作多做一步,后面能省下大量排查时间。

3. 从零到一:手把手实现一个真实可用的 skill

3.1 选场景:为什么我选了"前端组件代码审查"

光讲理论容易飘,我拿一个实际做过的 skill 举例:一个用于前端 React 组件代码审查的 skill。选这个场景有几个考虑:

  • 任务复杂度适中,既有确定性检查(比如 Hook 依赖数组),又有开放性判断(比如组件拆分是否合理)。
  • 结果可验证,审查结论可以对照资深前端工程师的手工审查结果来评估。
  • 具备通用性,很多人都在写 React,分享出来大家都能用。

你也可以按这个标准去选自己的第一个 skill 场景:不太简单、也不过于复杂,结果容易验收,且是自己反复要做的任务。第一个 skill 千万别选"帮我做架构设计""全面代码审计"这种又大又虚的,否则很容易在调试阶段就失去信心。

3.2 定义 SKILL.md 的内容结构

先看这个 skill 的目录结构:

react-component-review/ ├── SKILL.md ├── scripts/ │ └── check_hooks.py ├── rules/ │ └── react_rules.json └── examples/ ├── bad_component.jsx └── good_component.jsx

SKILL.md 的核心内容,我会这样设计:

# React Component Review ## Description Review React function components for code quality, focusing on hooks usage, state management, performance pitfalls, and accessibility issues. Use this skill when: - User asks to review a React component - User requests code quality assessment for frontend code - A pull request includes React component changes Do NOT use when: - Code is not React/JavaScript/TypeScript related - User only wants formatting fixes (use linting tools) ## Workflow 1. Understand the component's purpose and props - Read the component source code - Identify the component's responsibilities 2. Check hooks rules - Verify hook call order and conditions - Verify dependency arrays of useEffect/useCallback/useMemo - Look for missing cleanup functions 3. Check state and props handling - Identify unnecessary state duplication - Look for props drilling and suggest context if needed 4. Check performance patterns - Look for inline functions/objects in render - Check unnecessary re-renders 5. Check accessibility - Validate semantic HTML usage - Check aria attributes and keyboard support 6. Summarize findings into a report - Severity: critical/warning/suggestion - Include code snippets and concrete fix suggestions ## Standards - Critical: bugs, data loss, security risks - Warning: performance issues, maintainability concerns - Suggestion: style and best practice improvements

这个设计遵循了我前面说的原则:描述区先给触发条件,明确"何时用何时不用";流程区用有序列表把审查步骤拆成可执行的阶段;标准区解决"什么叫做好"的评判问题。整个文件控制在 100 行左右,信息密度足够高。

3.3 辅助脚本:让检查结果可量化

在辅助脚本这一层,我写了一个check_hooks.py,用 AST 解析 React 组件的 Hook 调用情况。

import ast import sys import json class HookVisitor(ast.NodeVisitor): def __init__(self): self.hook_calls = [] self.in_component = False def visit_FunctionDef(self, node): # 组件名以大写字母开头的函数视为组件 if node.name[0].isupper() and node.args.args: self.in_component = True self.generic_visit(node) self.in_component = False def visit_Call(self, node): if isinstance(node.func, ast.Name): name = node.func.id if name.startswith('use') and name[3].isupper(): self.hook_calls.append({ 'name': name, 'line': node.lineno, 'args_count': len(node.args), 'has_kw_args': bool(node.keywords) }) def main(filepath): with open(filepath, 'r', encoding='utf-8') as f: source = f.read() tree = ast.parse(source) visitor = HookVisitor() visitor.visit(tree) result = { 'file': filepath, 'hook_calls': visitor.hook_calls, 'count': len(visitor.hook_calls) } print(json.dumps(result, indent=2, ensure_ascii=False)) if __name__ == '__main__': main(sys.argv[1])

这个脚本本身很简单,但它做了一件很关键的事:把模型靠模糊推理容易漏掉的"客观事实"(比如这个文件里到底有几个 useEffect、每个在哪个行号)先精确抓出来,然后 agent 只需要在这个事实基础上做专业判断,推理负担大大降低。

AST 解析还有一点好处,不区分"组件内"和"组件外"的 Hook 逻辑才是真正考验水平的地方。比如 React 官方规则要求 Hooks 必须无条件、无循环地在组件顶层调用,这些规则仅靠人工 review 容易累,脚本可以辅助标记,然后把标记结果交给 agent 进行语义判断。

3.4 编写 rules 配置:把最佳实践沉淀下来

光检查 Hook 调用还不够。我在react_rules.json里沉淀了团队的最佳实践,这段配置驱动审查规则的方式,对 agent 来说非常有效。

{ "strict": [ { "rule": "hooks-dependency-completeness", "severity": "critical", "check": "useEffect/useCallback/useMemo dependency array must include all external variables used inside" }, { "rule": "hooks-no-conditional", "severity": "critical", "check": "React hooks must not be called inside conditions, loops, or nested functions" }, { "rule": "state-initialization-from-props", "severity": "warning", "check": "initializing useState directly from props without a key reset pattern indicates duplicated state" } ], "suggestions": [ { "rule": "use-object-memo", "severity": "suggestion", "check": "consider using useMemo or memo to prevent unnecessary re-renders" } ] }

写规则的时候要特别注意表达方式:规则必须是可以被"验证"的,而不是形而上的口号。比如"提高代码质量"这种规则,agent 读完无法转化为行动;而"依赖数组必须包含内部使用到的所有外部变量",则可以作为一条明确的校验项,agent 在审查时能照此逐条对照。

3.5 裁剪示例:让 agent 有样板可循

examples/bad_component.jsx和examples/good_component.jsx的作用是提供正反样本,帮助 agent 校准"好的审查结论"长什么样。

坏样本里我故意埋了几个典型问题:

import React, { useState, useEffect } from 'react'; export function UserProfile({ userId, user }) { const [name, setName] = useState(user?.name || ''); useEffect(() => { fetch(`/api/users/${userId}`) .then(res => res.json()) .then(data => setName(data.name)); }, []); if (user?.role === 'admin') { const [unused, setUnused] = useState(false); } return ( <div> <h2>{name}</h2> <button onClick={() => setName('')}>Clear</button> </div> ); }

好样本会把同样的需求用规范方式实现一遍:useState 传函数初始化、useEffect 依赖数组补全、不要在条件分支里调用 Hook、给按钮加 type 属性等等。样本的目的不是给 agent 抄答案,而是让它在审查时有一把"尺子",对照尺子判断待审代码的偏离程度。

4. 实战:把 skill 接入 agent 并完成一次完整审查

4.1 安装与注册 skill

不同的 agent 框架注册方式略有差异。以 Claude 系的 skill 机制为例,通常是把 skill 目录放到~/.claude/skills/下,或通过配置文件声明路径;Codex 则更倾向于用仓库内.codex/skills目录来管理项目级技能。无论哪种方式,核心步骤一致:

  1. 创建 skill 目录,命名采用短横线命名法,方便路径匹配。
  2. 在目录内放置 SKILL.md 作为入口。
  3. 通过 agent 的命令行或配置命令,指定 skills 目录。
  4. 触发一次会话,检查 agent 是否识别到该 skill。

有一个细节值得注意:很多人在本地调试时忘了重启 agent 会话,导致新加的 skill 一直"不生效"。"我加了 skill 为什么没反应",这个问题的排查优先级,第一步永远是确认 agent 是不是真的加载了最新配置,而不是去改 SKILL.md 内容。你可以直接问 agent:"你当前可用的 skills 有哪些?",如果能列出你刚添加的项,说明加载链路是通的。

4.2 准备待审查代码

实际的审查任务不会只针对一个组件,而是一个目录或多个文件。为了验证 skill 的泛化能力,我通常至少准备三个文件:

  • 一个相对规范的组件,预期输出应该是"少量建议"。
  • 一个问题明显的中型组件,预期输出应该同时包含 critical 和 warning。
  • 一个使用高阶 API(自定义 Hooks、context、memo)的复杂组件,用来测试 skill 的深度。

在 CLI 场景下,直接对 agent 说"请用 react-component-review 技能审查 src/components/UserProfile.tsx"。在带有工作台的场景下,界面一般会显示当前启用的 skill 列表,直接勾选后发起任务即可。

4.3 执行与观察:agent 的处理流程

实际运行时,agent 的行为大致分三个阶段:

第一阶段是信息收集。它先打开SKILL.md读取审查流程,然后读取被审文件,同时运行check_hooks.py拿到 Hook 统计结果。你会看到 agent 在对话里输出类似"正在检测 hooks 调用模式"的过程信息。

第二阶段是逐条对照规则。agent 会把代码切成几个关注点,对照react_rules.json中每条规则逐项打分。效果好的 skill,会让 agent 每确认一条规则都给出对应的行号或代码摘录,而不是空泛地说"这里有问题"。

第三阶段是生成报告。好的实现会用 markdown 表格组织问题清单,按严重程度排序,并给出可落地的修改建议。我见到过的优秀输出,甚至会顺带把修改后的代码片段完整贴出来,并说明为什么这样改。

4.4 审查报告长什么样

这个 skill 的典型输出大概长这样:

严重级别问题位置建议
CriticaluseEffect 依赖数组缺少 userId,闭包捕获了过期的值UserProfile.tsx:12改为[userId]
CriticalHooks 不能在条件分支中调用UserProfile.tsx:18将 useState 移到组件顶层
WarninguseState 直接从 props 初始化,父组件更新时状态不同步UserProfile.tsx:6使用 key 重置或受控组件
Suggestion内联箭头函数导致按钮组件每次渲染都重新创建UserProfile.tsx:24useCallback 或提取具名函数

我实测下来,这个报告的准确率和一致性,比"让 agent 直接审查但不引导流程"要高不少。尤其是"position"这一栏,AST 脚本提供的客观事实帮了大忙,agent 极少再把问题定位到错误的行号上。

5. 常见问题与排查技巧实录

5.1 skill 不触发或总是误触发

这是我最常被问到的问题。症状是:agent 明明装了 skill,但遇到对应的任务却像没看见一样,或者八竿子打不着的问题也把它拉出来用。

排查思路很固定。先检查SKILL.md里的 Description 措辞。我在写 Description 时有个经验:不要只用几个抽象名词描述任务,要尽可能写清触发场景。比如"review React components"就不如"use this skill when user asks to review a React function component, especially regarding hooks, state, and performance issues"更有效。模型对"when"从句的理解能力比对纯关键词的理解能力要强得多。

误触发的问题,往往出在"何时不要使用"区域写得不够用力。不要害怕把限制条件写得具体甚至苛刻,宁可少触发,也不要让它总在不合适的场景浪费上下文。因为 agent 一旦加载了一个错误的 skill,就会带着偏颇的框架去处理任务,结果往往会更糟。

5.2 辅助脚本执行报错

脚本报错是 skill 实战里几乎必然遇到的事情。常见的有三种类型:

  • 环境依赖缺失,比如系统没有 Python 3 或缺少某些 pip 包。
  • 路径问题,agent 有时用相对路径打开文件,但工作目录和 skill 脚本不在同一层。
  • 文件编码问题,Windows 下源码文件可能是 GBK 编码,Python 默认按 UTF-8 处理就会崩。

我在设计 skill 脚本时通常会加一层"防御式报错":脚本启动时先打印cwd和文件路径,遇到解析错误用 try 捕获并输出友好提示,而不是直接抛堆栈。这样可以大大降低 agent 在沙箱里反复猜测的成本。

另外,如果你用一个 skill 的本意是"让团队的普通工程师也能用",尽量把脚本依赖收敛到最基础环境。能用系统自带命令完成的,就不要引入第三方库。每多一个依赖,你的 skill 在其他机器上跑不起来的概率就会高一分。

5.3 同一份 skill,两次执行结果差异很大

这个问题的根源往往不是 skill 本身,而是模型的随机性和上下文干扰。即使设置了温度参数,长链路的 agent 任务也会因为中间推理路径的分叉,导致最终结果出现漂移。

我采取的应对策略有两个。

第一,在 SKILL.md 里尽量把"完成标准"写死。比如这个 skill 审查的是 React 组件,就明确"你必须在报告的末尾输出一份检查清单,逐项勾选已完成的项目"。这相当于给 agent 的推理过程加了一个锚点,让它不容易半路跑飞。

第二,利用脚本输出的客观数据作为硬约束。AST 脚本输出的 hook 列表、行号信息,agent 可以视作"不可置疑的地面真相"。它只能在这个事实基础上做进一步判断,而不能自行想象"大概这边有个 useEffect"。这大幅抑制了结果的随机性。

5.4 问题排查速查表

症状高频原因首选排查动作
skill 未加载配置目录错误询问 agent 列出当前 skills
skill 不触发Description 太抽象加上具体 when 场景描述
skill 误触发排除条件不足在 SKILL.md 写明 Do NOT use when
脚本无法运行环境依赖缺失在 skill 目录加 install 脚本
结果不稳定标准不明确增加完成清单和脚本硬约束
输出格式混乱SKILL.md 缺少输出示例增加 Expected Output 示例段
上下文消耗过大SKILL.md 冗长精简到 300 行以内,拆分多文件

5.5 一个很容易被忽略的点:上下文窗口的"预算"管理

很多开发者给 skill 塞了很多内容,包括历史经验、知识库链接、背景信息,但 agent 每次执行任务时能装的上下文是有限的,你不能什么都往里塞。

我在设计 skill 的时候会做一个"上下文预算规划":假设 agent 的可用上下文是 200K tokens,那么 skill 本身加载最多不超过 20K tokens,剩下的给代码文件、给推理过程、给用户对话留足空间。如果 skill 内容超过这个预算,就拆成"核心版"和"扩展版",默认只加载核心版,当 agent 判断需要更深的知识时,再读取扩展文件。

这个思路是向文档系统学的。就像写技术文档不能把全套 API 手册都放在首页,skill 的设计同样讲究"渐进式披露"——先给 agent 最少必要信息,让它的推理专注于当前阶段,再在需要时暴露更深层的知识。

6. 写在后面的一点个人体会

从更宏观的角度看,skills 真正值得关注的价值,是把人的经验注入到 agent 的执行框架里。我在做 react-component-review 这个 skill 时,最深的感触是:写 SKILL.md 的过程,本质上是一个"把自己的审查经验结构化"的过程。以前我看代码靠的是大脑里模糊的模式匹配,现在必须把它转译成明确的步骤、规则、标准,这个转译过程本身就倒逼我把方法论想得更清楚。

如果你准备开始写自己的第一个 skill,我的建议是:从你自己最能拿出手的那类任务入手。比如你是写文案的,就做一个文案审校 skill;你是做运维的,就做一个日志排查 skill;你是做测试的,就做一个测试用例设计 skill。技能本身虽然技术含量不高,但因为你足够懂这个领域,你写出来的流程和标准会比 AI 自己摸索出来的靠谱得多。

在你要把这个 skill 分享出去之前,再检查三件事:第一,SKILL.md 是否能在三分钟内读完并理解触发条件和执行步骤;第二,辅助脚本是否在干净环境里能跑通;第三,是否给了一份"预期输出示例"。这三件事做到位,你的 skill 才算真正具备了被其他人或模型顺畅使用的基础。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询