从 MCP 到 Agent Skills,AI Ready 的 .NET 10 正当时
使用 .NET File-Based Apps 编写高效 Agent Skills 脚本指南
前言
AI 工具生态正在经历一场深刻的变革。从 Anthropic 推出的 Model Context Protocol (MCP) 到最新发布的 Agent Skills,我们见证了 AI 能力扩展方式的演进:MCP 为 AI 提供了访问外部数据和工具的标准化接口,而 Agent Skills 则更进一步,专注于将人类的专业知识和工作流程封装为 AI 可理解、可执行的格式。
Agent Skills (https://agentskills.io) 中可以包含可执行脚本(位于 scripts/ 目录),官方规范支持 Python、Bash、JavaScript 等语言。而 .NET 10 引入的 File-Based Apps 特性为这些脚本的编写提供了一个强大的新选择:单个 .cs 文件即可作为完整应用运行,内联依赖声明,支持跨平台部署和 Native AOT 编译。
本文将带你了解 Agent Skills 的规范,以及如何使用 .NET File-Based Apps 编写高效、可靠的 Skill 脚本。你会发现,.NET 为 Agent Skills 的脚本开发提供了类型安全、高性能和优秀跨平台支持的独特优势。
一、什么是 Agent Skills?

1.1 核心概念
Agent Skills 是一种轻量级、开放的格式,用于扩展 AI Agent 的能力和专业知识。本质上,一个 Skill 就是一个包含 SKILL.md 文件的文件夹。
该文件包含:
- 元数据:
name和description(最少必需) - 指令:告诉 Agent 如何执行特定任务的 Markdown 文档
- 可选资源:脚本、模板、参考文档等
Skills 的核心价值在于:
- 专业知识封装:将特定领域的程序化知识(procedural knowledge)和公司/团队/用户特定的上下文打包
- 按需加载:Agent 启动时只加载 Skill 的
name和description,任务匹配时才加载完整指令 - 可执行能力:可以包含脚本、工具,扩展 Agent 的实际操作能力
- 版本化管理:Skills 就是文件,易于编辑、版本控制和分享
1.2 Agent Skills 能做什么?
根据官方文档,Agent Skills 的主要应用场景包括:
领域专长(Domain Expertise)
将专业知识打包为可复用的指令:
- 法律审查流程:标准化的合同审查检查清单和审批流程
- 数据分析管道:统一的数据清洗、转换、可视化工作流
- 代码审查规范:团队的编码标准、安全检查、性能优化指南
- 医疗诊断协议:基于症状的诊断路径和治疗建议流程
新能力(New Capabilities)
赋予 Agent 原本不具备的操作能力:
- 创建演示文稿:根据内容自动生成 PPT/Keynote
- 构建 MCP 服务器:生成 Model Context Protocol 服务器代码
- 分析数据集:执行统计分析、生成可视化图表
- 处理 PDF 文档:拆分、合并、提取文本、填写表单
可重复工作流(Repeatable Workflows)
将多步骤任务转化为一致且可审计的流程:
- CI/CD 流水线:标准化的构建、测试、部署步骤
- 客户入职流程:账户创建、权限配置、培训材料发送
- 月度报告生成:数据收集、分析、报告编写、分发
- 代码重构任务:识别问题、建议改进、执行修改、验证测试
跨工具互操作(Interoperability)
一次编写,多处使用:
- 在 GitHub Copilot 中辅助编码
- 在 Cursor 中进行项目重构
- 在 Claude 中进行文档写作
- 在 Goose 中执行自动化任务
这种标准化使得组织知识可以在不同工具间无缝流转。
1.3 谁在支持 Agent Skills?
目前已有多个主流 AI 开发工具支持该标准:

二、Agent Skills 规范解读
2.1 基本目录结构
一个最简单的 Skill 只需要包含 SKILL.md 文件:
skill-name/
└── SKILL.md # 必需
可选的支持目录:
skill-name/
├── SKILL.md # 必需:技能描述和使用说明
├── scripts/ # 可选:可执行脚本
│ └── tool.py
├── references/ # 可选:详细参考文档
│ └── REFERENCE.md
└── assets/ # 可选:静态资源
└── template.json
2.2 SKILL.md 格式规范
SKILL.md 文件包含两部分:YAML frontmatter 和 Markdown 正文。
Frontmatter 必需字段
---
name: skill-name
description: 描述技能功能和使用场景的文字,应包含帮助 Agent 识别相关任务的关键词
---
name 字段规则:
- 长度:1-64 字符
- 字符:仅允许小写字母、数字和连字符 (
a-z,-) - 不能以连字符开头或结尾
- 不能包含连续的连字符 (
--) - 必须与父目录名完全一致
description 字段规则:
- 长度:1-1024 字符
- 应说明技能的功能和使用时机
- 包含关键词帮助 Agent 识别适用场景
可选字段
---
name: pdf-processing
description: Extract text from PDFs and merge multiple documents
license: MIT
compatibility: Requires Python 3.8+ and poppler-utils
metadata:
author: your-org
version: "1.0.0"
---
2.3 渐进式信息披露
Agent Skills 采用渐进式加载策略来优化 token 使用:
- 元数据阶段 (~100 tokens):启动时加载所有 Skills 的
name和description - 指令阶段 (<5000 tokens 推荐):激活 Skill 时加载完整的
SKILL.md - 资源阶段 (按需):仅在需要时加载
scripts/、references/、assets/中的文件
最佳实践:
- 保持
SKILL.md在 500 行以内 - 将详细参考资料移至
references/目录 - 避免深层嵌套的文件引用
三、使用 .NET File-Based Apps 编写 Agent Skills 脚本
在进入具体实现之前,我们先来看看为什么 .NET File-Based Apps 是编写 Agent Skills 中 scripts/ 目录下可执行脚本的优秀选择。
3.0 .NET 作为脚本语言的独特优势
根据 Agent Skills 规范,scripts/ 目录中的可执行代码应该自包含或明确记录依赖、包含有用的错误消息、优雅处理边界情况。常见的脚本语言包括 Python、Bash、JavaScript,而 .NET File-Based Apps 为此提供了一个强大的替代方案:
对比其他脚本语言方案
在为 Agent Skills 编写 scripts/ 目录下的可执行脚本时,.NET File-Based Apps 与其他常用语言的对比:
| 特性 | .NET File-Based Apps | Python 脚本 | Node.js 脚本 |
|---|---|---|---|
| 单文件运行 | ✅ dotnet file.cs |
✅ python file.py |
✅ node file.js |
| 依赖声明 | ✅ 文件内声明 | ⚠️ 需 requirements.txt |
⚠️ 需 package.json |
| 类型安全 | ✅ 编译时检查 | ❌ 运行时错误 | ⚠️ 需 TypeScript |
| 性能 | ✅ Native AOT 编译 | ⚠️ 解释执行 | ⚠️ JIT 编译 |
| 跨平台部署 | ✅ 单个可执行文件 | ⚠️ 需 Python 运行时 | ⚠️ 需 Node.js 运行时 |
| 企业级库支持 | ✅ 丰富的 NuGet 生态 | ✅ PyPI 生态 | ✅ npm 生态 |
| AI Agent 可读性 | ✅ 结构清晰、自文档化 | ✅ 简洁 | ✅ 简洁 |
.NET 的三大杀手锏
1. 真正的自包含
依赖声明直接写在代码文件头部,Agent 一眼就能看懂需要什么包、什么版本,无需查找外部配置文件。
#:package PdfSharpCore@1.3.65
#:package Spectre.Console@0.49.1
2. 从开发到生产无缝过渡
开发时直接运行 .cs 文件,生产时一键发布为 Native AOT 可执行文件,启动速度可达毫秒级,内存占用极小。
3. AI 友好的代码结构
.NET 的强类型和清晰的语法结构,让 AI Agent 更容易理解代码意图、发现潜在问题、提出改进建议。
3.1 什么是 .NET File-Based Apps?
.NET 10 引入的 File-Based Apps 特性允许将单个 .cs 文件作为完整的应用程序运行,无需传统的项目文件(.csproj)。关键特性包括:
- 单文件即应用:一个
.cs文件包含完整程序 - 内联依赖声明:通过特殊注释声明 NuGet 包
- 直接运行:
dotnet file.cs即可执行 - 支持发布:可以发布为独立可执行文件或 Native AOT
- 零配置:无需
csproj、sln等项目文件
3.2 File-Based Apps 如何适配 Agent Skills 需求?
Agent Skills 规范强调「简洁」、「自包含」、「可理解」,.NET File-Based Apps 的设计理念与之完美契合:
适配点 1:渐进式复杂度
// 入门:10 行代码的简单工具
#!/usr/bin/env dotnet
if (args.Length == 0) { Console.WriteLine("Hello, Agent!"); return; }
Console.WriteLine($"Processing: {args[0]}");
// 进阶:添加依赖和错误处理
#:package Newtonsoft.Json@13.0.3
using Newtonsoft.Json;
try { /* 处理逻辑 */ }
catch (Exception ex) { Console.Error.WriteLine(ex.Message); return 1; }
// 生产:发布为高性能可执行文件
#:property PublishAot=true
// 一行命令:dotnet publish -r win-x64
从原型到生产,同一个文件,逐步迭代,没有项目结构的重构成本。
适配点 2:AI Agent 的理解成本
Python 方案:Agent 需要找到并理解多个文件
my-skill/
├── tool.py # Agent 需要读取
├── requirements.txt # Agent 需要读取
└── README.md # Agent 需要读取
.NET 方案:一个文件包含所有信息
my-skill/
└── scripts/
└── tool.cs # 依赖、逻辑、配置全在这里
Agent 只需读取一个文件,就能了解:
- 需要什么依赖(
#:package) - 如何运行(
#!/usr/bin/env dotnet) - 做什么事(代码逻辑)
- 如何部署(
#:property)
适配点 3:企业级可靠性
.NET 的类型系统在 Agent 驱动的开发中尤为重要:
// 编译时就能发现错误,而不是运行时崩溃
string pdfPath = args[0]; // Agent 知道这是字符串
int pageCount = GetPageCount(pdfPath); // Agent 知道返回值是整数
// Python 中相同的错误可能运行时才暴露
# pdf_path = args[0] # 类型不明确
# page_count = get_page_count(pdf_path) # 返回值类型不明确
这意味着 Agent 在生成或修改代码时,有更多的安全护栏。
适配点 4:性能与资源效率
AI Agent 可能频繁调用 Skills,启动性能至关重要:
# Python 脚本启动
$ time python tool.py input.pdf
real 0m0.234s # 需要加载解释器
# .NET File-Based App 启动
$ time dotnet tool.cs input.pdf
real 0m0.089s # JIT 编译
# Native AOT 编译后
$ time ./tool input.pdf
real 0m0.012s # 接近原生 C++ 性能
对于 Agent 执行的自动化任务,这种性能差异会累积成显著的时间节省。
3.3 实战案例:split-pdf Skill
让我们以一个实际的 PDF 拆分工具为例,演示如何开发符合规范的 Agent Skill。
步骤 1:创建目录结构
mkdir -p split-pdf/scripts
cd split-pdf
步骤 2:编写 SKILL.md
SKILL.md 是 Agent Skill 的核心,包含元数据和使用说明。创建 SKILL.md 文件:
---
name: split-pdf
description: Split PDF files into separate single-page documents or extract specific page ranges. Use when you need to divide a PDF into multiple files, extract particular pages, or process PDF pages individually. Works with multi-page PDF documents.
license: MIT
---
# Split PDF
将 PDF 文件拆分为多个单页文件或提取指定页面范围。
## 使用场景
- 将多页 PDF 拆分为独立的单页文件
- 提取 PDF 的特定页面范围
- 需要单独处理 PDF 各个页面时
## 使用方法
使用 `scripts/split-pdf.cs` 脚本进行 PDF 拆分:
### 拆分页面
# 拆分所有页面
dotnet scripts/split-pdf.cs input.pdf output-dir/
# 拆分第 1-5 页
dotnet scripts/split-pdf.cs input.pdf output-dir/ 1-5
## 输出格式
拆分后的文件命名格式:`{原文件名}_page_{页码}.pdf`
## 依赖项
- PdfSharpCore 1.3.65 - PDF 操作核心库
- Spectre.Console 0.49.1 - 美化的控制台输出
**注意**:
- `name` 必须与目录名 `split-pdf` 完全一致
- `description` 包含关键词 "split", "PDF", "pages" 帮助 Agent 识别场景
步骤 3:编写 File-Based App 脚本
在 scripts/ 目录下创建 .NET File-Based App 脚本 split-pdf.cs`:
#!/usr/bin/env dotnet
#:package PdfSharpCore@1.3.65
#:package Spectre.Console@0.49.1
#:property PublishAot=true
using PdfSharpCore.Pdf;
using PdfSharpCore.Pdf.IO;
using Spectre.Console;
using System;
using System.IO;
// ==================== 参数校验 ====================
if (args.Length < 2)
{
AnsiConsole.MarkupLine("[red]错误: 参数不足[/]");
AnsiConsole.MarkupLine("[yellow]用法: dotnet split-pdf.cs <PDF文件> <输出目录> [页面范围][/]");
return 1;
}
var pdfPath = args[0];
var outputDir = args[1];
var pageRange = args.Length >= 3 ? args[2] : null;
// 验证文件
if (!File.Exists(pdfPath))
{
AnsiConsole.MarkupLine($"[red]错误: 文件不存在: {pdfPath}[/]");
return 1;
}
// 创建输出目录
Directory.CreateDirectory(outputDir);
// ==================== 拆分 PDF ====================
try
{
using var inputDocument = PdfReader.Open(pdfPath, PdfDocumentOpenMode.Import);
var totalPages = inputDocument.PageCount;
// 解析页面范围
int startPage = 1, endPage = totalPages;
if (!string.IsNullOrEmpty(pageRange))
{
var parts = pageRange.Split('-');
if (parts.Length == 2 &&
int.TryParse(parts[0], out startPage) &&
int.TryParse(parts[1], out endPage))
{
startPage = Math.Max(1, Math.Min(startPage, totalPages));
endPage = Math.Max(startPage, Math.Min(endPage, totalPages));
}
}
var baseName = Path.GetFileNameWithoutExtension(pdfPath);
await AnsiConsole.Progress()
.StartAsync(async ctx =>
{
var task = ctx.AddTask("拆分 PDF 页面", maxValue: endPage - startPage + 1);
for (int i = startPage; i <= endPage; i++)
{
using var outputDocument = new PdfDocument();
outputDocument.AddPage(inputDocument.Pages[i - 1]);
var outputPath = Path.Combine(outputDir, $"{baseName}_page_{i:D3}.pdf");
outputDocument.Save(outputPath);
task.Increment(1);
await Task.CompletedTask;
}
});
AnsiConsole.MarkupLine($"[green]✅ 拆分完成!已生成 {endPage - startPage + 1} 个文件[/]");
return 0;
}
catch (Exception ex)
{
AnsiConsole.MarkupLine($"[red]❌ 错误: {ex.Message}[/]");
return 1;
}
关键要素解析:
- Shebang 行:
#!/usr/bin/env dotnet- 使脚本可在 Unix 系统直接执行 - 依赖声明:
#:package指令声明 NuGet 包及版本 - 发布配置:
#:property PublishAot=true- 支持 Native AOT 编译 - 顶层语句:无需
Main方法,直接编写逻辑 - 返回值:使用
return返回退出码
四、测试与验证
4.1 本地测试
直接运行测试
# 准备测试 PDF 文件
cd split-pdf
# 测试拆分所有页面
dotnet scripts/split-pdf.cs test.pdf ./output/
# 测试拆分指定范围
dotnet scripts/split-pdf.cs test.pdf ./output/ 1-3
# 验证输出
ls ./output/
# 应该看到:test_page_001.pdf, test_page_002.pdf, test_page_003.pdf
错误处理测试
# 测试文件不存在
dotnet scripts/split-pdf.cs nonexistent.pdf ./output/
# 测试参数不足
dotnet scripts/split-pdf.cs
# 测试无效页面范围
dotnet scripts/split-pdf.cs test.pdf ./output/ 100-200
4.2 Agent 集成测试
在支持 Agent Skills 的环境中测试(如 GitHub Copilot):
- 将 Skill 放置在
.github/skills/目录下 - 重启或刷新 Agent
- 测试 Agent 是否能发现和使用该 Skill
用户提问:请帮我把这个 PDF 文件拆分成单独的页面
Agent 行为:
1. 识别任务涉及 PDF 拆分
2. 查找并激活 split-pdf skill
3. 读取 SKILL.md 了解使用方法
4. 执行:dotnet scripts/split-pdf.cs document.pdf ./pages/
5. 向用户报告结果
五、最佳实践
5.1 脚本设计原则
清晰的参数设计
// ❌ 不好:参数含义不明
dotnet tool.cs input output 1
// ✅ 好:参数含义清晰
dotnet split-pdf.cs document.pdf ./pages/ 1-10
友好的错误提示
if (args.Length < 2)
{
AnsiConsole.MarkupLine("[red]错误: 参数不足[/]");
AnsiConsole.MarkupLine("[yellow]用法: dotnet split-pdf.cs <PDF文件> <输出目录> [页面范围][/]");
AnsiConsole.MarkupLine("[gray]示例: dotnet split-pdf.cs input.pdf ./output/ 1-5[/]");
return 1;
}
进度反馈
使用 Spectre.Console 提供直观的进度显示:
await AnsiConsole.Progress()
.StartAsync(async ctx =>
{
var task = ctx.AddTask("处理中", maxValue: totalItems);
foreach (var item in items)
{
// 处理逻辑
task.Increment(1);
}
});
5.2 依赖管理
选择稳定的包版本
// ✅ 指定明确版本
#:package PdfSharpCore@1.3.65
#:package Spectre.Console@0.49.1
// ❌ 避免使用不稳定版本
#:package SomePackage@*
#:package BetaPackage@2.0.0-beta
最小化依赖
只引入必需的包,减少潜在的兼容性问题。
5.3 文档编写
Description 关键词策略
在 description 中包含:
- 动作关键词:split, extract, convert, merge
- 领域关键词:PDF, document, pages
- 场景关键词:when you need to divide, when working with
# ✅ 好的 description
description: Split PDF files into separate single-page documents or extract specific page ranges. Use when you need to divide a PDF into multiple files, extract particular pages, or process PDF pages individually.
# ❌ 不够好
description: PDF tool for splitting.
提供清晰的示例
在 SKILL.md 正文中提供:
- 常见用例的示例
- 不同参数组合的效果
- 预期的输出格式
5.4 跨平台兼容性
路径处理
// ✅ 使用 Path.Combine
var outputPath = Path.Combine(outputDir, $"{baseName}_page_{i:D3}.pdf");
// ❌ 避免硬编码路径分隔符
var outputPath = outputDir + "\\" + baseName + "_page_" + i + ".pdf";
编码处理
// 确保控制台正确显示 Unicode
Console.OutputEncoding = System.Text.Encoding.UTF8;
六、进阶话题
6.1 支持多个相关工具
可以在一个 Skill 中包含多个相关脚本:
pdf-toolkit/
├── SKILL.md
└── scripts/
├── split.cs
├── merge.cs
└── extract-text.cs
在 SKILL.md 中说明每个工具的用途和使用场景。
6.2 使用 References 目录
对于复杂的 Skill,将详细文档分离:
data-analysis/
├── SKILL.md # 简要说明和快速开始
├── scripts/
│ └── analyze.cs
└── references/
├── REFERENCE.md # 详细 API 参考
├── examples.md # 更多示例
└── algorithms.md # 算法说明
在 SKILL.md 中引用:
详细的 API 参考请见 [REFERENCE.md](references/REFERENCE.md "REFERENCE.md")。
6.3 Native AOT 优化
对于性能敏感的工具,启用 Native AOT:
#:property PublishAot=true
#:property InvariantGlobalization=true // 减小体积
发布时使用:
dotnet publish scripts/tool.cs -r win-x64 --property:PublishAot=true
Native AOT 优势:
- 极快的启动时间
- 较小的内存占用
- 无需安装 .NET 运行时
- 单个可执行文件
6.4 团队协作
将 Skills 放入版本控制:
.github/
└── skills/
├── split-pdf/
├── data-analysis/
└── code-review/
在团队 README 中说明:
- 如何安装 Skills
- 如何贡献新 Skills
- 编码规范和测试要求
七、意义与展望
7.1 对开发者的价值
Agent Skills 为开发者带来三大核心价值:
能力复用:一次编写,在 Copilot、Cursor、Claude 等多个 Agent 产品中使用,还可跨团队共享或通过 GitHub 公开发布。
知识沉淀:将团队最佳实践固化为版本化的 Skills,如代码审查规范、部署流程、数据分析模板等,确保工作流程的一致性。
提升效率:通过明确的指导让 Agent 更准确地执行复杂任务,减少试错和修正,提供一致的输出质量。
7.2 .NET File-Based Apps 的机遇
File-Based Apps 为 .NET 带来了新的应用场景:
降低门槛:从复杂的项目结构到单文件脚本,让 Python、Node.js 开发者也能轻松尝试 .NET。
AI 协作优势:强类型系统帮助 AI 更准确理解代码、即时编译反馈加速修正、丰富的 API 文档提升 AI 可读性。
性能差异化:Native AOT 编译在批量任务中的性能优势(启动快 90%+),不仅提升用户体验,也降低云端成本。
生态拓展:.NET 开发者可以将企业实践打包为 Skills,在 AI Agent 生态中展现 .NET 价值,同时 .NET 的实践经验也能反哺 Agent Skills 标准演进。
7.3 未来展望
Agent Skills 生态正在快速发展,可以期待:
- Skills 市场:类似 npm 的包管理器和分发平台
- 工具链集成:IDE 内置 Agent Skills 模板和验证工具
- 应用拓展:从个人工具到企业知识库、教育培训、行业解决方案
.NET File-Based Apps 在这个生态中的定位清晰:作为 Agent Skills 脚本的强类型、高性能选择,为开发者提供从原型到生产的无缝体验。
八、总结
通过本文的探索,我们看到 .NET File-Based Apps 作为 Agent Skills 脚本语言的独特价值:单文件自包含、强类型安全、Native AOT 高性能,完美匹配 Agent Skills 规范对脚本的要求。
核心收获
本文从 Agent Skills 规范入手,通过 split-pdf 实战案例,展示了如何用 .NET File-Based Apps 编写高质量的 Skill 脚本,并探讨了其在 AI 时代的应用机遇。
开始行动
对于 .NET 开发者:用熟悉的 C# 为 Agent Skills 编写脚本,将专业知识封装为可复用的 Skills,在 AI 时代发挥 .NET 的价值。
对于其他技术栈开发者:.NET File-Based Apps 和 Python 一样简洁,但提供了类型安全和 Native AOT 性能。值得尝试:winget install Microsoft.DotNet.SDK.10 然后创建你的第一个 .cs 脚本。
下一步:动手实现你的第一个 Agent Skill,将专业知识转化为可复用的能力,在 AI 时代发挥更大价值。
参考资源
👆面向.NET开发者的AI Agent 开发课程【.NET+AI | 智能体开发进阶】已上线,欢迎扫码加入学习。👆
关注我的公众号『向 AI 而行』,我们微信不见不散。
阅罢此文,如果您觉得本文不错并有所收获,请【打赏】或【推荐】,也可【评论】留下您的问题或建议与我交流。 你的支持是我不断创作和分享的不竭动力!

浙公网安备 33010602011771号