目录
01 MAF 是什么:Semantic Kernel 和 Autogen 的继任者
02 Agent Skills 是什么:SKILL.md 加渐进式披露
03 四种技能源:博客说三种,文档有四种
File-based:SKILL.md 目录
Code-defined:AgentInlineSkill
Class-based:AgentClassSkill
MCP-based:skill:// URI
04 Provider 架构:Provider、Sources、Builder
Provider:AgentSkillsProvider
Sources:叶子源 + 装饰器
Builder:AgentSkillsProviderBuilder
05 生产治理:审批、沙箱、缓存、过滤
三个工具默认全部需要审批
脚本执行是重点风险
缓存和过滤解决规模问题
06 Skills vs Workflows:AI 决定怎么做,还是你定义做什么
对 .NET 开发者意味着什么
第一,技能资产可跨工具复用
第二,分发通道就绪
第三,生产治理不是事后补丁
2026 年 7 月 7 日,Microsoft Agent Framework 团队的 Principal Software Engineer Sergey Menshykh 在官方博客宣布:Agent Skills for .NET 正式发布,从实验性预览转为稳定版本,可以在生产环境使用。
这条消息表面看是“某 SDK 的某个特性 GA 了”。但它的分量不止于 .NET 生态内部。
Agent Skills 不是 .NET 专属的概念。它是一套开放规范,规范由 Anthropic 发起,仓库 agentskills/agentskills 在 GitHub 上已有两万多名开发者标星。已经采用这套规范的工具一长串:Claude Code、GitHub Copilot(VS Code / CLI / cloud agent)、Cursor、Gemini CLI、JetBrains 的 Junie、OpenCode、OpenHands、Mux、Autohand Code CLI。同一份 C1 技能文件,能在这些工具之间复用。
而 .NET,直到这次 GA,才正式被接进这个生态。
01 MAF 是什么:Semantic Kernel 和 Autogen 的继任者
先说载体。Agent Skills 是 Microsoft Agent Framework(下称 MAF)的一个能力。MAF 的定位和 .NET 开发者直接相关:它的官方文档源码仓库是 MicrosoftDocs/semantic-kernel-pr,文档站挂着“从 Semantic Kernel 迁移”和“从 Autogen 迁移”两份指南。换句话说,MAF 是 Semantic Kernel 和 Autogen 的统一继任者,不是又一个平行的新框架。在 SK 上有积累的团队,这是它的演进方向,不是另起炉灶。
MAF 同时提供 .NET 和 Python 两个 SDK。本文聚焦 .NET 侧,核心包是 Microsoft.Agents.AI,MCP 技能源另需 Microsoft.Agents.AI.Mcp。
02 Agent Skills 是什么:SKILL.md 加渐进式披露
一个技能就是一个目录,里面至少有一个 SKILL.md,可选地附带 scripts、references、assets 子目录:
expense-report/ ├── SKILL.md # 必需:frontmatter + 指令 ├── scripts/ # 可选:可执行脚本 ├── references/ # 可选:参考文档 └── assets/ # 可选:模板等静态资源SKILL.md 头部是 YAML frontmatter:
--- name: expense-report description: File and validate employee expense reports according to company policy. Use when asked about expense submissions, reimbursement rules, or spending limits. license: Apache-2.0 compatibility: Requires python3 metadata: author: contoso-finance version: "2.1" ---name 和 description 必填。name 限 64 字符以内、小写字母数字加连字符、必须和父目录名一致。description 最多 1024 字符,要写清“做什么”和“何时用”,因为它是代理判断要不要加载这个技能的依据。frontmatter 之后是 markdown 正文,写具体指令,建议不超过 500 行,长参考材料拆到 references/ 里。
格式本身不复杂。关键在它怎么被代理使用:渐进式披露(progressive disclosure),分四个阶段:
- Advertise · 约 100 tokens/skill
只有 name 和 description 注入系统提示,代理知道有哪些技能可用。
- Load · 建议 < 5000 tokens
任务匹配某个技能时,代理调用 load_skill 工具,拉取完整 SKILL.md 正文。
- Read resources · 按需
代理调用 read_skill_resource,读取 references、assets 里的补充文件。
- Run scripts · 按需
代理调用 run_skill_script,执行技能自带脚本。
这个设计的核心是 token 经济学。把领域知识塞进代理,传统做法要么写进系统提示(撑爆上下文窗口),要么做成 RAG(检索质量不可控)。Agent Skills 的做法是按需加载:平时只付 100 tokens 的“广告费”,真正要用时才付完整指令的代价,而且由模型自己判断什么时候需要。
一个细节:load_skill 永远会被广播;read_skill_resource 只在至少一个技能有 resources 时才广播;run_skill_script 同理。工具列表是动态的,不会平白多出用不到的工具占位置。
03 四种技能源:博客说三种,文档有四种
技能从哪来?.NET 实现支持四种技能源。这里有个差异:官方博客只提了三种(文件型、类、代码定义),但 Learn 文档实际描述了四种,多出来的是 MCP-based,目前还是实验性。
File-based:SKILL.md 目录
从文件系统的 SKILL.md 目录发现。适合放在共享仓库、由非开发人员维护的技能。脚本执行要传一个 SubprocessScriptRunner.RunAsync。
Code-defined:AgentInlineSkill
用 AgentInlineSkill 在代码里直接定义。适合技能内容需要动态生成(比如从数据库读)或要捕获调用点上下文的场景。资源用 .AddResource(),脚本用 .AddScript(),脚本在进程内执行,不需要 runner。
var unitConverterSkill = new AgentInlineSkill( name: "unit-converter", description: "Convert between common units using a conversion factor", instructions: """ Use this skill when the user asks to convert between units. 1. Review the conversion-table resource to find the correct factor. 2. Use the convert script, passing the value and factor from the table. """) .AddResource("conversion-table", """ # Conversion Tables Formula: **result = value × factor** | From | To | Factor | |------------|------------|----------| | miles | kilometers | 1.60934 | | kilometers | miles | 0.621371 | """) .AddScript("convert", (double value, double factor) => { double result = Math.Round(value * factor, 4); return JsonSerializer.Serialize(new { value, factor, result }); });Class-based:AgentClassSkill
继承 AgentClassSkill<T>,用 [AgentSkillResource] 和 [AgentSkillScript] 特性标注属性和方法。关键好处是可以打包成 NuGet 分发——团队独立编写技能,消费者 dotnet add package 加一行 .UseSkill() 就用上。
internal sealed class UnitConverterSkill : AgentClassSkill<UnitConverterSkill> { public override AgentSkillFrontmatter Frontmatter { get; } = new( "unit-converter", "Convert between common units using a multiplication factor. " + "Use when asked to convert miles, kilometers, pounds, or kilograms."); protected override string Instructions => """ Use this skill when the user asks to convert between units. 1. Review the conversion-table resource to find the correct factor. 2. Use the convert script, passing the value and factor from the table. """; [AgentSkillResource("conversion-table")] [Description("Lookup table of multiplication factors for common unit conversions.")] public string ConversionTable => """ # Conversion Tables Formula: **result = value × factor** | From | To | Factor | |------------|------------|----------| | miles | kilometers | 1.60934 | | kilometers | miles | 0.621371 | """; [AgentSkillScript("convert")] [Description("Multiplies a value by a conversion factor and returns the result as JSON.")] private static string ConvertUnits(double value, double factor) { double result = Math.Round(value * factor, 4); return JsonSerializer.Serialize(new { value, factor, result }); } }MCP-based:skill:// URI
从 MCP(Model Context Protocol)服务器发现技能,用 skill:// URI scheme,需要 Microsoft.Agents.AI.Mcp 包,目前实验性。支持两种索引类型:skill-md 按需从 MCP 服务器拉取 SKILL.md 和资源;archive 把整个技能打包成 ZIP/TAR 下载到本地解压。出于安全考虑,archive 型技能里的脚本永远不会被执行。
四种源各管一段:文件型给非开发人员,类给 NuGet 分发,代码定义给运行时动态场景,MCP 给跨进程、跨服务的技能分发。
04 Provider 架构:Provider、Sources、Builder
把技能接进代理,靠三个构建块。
Provider:AgentSkillsProvider
上下文提供程序,负责把技能广播进系统提示,并注册 load_skill、read_skill_resource、run_skill_script三个工具。
Sources:叶子源 + 装饰器
叶子源直接产出技能(AgentFileSkillsSource 从磁盘读,AgentInMemorySkillsSource 包代码定义和类的技能),装饰器包装别的源做变换(AggregatingAgentSkillsSource 聚合、DeduplicatingAgentSkillsSource 去重、CachingAgentSkillsSource 缓存、FilteringAgentSkillsSource 过滤)。装饰器能链式套用组成管道。每个源的 GetSkillsAsync 都拿到 AgentSkillsSourceContext,里面有当前请求的 Agent 和 Session,过滤逻辑可以据此按代理或租户做决策。
Builder:AgentSkillsProviderBuilder
链式组合多个源,自动加聚合、去重、缓存:
var skillsProvider = new AgentSkillsProviderBuilder() .UseFileSkill(Path.Combine(AppContext.BaseDirectory, "skills")) .UseSkill(volumeConverterSkill) // AgentInlineSkill .UseSkill(temperatureConverter) // AgentClassSkill .UseMcpSkills(mcpClient) // MCP-based .UseFileScriptRunner(SubprocessScriptRunner.RunAsync) .Build();最小用法更简单,一个文件路径就够:
var skillsProvider = new AgentSkillsProvider( Path.Combine(AppContext.BaseDirectory, "skills"), SubprocessScriptRunner.RunAsync); AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential()) .GetResponsesClient() .AsAIAgent(new ChatClientAgentOptions { Name = "MyAgent", ChatOptions = new() { Instructions = "You are a helpful assistant." }, AIContextProviders = [skillsProvider], }, model: deploymentName);05 生产治理:审批、沙箱、缓存、过滤
GA 的重点是“生产可用”。生产可用不是 API 稳定就够,关键在治理。
三个工具默认全部需要审批
load_skill、read_skill_resource、run_skill_script 在默认配置下,代理调用时都会暂停,返回 ToolApprovalRequestContent,等人确认后才执行。默认即安全。可以用 UseToolApproval 中间件配自动审批规则,对受信任的操作放宽:
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential()) .GetResponsesClient() .AsAIAgent(new ChatClientAgentOptions { Name = "SkillsAgent", ChatOptions = new() { Instructions = "You are a helpful assistant." }, AIContextProviders = [skillsProvider], }, model: deploymentName) .AsBuilder() .UseToolApproval(new ToolApprovalAgentOptions { // 自动批准只读的 load_skill / read_skill_resource, // run_skill_script 仍需人工确认 AutoApprovalRules = [AgentSkillsProvider.ReadOnlyToolsAutoApprovalRule], }) .Build();框架内置两条规则:ReadOnlyToolsAutoApprovalRule 自动放行 load 和 read,但脚本执行仍要人确认;AllToolsAutoApprovalRule 全放行。也可以用 AgentSkillsProviderOptions 单独禁用某个工具的审批。
脚本执行是重点风险
文件型脚本通过 SubprocessScriptRunner.RunAsync 以子进程方式执行,但官方文档明确写了:这个 runner仅供演示。生产环境要自己加沙箱(容器)、资源限制(CPU、内存、超时)、输入校验和白名单、结构化日志和审计。代码定义和类技能的脚本在进程内执行,不需要 runner,但同样要审。MCP archive 型技能的脚本直接不执行,这是刻意的安全措施——远程可执行内容必须显式信任。
缓存和过滤解决规模问题
Builder 默认包一层 CachingAgentSkillsSource,技能列表解析一次后复用。RefreshInterval 控制过期刷新,CacheIsolationKeySelector按上下文(比如租户 ID)隔离缓存,一个 provider 能给不同租户提供不同技能集。过滤用 FilteringAgentSkillsSource 或 Builder 的 UseFilter,谓词拿到技能和上下文,按代理或租户决定暴露哪些。开发期可以 DisableCaching() 让技能改动即时生效。
06 Skills vs Workflows:AI 决定怎么做,还是你定义做什么
MAF 里还有一个容易和 Skills 混的概念:Workflows。两者都扩展代理能力,底层逻辑不同。
- Skill:AI 决定怎么执行
单 agent turn 内跑。适合幂等、低风险操作,单领域任务。失败整体重试。
- Workflow:你定义执行路径
支持 checkpoint,失败可从上一步恢复。有副作用(发邮件、扣款)的步骤该走这里。
想让 AI 自己想清楚“怎么做”用 Skill,要保证“做什么步骤、什么顺序”用 Workflow。两者不互斥,可以组合。
对 .NET 开发者意味着什么
把这几块拼起来,这次 GA 对 .NET 开发者意味着三件事。
第一,技能资产可跨工具复用
为 .NET agent 写的 SKILL.md,同一份文件能被 Claude Code、GitHub Copilot、Cursor 识别。领域知识写一次,多端通用,这比绑死在某个框架的插件格式上值钱。
第二,分发通道就绪
Class-based 技能走 NuGet,团队独立发布,消费者一行 dotnet add package 加 .UseSkill() 就用上。这和 .NET 生态既有的协作方式一致,不需要另起一套。
第三,生产治理不是事后补丁
三个工具默认审批、缓存隔离、过滤管道、脚本沙箱警示,这些是企业落地要过的坎,框架在 GA 阶段就给到了。剩下的沙箱实现是用户自己的工程责任,框架不替你兜底,但也不挡路。
在 SK 或 Autogen 上有积累的团队,MAF 是明确的演进方向。在做企业内部 agent 的团队,Agent Skills 的“领域知识打包加按需加载加跨工具复用”值得放进技术选型。从官方文档和示例仓库起步即可。
参考资源
官方博客:https://devblogs.microsoft.com/agent-framework/agent-skills-for-net-is-now-released/
Learn 文档:https://learn.microsoft.com/en-us/agent-framework/agents/skills
Agent Skills 规范:https://agentskills.io
.NET 示例:https://github.com/microsoft/agent-framework/tree/main/dotnet/samples/02-agents/AgentSkills
引入地址