Agent Skills 完全科普指南

0 阅读25分钟

image.png

Agent Skills 是一个开放标准,用于为 AI Agent 扩展专用能力。本文将从概念、工作原理、规范、分类、脚本支持、最佳实践等多个维度,带你全面了解 Agent Skills。

一、什么是 Agent Skill?

1.1 基本概念

Agent Skill(技能) 是一种可移植、受版本控制的包,用来教会 AI Agent 执行特定领域的任务。你可以把它理解为给 AI Agent 安装的「插件」或「技能包」——它把特定领域的知识、工作流程、脚本和最佳实践打包封装,供 Agent 在合适的时机自动调用。

用一个更直观的比喻:如果 AI Agent 是一位通才型的新员工,那么 Skill 就是你为他准备的入职培训手册——它不会改变员工的智力水平,但会让他立刻掌握公司特定的工作流程和领域知识。

1.2 四大特性

特性说明
可移植Skill 可用于任何支持 Agent Skills 标准的 Agent,不锁定到特定平台
受版本控制Skill 以文件形式存储,可以在代码仓库中追踪,通过 GitHub 仓库链接安装
可操作Skill 可以包含脚本、模板和参考信息,Agent 会通过其工具对这些内容进行操作
渐进式Skill 按需加载资源,使上下文使用更加高效

1.3 为什么需要 Skill?

问题场景:你每次和 AI Agent 对话时,都需要反复提供相同的上下文——比如公司的代码规范、部署流程、数据库表结构等。这既浪费时间,也容易遗漏。

Skill 的解决方案

  • 专业化:让通用 Agent 变成特定领域的专家
  • 减少重复:一次创建,自动使用
  • 能力组合:多个 Skill 可以组合使用,构建复杂工作流
  • 知识沉淀:将团队的工作流程、最佳实践和机构知识固化下来

二、核心设计理念:渐进式披露

渐进式披露(Progressive Disclosure)是 Agent Skills 最核心的设计理念。它确保 Agent 只在需要时加载必要的信息,而非一开始就把所有内容塞进上下文窗口。

2.1 三级加载机制

graph TD
    A["🟢 Level 1: 元数据<br/>~100 tokens/Skill<br/>启动时始终加载"] --> B{"用户任务是否<br/>匹配 Skill?"}
    B -->|是| C["🟡 Level 2: 指令内容<br/>< 5000 tokens<br/>Skill 被触发时加载"]
    B -->|否| D["不加载,零消耗"]
    C --> E{"指令中引用了<br/>其他文件?"}
    E -->|是| F["🔴 Level 3: 资源文件<br/>按需加载<br/>脚本、参考文档等"]
    E -->|否| G["直接执行任务"]
    F --> G

    style A fill:#d4edda,stroke:#28a745
    style C fill:#fff3cd,stroke:#ffc107
    style F fill:#f8d7da,stroke:#dc3545
    style D fill:#e2e3e5,stroke:#6c757d
级别加载时机Token 消耗内容
Level 1: 元数据启动时始终加载~100 tokens/SkillYAML frontmatter 中的 namedescription
Level 2: 指令Skill 被触发时< 5000 tokensSKILL.md 主体内容(指令和指南)
Level 3: 资源按需加载理论上无限脚本、参考文档、模板等附属文件

2.2 为什么这很重要?

上下文窗口是一种公共资源,你的 Skill 和以下内容共享这个空间:

  • 系统提示词(System Prompt)
  • 对话历史
  • 其他 Skill 的元数据
  • 用户的实际请求

渐进式披露让你可以安装几十个 Skill 而不会产生上下文压力——Agent 只知道每个 Skill 的存在和用途,只有在真正需要时才加载完整内容。


三、Agent 如何消费 Skill?

理解 Skill 的消费机制是理解整个体系的关键。这里需要区分三个角色:Agent(程序)LLM(大模型)Skill 文件(文件系统)。Agent 是 LLM 的"外壳程序",负责管理对话、调用工具、组装 prompt;LLM 是做决策的大脑;Skill 文件是静态的知识包。

3.1 Agent、LLM 与 Skill 的完整交互流程

下面这张图完整展示了从 Agent 启动到 Skill 被使用的全过程。注意关键点:Skill 的筛选和激活是由 LLM 决策的,Agent 只负责执行 LLM 的指令(读文件、跑脚本)。

sequenceDiagram
    participant FS as 文件系统<br/>(Skill 文件)
    participant A as Agent<br/>(程序/外壳)
    participant LLM as LLM<br/>(大模型)
    participant U as 用户

    rect rgb(240, 248, 255)
    Note over FS,U: 阶段一:启动 — Agent 发现 Skill 并构建目录

    A->>FS: 扫描 .agents/skills/、~/.cursor/skills/ 等目录
    FS-->>A: 返回所有 SKILL.md 文件路径
    A->>A: 解析每个 SKILL.md 的 YAML frontmatter
    A->>A: 提取 name + description,构建 Skill 目录
    Note over A: 将 Skill 目录注入 System Prompt
    end

    rect rgb(255, 253, 240)
    Note over FS,U: 阶段二:请求 — 用户提问,LLM 决策是否需要 Skill

    U->>A: "帮我从这个 PDF 中提取文本并总结"
    A->>LLM: 发送 prompt =<br/>System Prompt(含 Skill 目录)<br/>+ 对话历史<br/>+ 用户消息<br/>+ 可用工具列表
    Note over LLM: LLM 看到 System Prompt 中的 Skill 目录:<br/>pdf-processing: "Extract PDF text..."<br/>data-analysis: "Analyze datasets..."<br/>→ 判断 pdf-processing 相关
    LLM-->>A: 返回 tool_use: Read("pdf-processing/SKILL.md")
    end

    rect rgb(240, 255, 240)
    Note over FS,U: 阶段三:激活 — Agent 加载 Skill 内容,返回给 LLM

    A->>FS: 读取 pdf-processing/SKILL.md
    FS-->>A: 返回 SKILL.md 完整内容(指令 + 工作流)
    A->>LLM: 将 SKILL.md 内容作为 tool_result 返回<br/>(指令进入上下文窗口)
    Note over LLM: LLM 现在拥有了 PDF 处理的<br/>完整专业指令
    end

    rect rgb(255, 240, 245)
    Note over FS,U: 阶段四:执行 — LLM 按照 Skill 指令操作

    LLM-->>A: tool_use: Bash("python scripts/extract.py input.pdf")
    A->>FS: 执行脚本 extract.py
    FS-->>A: 脚本输出:"Extracted 15 pages of text..."
    A->>LLM: 将脚本输出作为 tool_result 返回
    LLM-->>A: tool_use: Read("references/FORMS.md")
    Note over LLM: 判断不需要 FORMS.md,跳过
    LLM-->>A: 生成最终回复(文本)
    A->>U: 返回 PDF 提取和总结结果
    end
