从 MCP 到 Skill:基于FileBased Skill与 Agent Framework 的实践探索
目录什么是 MCP它解决了哪些问题又存在哪些局限什么是 Agent SkillsSkill的设计理念Agent Skill 文件系统的架构三种 Skill 内容对应三层加载加载机制总结Agent Framework 里使用Skill 总结在学习 Skill 之前我们先简单聊一聊几个基础概念帮大家把整体背景理清楚这样后面看具体实现的时候会更容易理解。什么是 MCP它解决了哪些问题又存在哪些局限MCPModel Context Protocol在官方文档中的定义是MCP 是一套开源标准用来让 AI 应用能够连接外部系统。使用 MCPAI 应用例如 Claude 或 ChatGPT可以连接到数据源例如本地文件、数据库、工具例如搜索引擎、计算器以及工作流例如特定的 prompt 流程从而获取关键信息并执行任务。同时官方也给了一个很形象的类比可以把 MCP 理解为 AI 应用的 USB-C 接口。就像 USB-C 提供了一种标准化的设备连接方式一样MCP 也提供了一种统一的方式让 AI 应用可以连接到各种外部系统。从这个角度看MCP 解决的是一个非常关键的问题让模型从一个封闭系统变成一个可以和外部世界交互的开放系统。以前模型只能依赖已有知识进行推理而有了 MCP 之后它可以接入实时数据可以访问业务系统也可以触发实际操作。这一步其实是 Agent 能够落地的前提。但问题也恰恰出在这里。MCP 虽然把工具都接进来了却没有告诉模型应该怎么用这些工具。当工具数量不多的时候这个问题还不明显但一旦工具变多模型面对的就不再是能力不足而是信息过多。它需要在一堆工具里做选择却缺少明确的判断依据很容易选错或者用错。更关键的是MCP 本身并不提供任何做事的方法。它只负责把能力暴露出来但不会告诉模型在一个具体任务里应该先做什么、再做什么也不会提供一套稳定的执行流程。对于多步骤的复杂任务来说这一点影响尤其明显。模型往往只能根据当前的 prompt 临时推理一套方案结果就是有时候表现很好有时候又完全跑偏很难保持稳定。从工程的角度看这其实是在说一件很简单的事情MCP 让模型有机会去调用外部能力但并不保证一定能用好。它提供的是能力本身却没有提供使用这些能力的经验。而在真实场景里后者往往才是决定结果好坏的关键。也正是在这个背景下Skill 才变得有意义。它并不是在替代 MCP而是在 MCP 之上加了一层让模型在面对具体任务时不只是有工具可用而是知道该怎么用这些工具把事情做好。什么是 Agent SkillsAgent Skills 可以理解为一组模块化的能力扩展用来让 AI Agent 在特定场景下具备更完整的做事能力。和普通工具不太一样Skill 不只是一个可以调用的功能它更像是一个打包好的能力单元里面通常会包含使用说明instructions—— 告诉模型什么时候用、怎么用基本信息metadata—— 比如名称、描述可选资源—— 比如 script、templates、参考资料在运行过程中Agent 会根据当前任务自动判断是否使用某个 Skill而不需要手动调用。Skill的设计理念Agent Skills 本质上是一种把“经验”封装起来的方式。 如果说 MCP 给智能体提供的是“手”让它能够去操作各种工具那么 Skills 更像是一份“操作手册”或者 SOP标准作业流程告诉它在具体场景下应该怎么用这些工具。 这个设计背后其实有一个很简单但挺关键的思路 “能连上工具”和“会用工具”应该是两件事 MCP 主要解决的是前者 —— 让智能体能够接触到外部的数据和能力。 而 Skills 解决的是后者 —— 在具体场景里应该怎么组合这些能力把事情做对。 换句话说两者的职责其实是分开的 MCP 做的是“连接”把数据库、API、文件系统这些能力暴露给智能体 Skills 做的是“方法”告诉智能体在某种任务下应该怎么用这些能力可以用一个比较直观的类比来理解 MCP 更像是驱动程序或者 USB 接口解决“设备能不能连上” Skills 更像是一套可复用的操作经验和流程指导解决“连上之后该怎么用” 比如你有一个功能完整的打印机驱动MCP说明电脑已经可以识别并使用打印机了。 但如果没有人告诉你怎么在 Word 里设置页边距、选择双面打印Skills你其实还是很难高效地完成打印任务。Agent Skill 文件系统的架构Agent Skills 最核心的架构是渐进式披露Progressive Disclosure机制。这种基于文件系统的架构支持渐进式披露模型根据需要分阶段加载信息而不是在一开始就消耗上下文。三种 Skill 内容对应三层加载Skills 可以包含三种类型的内容并在不同时间加载第 1 层元数据始终加载内容类型Content typeInstructions。Skill 的 YAML 前置信息frontmatter提供用于发现的相关信息--- name: unit-converter description: 用于执行单位转换通过 value 和 factor 计算结果 ---Agent 在启动时会加载这些元数据并将其纳入系统提示。这种轻量级方式意味着可以安装大量 Skills 而不会显著增加上下文开销Agent 只需要知道每个 Skill 的存在以及在什么情况下应该使用它。第 2 层指令在触发时加载内容类型Content typeInstructions。SKILL.md 的主体包含过程性知识例如工作流程、最佳实践以及使用指导## 使用方法 当用户请求单位转换时 1. 首先查看 references/conversion-table.md找到对应的换算系数 2. 运行 scripts/convert.py 脚本并传入参数 --value 数值 --factor 系数 例如--value 26.2 --factor 1.60934 3. 将转换结果清晰地展示出来并同时标明原单位和目标单位 当你的请求与某个 Skill 的描述匹配时模型会在需要时从文件系统加载 SKILL.md 的内容具体实现方式依赖运行环境。只有在此时这部分内容才会进入上下文窗口。第 3 层资源和代码按需加载内容类型Content typeInstructions、Code 和 Resources。Skills 可以打包额外的材料skills/ └── unit-converter/ ├── SKILL.md ├── references/ │ └── conversion-table.md └── scripts/ └── convert.pyInstructions指令额外的 Markdown 文件如 FORMS.md、REFERENCE.md用于提供更专业的指导和流程Code代码可执行脚本如 fill_form.py、validate.pyClaude 通过 bash 运行这些脚本脚本可以在不消耗上下文的情况下执行确定性操作Resources资源参考资料references例如数据库 schema、API 文档、模板或示例加载机制总结层级加载时机Token 开销内容Level 1Metadata始终加载启动时每个 Skill 约 100 tokensYAML 中的 name 和 descriptionLevel 2InstructionsSkill 被触发时小于 5k tokensSKILL.md 主体指令与指导Level 3Resources按需加载基本不受限制通过 bash 执行或读取的文件说到底MCP 解决的是“能不能做”但没有解决“该怎么做”。Skill 正是在这个缺口上出现的。它不去替代 MCP而是补上一层“经验和方法”。通过分层加载的设计Skills 让模型在不增加太多上下文负担的情况下获得必要的指导从而在面对具体任务时不只是有工具可用而是真正知道该怎么把事情做好。Agent Framework 里使用SkillAgent Framework 给我们提供了几种使用Agent的方式。今天我们主要介绍基于文件系统使用Skill的方式。首先我们需要引用如下包dotnet add package Azure.AI.OpenAI --version 2.9.0-beta.1 dotnet add package Azure.Identity --version 1.21.0 dotnet add package Microsoft.Agents.AI.OpenAI --version 1.1.0首先我们定义我们的skill目录结构 Skills 目录结构skills/ └── unit-converter/ ├── SKILL.md ├── references/ │ └── conversion-table.md └── scripts/ └── convert.py然后在代码里创建 Agent 的时候指定一个 AgentSkillsProvider创建时第一个参数是 Skill 存放的目录第二个参数是一个委托用来告诉 Agent Framework怎么运行 Skill 里的scripts脚本AgentFileSkillScriptRunner myRunner async (skill, script, args, ct) { try { Console.WriteLine($运行脚本: {script.Name}); // 你在这个方法里面 // ✔ 调 Python // ✔ 调 HTTP API // ✔ 调数据库 // ✔ 调你自己的 C# 方法 var psi new ProcessStartInfo(python) { RedirectStandardOutput true, RedirectStandardError true, UseShellExecute false, }; psi.ArgumentList.Add(Path.Combine(skill.Path, script.FullPath)); if (args ! null) { foreach (var (key, value) in args) { if (valueis not null !string.IsNullOrWhiteSpace(value.ToString())) { psi.ArgumentList.Add(key); psi.ArgumentList.Add(value.ToString()!); } } } usingvar process Process.Start(psi)!; string output await process.StandardOutput.ReadToEndAsync(); var error await process.StandardError.ReadToEndAsync(); Console.WriteLine(STDOUT: output); //Console.WriteLine(STDERR: error); await process.WaitForExitAsync(); return output.Trim(); } catch (Exception ex) { throw; } }; var skillsProvider new AgentSkillsProvider(Path.Combine(AppContext.BaseDirectory, skills), myRunner);接下来创建 Agent 的时候把这个 skillsProvider 传进去AIAgent agent new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) .GetResponsesClient() .AsAIAgent(new ChatClientAgentOptions { Name UnitConverterAgent, ChatOptions new() { Instructions 你是一个可以调用工具进行单位转换的助手。, }, AIContextProviders [skillsProvider], }, model: deploymentName); #pragma warning restore OPENAI001 Console.WriteLine(正在使用基于文件的技能进行单位转换); Console.WriteLine(newstring(-, 60)); var stringBuilder new StringBuilder(); awaitforeach (var response in agent.RunStreamingAsync(请严格用脚本计算。马拉松26.2 英里等于多少公里另外75 千克等于多少磅)) { stringBuilder.Append(response.Text); } Console.WriteLine(stringBuilder.ToString()); Console.ReadLine();运行后Agent 会根据 prompt 里的需求自动判断需要用到 unit-converter 这个 Skill然后根据 SKILL.md 里的指导调用我们在 AgentFileSkillScriptRunner 里定义的方式去运行 convert.py 这个脚本最终把结果返回给用户。运行效果源代码地址https://github.com/bingbing-gui/dotnet-platform/tree/master/src/09-AI-Agent/Agent-Framework/28-FileBased-Agent-Skills 总结MCPModel Context Protocol本质上解决的是“连接能力”的问题它通过标准化接口让 AI 应用能够接入外部数据、工具和系统使模型从一个封闭的推理引擎升级为可以与现实世界交互的开放系统。这是 Agent 能够真正落地的基础。但 MCP 的能力主要停留在“把工具接进来”并不包含“如何使用工具”。当工具数量增加时模型需要在众多选项中做出决策却缺乏稳定的判断依据和执行策略容易出现选择错误或执行不稳定的问题。因此从工程角度来看MCP 提供的是“能力”而不是“方法”。而 Skill 的价值正是在此基础上进行补充它通过结构化的方式为模型提供明确的执行路径和使用规范使模型不仅拥有工具还具备正确使用工具的能力。简而言之MCP 解决的是连接问题能不能用Skill 解决的是使用问题怎么用好两者结合才能真正支撑一个稳定、可控且可落地的 Agent 系统。下一篇引入地址