Claude Agent Skills:第一性原理深度解析(译)

原文链接:Claude Agent Skills: A First Principles Deep Dive

Claude 的 Agent Skills 系统是一套复杂的、基于提示词的“元工具”架构,通过注入专用指令来扩展 LLM 的能力。与传统的函数调用或代码执行不同,skills 通过提示词扩展上下文修改来影响 Claude 处理后续请求的方式,而不是编写可执行代码。

这篇深度解析从第一性原理拆解 Claude 的 Agent Skills 系统,记录了名为 “Skill” 的工具作为元工具、负责把领域提示词注入对话上下文的架构。我们会以 skill-creator 与 internal-comms 两个技能为案例,走完整生命周期,从文件解析、API 请求结构,一直到 Claude 的决策过程。

Claude Agent Skills 概览

Claude 使用 Skills 来提升执行特定任务的效果。Skills 以文件夹形式定义,包含指令、脚本与资源,Claude 会按需加载。Claude 通过声明式、基于提示词的机制发现并调用技能。模型(Claude)会根据系统提示词中提供的技能文字描述来决定是否调用技能;在代码层面没有算法化的技能选择或 AI 意图检测。决策完全发生在 Claude 的推理过程中,依据技能描述做匹配。

Skills 不是可执行代码。它们不会运行 Python 或 JavaScript,也没有隐藏的 HTTP 服务或函数调用。技能也不是硬编码进 Claude 的系统提示词里,而是存在于 API 请求结构的另一部分。

那么 Skills 到底是什么?它们是专门的提示模板,用于向对话上下文注入领域指令。当技能被调用时,它会同时修改对话上下文(注入指令提示)与执行上下文(更改工具权限、可能切换模型)。技能不会直接执行动作,而是扩展成详细提示,引导 Claude 解决特定类型问题。每个技能会作为 Claude 看到的工具 schema 的动态补充出现。

当用户发起请求时,Claude 会收到三样东西:用户消息、可用工具列表(Read、Write、Bash 等)以及 Skill 工具。Skill 工具的描述包含了所有可用技能的格式化清单(name、description 等字段组合在一起)。Claude 阅读这份清单,用自身语言理解将意图与技能描述匹配。例如你说“帮我创建一个写日志的 skill”,Claude 会看到 internal-comms 技能描述(“When user wants to write internal communications using format that his company likes to use”),识别到匹配,然后调用 Skill 工具并传入 command: "internal-comms"

术语说明

  • Skill 工具(S 大写)= 管理所有技能的元工具。它和 Read、Write、Bash 等并列出现在 Claude 的 tools 数组里。
  • skills(s 小写)= 具体技能,如 pdfskill-creatorinternal-comms。这些是由 Skill 工具加载的专用指令模板。

下面是更直观的示意图:

Claude Skill 流程图

技能选择机制在代码层面没有算法化的路由或意图分类。Claude Code 不使用 embedding、分类器或模式匹配来决定调用哪个技能。系统只是把可用技能格式化成文本描述,嵌入 Skill 工具提示中,让 Claude 的语言模型自己做决定。这是纯粹的 LLM 推理:没有正则、没有关键词匹配、没有基于 ML 的意图检测。决策发生在 transformer 的前向计算里,而非应用代码中。

当 Claude 调用某个技能时,系统会执行一个简单流程:加载 SKILL.md、扩展为详细指令、把指令注入对话上下文作为新的 user message、修改执行上下文(允许的工具、模型选择),并在富化后的环境中继续对话。这与传统工具完全不同,后者执行并返回结果;skills 是准备 Claude去解决问题,而不是直接解决问题。

下面的表格对比了 Tools 与 Skills 的差异:

维度 传统工具 Skills
执行模型 同步、直接 提示词扩展
目的 执行具体操作 引导复杂工作流
返回值 立即结果 对话上下文 + 执行上下文变更
示例 ReadWriteBash internal-commsskill-creator
并发性 一般安全 并发不安全
类型 多种 始终为 "prompt"

构建 Agent Skills

接下来以 Anthropic 技能仓库中的 skill-creator 为案例,深入看看如何构建 Skills。提醒一下:agent skills 是由指令、脚本、资源组织成的文件夹,agent 可以动态发现并加载,用来更好地完成特定任务。Skills 通过把你的专业知识打包成可组合资源,扩展 Claude 的能力,让通用 agent 变成更贴合需求的专用 agent。

关键结论:Skill = 提示模板 + 对话上下文注入 + 执行上下文修改 + 可选数据文件与 Python 脚本

每个 Skill 都定义在名为 SKILL.md(大小写不敏感)的 Markdown 文件中,可选的附带文件位于 /scripts/references/assets。这些附带文件可以是 Python 脚本、Shell 脚本、字体定义、模板等。以 skill-creator 为例,它包含 SKILL.md、用于许可证的 LICENSE.txt,以及 /scripts 目录下的若干 Python 脚本;它不包含 /references/assets

skill-creator 包结构

Skills 来自多个来源:Claude Code 会扫描用户设置(~/.config/claude/skills/)、项目设置(.claude/skills/)、插件提供的技能、内置技能,构建可用技能列表。对于 Claude Desktop,可以按如下方式上传自定义技能:

Claude Desktop 技能上传

注意:构建 Skills 最重要的概念是渐进披露(Progressive Disclosure)——先提供足够信息让 agent 做决策,再按需揭示更多细节。对于 agent skills:

  1. 披露 Frontmatter:最小信息(name、description、license)
  2. 选择某个 skill 后,加载 SKILL.md:完整但聚焦
  3. 执行 skill 时,再加载辅助 assets、references、scripts

编写 SKILL.md

SKILL.md 是 skill 提示词的核心。它遵循双段结构:frontmatter + 内容。frontmatter 配置如何运行(权限、模型、元数据),而正文则告诉 Claude 做什么。frontmatter 是 Markdown 文件开头的 YAML 区块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌─────────────────────────────────────┐
1. YAML Frontmatter (Metadata) Configuration
---
name: skill-name
description: Brief overview
allowed-tools: "Bash, Read"
version: 1.0.0
---
├─────────────────────────────────────┤
2. Markdown Content (Instructions) Prompt for Claude