关键要点

上面这张图有几个值得特别注意的地方:

1. Skill 目录在启动时就注入 System Prompt

Agent 启动时扫描文件系统,提取每个 Skill 的 namedescription(每个约 100 tokens),拼接成一个"技能目录"块,注入到 System Prompt 中。这个目录类似这样:

<available_skills>
  <skill>
    <name>pdf-processing</name>
    <description>Extract PDF text, fill forms, merge files. Use when handling PDFs.</description>
    <location>~/.agents/skills/pdf-processing/SKILL.md</location>
  </skill>
  <skill>
    <name>data-analysis</name>
    <description>Analyze datasets, generate charts, and create summary reports.</description>
    <location>~/project/.agents/skills/data-analysis/SKILL.md</location>
  </skill>
</available_skills>

2. Skill 筛选由 LLM 完成,不是 Agent 硬编码匹配

Agent 不会自己做关键词匹配来决定用哪个 Skill。而是将"技能目录"和用户消息一起发给 LLM,由 LLM 根据语义理解决定是否加载某个 Skill。LLM 的决策体现为一次工具调用——调用 Read 工具读取对应的 SKILL.md 文件。

3. Skill 内容通过"工具调用-工具结果"机制进入上下文

SKILL.md 的内容不是直接塞进 prompt 的,而是通过 LLM 主动发起一次 Read 工具调用,Agent 执行读取后将内容作为 tool_result 返回。这意味着 Skill 的加载使用的是和其他工具调用完全相同的通信机制

4. 后续操作(读引用文件、执行脚本)也都是 LLM 驱动的

加载 SKILL.md 后,LLM 可能继续发起工具调用来读取参考文档或执行脚本。每次都是 LLM 做决策、Agent 执行、结果返回,循环进行。

3.2 与 MCP Tool 交互流程的对比

Skills 和 MCP Tools 都是扩展 Agent 能力的方式,但交互模式有本质区别。下面用两张并排的时序图来对比:

MCP Tool 的交互流程
sequenceDiagram
    participant T as MCP Server<br/>(外部工具)
    participant A as Agent<br/>(程序/外壳)
    participant LLM as LLM<br/>(大模型)
    participant U as 用户

    rect rgb(240, 248, 255)
    Note over T,U: 步骤一:工具定义随请求发送
    U->>A: "帮我查一下北京今天的天气"
    A->>LLM: 发送 prompt +<br/>tools: [get_weather 的 JSON Schema 定义]
    end

    rect rgb(255, 253, 240)
    Note over T,U: 步骤二:LLM 决定调用工具
    LLM-->>A: tool_use: get_weather(city="北京")
    end

    rect rgb(240, 255, 240)
    Note over T,U: 步骤三:Agent 执行工具,拼接结果
    A->>T: 调用 MCP Server 的 get_weather
    T-->>A: {"temp": "22°C", "weather": "晴"}
    A->>LLM: 拼接 tool_result 到对话中,再次请求
    end

    rect rgb(255, 240, 245)
    Note over T,U: 步骤四:LLM 生成最终回复
    LLM-->>A: "北京今天天气晴,气温 22°C"
    A->>U: 返回回复
    end
Skill 与 MCP Tool 的本质区别
graph TB
    subgraph MCP["MCP Tool 模式"]
        direction TB
        M1["工具定义(JSON Schema)<br/>随每次请求发送"] --> M2["LLM 决定调用工具"]
        M2 --> M3["Agent 执行工具"]
        M3 --> M4["工具返回 <b>数据</b>"]
        M4 --> M5["LLM 基于数据生成回复"]
    end

    subgraph SK["Skill 模式"]
        direction TB
        S1["技能目录(name + description)<br/>注入 System Prompt"] --> S2["LLM 决定激活 Skill"]
        S2 --> S3["Agent 读取 SKILL.md"]
        S3 --> S4["Skill 返回 <b>指令</b>"]
        S4 --> S5["LLM <b>按照指令</b> 执行后续操作<br/>(可能继续调用工具/脚本)"]
    end

    style M4 fill:#e3f2fd,stroke:#1976D2
    style S4 fill:#e8f5e9,stroke:#388E3C

总结两者的核心差异:

维度MCP ToolAgent Skill
本质提供能力(做某件事)提供指令(教会怎么做)
信息注入位置工具定义随 tools 参数发送技能目录注入 System Prompt
触发结果返回数据(API 响应、查询结果)返回指令(工作流程、最佳实践)
LLM 行为变化获得一个新的数据源获得一整套新的行为指南
类比给员工一把新工具给员工一本操作手册
组合使用Skill 指令中可以指导 LLM 如何使用 MCP Tool

一个常见的强力组合场景:MCP 给 Agent 提供了调用 BigQuery 的能力(工具),Skill 教会 Agent 你们公司的表结构、查询规范和注意事项(指令)。两者互补,缺一不可。

3.3 完整的 Prompt 拼接示意

为了更直观地理解 Skill 是如何融入 Agent 与 LLM 的对话流程中的,下面展示一次完整交互中 Agent 发给 LLM 的 prompt 结构:

