Skills根本不是你想的那样!一个真实案例看懂 Skills 全流程 --知识铺
Skills根本不是你想的那样!
Han Lee 通过抓包和逆向工程从第一性原理深度解析 Claude Agent Skills 系统的内部架构与工作机制,还原了Skills的运行原理(原文链接见文末)
一句话:Claude Skills 并非可执行代码,而是一套基于 prompt 注入的元工具架构。
原文包含了大量的图表和概念,理解起来还是会有一些些困难的,所以我另外再结合官方的仓库提供的SkillA社自家的Claude Skills 仓库都有哪些宝贝技能?将流程进行了进一步的简化,相信会让你对于Skills 全流程有一个更清晰的了解。
在使用官方Skill处理一个 PDF 文件时,你在终端输入:
> 帮我从 report.pdf 提取文字
现在我们来看背后到底发生了什么。
第一步:Claude Code 启动时做了什么
你看到的
$ claude
Claude Code v1.0.0
Ready.
>
实际发生的(抓包内容)
Claude Code 扫描了这些目录:
~/.claude/skills/ # 你的个人 skills
.claude/skills/ # 项目 skills
plugins/*/skills/ # 插件提供的 skills
找到了一个 pdf skill,文件结构:
~/.claude/skills/pdf/
├── SKILL.md # 主文件
├── scripts/
│ └── extract.py # Python 脚本
└── references/
└── api-docs.md # API 文档
读取 SKILL.md 的头部:
---
name: pdf
description: 从 PDF 提取文字和表格。当用户提到 PDF、文档提取时使用
allowed-tools: Bash(python:*), Read, Write
---
注意这里只读这几行! 完整的 SKILL.md 有 800 行,但现在不读。
第二步:你的请求发送到 Claude
实际的 HTTP 请求简化后的版本如下:
POST https://api.anthropic.com/v1/messages
{
"model": "claude-sonnet-4-5",
"messages": [
{
"role": "user",
"content": "帮我从 report.pdf 提取文字"
}
],
"tools": [
{
"name": "Skill",
"description": "执行一个 skill\n\n可用的 skills:\n\"pdf\": 从 PDF 提取文字和表格。当用户提到 PDF、文档提取时使用\n\"excel\": 创建和编辑 Excel 文件\n\"ppt\": 创建演示文稿",
"input_schema": {
"type": "object",
"properties": {
"command": {"type": "string"}
}
}
},
{
"name": "Bash",
"description": "执行 bash 命令",
"input_schema": {...}
},
{
"name": "Read",
"description": "读取文件",
"input_schema": {...}
}
]
}
关键点:
pdfskill 的 800 行内容没有发送- 只发送了描述:“从 PDF 提取文字和表格。当用户提到 PDF、文档提取时使用”
- 这只有 20 个 token
第三步:Claude 决定调用 pdf skill
Claude 的响应(抓包内容)
{
"content": [
{
"type": "text",
"text": "我会帮你从 PDF 中提取文字。"
},
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "Skill",
"input": {
"command": "pdf"
}
}
]
}
Claude 的思考过程,我们看不到,大概它这么想的:
用户说 "从 report.pdf 提取文字"
→ 关键词: PDF, 提取, 文字
→ 看看我有什么工具...
→ "Skill" 工具里有 "pdf": 从 PDF 提取文字和表格
→ 完美匹配!
→ 调用 Skill 工具,command="pdf"
第四步:执行 Skill 工具(这里是重点了!)
Claude Code 收到 Claude 要调用 Skill(“pdf”)
现在才读取完整的 SKILL.md(800 行):
---
name: pdf
description: 从 PDF 提取文字和表格
allowed-tools: Bash(python:*), Read, Write
---
# PDF 处理专家
你是一个 PDF 处理专家。
## 工作流程
### 步骤 1: 检查文件
使用 Read 工具检查 PDF 文件是否存在
### 步骤 2: 提取文字
运行脚本:
python {baseDir}/scripts/extract.py report.pdf
### 步骤 3: 读取结果
Read 工具读取 output.txt
### 步骤 4: 展示给用户
## 可用工具
- Bash(python:*) - 运行 Python 脚本
- Read - 读取文件
- Write - 保存结果
基础目录: {baseDir}
准备发送给 Claude 的两条消息:
消息 1 (用户可见):
<command-message>正在加载 "pdf" skill</command-message>
<command-name>pdf</command-name>
消息 2 (用户看不见,但发给 API):
你是一个 PDF 处理专家。
## 工作流程
### 步骤 1: 检查文件
使用 Read 工具检查 PDF 文件是否存在
...
(完整 800 行)
第五步:发送增强后的请求给 Claude
你在界面上看到
> 帮我从 report.pdf 提取文字
正在加载 "pdf" skill
实际发送的完整 HTTP 请求
POST https://api.anthropic.com/v1/messages
{
"model": "claude-sonnet-4-5",
"messages": [
{
"role": "user",
"content": "帮我从 report.pdf 提取文字"
},
{
"role": "assistant",
"content": [
{"type": "text", "text": "我会帮你从 PDF 中提取文字。"},
{"type": "tool_use", "name": "Skill", "input": {"command": "pdf"}}
]
},
{
"role": "user",
"content": "<command-message>正在加载 \"pdf\" skill</command-message>"
// 这条你能看到 ↑
},
{
"role": "user",
"content": "你是一个 PDF 处理专家。\n\n## 工作流程\n\n### 步骤 1: 检查文件...",
"isMeta": true
// ↑ 这条你看不到,但发给了 Claude!
// 完整 800 行都在这里!
},
{
"role": "user",
"content": {
"type": "command_permissions",
"allowedTools": ["Bash(python:*)", "Read", "Write"]
}
// ↑ 这个告诉系统:这些工具预先批准了
}
]
}
Token 对比:
- 第一次请求: ~50 tokens (只有描述)
- 第二次请求: ~2,000 tokens (完整 skill 内容)
第六步:Claude 按照 skill 指令执行
现在 Claude 的"记忆"里有:
1.用户原始请求:“帮我从 report.pdf 提取文字”
2. 新注入的指令:“你是一个 PDF 处理专家。按照以下步骤。。。”
3. 预批准的工具: Bash(python:*), Read, Write
Claude 开始工作
第 1 个工具调用 - 检查文件:
{
"type": "tool_use",
"name": "Read",
"input": {
"path": "report.pdf",
"description": "检查 PDF 文件是否存在"
}
}
系统返回:
{
"type": "tool_result",
"content": "文件存在,大小 1.2MB"
}
第 2 个工具调用 - 运行 Python 脚本:
{
"type": "tool_use",
"name": "Bash",
"input": {
"command": "python ~/.claude/skills/pdf/scripts/extract.py report.pdf",
"description": "提取 PDF 文字"
}
}
这个调用不需要用户确认!
为什么? 因为 Bash(python:*) 在 allowed-tools 里被预批准了!
系统执行脚本,返回:
{
"type": "tool_result",
"content": "提取完成,输出保存到 output.txt"
}
第 3 个工具调用 - 读取结果:
{
"type": "tool_use",
"name": "Read",
"input": {
"path": "output.txt"
}
}
返回:
{
"type": "tool_result",
"content": "这是一份关于 2024 年度财务报告...\n\n总收入: 1000 万美元\n..."
}
第七步:Claude 返回结果给你
你看到的
> 帮我从 report.pdf 提取文字
正在加载 "pdf" skill
✓ 已从 report.pdf 提取文字
内容如下:
这是一份关于 2024 年度财务报告
总收入: 1000 万美元
总支出: 800 万美元
净利润: 200 万美元
...
为什么Skill高效又节省呢?
没有 Skill 的情况
你需要这样说:
> 用 pdftotext 命令从 report.pdf 提取文字,
> 然后读取输出文件,
> 如果遇到错误要处理,
> 最后格式化显示给我
每次都要重复这些指令!
API 请求(每次都发):
{
"messages": [
{
"role": "user",
"content": "用 pdftotext 命令从 report.pdf 提取文字,然后读取输出文件,如果遇到错误要处理,最后格式化显示给我"
}
]
}
Token: ~80 tokens × 每次使用
有 Skill 的情况
你只需要说:
> 帮我从 report.pdf 提取文字
第一次 API 请求(只发描述):
{
"tools": [{
"name": "Skill",
"description": "...\"pdf\": 从 PDF 提取文字和表格..."
}]
}
Token: ~20 tokens
第二次 API 请求(发完整指令):
{
"messages": [
...,
{"content": "你是 PDF 专家...(完整 800 行)", "isMeta": true}
]
}
Token: ~2,000 tokens × 只在激活时发一次
算下来你要处理 10 个 PDF
没有 Skill:
10 次 × 80 tokens = 800 tokens
有 Skill:
启动时: 20 tokens (描述)
第 1 次激活: 2,000 tokens (完整指令)
后续 9 次: 0 tokens (已在上下文中)
总计: 2,020 tokens
但实际上,Skill 会在对话过程中被压缩,所以后续调用可能会重新加载。
如果你真的抓包 Claude Code,你会看到:
请求头:
POST /v1/messages HTTP/1.1
Host: api.anthropic.com
anthropic-version: 2023-06-01
content-type: application/json
x-api-key: sk-ant-...
请求体(关键部分):
{
"model": "claude-sonnet-4-5-20250929",
"max_tokens": 4096,
"tools": [
{
"name": "Skill",
"description": "Execute a skill within the main conversation\n\n<skills_instructions>\nWhen users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively...\n\n<available_skills>\n\"pdf\": 从 PDF 提取文字和表格。当用户提到 PDF、文档提取时使用\n\"xlsx\": 创建和编辑 Excel 文件\n</available_skills>",
"input_schema": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "The skill name (no arguments). E.g., \"pdf\" or \"xlsx\""
}
},
"required": ["command"]
}
}
],
"messages": [...]
}
看到了吗?pdf skill 的 800 行内容不在这里只有一行描述
所以Skills 到底是怎么工作的?
就这几步:
- 启动时: 扫描所有 skills,只读前几行(name + description)
- 发请求时: 把所有 skills 的简短描述塞进 “Skill” 工具里
- Claude 匹配: 用 AI 理解能力匹配用户意图和 skill 描述
- 激活 skill: 读取完整的 SKILL.md,注入到对话中
- 执行: Claude 按照注入的指令工作,工具预批准,不用确认
这种架构的设计核心优势:
不用的 skill 不加载完整内容,可以有 100 个 skills,只占 2000 tokens,所有 skills 格式一样,容易分享安全, 工具权限仅在 skill 执行时有效。
https://link.bytenote.net/tvfkjl
希望这次够具体了!
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/ai002/post/20251125/Skills%E6%A0%B9%E6%9C%AC%E4%B8%8D%E6%98%AF%E4%BD%A0%E6%83%B3%E7%9A%84%E9%82%A3%E6%A0%B7%E4%B8%80%E4%B8%AA%E7%9C%9F%E5%AE%9E%E6%A1%88%E4%BE%8B%E7%9C%8B%E6%87%82-Skills-%E5%85%A8%E6%B5%81%E7%A8%8B/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com