Purpose explanation
Detailed instructions
Examples and guidelines
Step-by-step procedures
└─────────────────────────────────────┘

Frontmatter

frontmatter 包含控制 Claude 发现与使用 skill 的元数据。以下是 skill-creator 的 frontmatter 示例:

1
2
3
4
5
---
name: skill-creator
description: Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
license: Complete terms in LICENSE.txt
---

下面逐项解释 frontmatter 字段。

Claude Skills Frontmatter

name(必填)

顾名思义:skill 的名称。skill 的 name 会作为 Skill 工具中的 command

skill 的 name 会作为 Skill 工具的 command

description(必填)

description 提供 skill 的简要概述,这是 Claude 判断何时调用技能的首要信号。在示例里,它明确写道“当用户想创建新 skill 时使用”——这种清晰、以动作驱动的描述能帮助 Claude 将用户意图与 skill 能力匹配起来。

系统会自动在描述中追加来源信息(例如 (plugin:skills)),这有助于在多来源技能同时加载时区分不同来源。

when_to_use(未文档化——可能已废弃或未来特性)

⚠️ 重要提示when_to_use 字段在代码中大量出现,但未在任何官方 Anthropic 文档中记录。它可能是:

  • 正在废弃的旧功能
  • 仍未正式支持的内部/实验功能
  • 尚未发布的计划特性

建议:依赖更详细的 description 字段。官方文档出现之前,避免在生产技能中使用 when_to_use

尽管没文档,它在代码中的当前行为如下:

1
2
3
4
5
6
7
function formatSkill(skill) {
let description = skill.whenToUse
? `${skill.description} - ${skill.whenToUse}`
: skill.description;

return `"${skill.name}": ${description}`;
}

when_to_use 存在时,会以连字符追加到描述后,例如:

1
"skill-creator": Create well-structured, reusable skills... - When user wants to build a custom skill package with scripts, references, or assets

这条组合字符串就是 Claude 在 Skill 工具提示里看到的内容。但由于这一行为未被文档化,未来可能变更或移除。更安全的做法是把使用说明直接写入 description 字段(如上面 skill-creator 的示例)。

license(可选)

顾名思义。

allowed-tools(可选)

allowed-tools 定义该 skill 可以在无需用户批准情况下使用的工具,类似 Claude 的 allowed-tools。

它是一个以逗号分隔的字符串,会解析成工具名数组。可以用通配符限制权限范围,例如 Bash(git:*) 仅允许 git 子命令,而 Bash(npm:*) 允许所有 npm 操作。skill-creator 使用 "Read,Write,Bash,Glob,Grep,Edit" 以获得广泛的文件与搜索能力。常见误区是列出所有工具,这会引入安全风险并破坏安全模型。

只列出实际需要的工具——如果只是读写文件,"Read,Write" 就足够。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# ✅ skill-creator allows multiple tools
allowed-tools: "Read,Write,Bash,Glob,Grep,Edit"

# ✅ Specific git commands only
allowed-tools: "Bash(git status:*),Bash(git diff:*),Bash(git log:*),Read,Grep"

# ✅ File operations only
allowed-tools: "Read,Write,Edit,Glob,Grep"

# ❌ Unnecessary surface area
allowed-tools: "Bash,Read,Write,Edit,Glob,Grep,WebSearch,Task,Agent"

# ❌ Unnecessary surface area with all npm commands
allowed-tools: "Bash(npm:*),Read,Write"

model(可选)

model 定义 skill 可使用的模型。默认继承当前会话模型。对于复杂任务(如代码审查),skill 可以请求更强的模型,例如 Claude Opus 或其他 OSS 中文模型(懂的都懂)。

1
2
model: "claude-opus-4-20250514"  # Use specific model
model: "inherit" # Use session's current model (default)

versiondisable-model-invocationmode(可选)

Skills 支持三个可选 frontmatter 字段用于版本与调用控制。version(例如 version: "1.0.0")是用于记录 skill 版本的元数据,解析后主要用于文档与管理。

disable-model-invocation(布尔值)会阻止 Claude 通过 Skill 工具自动调用该 skill。设置为 true 时,技能不会出现在 Claude 可见列表中,只能由用户通过 /skill-name 手动调用,适合危险操作、配置命令或需要明确用户控制的交互流程。

mode(布尔值)会把 skill 标记为“模式命令”,即修改 Claude 行为或上下文的技能。设为 true 时,这类 skill 会在技能列表顶部的 “Mode Commands” 区域单独显示,例如 debug-mode、expert-mode、review-mode 等,方便建立特定操作上下文或工作流。

SKILL.md 提示内容

frontmatter 之后是 Markdown 正文——这才是 skill 被调用时 Claude 收到的实际提示。这里定义技能的行为、指令与工作流。写好 skill 提示的关键是保持聚焦并使用渐进披露:核心指令放在 SKILL.md,详细内容引用外部文件。

推荐的内容结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
---
# Frontmatter here
---

# [Brief Purpose Statement - 1-2 sentences]

## Overview
[What this skill does, when to use it, what it provides]

## Prerequisites
[Required tools, files, or context]

## Instructions

### Step 1: [First Action]
[Imperative instructions]
[Examples if needed]

### Step 2: [Next Action]
[Imperative instructions]

### Step 3: [Final Action]
[Imperative instructions]

## Output Format
[How to structure results]

## Error Handling
[What to do when things fail]

## Examples
[Concrete usage examples]

## Resources
[Reference scripts/, references/, assets/ if bundled]

例如 skill-creatorSKILL.md 里包含如下步骤:

1
2
3
4
5
6
7
## Skill Creation Process

### Step 1: Understanding the Skill with Concrete Examples
### Step 2: Planning the Reusable Skill Contents
### Step 3: Initializing the Skill
### Step 4: Edit the Skill
### Step 5: Packaging a Skill

当 Claude 调用该 skill 时,它会接收到完整提示,并在前面加上基础目录路径。{baseDir} 会解析为 skill 的安装目录,因此 Claude 可以用 Read 工具读取参考文件:Read({baseDir}/scripts/init_skill.py)。这种模式让主提示保持简洁,而详细文档可按需加载。