┌──────────────────────────────────────────────────────────┐
│  System Prompt                                           │
│  ┌────────────────────────────────────────────────────┐  │
│  │ 基础指令(你是一个 AI 助手...)                       │  │
│  ├────────────────────────────────────────────────────┤  │
│  │ 📦 可用技能目录(~100 tokens × NSkill)         │  │
│  │  • pdf-processing: Extract PDF text, fill forms... │  │
│  │  • data-analysis: Analyze datasets, generate...    │  │
│  │  • deploy-app: Deploy the application to...        │  │
│  │  当任务匹配技能描述时,使用 Read 工具加载 SKILL.md    │  │
│  ├────────────────────────────────────────────────────┤  │
│  │ 🔧 可用工具列表                                     │  │
│  │  • Read(读取文件)                                  │  │
│  │  • Bash(执行命令)                                  │  │
│  │  • get_weatherMCP 工具)                          │  │
│  │  • ...                                             │  │
│  └────────────────────────────────────────────────────┘  │
├──────────────────────────────────────────────────────────┤
│  对话历史                                                │
│  [user]: 帮我从这个 PDF 中提取文本                        │
│  [assistant]: tool_useRead("pdf-processing/SKILL.md") │
│  [tool_result]: # PDF Processing ...(SKILL.md 内容)     │
│  [assistant]: tool_useBash("python scripts/extract.py")│
│  [tool_result]: Extracted 15 pages of text...            │
│  [assistant]: 已从 PDF 中提取文本,以下是总结...            │
├──────────────────────────────────────────────────────────┤
│  当前用户消息                                             │
│  [user]: 再帮我把提取的内容生成一份 Word 文档               │
└──────────────────────────────────────────────────────────┘

可以看到:

  • Skill 目录MCP 工具定义同时存在于 prompt 中
  • Skill 的激活(读取 SKILL.md)在对话历史中表现为一次普通的工具调用
  • SKILL.md 的内容作为 tool_result 留在对话历史中,持续影响后续 LLM 的行为

3.4 发现阶段详解

Agent 启动时,会从以下目录自动发现技能:

位置级别说明
.agents/skills/项目级跨客户端通用目录
.cursor/skills/项目级Cursor 专用目录
~/.cursor/skills/用户级(全局)所有项目可用
.claude/skills/项目级Claude Code 兼容目录
~/.claude/skills/用户级Claude Code 全局兼容

扫描规则:

  • 跳过 .git/node_modules/ 等无关目录
  • 设置合理的扫描深度(一般 4-6 层)和目录数上限(~2000 个)
  • 项目级 Skill 优先级高于用户级 Skill(同名时覆盖)

3.5 触发激活方式

Skill 有两种激活方式:

自动触发(Model-driven):LLM 看到 System Prompt 中的技能目录后,根据用户请求的语义自动判断是否需要加载某个 Skill。这是最常见的方式——LLM 的决策体现为一次读取 SKILL.md 的工具调用。

手动调用(User-explicit):用户在对话中输入 /skill-name(斜杠命令)来显式调用特定 Skill。此时 Agent(程序侧)直接将 SKILL.md 内容注入上下文,不需要 LLM 做判断。适用于设置了 disable-model-invocation: true 的 Skill。

3.6 脚本执行的高效性

当 Skill 中的指令引用了脚本文件时,Agent 通过 bash 直接执行脚本,而不是将脚本代码读入上下文:

graph LR
    A["Agent 读取 SKILL.md"] --> B{"指令引用了<br/>scripts/extract.py"}
    B --> C["执行脚本<br/>bash: python scripts/extract.py"]
    C --> D["只有脚本输出<br/>进入上下文窗口"]

    style D fill:#d4edda,stroke:#28a745

这意味着:

  • 脚本代码本身不会消耗上下文 token
  • 只有脚本的输出结果会进入 Agent 的上下文
  • 比让 Agent 临时生成代码更可靠、更高效

四、Skill 的规范与结构

4.1 目录结构

每个 Skill 是一个包含 SKILL.md 文件的文件夹:

my-skill/
├── SKILL.md              # 必需:元数据 + 指令
├── scripts/              # 可选:可执行代码
│   ├── deploy.sh
│   └── validate.py
├── references/           # 可选:补充文档
│   ├── REFERENCE.md
│   └── FORMS.md
├── assets/               # 可选:模板、图片等静态资源
│   └── config-template.json
└── ...                   # 任何其他文件或目录

各目录的职责:

目录用途加载时机
SKILL.md主要指令文件(核心)Skill 被触发时加载
scripts/Agent 可执行的代码被指令引用时执行
references/按需加载的补充文档被指令引用时读取
assets/模板、图片、数据文件等静态资源被指令引用时读取

4.2 SKILL.md 文件格式

每个 Skill 在带有 YAML frontmatter 的 SKILL.md 文件中定义:

---
name: pdf-processing
description: Extract PDF text, fill forms, merge files. Use when handling PDFs.
license: Apache-2.0
metadata:
  author: example-org
  version: "1.0"
---

# PDF Processing

## Quick start

Use pdfplumber to extract text from PDFs:

```python
import pdfplumber

with pdfplumber.open("file.pdf") as pdf:
    text = pdf.pages[0].extract_text()

Advanced features

Form filling: See FORMS.md for complete guide API reference: See REFERENCE.md for all methods


### 4.3 Frontmatter 字段详解

#### 必填字段

| 字段 | 约束 | 说明 |
|------|------|------|
| `name` | 最多 64 字符,仅允许小写字母、数字和连字符,不能以连字符开头或结尾,不能包含连续连字符,必须与父文件夹名一致 | 技能标识符 |
| `description` | 最多 1024 字符,不能为空 | 描述技能功能和使用场景,Agent 用它来判断相关性 |

#### 可选字段

| 字段 | 约束 | 说明 |
|------|------|------|
| `license` |  | 许可证名称或对随附许可证文件的引用 |
| `compatibility` | 最多 500 字符 | 环境要求(目标产品、系统软件包、网络访问等) |
| `metadata` | 键值对映射 | 用于附加元数据(如 author、version) |
| `disable-model-invocation` | 布尔值 |  `true` 时仅在通过 `/skill-name` 显式调用时才使用 |
| `allowed-tools` | 空格分隔的工具列表 | 预批准该 Skill 可使用的工具(实验性功能) |

#### name 字段示例

```yaml
# ✅ 合法
name: pdf-processing
name: data-analysis
name: code-review

