AI 技术专题MCP 与 Claude 生态Ch 2.从零到一开发Agent Skills系统本页总览 Ch 2.从零到一开发Agent Skills系统 [toc] 课件领取 核心项目:FuFan OpenClaw项目演示 1. Anthropic 官方 Agent Skills 范式介绍 要构建一个企业级的 Agent Skills 系统,首先必须理解 Anthropic 官方制定的标准范式。这套范式不仅仅是文件格式的约定,更是一套关于 “如何将人类专家的隐性知识(Tacit Knowledge)转化为机器可执行的显性资产(Explicit Assets)” 的工程标准。 Agent Skills官方介绍:https://agentskills.io/ 1.1 Agent Skills 核心定义:从“Prompt”到“资产包” 在传统的 Agent 开发中,我们习惯于将所有指令都塞进 System Prompt。但在 Agent Skills 范式下,我们引入了 “技能即文件” (Skill as a File) 的核心概念。 根据 agentskills.io 的定义,Agent Skill 是一个标准化的文件夹结构,它封装了扩展智能体能力所需的特定领域知识、指令和工具定义。 它不再是一段虚无缥缈的提示词,而是一个实实在在的资产包 (Asset Package)。一个标准的 Skill 必须包含以下核心要素,可以用一个公式来表示: $$Skill = Metadata + Instructions (SOP) + Examples + Tools$$ Metadata (元数据):用于被系统索引和路由的标签(如名称、描述)。 Instructions (指令):自然语言编写的算法或 SOP(标准作业程序)。 Examples (示例):用于 Few-Shot Learning 的输入输出对,锁定模型行为。 Tools (依赖):该技能运行所需的底层原子能力(如联网、数据库连接)。 这种结构化的定义,使得 Skill 具备了 可移植性 (Portability) 和 可复用性 (Reusability)。 1.2 架构核心:三层渐进式加载机制 (Progressive Disclosure) Agent Skills 系统设计的最大挑战在于 Context Window(上下文窗口)的限制。为了在有限的 Token 预算内实现无限的能力扩展,Anthropic 提出了一套 “渐进式披露” (Progressive Disclosure) 的加载机制。 这套机制将 Skill 的生命周期划分为三个层级: Level 1: 索引层 (Index Layer) - System Init 加载内容:仅加载 Skill 的 元数据 (Metadata),通常只有 name 和 description。 位置:常驻于 System Prompt。 作用:建立 “能力目录”。此时,Agent 知道自己“能做什么”(比如“能查天气”),但完全不知道“具体怎么做”。 Token 消耗:极低(每个 Skill 约消耗 20-50 Tokens)。 Level 2: 指令层 (Instruction Layer) - On Demand 加载内容:SKILL.md 的完整正文(包含 SOP 和 Examples)。 触发机制:当 Agent 的意图识别(Router)命中某个 Metadata 时,系统触发 Function Calling (read_file)。 位置:动态注入到 Current Context(当前对话上下文)。 作用:JIT (Just-in-Time) 知识注入。Agent 在这一刻才真正“学会”了该技能的业务逻辑。 Level 3: 执行层 (Runtime Layer) - Execution 加载内容:具体的原子工具调用(Function Arguments)和外部资源。 触发机制:Agent 阅读指令层后,根据 SOP 发起具体的 Tool Calls。 作用:物理执行。调用 API、运行 Python 脚本或查询数据库,获取最终结果。 1.3 标准协议详解:SKILL.md 解剖学 在 Agent Skills 范式中,SKILL.md 是承载业务逻辑的核心载体。它采用 Markdown + YAML Frontmatter 的混合格式。一个符合规范的 SKILL.md 必须包含以下结构: FENCE0 1.4 关键辨析:Skill vs Tool vs MCP 在系统架构中,必须清晰界定 Skill (技能)、Tool (工具) 和 MCP (模型上下文协议) 的边界: 概念定义形象比喻职责Skill业务逻辑封装 (SOP)菜谱告诉 Agent “先切菜,再热油,最后炒”。它不直接操作物理世界,而是编排工具的使用顺序。Tool原子能力接口 (API)菜刀/炒锅执行具体的物理动作(如 fetch_url, execute_sql)。它没有业务逻辑,只有功能。MCP连接标准协议厨房接口标准规定了“菜刀”如何连接到“手臂”上。它解决了连接问题,但不解决“怎么做菜”的问题。 结论:Agent Skills 是位于 MCP 和 Tool 之上的 应用层 (Application Layer)。它通过编排底层的原子工具(Tool),利用标准的连接协议(MCP),来实现复杂的业务目标。 1.5 Agent Skill 示例:get_weather 技能介绍 为了验证上述理论,我们来回顾之前演示的 get_weather 技能。这是一个完全符合 Anthropic 标准的最简 Skill 实现。 1. 文件结构验证 FENCE1 符合“技能即文件夹”的定义。 2. SKILL.md 内容验证 Metadata (索引层): name: get_weatherdescription: 获取指定城市的实时天气信息 解析:Agent 通过 description 里的语义信息,将用户 query "北京天气怎么样" 路由到此技能。 Usage (使用场景): “当用户询问某个城市的天气情况时使用此技能。” 解析:进一步强化了触发条件。 Steps (指令层 - SOP): 从用户消息中提取城市名称 使用 fetch_url 工具访问 wttr.in... 解析返回的 JSON 数据... 解析:这是典型的 Logic Orchestration (逻辑编排)。它没有写 Python 代码,而是用自然语言指导 Agent 调用 fetch_url 这个原子工具。 Examples (对齐层): 用户:「查询北京的天气」 -> ... -> 回复:「北京当前天气...」 解析:通过 Few-Shot 样本,锁定了 Agent 的输出格式,防止它直接把 JSON 扔给用户。 通过 get_weather 这个简单的例子,我们可以看到:Agent Skill 的本质,就是用结构化的自然语言,编写了一段能够被 LLM 及其 Runtime 环境(Agent)所理解和执行的“软代码”。 1.6 复杂 Agent Skill 示例:docx 技能介绍 在掌握了基础的 Skill 开发后,我们需要将视线投向更复杂的业务场景。Anthropic 官方仓库中的 skills/docx 是一个教科书般的案例,它展示了 Agent 如何像一个全栈工程师一样,操控 Word 文档的创建、读取、编辑和渲染。 项目地址:https://github.com/anthropics/skills/tree/main/skills/docx 整个项目较为复杂,涉及到多个脚本: 其中SKILL.md如下: 翻译后完整内容如下: FENCE2 阅读内容 FENCE3 转换为图片 FENCE4 接受跟踪更改 要生成一个干净的文档,其中所有跟踪更改已被接受(需要 LibreOffice): FENCE5 创建新文档 使用 JavaScript 生成 .docx 文件,然后验证。安装:npm install -g docx 设置 FENCE6 验证 创建文件后,进行验证。如果验证失败,解压、修复 XML 然后重新打包。 FENCE7 页面大小 FENCE8 常见页面尺寸(DXA 单位,1440 DXA = 1 英寸): 纸张宽度高度内容宽度(1 英寸边距)美国信纸12,24015,8409,360A4(默认)11,90616,8389,026 横向布局: docx-js 会内部交换宽度和高度,因此传入纵向尺寸并让它处理交换: FENCE9 样式(覆盖内置标题) 使用 Arial 作为默认字体(普遍支持)。保持标题为黑色以增强可读性。 FENCE10 列表(绝对不要使用 Unicode 项符号) FENCE11 表格 关键:表格需要设置双重宽度 - 同时设置 columnWidths 和每个单元格的 width。如果没有同时设置,它们在某些平台上的渲染可能会出错。 FENCE12 表格宽度计算: 始终使用 WidthType.DXA — WidthType.PERCENTAGE 在 Google Docs 中会导致问题。 FENCE13 宽度规则: 始终使用 WidthType.DXA — 永远不要使用 WidthType.PERCENTAGE(与 Google Docs 不兼容) 表格宽度必须等于列宽之和 单元格 width 必须与对应的 columnWidth 匹配 单元格 margins 是内边距 - 它们减少内容区域,而不是增加单元格宽度 对于全宽表格:使用内容宽度(页面宽度减去左右边距) 图片 FENCE14 分页符 FENCE15 目录 FENCE16 页眉/页脚 FENCE17 docx-js 的关键规则 显式设置页面大小 - docx-js 默认是 A4;对于美国文档,使用 US Letter(12240 x 15840 DXA) 横向布局:传递纵向尺寸 - docx-js 内部交换宽度/高度;传递短边为 width,长边为 height,并设置 orientation: PageOrientation.LANDSCAPE 永远不要使用 \n - 使用单独的 Paragraph 元素 永远不要使用 Unicode 项符号 - 使用 LevelFormat.BULLET 和编号配置 分页符必须在 Paragraph 内 - 单独使用会创建无效的 XML ImageRun 必须指定 type - 始终指定 png/jpg 等格式 始终设置表格 width 使用 DXA - 永远不要使用 WidthType.PERCENTAGE(在 Google Docs 中不兼容) 表格需要双重宽度 - columnWidths 和单元格 width,两者必须匹配 始终添加单元格边距 - 使用 margins: { top: 80, bottom: 80, left: 120, right: 120 } 使其可读 使用 ShadingType.CLEAR - 永远不要使用 SOLID 作为表格阴影 目录必须使用 HeadingLevel - 标题段落上不能使用自定义样式 覆盖内置样式 - 使用准确的 ID:"Heading1","Heading2" 等 包含 outlineLevel - 目录需要此参数(0 对于 H1,1 对于 H2 等) 每个段落使用单独的 Paragraph 元素 所有图像必须使用 type - 必须指定图像类型,例如 png、jpg、jpeg 等 编辑现有文档 按照以下三步操作。 第 1 步:解压 FENCE18 提取 XML,格式化,合并相邻的 runs,并将智能引号转换为 XML 实体(“ 等),以便它们在编辑时能保留。使用 --merge-runs false 可以跳过合并运行。 第 2 步:编辑 XML 编辑 unpacked/word/ 中的文件。更多模式请参见 XML 参考部分。 请使用“Claude”作为作者,用于跟踪更改和评论,除非用户明确要求使用其他名字。 直接使用编辑工具进行字符串替换。不要编写 Python 脚本。脚本会引入不必要的复杂性,编辑工具可以准确地显示正在替换的内容。 关键:使用智能引号添加新内容。 添加带有撇号或引号的文本时,使用 XML 实体来生成智能引号: FENCE19 第 3 步:打包 FENCE20 验证并自动修复,压缩 XML 并创建 DOCX 文件。使用 --validate false 跳过验证。 XML 参考 模式兼容性 <w:pPr> 中元素的顺序:<w:pStyle>、<w:numPr>、<w:spacing>、<w:ind>、<w:jc>,<w:rPr> 最后 空格:在包含前导/尾随空格的 <w:t> 中,添加 xml:space="preserve" RSID:必须是 8 位十六进制(例如,00AB1234) 跟踪更改 插入: FENCE21 删除: FENCE22 FENCE23 skills/docx/ ├── SKILL.md # 核心大脑:SOP 与 知识库 └── scripts/ # 肢体动作:原子工具脚本库 └── office/ ├── unpack.py # 工具:将 .docx 解压为 XML 目录 ├── pack.py # 工具:将 XML 目录重打包为 .docx └── soffice.py # 工具:调用 LibreOffice 转换 PDF FENCE24 name: docx description: Create, read, edit, and manipulate Word documents (.docx). Use when user mentions "Word doc", "report", or needs professional formatting. FENCE25 代码深度解析 沙箱机制 (root_dir):大家注意 ReadFileTool 的初始化。我们并没有让 Agent 满磁盘随便读,而是将它的视野通过 root_dir="./backend/skills" 锁死在技能目录中。这是 Agent 系统安全设计的第一道防线。 装饰器 (@tool):LangChain 的 @tool 装饰器不仅是将函数转为工具,它还会自动读取函数的 Docstring (注释)。read_file 下面那段中文注释:“用于读取 Agent Skills 的定义文件...” 最终会被转换成 Prompt 告诉大模型,所以这段注释必须写得非常精准。 上下文保护 ([:2000]):在 fetch_url 中,我们做了一个简单的截断处理。真实的网页往往包含大量无用信息,如果不做处理直接丢给 LLM,不仅浪费钱,还会挤占 Skill 指令的空间。 2.3 技能引导层 (Skill Bootstrap) 实现 Agent 怎么知道自己有哪些技能?我们需要在系统启动时,通过代码自动扫描目录。这被称为 “Bootstrap (引导过程)”。我们将编写一个 bootstrap.py,它的作用是生成一份 “技能菜单”: FENCE26 代码解析 为什么用 XML?:注意看 snapshot 变量,我们使用了 <available_skills> 这种 XML 标签。在最新的 Prompt Engineering 实践中(特别是 Claude 系列),模型对 XML 结构的理解能力远强于 JSON 或纯文本列表。这能显著提高 Agent 检索技能的准确率。 动态扫描:这个函数的存在,实现了 “热插拔”。你只需要在文件夹里新建一个 get_stock 目录,下次运行代码时,这个函数就会自动把它加入到 Agent 的菜单里,完全不需要修改核心代码。 路径映射:注意 <path> 标签。我们告诉了 Agent 技能的名称,同时告诉了它文件在哪里。这为后续 Agent 调用 read_file 埋下了伏笔。 2.4 Agent 运行时构建 (LangChain 1.x Standard) 这是最关键的一步。在 LangChain 1.x 中,官方引入了基于 Graph 理念的 create_agent API,它自动封装了“思考-工具调用-再思考”的复杂循环。 FENCE27 代码解析 System Prompt 的动态注入:这是整个系统的灵魂。变量 snapshot_content 是运行时生成的,这意味着 Agent 的知识库是活的。 核心协议 (CRITICAL):我们在 System Prompt 中用加粗语气写了一段“核心协议”。这是为了对抗大模型的幻觉。大模型有时候会“自作聪明”,觉得自己知道怎么查天气就直接编造 API。我们必须强制它:“先读文件,再行动”。 create_agent API:这个 API 是 LangChain 1.x 的集大成者。 它自动识别 Model 是否支持 Tool Calling。 它自动把 core_tools 里的函数签名转换为 OpenAI 格式的 JSON Schema。 它自动管理对话历史(Memory),当 Tool 返回结果后,它会自动把结果喂回给模型进行下一轮推理。 开发者不再需要手写 while 循环来处理“多步执行”了。 2.5 Fufan-OpenClaw需求文档