提示内容最佳实践:

  • 控制在 5,000 字(约 800 行)以内,避免上下文过载
  • 使用祈使句(“Analyze code for …”),而不是第二人称(“You should analyze …”)
  • 详细内容放外部文件,不要把全部内容塞进主提示
  • 路径用 {baseDir},不要硬编码绝对路径如 /home/user/project/
1
2
Read /home/user/project/config.json
Read {baseDir}/config.json

当技能被调用时,Claude 只会获得 allowed-tools 中指定的工具权限;frontmatter 若指定 model,也可能覆盖当前模型。同时系统会自动提供 skill 的基础目录路径,以访问打包资源。

为技能打包资源

当你在 SKILL.md 之外打包辅助资源时,技能会变得更强大。标准结构包含三个目录:

1
2
3
4
5
my-skill/
├── SKILL.md # Core prompt and instructions
├── scripts/ # Executable Python/Bash scripts
├── references/ # Documentation loaded into context
└── assets/ # Templates and binary files

为什么要打包资源?保持 SKILL.md 简洁(少于 5,000 字)可以避免 Claude 的上下文窗口被淹没。打包资源能让你提供详细文档、自动化脚本与模板,而不会撑大主提示。Claude 只在需要时通过渐进披露加载这些资源。

scripts/ 目录

scripts/ 目录包含 Claude 通过 Bash 工具执行的代码——自动化脚本、数据处理器、校验器或代码生成器等确定性操作。

例如 skill-creatorSKILL.md 会这样引用脚本:

1
2
3
4
5
从头开始创建新 skill 时,始终运行 `init_skill.py` 脚本。该脚本方便地生成新的模板 skill 目录,自动包含 skill 所需的一切,使 skill 创建过程更加高效和可靠。

使用方法:

```scripts/init_skill.py <skill-name> --path <output-directory>

该脚本:

  • 在指定路径创建 skill 目录
  • 生成带有正确 frontmatter 和 TODO 占位符的 SKILL.md 模板
  • 创建示例资源目录:scripts/、references/ 和 assets/
  • 在每个目录中添加可自定义或删除的示例文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    Claude 看到这个指令后,会执行 `python {baseDir}/scripts/init_skill.py`。`{baseDir}` 自动解析为 skill 安装路径,使技能可在不同环境下移植。

    对于复杂多步骤操作、数据转换、API 交互或逻辑更适合代码表达的任务,用 `scripts/` 最合适。

    #### `references/` 目录

    `references/` 存放 Claude 会读取进上下文的文档(文本内容):Markdown、JSON schema、配置模板或任务所需的说明文档。

    例如 `mcp-creator` 的 `SKILL.md` 会这样引用 references:

1.4 Study Framework Documentation

加载并读取以下参考文件:

对于 Python 实现,还要加载:

  • Python SDK 文档:使用 WebFetch 加载 https://raw.githubusercontent.com/modelcontextprotocol/python-sdk/main/README.md
  • 🐍 Python 实现指南 - Python 特定的最佳实践和示例

对于 Node/TypeScript 实现,还要加载:

  • TypeScript SDK 文档:使用 WebFetch 加载 https://raw.githubusercontent.com/modelcontextprotocol/typescript-sdk/main/README.md
  • ⚡ TypeScript 实现指南 - Node/TypeScript 特定的最佳实践和示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    当 Claude 遇到这些指令时,会使用 Read 工具:`Read({baseDir}/references/mcp_best_practices.md)`。内容会被加载到上下文,而不污染 `SKILL.md`。

    `references/` 适用于详细文档、大型模式库、检查清单、API schema 等过于冗长但任务需要的文本内容。

    #### `assets/` 目录

    `assets/` 目录包含模板与二进制文件,Claude 只通过路径引用它们,不会把内容读入上下文。它们是技能的静态资源——HTML 模板、CSS 文件、图片、配置样板或字体等。

    在 `SKILL.md` 中:

使用 {baseDir}/assets/report-template.html 处的模板作为报告结构。
引用 {baseDir}/assets/diagram.png 处的架构图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Claude 看到的是路径,但不会读取内容。它可能会复制模板到新位置、填充占位符或在输出中引用路径。

`assets/` 适用于 HTML/CSS 模板、图片、二进制文件、配置模板等仅通过路径操作而非读入上下文的文件。

`references/``assets/` 的关键区别是:

- `references/`:文本内容通过 Read 工具读入 Claude 上下文
- `assets/`:文件仅以路径引用,不读入上下文

这个区别很重要:`references/` 中的 10KB Markdown 会占用上下文 token;`assets/` 中的 10KB HTML 模板不会。Claude 只知道该路径存在。

> 最佳实践:路径永远使用 `{baseDir}`,不要硬编码绝对路径。这能让 skills 在不同用户环境、项目目录与安装路径中保持可移植性。

### 常见 Skill 模式

在工程实践中,理解通用模式有助于设计更有效的 skills。以下是工具集成与工作流设计的常见模式。

#### 模式 1:脚本自动化(Script Automation)

**适用场景**:需要多个命令或确定性逻辑的复杂操作。

该模式把计算任务交给 `scripts/` 中的 Python/Bash 脚本。skill 提示告诉 Claude 运行脚本并处理输出。

![Claude Skill Script Automation](https://leehanchung.github.io/assets/img/2025-10-26/09-script-automation.png)

`SKILL.md` 示例:

Run scripts/analyzer.py on the target directory:

python {baseDir}/scripts/analyzer.py --path "$USER_PATH" --output report.json

Parse the generated report.json and present findings.

1
2

所需工具:

allowed-tools: “Bash(python {baseDir}/scripts/:), Read, Write”

1
2
3
4
5
6
7
8
9
10

#### 模式 2:读 - 处理 - 写(Read - Process - Write)

**适用场景**:文件转换与数据处理。

这是最简单的模式:读取输入,按指令转换,写出结果。适用于格式转换、数据清洗或报告生成。

![Claude Skill Read Process Write](https://leehanchung.github.io/assets/img/2025-10-26/10-read-process-write.png)

`SKILL.md` 示例:

Processing Workflow

  1. Read input file using Read tool
  2. Parse content according to format
  3. Transform data following specifications
  4. Write output using Write tool
  5. Report completion with summary
    1
    2

    所需工具:

allowed-tools: “Read, Write”

1
2
3
4
5
6
7
8
9
10

#### 模式 3:搜索 - 分析 - 报告(Search - Analyze - Report)

**适用场景**:代码库分析与模式检测。

使用 Grep 搜索代码库中的模式,读取匹配文件上下文,进行分析并生成结构化报告。也可用于检索企业数据并分析输出报告。

![Claude Skill Search Analyze Report](https://leehanchung.github.io/assets/img/2025-10-26/06-search-analyze-report.png)

`SKILL.md` 示例:

Analysis Process

  1. Use Grep to find relevant code patterns
  2. Read each matched file
  3. Analyze for vulnerabilities
  4. Generate structured report
    1
    2

    所需工具:

allowed-tools: “Grep, Read”

1
2
3
4
5
6
7
8
9
10

#### 模式 4:命令链执行(Command Chain Execution)

**适用场景**:有依赖关系的多步骤操作。

按顺序执行命令,每步依赖前一步成功,常用于 CI/CD 风格的流程。

![Claude Skill Command Chain Execution](https://leehanchung.github.io/assets/img/2025-10-26/05-command-chain-execution.png)

`SKILL.md` 示例:

Execute analysis pipeline:
npm install && npm run lint && npm test

Report results from each stage.

1
2

所需工具:

allowed-tools: “Bash(npm install:), Bash(npm run:), Read”

1
2
3
4
5
6
7
8
9
10

### 高级模式(Advanced Patterns)

#### 向导式多步骤流程(Wizard-Style Multi-Step Workflows)

**适用场景**:需要在每一步都获取用户输入的复杂流程。

把复杂任务拆分为离散步骤,每一步都需要用户确认后继续。适合安装向导、配置工具或引导式流程。

`SKILL.md` 示例:

Workflow

Step 1: Initial Setup

  1. Ask user for project type
  2. Validate prerequisites exist
  3. Create base configuration
    Wait for user confirmation before proceeding.

Step 2: Configuration

  1. Present configuration options
  2. Ask user to choose settings
  3. Generate config file
    Wait for user confirmation before proceeding.

Step 3: Initialization

  1. Run initialization scripts
  2. Verify setup successful
  3. Report results
    1
    2
    3
    4
    5
    6
    7
    8

    #### 模板驱动生成(Template-Based Generation)

    **适用场景**:从 `assets/` 中的模板生成结构化输出。

    加载模板,填充用户提供或生成的数据,然后写出结果。常用于报告生成、样板代码或文档。

    `SKILL.md` 示例:

Generation Process

  1. Read template from {baseDir}/assets/template.html
  2. Parse user requirements
  3. Fill template placeholders:
    • → user-provided name
    • → generated summary
    • → current date
  4. Write filled template to output file
  5. Report completion
    1
    2
    3
    4
    5
    6
    7
    8

    #### 迭代精化(Iterative Refinement)

    **适用场景**:需要多轮、逐步深入的流程。

    先做广泛分析,再对发现的问题进行更深入的检查。适用于代码评审、安全审计或质量分析。

    `SKILL.md` 示例:

Iterative Analysis

Pass 1: Broad Scan

  1. Search entire codebase for patterns
  2. Identify high-level issues
  3. Categorize findings

Pass 2: Deep Analysis

For each high-level issue:

  1. Read full file context
  2. Analyze root cause
  3. Determine severity

Pass 3: Recommendation

For each finding:

  1. Research best practices
  2. Generate specific fix
  3. Estimate effort

Present final report with all findings and recommendations.

1
2
3
4
5
6
7
8

#### 上下文聚合(Context Aggregation)

**适用场景**:从多来源汇总信息以形成完整理解。

从不同文件与工具收集数据,综合成连贯结论。适合项目总结、依赖分析或影响评估。

`SKILL.md` 示例:

Context Gathering

  1. Read project README.md for overview
  2. Analyze package.json for dependencies
  3. Grep codebase for specific patterns
  4. Check git history for recent changes
  5. Synthesize findings into coherent summary
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    # Agent Skills 内部架构

    有了概览与构建流程后,我们再深入技能系统的内部。Skill 系统是一个元工具架构:名为 Skill 的工具充当容器与调度器,管理所有具体技能。这个设计在实现与目的上都与传统工具截然不同。

    > Skill 工具是管理所有技能的元工具。

    ## Skills 对象设计

    传统工具(Read、Bash、Write)执行离散动作并返回即时结果;skills 则不同。它们不直接执行动作,而是**向对话历史注入专门指令**,并动态修改 Claude 的执行环境。具体做法是:注入两条 user message(一条可见的元数据消息,另一条隐藏但发送给 Claude 的完整技能提示),同时调整 agent 的上下文(修改权限、切换模型、调整思考 token 参数),作用范围仅限技能执行期间。

    ![Claude Skill 执行流程](https://leehanchung.github.io/assets/img/2025-10-26/08-claude-skill-execution-flow.png)

    | 特性 | 普通工具 | Skill 工具 |
    | --- | --- | --- |
    | 本质 | 直接执行动作 | 提示词注入 + 上下文修改 |
    | 消息角色 | assistant → tool_use;user → tool_result | assistant → tool_use Skill;user → tool_result;user → skill prompt(注入) |
    | 复杂度 | 简单(3-4 条消息) | 复杂(5-10+ 条消息) |
    | 上下文 | 静态 | 动态(每轮修改) |
    | 持久性 | 仅工具交互 | 工具交互 + skill prompts |
    | token 开销 | 低(~100 tokens) | 高(~1,500+ tokens/轮) |
    | 使用场景 | 简单直接任务 | 复杂引导工作流 |

    复杂度显著提升:普通工具只产生“assistant 工具调用 + user 返回结果”的简单交互;skills 会注入多条消息,在动态上下文中运行,并带来可观 token 开销,以提供引导 Claude 行为的专用指令。

    理解 Skill 元工具的运作机制尤为关键。其结构如下:

Pd = {
name: “Skill”, // The tool name constant: $N = “Skill”

inputSchema: {
command: string // E.g., “pdf”, “skill-creator”
},

outputSchema: {
success: boolean,
commandName: string
},

// 🔑 KEY FIELD: This generates the skills list
prompt: async () => fN2(),

// Validation and execution
validateInput: async (input, context) => { / 5 error codes / },
checkPermissions: async (input, context) => { / allow/deny/ask / },
call: async (input, context) => { / yields messages + context modifier */ }
}

1
2

`prompt` 字段让 Skill 工具区别于 Read/Bash 之类的普通工具。普通工具的描述是固定字符串,而 Skill 工具会在运行时**动态生成描述**,把所有可用技能的 name 与 description 汇总起来。这就是渐进披露:系统只把最小元数据(skills 名称与描述)放入 Claude 初始上下文,让模型决定匹配的技能;完整 skill prompt 只有在选择后才加载,既保证可发现性,又避免上下文膨胀。

async function fN2() {
let A = await atA(),
{
modeCommands: B,
limitedRegularCommands: Q
} = vN2(A),
G = […B, …Q].map((W) => W.userFacingName()).join(“, “);
l(Skills and commands included in Skill tool: ${G});
let Z = A.length - B.length,
Y = nS6(B),
J = aS6(Q, Z);
return `在主对话中执行技能