# ❌ 非法
name: PDF-Processing    # 不允许大写
name: -pdf              # 不能以连字符开头
name: pdf--processing   # 不能有连续连字符
description 字段示例
# ✅ 好的描述:具体且包含触发关键词
description: >
  Extract text and tables from PDF files, fill forms, merge documents.
  Use when working with PDF files or when the user mentions PDFs,
  forms, or document extraction.

# ❌ 差的描述:太模糊
description: Helps with PDFs.

4.4 文件引用规范

在 Skill 中引用其他文件时,使用相对于 Skill 根目录的路径:

See [the reference guide](references/REFERENCE.md) for details.

Run the extraction script:
scripts/extract.py

关键规则:

  • 始终使用正斜杠 references/guide.md,而非反斜杠
  • 文件引用保持一层深度,避免嵌套引用链
  • 文件名应当有描述性:用 form_validation_rules.md 而不是 doc2.md

五、Skill 的分类

graph TD
    S["Agent Skills"] --> A["预构建 Skill<br/>(Anthropic 官方)"]
    S --> B["自定义 Skill<br/>(Custom Skills)"]
    S --> C["组织级 Skill<br/>(Organization Provisioned)"]
    S --> D["合作伙伴 Skill<br/>(Partner Skills)"]

    A --> A1["PowerPoint (pptx)"]
    A --> A2["Excel (xlsx)"]
    A --> A3["Word (docx)"]
    A --> A4["PDF (pdf)"]

    B --> B1["纯指令型 Skill"]
    B --> B2["包含脚本的 Skill"]
    B --> B3["包含参考文档的 Skill"]
    B --> B4["复合型 Skill"]

    C --> C1["管理员统一分发"]
    C --> C2["团队共享标准流程"]

    D --> D1["Notion"]
    D --> D2["Figma"]
    D --> D3["Atlassian"]

    style A fill:#e3f2fd,stroke:#1976D2
    style B fill:#e8f5e9,stroke:#388E3C
    style C fill:#fff3e0,stroke:#F57C00
    style D fill:#f3e5f5,stroke:#7B1FA2

5.1 预构建 Skill(Anthropic Skills)

由 Anthropic 官方创建和维护的 Skill,开箱即用:

Skillskill_id功能
PowerPointpptx创建演示文稿、编辑幻灯片、分析演示内容
Excelxlsx创建电子表格、分析数据、生成图表报告
Worddocx创建文档、编辑内容、格式化文本
PDFpdf生成格式化的 PDF 文档和报告

这些 Skill 在 claude.ai 和 Claude API 上对所有用户可用,Agent 会在相关任务中自动调用。

5.2 自定义 Skill(Custom Skills)

用户或组织自行创建的 Skill,用于特定领域的工作流。按内容构成可分为:

纯指令型 Skill

只包含 SKILL.md,通过自然语言指令指导 Agent:

code-review/
└── SKILL.md

适用场景:代码审查流程、写作风格指南、会议纪要模板等不需要执行代码的任务。

包含参考文档的 Skill

除主指令外,附带额外的参考文档,Agent 按需读取:

bigquery-skill/
├── SKILL.md
└── reference/
    ├── finance.md
    ├── sales.md
    └── product.md

适用场景:需要大量领域知识的任务,如数据库分析、API 对接等。

包含脚本的 Skill

附带可执行脚本,Agent 在执行任务时调用:

deploy-app/
├── SKILL.md
└── scripts/
    ├── deploy.sh
    └── validate.py

适用场景:部署、数据处理、表单填充等需要确定性操作的任务。

复合型 Skill

同时包含指令、参考文档、脚本和资源:

pdf-processing/
├── SKILL.md
├── FORMS.md
├── REFERENCE.md
├── examples.md
├── scripts/
│   ├── analyze_form.py
│   ├── fill_form.py
│   └── validate.py
└── assets/
    └── template.json

5.3 组织级 Skill(Organization Provisioned)

针对 Team 和 Enterprise 计划,组织的管理员可以为所有用户统一配置 Skill:

  • 分发经过审批的工作流,确保全员一致
  • 确保团队使用标准化的流程和最佳实践
  • 部署新能力无需每个用户单独上传
  • Skill 可设为默认启用或禁用

5.4 合作伙伴 Skill(Partner Skills)

由合作伙伴(如 Notion、Figma、Atlassian 等)专业构建的 Skill,设计为与对应的 MCP 连接器无缝配合使用,实现强大的集成工作流。


六、支持脚本的 Skill

支持脚本是 Agent Skill 最强大的能力之一。它将确定性的代码执行与 Agent 的灵活决策结合起来。

6.1 脚本 vs 指令的选择

graph TD
    A["任务类型判断"] --> B{"操作是否需要<br/>确定性结果?"}
    B -->|是| C{"操作是否复杂<br/>且容易出错?"}
    B -->|否| D["使用文本指令<br/>(高自由度)"]
    C -->|是| E["使用脚本<br/>(低自由度)"]
    C -->|否| F["使用伪代码或<br/>带参数的脚本<br/>(中等自由度)"]

    style D fill:#d4edda
    style E fill:#f8d7da
    style F fill:#fff3cd
自由度方式适用场景示例
文本指令多种方法均可、依赖上下文判断代码审查、写作指导
伪代码/带参数脚本有推荐模式但允许变通报告生成、数据转换
固定脚本操作脆弱、一致性关键数据库迁移、部署流程

