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 是一种轻量级、开放的格式,用于扩展 AI Agent 的能力和专业知识。本质上,一个 Skill 就是一个包含 SKILL.md 文件的文件夹。
该文件包含:
name 和 description(最少必需)Skills 的核心价值在于:
name 和 description,任务匹配时才加载完整指令根据官方文档,Agent Skills 的主要应用场景包括:
将专业知识打包为可复用的指令:
赋予 Agent 原本不具备的操作能力:
将多步骤任务转化为一致且可审计的流程:
一次编写,多处使用:
这种标准化使得组织知识可以在不同工具间无缝流转。
目前已有多个主流 AI 开发工具支持该标准:

一个最简单的 Skill 只需要包含 SKILL.md 文件:
skill-name/
└── SKILL.md # 必需可选的支持目录:
skill-name/
├── SKILL.md # 必需:技能描述和使用说明
├── scripts/ # 可选:可执行脚本
│ └── tool.py
├── references/ # 可选:详细参考文档
│ └── REFERENCE.md
└── assets/ # 可选:静态资源
└── template.jsonSKILL.md 文件包含两部分:YAML frontmatter 和 Markdown 正文。
---
name: skill-name
description: 描述技能功能和使用场景的文字,应包含帮助 Agent 识别相关任务的关键词
---name 字段规则:
a-z, -)--)description 字段规则:
---
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"
---Agent Skills 采用渐进式加载策略来优化 token 使用:
name 和 descriptionSKILL.mdscripts/、references/、assets/ 中的文件最佳实践:
SKILL.md 在 500 行以内references/ 目录在进入具体实现之前,我们先来看看为什么 .NET File-Based Apps 是编写 Agent Skills 中 scripts/ 目录下可执行脚本的优秀选择。
根据 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 可读性 | ✅ 结构清晰、自文档化 | ✅ 简洁 | ✅ 简洁 |
1. 真正的自包含 依赖声明直接写在代码文件头部,Agent 一眼就能看懂需要什么包、什么版本,无需查找外部配置文件。
#:package PdfSharpCore@1.3.65
#:package Spectre.Console@0.49.12. 从开发到生产无缝过渡
开发时直接运行 .cs 文件,生产时一键发布为 Native AOT 可执行文件,启动速度可达毫秒级,内存占用极小。
3. AI 友好的代码结构 .NET 的强类型和清晰的语法结构,让 AI Agent 更容易理解代码意图、发现潜在问题、提出改进建议。
.NET 10 引入的 File-Based Apps 特性允许将单个 .cs 文件作为完整的应用程序运行,无需传统的项目文件(.csproj)。关键特性包括:
.cs 文件包含完整程序dotnet file.cs 即可执行csproj、sln 等项目文件Agent Skills 规范强调「简洁」、「自包含」、「可理解」,.NET File-Based Apps 的设计理念与之完美契合:
// 入门: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从原型到生产,同一个文件,逐步迭代,没有项目结构的重构成本。
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).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 在生成或修改代码时,有更多的安全护栏。
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 执行的自动化任务,这种性能差异会累积成显著的时间节省。
让我们以一个实际的 PDF 拆分工具为例,演示如何开发符合规范的 Agent Skill。
mkdir -p split-pdf/scripts
cd split-pdfSKILL.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 识别场景在 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;
}关键要素解析:
#!/usr/bin/env dotnet - 使脚本可在 Unix 系统直接执行#:package 指令声明 NuGet 包及版本#:property PublishAot=true - 支持 Native AOT 编译Main 方法,直接编写逻辑return 返回退出码# 准备测试 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在支持 Agent Skills 的环境中测试(如 GitHub Copilot):
.github/skills/ 目录下用户提问:请帮我把这个 PDF 文件拆分成单独的页面
Agent 行为:
1. 识别任务涉及 PDF 拆分
2. 查找并激活 split-pdf skill
3. 读取 SKILL.md 了解使用方法
4. 执行:dotnet scripts/split-pdf.cs document.pdf ./pages/
5. 向用户报告结果// ❌ 不好:参数含义不明
dotnet tool.cs input output 1
// ✅ 好:参数含义清晰
dotnet split-pdf.cs document.pdf ./pages/ 1-10if (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);
}
});// ✅ 指定明确版本
#:package PdfSharpCore@1.3.65
#:package Spectre.Console@0.49.1
// ❌ 避免使用不稳定版本
#:package SomePackage@*
#:package BetaPackage@2.0.0-beta只引入必需的包,减少潜在的兼容性问题。
在 description 中包含:
# ✅ 好的 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 正文中提供:
// ✅ 使用 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;可以在一个 Skill 中包含多个相关脚本:
pdf-toolkit/
├── SKILL.md
└── scripts/
├── split.cs
├── merge.cs
└── extract-text.cs在 SKILL.md 中说明每个工具的用途和使用场景。
对于复杂的 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")。对于性能敏感的工具,启用 Native AOT:
#:property PublishAot=true
#:property InvariantGlobalization=true // 减小体积发布时使用:
dotnet publish scripts/tool.cs -r win-x64 --property:PublishAot=trueNative AOT 优势:
将 Skills 放入版本控制:
.github/
└── skills/
├── split-pdf/
├── data-analysis/
└── code-review/在团队 README 中说明:
Agent Skills 为开发者带来三大核心价值:
能力复用:一次编写,在 Copilot、Cursor、Claude 等多个 Agent 产品中使用,还可跨团队共享或通过 GitHub 公开发布。
知识沉淀:将团队最佳实践固化为版本化的 Skills,如代码审查规范、部署流程、数据分析模板等,确保工作流程的一致性。
提升效率:通过明确的指导让 Agent 更准确地执行复杂任务,减少试错和修正,提供一致的输出质量。
File-Based Apps 为 .NET 带来了新的应用场景:
降低门槛:从复杂的项目结构到单文件脚本,让 Python、Node.js 开发者也能轻松尝试 .NET。
AI 协作优势:强类型系统帮助 AI 更准确理解代码、即时编译反馈加速修正、丰富的 API 文档提升 AI 可读性。
性能差异化:Native AOT 编译在批量任务中的性能优势(启动快 90%+),不仅提升用户体验,也降低云端成本。
生态拓展:.NET 开发者可以将企业实践打包为 Skills,在 AI Agent 生态中展现 .NET 价值,同时 .NET 的实践经验也能反哺 Agent Skills 标准演进。
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 时代发挥更大价值。