<skills_instructions>
当用户要求执行任务时,检查下面可用的技能是否可以更有效地完成任务。技能提供专门的能力和领域知识。

如何使用技能:
- 使用此工具仅通过技能名称调用技能(无参数)
- 调用技能时,您会看到 正在加载”{name}”技能
- 技能提示将展开并提供完成任务的详细说明
- 示例:
- `command: “pdf”` - 调用 pdf 技能
- `command: “xlsx”` - 调用 xlsx 技能
- `command: “ms-office-suite:pdf”` - 使用完全限定名称调用

重要:
- 仅使用下面 <available_skills> 中列出的技能
- 不要调用已运行的技能
- 不要将此工具用于内置 CLI 命令(如 /help、/clear 等)
</skills_instructions>

<available_skills>
${Y}${J}
</available_skills>
`;
}

1
2

不同于某些工具(如 ChatGPT)把工具列表写在系统提示词中,Claude 的 agent skills 并不在 system prompt 里,而是在 tools 数组中,以 Skill 工具描述的一部分呈现。每个 skill 名称对应 Skill 元工具输入 schema 的 `command` 字段。为了更直观地理解,以下是 API 请求结构:

{
“model”: “claude-sonnet-4-5-20250929”,
“system”: “You are Claude Code, Anthropic’s official CLI…”, // ← System prompt
“messages”: [
{“role”: “user”, “content”: “Help me create a new skill”},
// … conversation history
],
“tools”: [ // ← Tools array sent to Claude
{
“name”: “Skill”, // ← The meta-tool
“description”: “Execute a skill…\n\n<skills_instructions>…\n\n<available_skills>\n…”,
“input_schema”: {
“type”: “object”,
“properties”: {
“command”: {
“type”: “string”,
“description”: “The skill name (no arguments)” // ← Name of individual skill
}
}
}
},
{
“name”: “Bash”,
“description”: “Execute bash commands…”,
// …
},
{
“name”: “Read”,
// …
}
// … other tools
]
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

`<available_skills>` 位于 Skill 工具描述中,每次 API 请求都会重生成。系统会汇总当前已加载的技能(用户/项目配置、插件技能、内置技能),并受默认 15,000 字符的 token 预算限制。这迫使作者写出简洁的技能描述,也确保工具描述不会淹没模型上下文。

## Skill 的对话与执行上下文注入设计

多数 LLM API 支持 `role: "system"` 消息,可承载系统提示词。实际上,OpenAI 的 ChatGPT 会把默认工具写在系统提示词里,包括 bio(记忆)、automations(任务调度)、canmore(控制 canvas)、img_gen(图像生成)、file_search、python、web(联网搜索)等。而且工具提示占据系统提示词约 90% 的 token。对于有大量工具或技能的场景,这种方式并不高效。

system message 的语义不同,导致它不适合作为技能载体:system message 设置的是**全局上下文**,在整个对话中持续生效,权限高于用户指令。

Skills 需要临时、范围限定的行为。`skill-creator` 只应影响技能创建任务,而不该把 Claude 永久变成 PDF 专家。使用 `role: "user"` 且 `isMeta: true` 的方式,使 skill prompt 以“用户输入”的形式注入 Claude,从而保持临时性与局部性;技能完成后,对话上下文与执行上下文会回归正常,不留下残留影响。

普通工具如 Read/Write/Bash 通信模式简单:Claude 调用 Read,发送文件路径,拿到文件内容即可。用户在聊天记录中看到“Claude 使用了 Read 工具”,这就够了。但 skills 不是执行离散动作,而是注入完整指令集,改变 Claude 处理任务的方式。因此出现新的设计挑战:用户需要知道正在运行哪个 skill 以及它在做什么,而 Claude 需要详细(可能很长)的指令。如果用户看到完整 skill prompt,UI 会被成千上万字的内部指令淹没;如果完全隐藏 skill 激活,用户又会失去可见性。解决方案是分离两个沟通通道:不同可见性规则的消息。

Skills 系统通过 `isMeta` 标记控制消息是否出现在 UI 中:`isMeta: false`(或省略时默认 false)会显示在用户对话记录;`isMeta: true` 会发送给 API 但不显示在 UI。这个简单的布尔标记实现了双通道通信:一条给人类,一条给 AI。

当 skill 执行时,系统会注入两条 user message:第一条携带元数据(`isMeta: false`,对用户可见,作为状态指示);第二条携带完整 skill prompt(`isMeta: true`,对 UI 隐藏,但 Claude 可见)。这样在不淹没用户的前提下,仍然保证透明度。

元数据消息使用简洁 XML 结构,前端可解析并展示:

let metadata = [
<command-message>${statusMessage}</command-message>,
<command-name>${skillName}</command-name>,
args ? <command-args>${args}</command-args> : null
].filter(Boolean).join(‘\n’);

// Message 1: NO isMeta flag → defaults to false → VISIBLE
messages.push({
content: metadata,
autocheckpoint: checkpointFlag
});

1
2

例如 PDF 技能激活时,用户会看到:

The “pdf” skill is loading

pdf

report.pdf

1
2
3
4

这条消息刻意保持简短(约 50-200 字符)。XML 标签让前端可用特殊样式渲染、校验 `<command-message>` 标签存在,并为会话中的技能执行维护审计轨迹。由于 `isMeta` 默认 false,这条元数据会自动出现在 UI。

skill prompt 消息则相反:它加载 `SKILL.md` 的完整内容,可能附加上下文,显式设置 `isMeta: true`:

let skillPrompt = await skill.getPromptForCommand(args, context);

// Augment with prepend/append content if needed
let fullPrompt = prependContent.length > 0 || appendContent.length > 0
? […prependContent, …appendContent, …skillPrompt]
: skillPrompt;

// Message 2: Explicit isMeta: true → HIDDEN
messages.push({
content: fullPrompt,
isMeta: true // HIDDEN FROM UI, SENT TO API
});

1
2

典型 skill prompt 长度 500-5,000 词,为改变 Claude 行为提供完整指导。例如 PDF skill prompt 可能是:

您是 PDF 处理专家。

您的任务是使用 pdftotext 工具从 PDF 文档中提取文本。

流程

  1. 验证 PDF 文件是否存在
  2. 运行 pdftotext 命令提取文本
  3. 读取输出文件
  4. 向用户呈现提取的文本

可用工具

您可以访问:

  • Bash(pdftotext:*) - 用于运行 pdftotext 命令
  • Read - 用于读取提取的文本
  • Write - 用于在需要时保存结果

输出格式

以清晰格式呈现提取的文本。

基础目录:/path/to/skill
用户参数:report.pdf

1
2
3
4

这个提示建立任务上下文、列出工作流、指定可用工具、定义输出格式,并提供环境路径。通过标题、列表、代码块的 Markdown 结构,Claude 更容易解析并遵循指令。`isMeta: true` 让完整提示发送给 API,却不会污染用户对话记录。

除了元数据与 skill prompt 之外,skill 还可注入附加消息(附件、权限等):

let allMessages = [
createMessage({ content: metadata, autocheckpoint: flag }), // 1. Metadata
createMessage({ content: skillPrompt, isMeta: true }), // 2. Skill prompt
…attachmentMessages, // 3. Attachments (conditional)
…(allowedTools.length || skill.model ? [
createPermissionsMessage({ // 4. Permissions (conditional)
type: “command_permissions”,
allowedTools: allowedTools,
model: skill.useSmallFastModel ? getFastModel() : skill.model
})
] : [])
];

1
2
3
4
5
6

附件消息可以携带诊断信息、文件引用或补充上下文。权限消息只有在 frontmatter 指定 `allowed-tools` 或请求模型覆盖时才出现,提供修改运行时环境的元数据。模块化组合让每条消息都有清晰职责,基于 skill 配置可选拼装,在保持 `isMeta` 可见性控制的同时扩展两消息模式以适配更复杂场景。

### 为什么要两条消息,而不是一条?

如果只用一条消息,就必须在可见性上做不可能的取舍:设置 `isMeta: false` 会把整条消息显示出来,数千字的 AI 指令会淹没聊天记录;用户会看到:

┌─────────────────────────────────────────────┐
│ The “pdf” skill is loading │
│ │
│ You are a PDF processing specialist. │
│ │
│ Your task is to extract text from PDF │
│ documents using the pdftotext tool. │
│ │
│ ## Process │
│ │
│ 1. Validate the PDF file exists │
│ 2. Run pdftotext command to extract text │
│ 3. Read the output file │
│ … [500 more lines] … │
└─────────────────────────────────────────────┘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

UI 会变得不可用,因为内部实现细节充斥其中。如果设置 `isMeta: true`,则所有内容都被隐藏,用户看不到哪个技能被激活、传入了什么参数。系统对用户完全不透明。

两条消息的分拆正好解决这个矛盾:第一条 `isMeta: false` 提供用户透明度;第二条 `isMeta: true` 为 Claude 提供详细指令。精细化控制让透明度与清晰度兼得。

两类消息服务的对象与目的也不同:

| 维度 | 元数据消息 | Skill Prompt 消息 |
| --- | --- | --- |
| 受众 | 人类用户 | Claude(AI) |
| 目的 | 状态/透明度 | 指令/引导 |
| 长度 | ~50-200 字符 | ~500-5,000 词 |
| 格式 | 结构化 XML | 自然语言 Markdown |
| 可见性 | 应可见 | 应隐藏 |
| 内容 | “发生了什么?” | “如何完成?” |

代码库对这两类消息走不同处理路径:元数据消息会解析 `<command-message>` 标签、校验并格式化后展示;skill prompt 直接发给 API,不解析不校验——它是纯粹的指令内容。把两者合并会违反单一职责原则,让一条消息承担两种受众与两种处理流程。

## 案例:执行生命周期

在理解 Agent Skills 内部架构后,我们以“Extract text from report.pdf”这个请求为例,完整走一遍假设的 pdf skill 执行流程。

![Claude Skill 执行时序图](https://leehanchung.github.io/assets/img/2025-10-26/07-claude-skill-sequence-diagram.png)

### Phase 1:发现与加载(启动)

Claude Code 启动时会扫描 skills:

async function getAllCommands() {
// Load from all sources in parallel
let [userCommands, skillsAndPlugins, pluginCommands, builtins] =
await Promise.all([
loadUserCommands(), // ~/.claude/commands/
loadSkills(), // .claude/skills/ + plugins
loadPluginCommands(), // Plugin-defined commands
getBuiltinCommands() // Hardcoded commands
]);

return […userCommands, …skillsAndPlugins, …pluginCommands, …builtins]
.filter(cmd => cmd.isEnabled());
}

// Specific skill loading
async function loadPluginSkills(plugin) {
// Check if plugin has skills
if (!plugin.skillsPath) return [];

// Two patterns supported:
// 1. Root SKILL.md in skillsPath
// 2. Subdirectories with SKILL.md

const skillFiles = findSkillMdFiles(plugin.skillsPath);
const skills = [];

for (const file of skillFiles) {
const content = readFile(file);
const { frontmatter, markdown } = parseFrontmatter(content);

skills.push({
  type: "prompt",
  name: `${plugin.name}:${getSkillName(file)}`,
  description: `${frontmatter.description} (plugin:${plugin.name})`,
  whenToUse: frontmatter.when_to_use,  // ← Note: underscores!
  allowedTools: parseTools(frontmatter['allowed-tools']),
  model: frontmatter.model === "inherit" ? undefined : frontmatter.model,
  isSkill: true,
  promptContent: markdown,
  // ... other fields
});

}

return skills;
}

1
2

对于 pdf skill,最终会生成:

{
type: “prompt”,
name: “pdf”,
description: “Extract text from PDF documents (plugin:document-tools)”,
whenToUse: “When user wants to extract or process text from PDF files”,
allowedTools: [“Bash(pdftotext:*)”, “Read”, “Write”],
model: undefined, // Uses session model
isSkill: true,
disableModelInvocation: false,
promptContent: “You are a PDF processing specialist…”,
// … other fields
}

1
2
3
4
5
6
7
8

### Phase 2:第 1 轮用户请求与技能选择

用户请求:“Extract text from report.pdf”。Claude 收到消息以及 tools 数组中的 Skill 工具。在 Claude 决定调用 pdf skill 前,系统必须在 Skill 工具描述中列出可用技能。

#### 技能过滤与呈现

并非所有技能都显示在 Skill 工具中。一个技能必须在 frontmatter 中包含 `description` 或 `when_to_use`,否则会被过滤。过滤条件如下:

async function getSkillsForSkillTool() {
const allCommands = await getAllCommands();

return allCommands.filter(cmd =>
cmd.type === “prompt” &&
cmd.isSkill === true &&
!cmd.disableModelInvocation &&
(cmd.source !== “builtin” || cmd.isModeCommand === true) &&
(cmd.hasUserSpecifiedDescription || cmd.whenToUse) // ← Must have one!
);
}

1
2
3
4

#### 技能格式化

每个技能都会被格式化进 `<available_skills>`。例如 pdf skill 可能呈现为:

“pdf”: Extract text from PDF documents - When user wants to extract or process text from PDF files

1
2

对应格式函数:

function formatSkill(skill) {
let name = skill.name;
let description = skill.whenToUse
? ${skill.description} - ${skill.whenToUse}
: skill.description;

return "${name}": ${description};
}

1
2
3
4

#### Claude 的决策过程

当用户提示“Extract text from report.pdf”时,Claude 会在 API 请求里看到 Skill 工具与 `<available_skills>`,然后进行推理(这里是合理的假设,因为我们看不到真实推理轨迹):

Internal reasoning:

  • User wants to “extract text from report.pdf”
  • This is a PDF processing task
  • Looking at available skills…
  • “pdf”: Extract text from PDF documents - When user wants to extract or process text from PDF files
  • This matches! The user wants to extract text from a PDF
  • Decision: Invoke Skill tool with command=”pdf”
    1
    2

    注意:这里没有任何算法匹配,没有词法匹配、语义匹配或搜索。完全是 LLM 的推理决策。完成后,Claude 会返回工具调用:

{
“type”: “tool_use”,
“id”: “toolu_123abc”,
“name”: “Skill”,
“input”: {
“command”: “pdf”
}
}

1
2
3
4
5
6

### Phase 3:Skill 工具执行

Skill 工具开始执行,对应时序图中黄色的 “SKILL TOOL EXECUTION” 盒子,包含验证、权限检查、文件加载、上下文修改等步骤。

#### Step 1:验证

async validateInput({ command }, context) {
let skillName = command.trim().replace(/^\//, “”);

// Error 1: Empty
if (!skillName) return { result: false, errorCode: 1 };

// Error 2: Unknown skill
const allSkills = await getAllCommands();
if (!skillExists(skillName, allSkills)) {
return { result: false, errorCode: 2 };
}

// Error 3: Can’t load
const skill = getSkill(skillName, allSkills);
if (!skill) return { result: false, errorCode: 3 };

// Error 4: Model invocation disabled
if (skill.disableModelInvocation) {
return { result: false, errorCode: 4 };
}

// Error 5: Not prompt-based
if (skill.type !== “prompt”) {
return { result: false, errorCode: 5 };
}

return { result: true };
}

1
2
3
4

pdf skill 通过全部校验 ✓

#### Step 2:权限检查

async checkPermissions({ command }, context) {
const skillName = command.trim().replace(/^\//, “”);
const permContext = (await context.getAppState()).toolPermissionContext;

// Check deny rules
for (const [pattern, rule] of getDenyRules(permContext)) {
if (matches(skillName, pattern)) {
return { behavior: “deny”, message: “Blocked by permission rules” };
}
}

// Check allow rules
for (const [pattern, rule] of getAllowRules(permContext)) {
if (matches(skillName, pattern)) {
return { behavior: “allow” };
}
}

// Default: ask user
return { behavior: “ask”, message: Execute skill: ${skillName} };
}

1
2
3
4
5
6

若无规则限制,用户会看到提示:“Execute skill: pdf?”,用户批准 ✓

#### Step 3:加载 Skill 文件并生成执行上下文修改

完成验证与权限审批后,Skill 工具加载 skill 文件并准备执行上下文修改:

async *call({ command }, context) {
const skillName = command.trim().replace(/^\//, “”);
const allSkills = await getAllCommands();
const skill = getSkill(skillName, allSkills);

// Load the skill prompt
const promptContent = await skill.getPromptForCommand(“”, context);

// Generate metadata tags
const metadata = [
<command-message>The "${skill.userFacingName()}" skill is loading</command-message>,
<command-name>${skill.userFacingName()}</command-name>
].join(‘\n’);

// Create messages
const messages = [
{ type: “user”, content: metadata }, // Visible to user
{ type: “user”, content: promptContent, isMeta: true }, // Hidden from user, visible to Claude
// … attachments, permissions
];

// Extract configuration
const allowedTools = skill.allowedTools || [];
const modelOverride = skill.model;

// Yield result with execution context modifier
yield {
type: “result”,
data: { success: true, commandName: skillName },
newMessages: messages,

// 🔑 Execution context modification function
contextModifier(context) {
  let modified = context;

  // Inject allowed tools
  if (allowedTools.length > 0) {
    modified = {
      ...modified,
      async getAppState() {
        const state = await context.getAppState();
        return {
          ...state,
          toolPermissionContext: {
            ...state.toolPermissionContext,
            alwaysAllowRules: {
              ...state.toolPermissionContext.alwaysAllowRules,
              command: [
                ...state.toolPermissionContext.alwaysAllowRules.command || [],
                ...allowedTools  // ← Pre-approve these tools
              ]
            }
          }
        };
      }
    };
  }

  // Override model
  if (modelOverride) {
    modified = {
      ...modified,
      options: {
        ...modified.options,
        mainLoopModel: modelOverride
      }
    };
  }

  return modified;
}

};
}

1
2
3
4
5
6

Skill 工具返回结果,包含 `newMessages`(元数据 + skill prompt + 权限消息,用于对话上下文注入)和 `contextModifier`(工具权限 + 模型覆盖,用于执行上下文修改)。这对应时序图中黄色的 “SKILL TOOL EXECUTION” 盒子。

### Phase 4:发送到 API(第 1 轮完成)

系统组装完整消息数组发送给 Anthropic API:包括对话历史 + 新注入的 skill 消息。

// Complete message array sent to API for Turn 1
{
model: “claude-sonnet-4-5-20250929”,
messages: [
{
role: “user”,
content: “Extract text from report.pdf”
},
{
role: “assistant”,
content: [
{
type: “tool_use”,
id: “toolu_123abc”,
name: “Skill”,
input: { command: “pdf” }
}
]
},
{
role: “user”,
content: “The \”pdf\” skill is loading\npdf
// isMeta: false (default) - VISIBLE to user in UI
},
{
role: “user”,
content: “You are a PDF processing specialist…\n\n## Process\n1. Validate PDF exists\n2. Run pdftotext…”,
isMeta: true // HIDDEN from UI, sent to API
},
{
role: “user”,
content: {
type: “command_permissions”,
allowedTools: [“Bash(pdftotext:*)”, “Read”, “Write”],
model: undefined
}
}
]
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

![Turn 1 Completion](https://leehanchung.github.io/assets/img/2025-10-26/11-turn-1-completion.png)

这里展示了到此为止发生的事情:执行上下文修改器被应用,预先批准 `Bash(pdftotext:*)``Read``Write`;请求被发送到 Anthropic API。至此 skill 工具执行结束。如果这是普通工具就结束了,但 skills 不同——它们只注入了对话与执行上下文,所以还需要在这些上下文下再次调用 Claude 来完成用户请求。

### Phase 5:Bash 工具执行(带 Skill 上下文)

Claude 接收带注入上下文的 API 响应,skill prompt 改变了 Claude 的行为,提供:

- 专门的 PDF 处理指令(对话上下文)
- 预批准的 `Bash(pdftotext:*)``Read``Write` 权限(执行上下文)
- 清晰的执行流程(对话上下文)

Claude 按 pdf skill 的流程执行:

I’ll extract text from report.pdf. Let me process the file.

[Following pdf skill’s instructions]

  1. Validate that report.pdf exists
  2. Run pdftotext command to extract text
  3. Read the output file
  4. Present the extracted text to you
    1
    2

    Claude 使用 Bash 工具(已预批准,无需用户确认):

{
“type”: “tool_use”,
“id”: “toolu_456def”,
“name”: “Bash”,
“input”: {
“command”: “pdftotext report.pdf output.txt”,
“description”: “使用 pdftotext 从 PDF 中提取文本”
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

Bash 成功执行,返回结果。Claude 再用 Read 读取输出文件并把提取文本呈现给用户。通过注入指令与修改工具权限,skill 成功引导 Claude 完成专业的 PDF 提取流程。

# 结论:心智模型总结

Claude Code 中的 skills 是基于提示词的对话与执行上下文修改器,通过元工具架构运行:

**关键要点**:

1. Skills 是 `SKILL.md` 中的提示模板,而非可执行代码
2. Skill 工具(S 大写)是工具数组中的元工具,用于管理各个 skill,不在 system prompt 中
3. Skills 通过注入指令提示(`isMeta: true`)修改对话上下文
4. Skills 通过更改工具权限与模型选择修改执行上下文
5. 选择 skill 的过程由 LLM 推理完成,而非算法匹配
6. 工具权限通过执行上下文修改进行范围限定
7. 每次调用 skill 会注入两条用户消息:一条用户可见元数据,一条隐藏指令发给 API

**优雅的设计**:把专用知识作为“修改对话上下文的提示词”,把权限作为“修改执行上下文的元信息”,而不是执行代码,使 Claude Code 获得了传统函数调用难以兼得的灵活性、安全性与可组合性。

# 参考资料

- Introducing Agent Skills
- Equipping Agents for the Real World with Agent Skills
- Claude Code Documentation
- Anthropic API Reference
- Official Documented Frontmatter Fields
- Internal Comms Skill
- Skill Creator Skill
- ChatGPT 5 System Prompt (leaked, not official)

@article{
leehanchung_bullshit_jobs,
author = {Lee, Hanchung},
title = {Claude Agent Skills: A First Principles Deep Dive},
year = {2025},
month = {10},
day = {26},
howpublished = {\url{https://leehanchung.github.io}},
url = {https://leehanchung.github.io/blogs/2025/10/26/claude-skills-deep-dive/}
}
`

最近的文章

PayPal 中国境内开户与跨境收款图文教程

如果你在中国境内想用 PayPal 接收海外客户付款,这篇教程会带你从注册、验证、收款到提现,按步骤完成设置,并附上操作清单与注意事项。 …

于  PayPal, 出海, 跨境收款 继续阅读
更早的文章

MCP、Agent Skills 与 Cursor Rules:前端开发中的作用与差异

在 AI 辅助编程进入“智能体时代”后,前端开发者开始接触三个高频概念:MCP(模型上下文协议)、Agent Skills(智能体技能)与 Cursor Rules。它们分别解决“能做什么、怎么做、要按什么规范做”的问题,却又常被混为一谈。本文将从概念、场景应用、关键差异与选择策略四个角度,给出清晰的系统化对比,帮助你在实际项目中做出更好的选择。 …

于  AI, 前端, 工程化 继续阅读
微信搜一搜:智简 Smart&Concise 公众号二维码

关注公众号

智简 Smart&Concise

微信搜一搜,获取独立开发与 AI 实践更新。