6.2 一次性命令

当现有工具包已经能满足需求时,可以直接在 SKILL.md 中引用,而不需要 scripts/ 目录:

工具语言生态命令示例
uvxPythonuvx ruff@0.8.0 check .
pipxPythonpipx run 'black==24.10.0' .
npxNode.jsnpx eslint@9 --fix .
bunxBunbunx eslint@9 --fix .
deno runDenodeno run npm:create-vite@6 my-app
go runGogo run golang.org/x/tools/cmd/goimports@v0.28.0 .

关键原则:锁定版本号,确保行为一致。

6.3 自包含脚本

当需要自定义逻辑时,将脚本放入 scripts/ 目录并声明内联依赖:

Python 示例(PEP 723)

# /// script
# dependencies = [
#   "beautifulsoup4",
# ]
# ///

from bs4 import BeautifulSoup

html = '<html><body><h1>Welcome</h1><p class="info">Test.</p></body></html>'
print(BeautifulSoup(html, "html.parser").select_one("p.info").get_text())

使用 uv run scripts/extract.py 运行,uv 会自动创建隔离环境并安装依赖。

Deno 示例

#!/usr/bin/env -S deno run
import * as cheerio from "npm:cheerio@1.0.0";

const html = `<html><body><p class="info">Test.</p></body></html>`;
const $ = cheerio.load(html);
console.log($("p.info").text());

6.4 脚本设计原则

为 Agent 设计脚本时,需要遵循以下原则:

禁止交互式提示

Agent 在非交互式 shell 中运行,无法响应 TTY 提示。所有输入通过命令行参数、环境变量或 stdin 接收:

# ❌ 错误:会挂起等待输入
$ python scripts/deploy.py
Target environment: _

# ✅ 正确:清晰的错误提示
$ python scripts/deploy.py
Error: --env is required. Options: development, staging, production.
Usage: python scripts/deploy.py --env staging --tag v1.2.3
提供 --help 文档

--help 输出是 Agent 了解脚本接口的主要方式:

Usage: scripts/process.py [OPTIONS] INPUT_FILE

Process input data and produce a summary report.

Options:
  --format FORMAT    Output format: json, csv, table (default: json)
  --output FILE      Write output to FILE instead of stdout
  --verbose          Print progress to stderr
提供有意义的错误信息
# ❌ 不好:模糊
Error: invalid input

# ✅ 好:具体且有指导性
Error: --format must be one of: json, csv, table.
       Received: "xml"
使用结构化输出

优先使用 JSON、CSV 等结构化格式,而非自由文本。将数据输出到 stdout,诊断信息输出到 stderr。

其他原则
  • 幂等性:Agent 可能重试命令,「不存在则创建」比「创建然后在重复时失败」更安全
  • 干运行支持:对于破坏性操作,提供 --dry-run 标志
  • 有意义的退出码:不同失败类型使用不同退出码
  • 可预测的输出大小:Agent 的工具输出通常有截断阈值,支持 --offset 等分页参数

6.5 工作流与反馈循环

支持脚本的 Skill 特别适合构建验证反馈循环

graph LR
    A["1. 分析<br/>analyze_form.py"] --> B["2. 创建计划<br/>fields.json"]
    B --> C["3. 验证计划<br/>validate_fields.py"]
    C -->|失败| B
    C -->|通过| D["4. 执行<br/>fill_form.py"]
    D --> E["5. 验证输出<br/>verify_output.py"]
    E -->|失败| B
    E -->|通过| F["完成 ✅"]

    style F fill:#d4edda,stroke:#28a745

这种「计划-验证-执行」模式通过在每个关键步骤后加入机器可验证的检查,大幅提高输出质量:

  • 早期捕获错误:验证在变更应用之前发现问题
  • 机器可验证:脚本提供客观验证
  • 可逆规划:Agent 可以在不触碰原始文件的情况下迭代计划

6.6 实战 Demo:天气查询 Skill

下面通过一个完整的、可运行的天气查询 Skill,来展示脚本型 Skill 的完整结构和工作方式。

目录结构
check-weather/
├── SKILL.md
└── scripts/
    └── get-weather.mjs
SKILL.md 文件
---
name: check-weather
description: >
  Query current weather conditions for any city worldwide.
  Use when the user asks about weather, temperature, wind,
  humidity, or atmospheric conditions for a specific location.
compatibility: Requires Node.js 18+ (uses native fetch API)
metadata:
  author: demo
  version: "1.0"
---

# Check Weather

Query real-time weather data for any city using the wttr.in API.

## Usage

Run the weather script with the city name:

```bash
node scripts/get-weather.mjs <city>

Examples:

node scripts/get-weather.mjs Beijing
node scripts/get-weather.mjs "New York"
node scripts/get-weather.mjs Tokyo

Output Format

The script outputs JSON with the following fields:

{
  "city": "Beijing",
  "country": "China",
  "temperature": "22°C",
  "feels_like": "20°C",
  "weather": "Partly cloudy",
  "humidity": "45%",
  "wind_speed": "15 km/h",
  "wind_direction": "NE",
  "visibility": "10 km",
  "pressure": "1015 mb",
  "uv_index": "5",
  "observation_time": "02:30 PM"
}

Guidelines

  • If the user provides a Chinese city name, translate it to English before calling the script (e.g. 北京 → Beijing)
  • If the script fails due to network issues, inform the user and suggest trying again later
  • Present the weather data in a readable, conversational format rather than dumping raw JSON

#### scripts/get-weather.mjs 脚本

```javascript
#!/usr/bin/env node

const city = process.argv[2];

if (!city) {
  console.error(JSON.stringify({
    error: "City name is required",
    usage: "node scripts/get-weather.mjs <city>",
    examples: [
      'node scripts/get-weather.mjs Beijing',
      'node scripts/get-weather.mjs "New York"'
    ]
  }, null, 2));
  process.exit(1);
}

