Claude-Code-Skill-深度解析

admin 2026-01-27 00:37:40 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文解析了ClaudeCode的Skill系统,通过三级指针架构实现知识按需加载,解决大模型上下文窗口有限的问题。文章对比了静态与动态意图,阐述了Skill在节点静态、边动态架构下的优势,并提供了编写Skill的实操建议,旨在利用语义匹配高效管理上下文资源。 综合评分: 94 文章分类: 产品介绍,解决方案


cover_image

Claude-Code-Skill-深度解析

原创

xsser xsser

xsser的博客

2026年1月26日 15:34 浙江

一个反直觉的问题

假设你是一家公司的 CTO,手下有一个能力超强的员工。他能写代码、能做设计、能分析数据、能写文档,几乎无所不能。但有个问题:他的工位只有一张 A4 纸大小的桌面。

每次给他布置任务,你都得把所有可能用到的参考资料、规范文档、历史案例全部堆在这张小桌子上。桌面很快就满了,他开始把早期的资料推到地上,然后忘记那些内容。

这就是大语言模型面临的核心困境:Context Window 有限。

Claude 的上下文窗口大约 200K tokens,听起来很多,但在真实的工程场景下,这点空间消耗得比想象中快得多。系统提示词、对话历史、代码文件、API 文档、业务规则……每一样都在争抢这块宝贵的「桌面空间」。

Anthropic 的 Skill 系统,就是为了解决这个问题而生的。

Skill 到底是什么?

很多人第一次听到 Skill 这个概念,会以为是某种插件或者扩展。这个理解方向对了一半。

如果用程序员更熟悉的概念来类比:Skill 本质上是一种「知识指针」。

从一个内存管理的视角理解

假设 Claude 的 Context Window 是一块有限的内存空间,大约 200K tokens。你有一堆知识库要让 Claude 使用:Skill 开发规范(17000 字)、MCP 协议文档(25000 字)、PDF 处理指南(8000 字)、API 设计原则(12000 字)……

最笨的做法是什么?全部 copy 进内存:

12345678910// 反模式:值传递,全量复制void handleRequest(    string skill_spec,      // 17000 字,复制进来    string mcp_docs,        // 25000 字,复制进来    string pdf_guide,       // 8000 字,复制进来    string api_principles,  // 12000 字,复制进来    string user_request     // 用户的实际问题) {    // Context Window 已经快满了    // 留给真正处理问题的空间所剩无几

这就是很多人用 LLM 的方式:把所有可能用到的参考资料一股脑塞进 System Prompt。结果呢?上下文被撑爆,模型还没开始干活就已经「内存溢出」了。

Skill 系统的做法完全不同。它用的是指针 + 懒加载的模式:

111213141516171819202122232425262728293031// Skill 模式:指针传递,按需解引用struct SkillPointer {    string name;         // "skill-creator"    string description;  // "当用户想创建 skill 时触发"  (~100 字)    string* body;        // 指向完整内容的指针,暂不加载    string* references;  // 指向参考文档的指针,暂不加载};
void&nbsp;handleRequest(&nbsp; &nbsp; vector<SkillPointer> skill_registry, &nbsp;// 只有指针和描述,很轻量&nbsp; &nbsp;&nbsp;string&nbsp;user_request) {&nbsp; &nbsp;&nbsp;// Step 1: 扫描所有指针的 description,判断哪些相关&nbsp; &nbsp; auto relevant =&nbsp;semanticMatch(skill_registry, user_request);
&nbsp; &nbsp;&nbsp;// Step 2: 只对相关的 Skill 执行「解引用」&nbsp; &nbsp;&nbsp;for&nbsp;(auto& skill : relevant) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;loadIntoContext(*skill.body); &nbsp;// 按需加载&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;// Step 3: 处理请求,此时上下文里只有真正需要的知识

看出区别了吗?

在值传递模式下,所有知识在函数调用时就被复制进来,无论用不用得到。在指针模式下,你只持有一堆轻量的「引用」,真正需要时才去「解引用」获取完整数据。

三级指针:Skill 的内存模型

Skill 系统的精妙之处在于,它设计了一套三级指针结构,每一级的「解引用成本」不同:

32333435363738394041424344454647484950515253545556575859606162Level&nbsp;0: Skill Registry(始终在内存)┌─────────────────────────────────────────────────────────┐│ &nbsp;skill_creator_ptr &nbsp; → &nbsp;name: "skill-creator" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;desc: "创建 skill 时触发" &nbsp; &nbsp; &nbsp; │ &nbsp;~100&nbsp;tokens│ &nbsp;mcp_builder_ptr &nbsp; &nbsp; → &nbsp;name: "mcp-builder" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;desc: "构建 MCP 服务器时触发" &nbsp; │ &nbsp;~100&nbsp;tokens│ &nbsp;pdf_processor_ptr &nbsp; → &nbsp;name: "pdf-processor" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;desc: "处理 PDF 文件时触发" &nbsp; &nbsp; │ &nbsp;~100&nbsp;tokens└─────────────────────────────────────────────────────────┘&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ 触发后解引用(Level&nbsp;1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ▼Level&nbsp;1: Skill Body(触发后加载)┌─────────────────────────────────────────────────────────┐│ &nbsp;skill-creator.body: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp;"

创建流程 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; 1. 理解需求 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; 2. 规划内容 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp;2000 tokens│ &nbsp; &nbsp; 3. 初始化目录 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; ..." &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp;references_ptr &nbsp;→ &nbsp;指向更详细的文档 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│└─────────────────────────────────────────────────────────┘&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ 需要时再解引用(Level&nbsp;2)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ▼Level&nbsp;2:&nbsp;References(按需加载)┌─────────────────────────────────────────────────────────┐│ &nbsp;workflows.md: &nbsp; &nbsp; &nbsp; &nbsp;"## 顺序工作流 ... ## 条件工作流" &nbsp;│ &nbsp;3000&nbsp;tokens│ &nbsp;output-patterns.md: &nbsp;"## 模板模式 ... ## 示例模式" &nbsp; &nbsp; │ &nbsp;2000&nbsp;tokens│ &nbsp;advanced.md: &nbsp; &nbsp; &nbsp; &nbsp; "## 进阶技巧 ..." &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp;5000&nbsp;tokens

用 TypeScript 来表达这个结构可能更清晰:

636465666768697071727374757677787980818283848586878889909192939495969798interface&nbsp;SkillMetadata&nbsp;{&nbsp;&nbsp;name:&nbsp;string;&nbsp;&nbsp;description:&nbsp;string; &nbsp;// 语义匹配的依据}
interface&nbsp;SkillBody&nbsp;{&nbsp;&nbsp;content:&nbsp;string; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 核心指令,~2000 tokens&nbsp;&nbsp;references:&nbsp;Map<string,&nbsp;() =>&nbsp;string>; &nbsp;// 懒加载函数}
interface&nbsp;SkillRegistry&nbsp;{&nbsp;&nbsp;skills:&nbsp;Map<string, {&nbsp; &nbsp;&nbsp;metadata:&nbsp;SkillMetadata; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 始终加载&nbsp; &nbsp;&nbsp;loadBody:&nbsp;() =>&nbsp;SkillBody; &nbsp; &nbsp; &nbsp;&nbsp;// 懒加载函数&nbsp; }>;}
// Claude 的处理流程function&nbsp;processRequest(registry:&nbsp;SkillRegistry,&nbsp;userInput:&nbsp;string) {&nbsp;&nbsp;// Step 1: O(n) 扫描 metadata,每个只有 ~100 tokens&nbsp;&nbsp;const&nbsp;candidates =&nbsp;Array.from(registry.skills.entries())&nbsp; &nbsp; .filter(([_, skill]) =>&nbsp;semanticMatch(skill.metadata.description, userInput));
&nbsp;&nbsp;// Step 2: 只加载匹配的 Skill Body&nbsp;&nbsp;const&nbsp;loadedSkills = candidates.map(([name, skill]) =>&nbsp;({&nbsp; &nbsp; name,&nbsp; &nbsp;&nbsp;body: skill.loadBody() &nbsp;// 此时才真正加载 ~2000 tokens&nbsp; }));
&nbsp;&nbsp;// Step 3: 执行任务时,如果需要更多细节,再加载 references&nbsp;&nbsp;for&nbsp;(const&nbsp;skill&nbsp;of&nbsp;loadedSkills) {&nbsp; &nbsp;&nbsp;if&nbsp;(needsMoreDetail(currentTask)) {&nbsp; &nbsp; &nbsp;&nbsp;const&nbsp;detail = skill.body.references.get('workflows.md')?.(); &nbsp;// 懒加载&nbsp; &nbsp; &nbsp;&nbsp;appendToContext(detail);&nbsp; &nbsp; }&nbsp; }

为什么这套设计有效?

回到内存管理的类比。传统的 System Prompt 塞满知识的做法,相当于把所有数据都分配在栈上,函数一调用就全部复制。Skill 系统相当于把数据分配在堆上,只传递指针,按需分配。

具体来说:

1. 空间效率

假设你有 50 个 Skill,每个完整内容 3000 tokens。

全量加载:50 × 3000 = 150,000 tokens(直接爆掉上下文)

Skill 模式:50 × 100(metadata)+ 2 × 3000(触发的 Skill)= 11,000 tokens

节省了 93% 的上下文空间。

2. 语义级的「智能指针」

C++ 的智能指针能自动管理内存生命周期。Skill 系统更进一步:它的「指针解引用」由 LLM 的语义理解来驱动。

99100101102103用户说:&nbsp;"帮我做一个能识别发票的东西"
Claude&nbsp;内部推理:-&nbsp;"做一个东西"&nbsp;≈&nbsp;"创建某种能力"&nbsp;→ 匹配 skill-creator-&nbsp;"识别发票"&nbsp;≈&nbsp;"处理 PDF/图片"&nbsp;→ 匹配 pdf-processor

这种基于语义的自动解引用,是传统的 if-else 或者关键词匹配做不到的。Claude 能理解「做一个东西」和「创建 Skill」在这个语境下是等价的,自动完成指针的选择。

3. 分层解引用的成本控制

104Level&nbsp;0&nbsp;→ Level&nbsp;1: 成本 ~2000&nbsp;tokens

大多数请求在 Level 1 就能完成。只有用户追问细节(「工作流有哪几种模式?」)时,才会触发 Level 2 的解引用。这种分层设计让 token 消耗与任务复杂度成正比,避免了一刀切的浪费。

一个更完整的代码类比

如果把整个 Skill 系统用代码来模拟,大概是这样的结构:

105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171class&nbsp;Skill:&nbsp; &nbsp;&nbsp;"""一个 Skill 就是一个带懒加载的知识容器"""
&nbsp; &nbsp;&nbsp;def&nbsp;__init__(self, skill_dir:&nbsp;str):&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.dir&nbsp;= skill_dir&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;Level 0: 元数据立即加载&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.metadata =&nbsp;self._parse_metadata()&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# Level 1 & 2: 延迟加载&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self._body_cache =&nbsp;None&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self._ref_cache = {}
&nbsp; &nbsp;&nbsp;def&nbsp;_parse_metadata(self) ->&nbsp;dict:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"""只解析 YAML frontmatter,约 100 tokens"""&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;with&nbsp;open(f"{self.dir}/SKILL.md")&nbsp;as&nbsp;f:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 只读取 --- 之间的内容&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;yaml.parse(extract_frontmatter(f.read()))
&nbsp; &nbsp; @property&nbsp; &nbsp;&nbsp;def&nbsp;body(self) ->&nbsp;str:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"""懒加载 Level 1:Skill 主体内容"""&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;self._body_cache&nbsp;is&nbsp;None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;with&nbsp;open(f"{self.dir}/SKILL.md")&nbsp;as&nbsp;f:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self._body_cache = extract_body(f.read()) &nbsp;# ~2000 tokens&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;self._body_cache
&nbsp; &nbsp;&nbsp;def&nbsp;get_reference(self, name:&nbsp;str) ->&nbsp;str:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"""懒加载 Level 2:参考文档"""&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;name&nbsp;not&nbsp;in&nbsp;self._ref_cache:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; path =&nbsp;f"{self.dir}/references/{name}"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;with&nbsp;open(path)&nbsp;as&nbsp;f:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self._ref_cache[name] = f.read() &nbsp;# 按需加载&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;self._ref_cache[name]

class&nbsp;SkillRegistry:&nbsp; &nbsp;&nbsp;"""Skill 注册表:管理所有 Skill 的指针"""
&nbsp; &nbsp;&nbsp;def&nbsp;init(self, skills_dir:&nbsp;str):&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.skills = {}&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;skill_name&nbsp;in&nbsp;os.listdir(skills_dir):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; skill = Skill(f"{skills_dir}/{skill_name}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 只存储轻量的 metadata,不加载完整内容&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.skills[skill_name] = skill
&nbsp; &nbsp;&nbsp;def&nbsp;get_context_for_request(self, user_input:&nbsp;str) ->&nbsp;str:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"""根据用户输入,构建最小化的上下文"""&nbsp; &nbsp; &nbsp; &nbsp; context_parts = []
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 始终包含所有 metadata(用于意图匹配)&nbsp; &nbsp; &nbsp; &nbsp; context_parts.append("## Available Skills\n")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;name, skill&nbsp;in&nbsp;self.skills.items():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context_parts.append(f"-&nbsp;{name}:&nbsp;{skill.metadata['description']}")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# Claude 判断需要哪些 Skill(语义匹配)&nbsp; &nbsp; &nbsp; &nbsp; triggered =&nbsp;self._semantic_match(user_input)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 只加载被触发的 Skill Body&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;skill_name&nbsp;in&nbsp;triggered:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; skill =&nbsp;self.skills[skill_name]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context_parts.append(f"\n##&nbsp;{skill_name}\n{skill.body}")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;"\n".join(context_parts)
&nbsp; &nbsp;&nbsp;def&nbsp;_semantic_match(self, user_input:&nbsp;str) ->&nbsp;list[str]:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"""让 LLM 基于 metadata 判断哪些 Skill 相关"""&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 这一步由 Claude 的语义理解完成&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 返回相关的 Skill 名称列表

这段代码展示了 Skill 系统的核心机制:用轻量的 metadata 做索引,用懒加载避免无谓的内存占用,用语义匹配代替硬编码的路由逻辑。

如果你写过 ORM 框架里的 lazy loading,或者用过 React 的React.lazy(),对这套模式应该不陌生。Skill 系统把这些工程实践搬到了 LLM 的知识管理领域。

三层渐进式披露:Skill 的核心设计

Anthropic 的工程师们在设计 Skill 系统时,引入了一个叫做「渐进式披露」(Progressive Disclosure)的架构模式。这套机制分三层,每一层的加载时机和 token 预算都不一样。

第一层:元数据(Metadata)

这是最轻量的一层,大约只有 100 个词,始终驻留在上下文中。

172173174---name: skill-creatordescription: 当用户想创建新 skill、编写 skill、设计 skill 时触发此技能

元数据的作用是让 Claude 知道「有哪些能力可用」以及「什么情况下该用」。就像药柜上的标签,医生一眼扫过去就知道有什么药,但不需要把每种药的详细说明书都读一遍。

Claude 在处理用户请求时,会先扫描所有 Skill 的元数据,判断哪些 Skill 与当前任务相关。这个过程是语义级别的匹配,Claude 能够理解「帮我做一个处理 PDF 的东西」和「创建 PDF 处理工具」表达的是同一个意图。

第二层:主体内容(Body)

当某个 Skill 被触发后,Claude 才会加载它的主体内容。这部分建议控制在 2000 词以内。

175176177178179180181182183184185186187188189
Skill Creator
## 创建流程
1.&nbsp;理解需求:询问用户具体用途和使用场景2.&nbsp;规划内容:确定需要哪些 scripts、references、assets3.&nbsp;初始化目录:运行 init_skill.py 脚本4. 编写核心文件:完成 SKILL.md 和相关资源5. 打包发布:运行 package_skill.py6.&nbsp;收集反馈迭代
## 写作规范
使用祈使句式,例如「创建文件」而非「你应该创建文件」描述字段使用第三人称:「此技能应在用户需要...时使用」

主体内容包含了执行任务所需的核心指令、工作流程、质量标准。这些信息只在需要时才进入上下文,用完就可以释放空间。

第三层:参考资源(References)

有些知识太过详细,放在主体内容里会让文件变得臃肿。Skill 系统允许把这类内容拆分到references/目录下,Claude 会在需要时主动读取。

190191192193194skill-creator/├── SKILL.md &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;主体内容(2000 词)└── references/&nbsp; &nbsp; ├── workflows.md &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# 工作流模式详解(3000 词)&nbsp; &nbsp; ├── output-patterns.md &nbsp; &nbsp; &nbsp;# 输出格式规范(~2000 词)

比如用户问「Skill 支持哪些工作流模式」,Claude 会判断这个问题需要更详细的信息,然后主动去读取workflows.md。读完回答完,这部分内容也可以从上下文中移除。

这种设计的精妙之处在于:知识的粒度和加载时机都经过了精心编排。核心指令常驻内存,详细文档按需调用,上下文窗口的利用效率因此大幅提升。

静态意图 vs 动态意图:一个架构层面的关键区别

如果你尝试过自己写一个 AI Agent,大概率会写出这样的代码:

195196197198199200201202def&nbsp;handle_request(user_input):&nbsp; &nbsp;&nbsp;if&nbsp;"创建 skill"&nbsp;in&nbsp;user_input:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;create_skill_workflow()&nbsp; &nbsp;&nbsp;elif&nbsp;"修改 skill"&nbsp;in&nbsp;user_input:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;modify_skill_workflow()&nbsp; &nbsp;&nbsp;elif&nbsp;"删除 skill"&nbsp;in&nbsp;user_input:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;delete_skill_workflow()&nbsp; &nbsp;&nbsp;else:

这是典型的「静态意图」设计。你需要预先穷举所有可能的用户表达方式,然后硬编码对应的处理逻辑。问题很明显:

用户说「帮我做一个 skill」,匹配失败

用户说「我想 build 一个 skill」,匹配失败

用户说「搞一个处理 Excel 的东西」,匹配失败

每发现一种新的表达方式,你就得改代码、加规则、重新部署。这套路子在传统软件开发里能用,放到 AI Agent 场景下就显得笨拙。

Skill 系统采用了完全不同的策略:把意图识别的任务交给 LLM 本身。

203204205description: |&nbsp; 当用户想创建新 skill 时触发。&nbsp; 包括但不限于:创建、编写、设计、开发、搭建新的 skill,

Claude 读到这段描述后,能够自动理解各种语义上等价的表达:

「创建一个 skill」→ 触发

「帮我做一个处理 PDF 的工具」→ 触发(组合推理:做工具 ≈ 创建 skill)

「我想让 Claude 学会分析日志」→ 触发(深层理解:让 Claude 学会 ≈ 创建能力 ≈ 创建 skill)

这就是「动态意图」的威力。你不需要穷举所有可能的输入,只需要用自然语言描述触发条件,剩下的交给 LLM 的语义理解能力。

更有意思的是,Claude 可以同时触发多个 Skill。当用户说「创建一个处理发票 PDF 的 skill」,Claude 会判断这个请求同时涉及「创建 skill」和「PDF 处理」两个领域,于是把两个 Skill 的知识都加载进来,综合使用。

这种能力在传统的 if-else 架构下极难实现。你要么写一堆组合判断逻辑,要么就得搞一套复杂的意图分类模型。Skill 系统把这些麻烦事儿都甩给了 LLM。

用图论视角理解:节点与边的静态/动态频谱

上面讲的「静态意图」和「动态意图」,可以用图论的语言更精确地描述。

把一个 AI Agent 系统抽象成一张有向图:

节点(Node)

= 能力模块、知识单元、处理函数

边(Edge)

= 节点之间的调用关系、触发条件、执行顺序

不同的系统架构,区别在于节点和边的「静态程度」不同。

第一类:传统 Workflow(节点静态 + 边静态)

这是最常见的自动化系统。你用 Airflow、n8n、或者自己写的编排代码,把一堆处理步骤串起来。

┌─────────────────────────────────────────────────────────────────────┐│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;传统 Workflow 架构 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp;┌──────────┐ &nbsp; &nbsp; &nbsp;┌──────────┐ &nbsp; &nbsp; &nbsp;┌──────────┐ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp;│ 接收请求 &nbsp;│ ───► │ 解析意图 &nbsp;│ ───► │ 路由分发 &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp;└──────────┘ &nbsp; &nbsp; &nbsp;└──────────┘ &nbsp; &nbsp; &nbsp;└──────────┘ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;┌─────────────────────────┼─────────────────┐ &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▼ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ▼ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ▼ &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ┌──────────┐ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;┌──────────┐ &nbsp; &nbsp; &nbsp;┌──────────┐││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ 创建流程 &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ 修改流程 &nbsp;│ &nbsp; &nbsp; &nbsp;│ 删除流程 &nbsp;│││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; └──────────┘ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└──────────┘ &nbsp; &nbsp; &nbsp;└──────────┘││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▼ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ▼ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ▼ &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ┌──────────┐ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;┌──────────┐ &nbsp; &nbsp; &nbsp;┌──────────┐││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ 生成文件 &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ 更新文件 &nbsp;│ &nbsp; &nbsp; &nbsp;│ 清理文件 &nbsp;│││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; └──────────┘ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└──────────┘ &nbsp; &nbsp; &nbsp;└──────────┘││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp;节点:在部署时就固定了(create/update/delete&nbsp;三个分支) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp;边:在代码里写死了(if-else&nbsp;决定走哪条路) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │

用 Mermaid 画出来是这样:

flowchart TD&nbsp; &nbsp; A[接收请求]&nbsp;--> B[解析意图]&nbsp; &nbsp; B&nbsp;--> C{路由分发}&nbsp; &nbsp; C&nbsp;-->|"创建"| D[创建流程]&nbsp; &nbsp; C&nbsp;-->|"修改"| E[修改流程]&nbsp; &nbsp; C&nbsp;-->|"删除"| F[删除流程]&nbsp; &nbsp; D&nbsp;--> G[生成文件]&nbsp; &nbsp; E&nbsp;--> H[更新文件]&nbsp; &nbsp; F&nbsp;--> I[清理文件]
&nbsp; &nbsp; style C fill:#ffcccc&nbsp; &nbsp; style D fill:#cccccc&nbsp; &nbsp; style E fill:#cccccc

这张图的特点:

| 维度 | 状态 | 含义 | | — | — | — | | 节点 | 静态 | 系统有哪些能力,部署时就定死了 | | 边 | 静态 | 节点之间怎么连接,代码里写死了 | | 路由逻辑 | 静态 | if-else / switch-case / 正则匹配 |

问题在哪?

假设用户说「帮我搞一个能处理 Excel 的东西,顺便也支持 PDF」。这个请求同时涉及「创建」+「Excel 处理」+「PDF 处理」三个概念。在静态 Workflow 里,你得预先定义好这种组合场景的处理路径。有 N 个能力模块,理论上就有 2^N 种组合可能。穷举是不现实的。

第二类:Skill 系统(节点静态 + 边动态)

Skill 系统的突破在于:节点还是预定义的,但节点之间的连接关系由 LLM 动态决定。

241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271┌─────────────────────────────────────────────────────────────────────┐│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Skill 系统架构 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp;┌──────────────────────────────────────────────────────────┐ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Skill Registry &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; ┌─────────┐ &nbsp;┌─────────┐ &nbsp;┌─────────┐ &nbsp;┌─────────┐ &nbsp; &nbsp;│ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; │ skill- &nbsp;│ &nbsp;│ &nbsp;mcp- &nbsp; │ &nbsp;│ &nbsp;pdf- &nbsp; │ &nbsp;│ &nbsp;xlsx- &nbsp;│ &nbsp; &nbsp;│ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; │ creator │ &nbsp;│ builder │ &nbsp;│processor│ &nbsp;│processor│ &nbsp; &nbsp;│ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; └─────────┘ &nbsp;└─────────┘ &nbsp;└─────────┘ &nbsp;└─────────┘ &nbsp; &nbsp;│ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp;▲ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▲ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▲ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▲ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp;││ &nbsp; &nbsp;└────────┼────────────┼────────────┼────────────┼──────────┘ &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; └────────────┴─────┬──────┴────────────┘ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;┌───────────┴───────────┐ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp;LLM 语义匹配 &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;"这个请求需要哪些 &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; Skill?怎么组合?" &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└───────────┬───────────┘ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▼ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;┌───────────────────────┐ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; 用户请求 &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│&nbsp;"帮我搞一个能处理 &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;Excel 的东西" &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└───────────────────────┘ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp;节点:预定义的 Skill(skill-creator, pdf-processor 等) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp;边:由 LLM 在运行时动态决定(语义匹配 + 组合推理) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │

用 Mermaid 表达这种动态连接:

272273274275276277278279280281282283284285286287288289flowchart TD&nbsp; &nbsp; subgraph Registry["Skill Registry(节点池)"]&nbsp; &nbsp; &nbsp; &nbsp; S1[skill-creator]&nbsp; &nbsp; &nbsp; &nbsp; S2[mcp-builder]&nbsp; &nbsp; &nbsp; &nbsp; S3[pdf-processor]&nbsp; &nbsp; &nbsp; &nbsp; S4[xlsx-processor]&nbsp; &nbsp; &nbsp; &nbsp; S5[api-designer]&nbsp; &nbsp;&nbsp;end
&nbsp; &nbsp; U[用户请求]&nbsp;--> LLM{LLM 语义匹配}
&nbsp; &nbsp; LLM&nbsp;-.->|"动态连接"|&nbsp;S1&nbsp; &nbsp; LLM&nbsp;-.->|"动态连接"|&nbsp;S3&nbsp; &nbsp; LLM&nbsp;-.->|"动态连接"|&nbsp;S4
&nbsp; &nbsp; S1&nbsp;-.->|"组合执行"|&nbsp;S4
&nbsp; &nbsp; style LLM fill:#90EE90

关键区别:

| 维度 | 状态 | 含义 | | — | — | — | | 节点 | 静态 | Skill 是预先写好的,知识内容固定 | | 边 | 动态 | 哪些 Skill 被调用、以什么顺序组合,运行时决定 | | 路由逻辑 | 动态 | LLM 基于语义理解自动匹配,无需穷举规则 |

为什么边可以动态?

传统 Workflow 的边是代码逻辑,改一条边就得改代码、重新部署。Skill 系统的边是 LLM 的推理结果,模型「想通了」哪些 Skill 相关,边就自动建立了。

290291292293294295296297298299300301302303304305
传统 Workflow:边是硬编码的def&nbsp;route(intent):&nbsp; &nbsp;&nbsp;if&nbsp;intent ==&nbsp;"create":&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;[create_workflow] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# 固定返回一个节点&nbsp; &nbsp;&nbsp;elif&nbsp;intent ==&nbsp;"create_excel":&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;[create_workflow, excel_processor] &nbsp;# 又一条硬编码的边&nbsp; &nbsp;&nbsp;# ... 穷举所有组合
# Skill 系统:边是 LLM 推理出来的def&nbsp;route(user_input, skill_registry):&nbsp; &nbsp;&nbsp;# LLM 看完所有 Skill 的 description,自己决定激活哪些&nbsp; &nbsp;&nbsp;return&nbsp;llm.reason(&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f"用户说:{user_input}\n"&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f"可用 Skill:{skill_registry.descriptions}\n"&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f"请判断需要哪些 Skill,以及执行顺序。"&nbsp; &nbsp; )

这就是「边动态」的含义:连接关系在运行时由 LLM 的语义推理生成,而非在编译时由程序员硬编码。

第三类:更激进的动态系统(节点动态 + 边动态)

如果把思路再推进一步:节点本身也可以是动态的。

这就是一些前沿 Agent 框架在探索的方向。比如让 LLM 在运行时「发明」新的工具、「生成」新的处理函数。AutoGPT、MetaGPT 等项目都有类似的尝试。

306307308309310311312313314315316317318319320321322323324325326327328329330331┌─────────────────────────────────────────────────────────────────────┐│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 全动态 Agent 系统(概念性) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp;┌──────────────────────────────────────────────────────────┐ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;动态节点池 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; ┌─────────┐ &nbsp;┌─────────┐ &nbsp;┌ ─ ─ ─ ─ ┐ &nbsp;┌ ─ ─ ─ ─ ┐ &nbsp; │ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; │ 预定义 &nbsp;│ &nbsp;│ 预定义 &nbsp; │ &nbsp; │ 运行时 &nbsp;│ &nbsp; │ 运行时 &nbsp;│ &nbsp; │ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; │ Tool&nbsp;A&nbsp; │ &nbsp;│ Tool&nbsp;B&nbsp; │ &nbsp; │ 生成的 &nbsp;│ &nbsp; │ 生成的 &nbsp;│ &nbsp; │ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; │ Tool&nbsp;X&nbsp; │ &nbsp; │ Tool&nbsp;Y&nbsp; │ &nbsp; │ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; └─────────┘ &nbsp;└─────────┘ &nbsp;└ ─ ─ ─ ─ ┘ &nbsp;└ ─ ─ ─ ─ ┘ &nbsp; │ &nbsp; &nbsp;││ &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp;▲ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▲ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▲ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▲ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp;││ &nbsp; &nbsp;└────────┼────────────┼────────────┼────────────┼──────────┘ &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; └────────────┴─────┬──────┴────────────┘ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;┌───────────┴───────────┐ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp;LLM 大脑 &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;• 选择现有工具 &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;• 组合多个工具 &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;• 必要时生成新工具 &nbsp; &nbsp;│ ← 节点也变成动态的 &nbsp; &nbsp;││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└───────────────────────┘ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp;节点:部分预定义 + 部分运行时生成 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;││ &nbsp; &nbsp;边:完全动态 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ││ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │

三种架构的对比总结

| 架构类型 | 节点 | 边 | 代表系统 | 适用场景 | | — | — | — | — | — | | 传统 Workflow | 静态 | 静态 | Airflow, n8n, 自定义脚本 | 流程固定、可穷举的业务 | | Skill 系统 | 静态 | 动态 | Claude Code Skill, GPTs | 能力固定、组合方式灵活 | | 全动态 Agent | 动态 | 动态 | AutoGPT, 实验性框架 | 开放探索、研究场景 |

Skill 系统选择了一个务实的平衡点:节点静态保证了可控性和可审计性,边动态提供了灵活性和泛化能力。

你不用担心 LLM 会「发明」出奇怪的处理逻辑,因为所有可用的能力都是你预先定义好的 Skill。但在这些 Skill 之间如何选择、如何组合、以什么顺序执行,LLM 有充分的自由度去推理和决策。

这种设计在工程上很讨巧:既享受了 LLM 语义理解的红利,又避免了完全放开控制带来的不可预测性。

一个具体的例子

用户说:「帮我创建一个能处理发票 PDF 的 Skill,支持提取金额和日期,最后导出成 Excel」

传统 Workflow 的处理方式:

332333334335336337338339
需要预定义这条精确的路径if&nbsp;"创建"&nbsp;in&nbsp;input&nbsp;and&nbsp;"PDF"&nbsp;in&nbsp;input&nbsp;and&nbsp;"发票"&nbsp;in&nbsp;input&nbsp;and&nbsp;"Excel"&nbsp;in&nbsp;input:&nbsp; &nbsp; run_pipeline([&nbsp; &nbsp; &nbsp; &nbsp; create_skill_step,&nbsp; &nbsp; &nbsp; &nbsp; add_pdf_capability,&nbsp; &nbsp; &nbsp; &nbsp; add_invoice_extraction,&nbsp; &nbsp; &nbsp; &nbsp; add_excel_export&nbsp; &nbsp; ])

Skill 系统的处理方式:

340341342343344345346347348349350351用户输入 →&nbsp;LLM&nbsp;语义分析
LLM&nbsp;推理过程:├──&nbsp;"创建一个 Skill"&nbsp;→ 触发 skill-creator├──&nbsp;"处理 PDF"&nbsp;→ 触发 pdf-processor├──&nbsp;"提取金额和日期"&nbsp;→ 这是&nbsp;OCR/信息抽取任务,pdf-processor 能处理├──&nbsp;"导出成 Excel"&nbsp;→ 触发 xlsx-processor└── 组合策略:先用 skill-creator 搭框架,在其中集成 pdf 和 xlsx 的能力
动态生成的执行图:skill-creator ──┬──► pdf-processor ──► xlsx-processor&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │

同样的请求,用户换一种说法:「我想让 Claude 学会处理发票,能识别里面的数字,整理成表格」

传统 Workflow 大概率匹配失败(没有「创建」「PDF」「Excel」这些关键词)。Skill 系统仍然能正确理解:

352353354355356LLM&nbsp;推理过程:├──&nbsp;"让 Claude 学会"&nbsp;≈&nbsp;"创建新能力"&nbsp;→ 触发 skill-creator├──&nbsp;"处理发票"&nbsp;→ 发票通常是&nbsp;PDF/图片 → 触发 pdf-processor├──&nbsp;"识别数字"&nbsp;≈&nbsp;"信息提取"&nbsp;→ pdf-processor 能处理├──&nbsp;"整理成表格"&nbsp;≈&nbsp;"导出 Excel"&nbsp;→ 触发 xlsx-processor

边的动态性让系统具备了对同一意图不同表达的鲁棒性。节点(能力)是固定的,但通往这些节点的路径可以有无数条。LLM 扮演的角色,就是在这个图上做实时的路径规划。

从案例中抽象方法论:Skill 的另一种理解视角

回到开头那个 CTO 和超强员工的比喻。

假设这个员工处理了 1000 个「创建 Skill」的任务。如果你去复盘这 1000 个案例,会发现它们有很多共同点:

都需要先理解用户的具体需求

都需要规划文件结构

都需要写 SKILL.md

都需要测试和迭代

这些共同点抽象出来,就是一套「方法论」或者叫「SOP」(标准操作流程)。

传统的做法是:由人类工程师分析案例、总结规律、编写代码。这个过程依赖人的经验和判断,耗时耗力,而且容易遗漏边界情况。

Skill 系统提供了另一条路:把案例和方法论都写进 Skill 文件,让 LLM 自己去理解和运用。

357358359360361skill-creator/├── SKILL.md &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;抽象出的方法论└── references/&nbsp; &nbsp; ├── example-docx-skill.md &nbsp;&nbsp;# 案例:创建文档处理 Skill&nbsp; &nbsp; ├── example-api-skill.md &nbsp; &nbsp;# 案例:创建 API 测试 Skill

Claude 在执行任务时,会参考这些案例来理解方法论的具体应用方式。遇到新的场景,它能够基于案例中的模式进行类比推理,而不是机械地执行固定步骤。

某种程度上,这有点像人类专家的学习过程:先看大量案例,然后归纳出规律,最后在新情况下灵活运用。Skill 系统把这个过程工程化了。

Skill 的目录结构:一份实操指南

说了这么多概念,来看看一个 Skill 到底长什么样。

362363364365366367368369370371my-skill/├── SKILL.md &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[必需] 核心文件├── scripts/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# [可选] 可执行脚本│ &nbsp; ├──&nbsp;init.py│ &nbsp; └── validate.sh├── references/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# [可选] 参考文档│ &nbsp; ├── api-docs.md│ &nbsp; └── patterns.md└── assets/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# [可选] 输出资源&nbsp; &nbsp; ├── template.docx

SKILL.md:唯一的必需文件

这个文件由两部分组成:YAML 格式的元数据,和 Markdown 格式的主体内容。

372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403---name: invoice-processordescription: |&nbsp; 当用户需要处理发票相关任务时触发。&nbsp; 包括:发票识别、信息提取、格式转换、批量处理、数据校验等。---

发票处理指南
## 核心能力
支持 PDF、图片、扫描件等多种格式的发票识别和信息提取。
## 处理流程
1.&nbsp;确认发票来源和格式2.&nbsp;选择合适的识别方案3.&nbsp;执行信息提取4.&nbsp;校验提取结果5.&nbsp;输出结构化数据
## 输出规范
提取的发票信息应包含以下字段:-&nbsp;发票号码-&nbsp;开票日期-&nbsp;购买方信息-&nbsp;销售方信息-&nbsp;商品明细-&nbsp;金额合计-&nbsp;税额

元数据中的description字段非常关键,它直接决定了 Skill 在什么情况下会被触发。好的描述应该涵盖各种可能的触发场景,用自然语言写清楚适用范围。

scripts/:放可执行脚本的地方

有些任务需要确定性的执行结果,比如文件格式转换、数据校验、模板生成。这类操作用脚本实现比让 LLM 临时生成代码更可靠。

404405406407408409410411412413
scripts/extract_invoice.pyimport&nbsp;pdfplumber
def&nbsp;extract_invoice_info(pdf_path):&nbsp; &nbsp;&nbsp;with&nbsp;pdfplumber.open(pdf_path)&nbsp;as&nbsp;pdf:&nbsp; &nbsp; &nbsp; &nbsp; text =&nbsp;""&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;page&nbsp;in&nbsp;pdf.pages:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text += page.extract_text()
&nbsp; &nbsp;&nbsp;# 解析逻辑...

Claude 在执行任务时可以直接调用这些脚本,而不需要每次都重新生成代码。这既节省了 token,也提高了执行的稳定性。

references/:放详细文档的地方

主体内容应该保持精简,通常不超过 2000 词。那些详细的 API 文档、复杂的业务规则、大量的示例代码,都应该放到references/目录下。

414415416417418419420421422423424425426427428429430431432433434435<!-- references/ocr-comparison.md -->

OCR 方案对比
## 腾讯云 OCR
优势:识别准确率高,支持增值税发票专用模板劣势:需要联网,有调用成本适用场景:对准确率要求高的正式场景
## PaddleOCR
优势:开源免费,可本地部署劣势:需要配置环境,通用模板识别率一般适用场景:成本敏感或离线环境
## Tesseract
优势:老牌方案,社区成熟劣势:中文支持较弱,需要训练模型适用场景:简单英文文档

Claude 在需要时会主动读取这些文件。比如用户问「用什么方案识别发票比较好」,Claude 会判断需要参考 OCR 方案对比的文档,然后加载它来回答问题。

assets/:放模板和资源文件的地方

有些 Skill 需要输出特定格式的文件,比如 Word 文档、PPT、图片。这些模板文件放在assets/目录下,Claude 可以基于模板生成最终产出。

436437438assets/├── invoice-template.xlsx &nbsp; &nbsp;发票数据导出模板├── report-template.docx &nbsp; &nbsp;&nbsp;# 分析报告模板

这个目录下的文件通常不需要加载到上下文中,Claude 只需要知道它们的路径,然后在生成输出时引用即可。

Skill 与自建 Agent 的权衡

读到这里,可能有人会问:我自己写一个 ReAct Agent 不行吗?为什么要用 Anthropic 的 Skill 系统?

这是个好问题,答案取决于你的具体需求。

选择 Skill 系统的场景

开发效率优先。Skill 本质上是 Markdown 文件,写一个新 Skill 可能只需要半小时。你不用关心意图识别、上下文管理、工具调用这些底层细节,框架都帮你处理好了。

需要与 Claude Code 深度集成。如果你的工作场景是在 Claude Code 里完成各种开发任务,Skill 系统能无缝融入现有的工作流。你可以用/skill-name直接调用,也可以让 Claude 自动判断何时使用。

知识复用和团队协作。Skill 可以打包分发,可以通过插件市场安装,可以在团队内共享。这套机制让知识的沉淀和传播变得很方便。

选择自建 Agent 的场景

需要完全的控制权。Skill 系统的意图识别、Skill 触发、资源加载都由框架控制。如果你的业务逻辑有特殊要求,比如需要自定义的推理策略、特殊的记忆机制、或者对接私有的工具系统,自建 Agent 能给你更大的灵活性。

性能和成本有严格约束。Skill 系统在每次会话时都会加载所有 Skill 的元数据,当 Skill 数量很多时,这部分开销不可忽视。如果你的场景对延迟和成本非常敏感,精心优化过的自建方案可能更合适。

需要脱离 Claude 生态。Skill 系统目前主要在 Claude Code 和 Claude.ai 中使用。如果你的产品需要部署在其他 LLM 上,或者需要完全自主可控的技术栈,自建是唯一的选择。

两种方案并不互斥。很多团队的做法是:用 Skill 系统快速搭建原型、验证想法,等业务模式跑通后,再根据需要把核心能力迁移到自建的 Agent 架构上。

写好 Skill 的几个实用建议

最后分享一些从实践中总结出来的经验。

描述字段要具体,要包含触发场景

差的写法:

好的写法:

439440441442description: |&nbsp; 当用户需要处理 PDF 文件时触发。&nbsp; 包括:PDF 文本提取、页面旋转、文件合并拆分、&nbsp; 表单填写、水印添加、格式转换(PDF 转 Word/图片)等。

描述写得越具体,Claude 越能准确判断何时触发这个 Skill。模糊的描述会导致该触发时不触发,或者不该触发时乱触发。

主体内容要精简,详细文档放 references

上下文窗口是稀缺资源。SKILL.md 的主体内容建议控制在 2000 词以内,超出的部分拆分到references/目录。这样既保证了核心信息的可用性,又不会在不需要时浪费空间。

使用祈使句式,避免第二人称

差的写法:

好的写法:

Skill 是给 Claude 看的指令,用祈使句更直接、更清晰,也更节省 token。

包含具体的示例和模板

抽象的规则容易产生歧义,具体的示例能消除误解。

443444445446447448449450451452453454455456457
输出格式
发票信息以 JSON 格式输出:
{&nbsp;&nbsp;"invoice_number":&nbsp;"12345678",&nbsp;&nbsp;"date":&nbsp;"2026-01-15",&nbsp;&nbsp;"buyer": {&nbsp; &nbsp;&nbsp;"name":&nbsp;"某某公司",&nbsp; &nbsp;&nbsp;"tax_id":&nbsp;"91110000..."&nbsp; },&nbsp;&nbsp;"items": [&nbsp; &nbsp; {"name":&nbsp;"商品A",&nbsp;"quantity": 2,&nbsp;"price": 100}&nbsp; ],&nbsp;&nbsp;"total": 200

有了这个示例,Claude 就知道具体该输出什么样的数据结构。

结语

Skill 系统的设计思路,代表了 AI 工程领域的一个重要方向:把 LLM 的语义理解能力用到系统架构中去。

传统软件架构依赖程序员预先定义好所有的逻辑路径。AI 原生的架构可以把一部分决策权交给模型,让它基于语义理解来动态选择执行路径。这种范式转换带来了更高的灵活性和更低的开发成本,当然也带来了新的挑战——比如如何保证行为的可预测性,如何调试难以复现的问题。

Anthropic 的 Skill 系统,可以看作这个方向上的一次工程实践。它在灵活性和可控性之间找到了一个平衡点:用自然语言定义触发条件(灵活),用结构化的文件组织知识(可控),用渐进式披露管理上下文(高效)。

对于 AI 应用的开发者来说,理解这套系统的设计思路,比会用它更重要。因为同样的思路可以迁移到你自己的 Agent 架构中,无论你用的是 Claude、GPT 还是其他模型。

上下文窗口的大小会继续增长,但「按需加载」的思想不会过时。毕竟,即使桌面变大了,保持整洁依然是一种美德。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:xsser的博客 xsser xsser《Claude-Code-Skill-深度解析》

评论:0   参与:  0