try {
  const url = `https://wttr.in/${encodeURIComponent(city)}?format=j1`;
  const response = await fetch(url);

  if (!response.ok) {
    console.error(JSON.stringify({
      error: `HTTP ${response.status}: Failed to fetch weather for "${city}"`,
      suggestion: "Check the city name and try again"
    }));
    process.exit(1);
  }

  const data = await response.json();
  const current = data.current_condition?.[0];
  const area = data.nearest_area?.[0];

  if (!current) {
    console.error(JSON.stringify({
      error: `No weather data available for "${city}"`
    }));
    process.exit(1);
  }

  const result = {
    city: area?.areaName?.[0]?.value ?? city,
    country: area?.country?.[0]?.value ?? "Unknown",
    temperature: `${current.temp_C}°C`,
    feels_like: `${current.FeelsLikeC}°C`,
    weather: current.weatherDesc?.[0]?.value ?? "Unknown",
    humidity: `${current.humidity}%`,
    wind_speed: `${current.windspeedKmph} km/h`,
    wind_direction: current.winddir16Point,
    visibility: `${current.visibility} km`,
    pressure: `${current.pressure} mb`,
    uv_index: current.uvIndex,
    observation_time: current.observation_time
  };

  console.log(JSON.stringify(result, null, 2));
} catch (err) {
  console.error(JSON.stringify({
    error: `Network error: ${err.message}`,
    suggestion: "Check your internet connection and try again"
  }));
  process.exit(1);
}
实际交互过程

当用户说 "北京今天天气怎么样",Agent 和 LLM 的交互过程如下:

sequenceDiagram
    participant U as 用户
    participant A as Agent
    participant LLM as LLM
    participant FS as 文件系统

    U->>A: "北京今天天气怎么样"
    A->>LLM: prompt(含 Skill 目录中的 check-weather 描述)

    Note over LLM: 匹配到 check-weather Skill
    LLM-->>A: tool_use: Read("check-weather/SKILL.md")
    A->>FS: 读取 SKILL.md
    FS-->>A: 返回 Skill 指令内容
    A->>LLM: tool_result: SKILL.md 内容

    Note over LLM: 按照指令:先翻译城市名<br/>北京 → Beijing,然后执行脚本
    LLM-->>A: tool_use: Bash('node scripts/get-weather.mjs Beijing')
    A->>FS: 执行脚本
    FS-->>A: {"city":"Beijing","temperature":"22°C","weather":"Partly cloudy",...}
    A->>LLM: tool_result: JSON 天气数据

    Note over LLM: 按照指令中的 Guidelines:<br/>"以可读的对话格式呈现"
    LLM-->>A: "北京今天天气多云,气温 22°C,体感温度 20°C,<br/>湿度 45%,东北风 15km/h。"
    A->>U: 返回天气信息

这个 Demo 体现了脚本型 Skill 的几个核心价值:

  • 脚本提供确定性能力:API 调用和数据解析由脚本保证,不依赖 LLM 生成代码
  • 指令提供灵活指导:翻译城市名、格式化输出等由 LLM 根据指令灵活完成
  • 错误处理自包含:脚本自己处理各种异常,提供结构化的错误信息
  • 零 token 浪费:脚本代码不进入上下文,只有 JSON 输出进入

七、Skill 在不同平台的使用

Agent Skills 可以在多个平台上使用,但各平台的支持程度和限制有所不同:

7.1 平台支持矩阵

特性Claude APIClaude CodeClaude.aiAgent SDK
预构建 Skill
自定义 Skill
网络访问视设置而定
运行时安装包✅(建议仅本地安装)✅(npm/PyPI)
共享范围工作区级个人/项目级仅个人项目级

7.2 跨平台限制

自定义 Skill 不会在不同平台之间自动同步

  • 上传到 claude.ai 的 Skill 需要单独上传到 API
  • 通过 API 上传的 Skill 在 claude.ai 上不可用
  • Claude Code 的 Skill 是基于文件系统的,与 claude.ai 和 API 均独立

7.3 在 Claude API 中使用

使用 Claude API 时,通过 container 参数指定 Skill:

response = client.beta.messages.create(
    model="claude-opus-4-6",
    max_tokens=4096,
    betas=["code-execution-2025-08-25", "skills-2025-10-02"],
    container={
        "skills": [
            {"type": "anthropic", "skill_id": "pptx", "version": "latest"}
        ]
    },
    messages=[
        {"role": "user", "content": "Create a presentation about AI"}
    ],
    tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)

需要三个 beta 头:

  • code-execution-2025-08-25:Skill 在代码执行容器中运行
  • skills-2025-10-02:启用 Skills 功能
  • files-api-2025-04-14:用于上传/下载文件到容器

7.4 在 Cursor 中使用

Cursor 支持自定义 Skill,从以下目录自动发现:

位置级别
.agents/skills/项目级
.cursor/skills/项目级
~/.cursor/skills/用户级(全局)

也可以在 Cursor Settings → Rules 的「Agent Decides」区域查看已发现的 Skill。

手动调用方式:在 Agent 对话中输入 / 并搜索技能名称。


八、Skill 的安装与管理

8.1 本地创建

最简单的方式,直接在项目或全局目录中创建 Skill 文件夹:

# 项目级
mkdir -p .agents/skills/my-skill
touch .agents/skills/my-skill/SKILL.md

# 全局级
mkdir -p ~/.agents/skills/my-skill
touch ~/.agents/skills/my-skill/SKILL.md

8.2 从 GitHub 安装

在 Cursor 中:

  1. 打开 Cursor Settings → Rules
  2. 在 Project Rules 部分,点击 Add Rule
  3. 选择 Remote Rule (Github)
  4. 输入 GitHub 仓库地址

8.3 通过 API 上传

使用 Skills API (/v1/skills 端点) 上传自定义 Skill,上传后在整个工作区范围内共享。

8.4 在 claude.ai 上传

通过 Settings > Features 上传 Skill 的 zip 文件。需要 Pro、Max、Team 或 Enterprise 计划,且启用代码执行。

8.5 规则和命令迁移

Cursor 2.4 版本内置了 /migrate-to-skills 技能,可以将现有的动态规则和斜杠命令转换为 Skill:

  • 动态规则alwaysApply: false)→ 转换为标准 Skill
  • 斜杠命令 → 转换为设置了 disable-model-invocation: true 的 Skill

8.6 使用验证工具

使用 skills-ref 参考库验证 Skill:

skills-ref validate ./my-skill

九、编写高质量 Skill 的最佳实践

9.1 简洁是关键

Agent 已经非常聪明,只添加它真正不知道的信息:

# ✅ 好的:简洁(~50 tokens)
## Extract PDF text
Use pdfplumber for text extraction:
```python
import pdfplumber
with pdfplumber.open("file.pdf") as pdf:
    text = pdf.pages[0].extract_text()

❌ 差的:啰嗦(~150 tokens)

Extract PDF text

PDF (Portable Document Format) files are a common file format that contains text, images, and other content. To extract text from a PDF, you'll need to use a library...


对每条信息的价值进行挑战:
- "Agent 真的需要这个解释吗?"
- "我能假设 Agent 已经知道这个吗?"
- "这段内容值得它占用的 token 吗?"

### 9.2 编写有效的 description

`description` 字段是 Skill 能否被正确触发的**决定性因素**- **使用第三人称**`"Processes Excel files"` 而非 `"I can help you process"`
- **包含触发关键词**:既描述做什么,也描述何时使用
- **具体而不模糊**:列出具体的操作和文件类型
- **适度宽泛**:包含用户可能不会直接点名但仍然相关的场景

```yaml
# ✅ 优秀的 description
description: >
  Analyze CSV and tabular data files — compute summary statistics,
  add derived columns, generate charts, and clean messy data. Use
  when the user has a CSV, TSV, or Excel file and wants to explore,
  transform, or visualize the data, even if they don't explicitly
  mention "CSV" or "analysis."

# ❌ 糟糕的 description
description: Process CSV files.

9.3 命名规范

推荐使用动名词形式(gerund),清晰描述 Skill 提供的能力:

推荐可接受避免
processing-pdfspdf-processinghelper
analyzing-spreadsheetsspreadsheet-analysisutils
managing-databasesprocess-pdfstools
testing-codeanalyze-spreadsheetsdocuments

9.4 渐进式披露的文件组织

graph TD
    A["SKILL.md<br/>(< 500 行)<br/>总览 + 导航"] --> B["references/finance.md<br/>收入指标"]
    A --> C["references/sales.md<br/>管道数据"]
    A --> D["references/product.md<br/>使用分析"]
    A --> E["scripts/validate.py<br/>验证脚本"]

    style A fill:#e3f2fd,stroke:#1976D2
    style B fill:#f5f5f5,stroke:#9E9E9E
    style C fill:#f5f5f5,stroke:#9E9E9E
    style D fill:#f5f5f5,stroke:#9E9E9E
    style E fill:#fff3e0,stroke:#F57C00

核心原则:

  • SKILL.md 主体控制在 500 行以内
  • 详细内容拆分到独立文件
  • 文件引用保持一层深度(不嵌套引用)
  • 超过 100 行的参考文件加上目录索引

9.5 避免常见反模式

反模式正确做法
使用 Windows 风格路径 scripts\helper.py使用正斜杠 scripts/helper.py
提供过多选项让 Agent 困惑给出一个默认方案 + 备选方案
嵌套引用链 A → B → C → 实际内容所有文件从 SKILL.md 直接引用
包含时效性信息使用「当前方法」+「旧模式」结构
术语不一致(混用 API endpoint/URL/route)选定一个术语,全程一致
脚本中使用魔法数字每个配置值都有注释说明理由

9.6 使用一致的术语

# ✅ 一致
Always "API endpoint"
Always "field"
Always "extract"

# ❌ 不一致
Mix "API endpoint", "URL", "API route", "path"
Mix "field", "box", "element", "control"
Mix "extract", "pull", "get", "retrieve"

十、Skill 的评估与迭代

10.1 评估驱动的开发

在编写大量文档之前,先创建评估用例。这确保你的 Skill 解决的是真实问题:

graph LR
    A["1. 识别差距<br/>无 Skill 时测试"] --> B["2. 创建评估<br/>3 个测试场景"]
    B --> C["3. 建立基准<br/>无 Skill 的表现"]
    C --> D["4. 编写最小指令<br/>仅解决差距"]
    D --> E["5. 运行评估<br/>对比基准"]
    E -->|未达标| D
    E -->|达标| F["完成 ✅"]

    style F fill:#d4edda,stroke:#28a745

10.2 测试用例结构

{
  "skill_name": "csv-analyzer",
  "evals": [
    {
      "id": 1,
      "prompt": "我有一个月度销售数据的 CSV 文件,能找出收入最高的 3 个月并做一个柱状图吗?",
      "expected_output": "柱状图显示收入最高的 3 个月,有标注的坐标轴和数值。",
      "files": ["evals/files/sales_2025.csv"],
      "assertions": [
        "输出包含柱状图文件",
        "图表恰好显示 3 个月",
        "两个坐标轴都有标签",
        "图表标题或说明提到了收入"
      ]
    }
  ]
}

10.3 双实例迭代法

最有效的 Skill 开发过程涉及两个 Agent 实例协作:

角色职责
Claude A(设计者)帮助设计和优化 Skill 内容
Claude B(使用者)使用 Skill 执行真实任务,暴露问题

迭代步骤:

  1. 用 Claude A 完成一个没有 Skill 的任务,记录你提供的上下文
  2. 让 Claude A 将这些上下文转化为 Skill
  3. 用 Claude B 测试 Skill 在相似任务上的表现
  4. 将观察结果反馈给 Claude A 进行改进
  5. 循环往复

10.4 触发描述优化

通过设计触发评估查询来测试和优化 description 的准确性:

  • 准备约 20 个查询:8-10 个应当触发、8-10 个不应触发
  • 每个查询运行多次(至少 3 次),计算触发率
  • 使用训练集/验证集拆分(60%/40%)避免过拟合
  • 迭代 5 次通常足够

10.5 观察 Agent 如何使用 Skill

在迭代过程中注意观察:

  • 意外的浏览路径:Agent 是否按你预期的顺序读取文件?
  • 遗漏的连接:Agent 是否未能跟踪到重要文件的引用?
  • 过度依赖某些部分:Agent 反复读取同一个文件,可能该内容应放入主 SKILL.md
  • 被忽略的内容:Agent 从未访问的文件,可能是不必要的

十一、安全考量

11.1 信任模型

graph TD
    A["Skill 来源"] --> B{"来源是否<br/>可信?"}
    B -->|自己创建| C["✅ 安全"]
    B -->|Anthropic 官方| C
    B -->|未知/第三方| D["⚠️ 需要审计"]

    D --> E["审查所有文件:<br/>SKILL.md、脚本、资源"]
    E --> F{"是否发现<br/>异常模式?"}
    F -->|否| G["谨慎使用"]
    F -->|是| H["❌ 拒绝使用"]

    style C fill:#d4edda,stroke:#28a745
    style D fill:#fff3cd,stroke:#ffc107
    style H fill:#f8d7da,stroke:#dc3545

11.2 关键安全原则

风险类别说明防范建议
工具滥用恶意 Skill 可能以有害方式调用工具(文件操作、bash 命令)审查所有脚本和指令
数据泄露具有敏感数据访问权限的 Skill 可能向外部系统泄露信息检查是否有意外的网络调用
外部源风险从外部 URL 获取数据的 Skill 风险特别高,获取的内容可能包含恶意指令避免 Skill 依赖外部数据源
项目级注入不受信任的仓库可能通过项目级 Skill 注入指令对不受信任的项目设置信任检查

11.3 审计清单

  • 审查 SKILL.md 中的所有指令
  • 审查 scripts/ 中的所有脚本文件
  • 检查是否有意外的网络请求
  • 检查文件访问模式是否与 Skill 声明的用途一致
  • 检查是否有操作不匹配 Skill 声明用途的行为

十二、与其他能力的对比

Agent Skills 并不是 Agent 扩展能力的唯一方式,理解它与其他方式的区别有助于在正确的场景选择正确的工具:

维度Agent SkillsProjects(项目)MCPCustom Instructions
定位特定任务的专业能力静态背景知识连接外部服务和数据源全局通用偏好
加载方式动态按需加载始终加载始终可用始终加载
适用范围特定任务类型特定项目内跨对话所有对话
典型内容工作流、脚本、领域知识项目文档、代码工具连接语言、风格偏好
组合使用可与 MCP 配合独立使用可与 Skills 配合独立使用

一个常见的强力组合:MCP 提供工具访问,Skill 教会 Agent 如何有效使用这些工具

例如,MCP 连接让 Agent 可以调用 BigQuery API,而 Skill 告诉 Agent 你们公司的表结构、命名规范和常见查询模式。


十三、开放标准与生态

13.1 开放标准

Agent Skills 规范作为开放标准发布在 agentskills.io。这意味着:

  • 你创建的 Skill 不会被锁定到特定平台
  • 同一套 Skill 格式可以在所有采用该标准的 AI 平台和工具中使用
  • 提供 Python 参考 SDK 供开发者在自己的平台中实现 Skills 支持

13.2 为你的 Agent 添加 Skills 支持

如果你在开发自己的 AI Agent 或开发工具,可以按照以下步骤添加 Skills 支持:

graph LR
    A["Step 1<br/>发现 Skill"] --> B["Step 2<br/>解析 SKILL.md"]
    B --> C["Step 3<br/>向模型披露<br/>可用 Skill"]
    C --> D["Step 4<br/>激活 Skill"]
    D --> E["Step 5<br/>管理 Skill<br/>上下文"]

    style A fill:#e3f2fd
    style B fill:#e8f5e9
    style C fill:#fff3e0
    style D fill:#f3e5f5
    style E fill:#fce4ec

核心实现要点:

  1. 发现:扫描约定目录,查找包含 SKILL.md 的子目录
  2. 解析:提取 YAML frontmatter 和 markdown 主体
  3. 披露:在系统提示词中注入技能目录(仅 name + description)
  4. 激活:通过文件读取或专用工具将完整指令加载到上下文
  5. 上下文管理:保护 Skill 内容不被上下文压缩算法移除,去重重复激活

13.3 生态现状

目前支持 Agent Skills 标准的平台包括:

  • Cursor:通过文件系统自动发现和使用
  • Claude Code:原生支持,文件系统集成
  • Claude API:通过 Skills API 上传和使用
  • Claude.ai:通过设置上传和使用
  • Agent SDK:TypeScript 和 Python SDK 支持

附录:Skill 效果检查清单

在分享你的 Skill 之前,逐一确认以下项目:

核心质量

  • description 具体且包含关键词
  • description 同时说明做什么和何时使用
  • SKILL.md 主体在 500 行以内
  • 额外细节放在独立文件中
  • 没有时效性信息(或放在「旧模式」区域)
  • 全程术语一致
  • 示例具体,非抽象
  • 文件引用只有一层深度
  • 合理使用渐进式披露
  • 工作流有清晰的步骤

代码和脚本

  • 脚本主动处理错误,而非把问题抛给 Agent
  • 错误处理明确且有帮助
  • 没有「魔法常数」(所有值都有注释说明)
  • 所需软件包在指令中列出并验证可用
  • 脚本有清晰的 --help 文档
  • 不使用 Windows 风格路径
  • 关键操作有验证/确认步骤
  • 质量关键任务包含反馈循环

测试

  • 至少创建 3 个评估用例
  • 在计划使用的所有模型上测试
  • 使用真实使用场景测试
  • 纳入团队反馈(如适用)