大家好,我是Edison。
最近我一直在跟着圣杰的《.NET+AI智能体开发进阶》课程学习MAF开发多智能体工作流,我强烈推荐你也上车跟我一起出发!
上一篇,我们初步学习了Agent Skill如何集成脚本执行能力,虽然它不是官方方案,但至少提供了可行的思路。本篇,我们来了解下.NET 10新推出的File-Based App模式,它和MAF一起可以形成一个强大的"王牌组合"!
1 File-Based App模式介绍
曾经做过Python开发的朋友应该都知道,Python的单文件运行项目让很多非IT专业的开发者都能快速地上手一个实际项目出来,也因此在企业中流行。特别是Edison所在的制造业企业中,广大的非IT部门的同事都喜爱Python开发,不管是机器学习还是Web API项目,虽然都不够工程化,不好维护的屎山占多数。在那时,我就在想,.NET什么时候也可以搞个单文件模式,等着等着,它就来了。
随着.NET 10 的发布,微软通过推出"基于文件的应用程序"(File-Based Apps,通常通过 dotnet file 命令调用)这一功能,标志着 C# 正在经历一场根本性的范式转移。这一特性并非仅仅是 CLI 工具链的微小更新,而是 C# 试图在智能体(Agentic AI)时代夺取生态话语权的战略王牌。我知道,这是要抢Python的快速Agent原型开发的阵地了!与 Python 不同,Python 脚本在规模扩大后往往面临性能重构或维护性崩塌;而 C# 脚本本身就是完整的 C# 代码。
传统C#开发的"工程负担"
传统 C# 偏"工程导向",依赖 .csproj/.sln 等完整脚手架,适合大规模软件但在脚本化、快速迭代和 AI 动态生成代码时显得繁琐;Python 之所以在 AI/脚本领域强势,关键在于"零配置、即写即用"。
单文件C#开发的"一把梭"
.NET 10 的 File-Based Apps 通过"单个 .cs 文件 + 内嵌指令声明依赖/环境 + 直接运行"来降低摩擦,让 C# 具备类似脚本语言的灵活性,同时保留性能、并发与类型安全优势,更适合智能体场景。
因为智能体生成代码通常强调"自包含、立刻可执行、易于单文件分发",File-Based Apps 正好匹配这些需求。
FileBased App + MAF的"王牌组合"
微软在 .NET 10 推进 File-Based Apps,本质是在为更上层的智能体战略------Microsoft Agent Framework(MAF)铺路。MAF 将 Semantic Kernel 与 AutoGen 的核心能力统一起来,提供一套"构建、编排、观测"智能体系统的标准化框架,让多智能体协作从"拼工具"走向"有体系"。
MAF 支持多种协作模式:顺序(Sequential)、并发(Concurrent)、移交(Handoff)、群聊(GroupChat)、主从(Magnetic)。这些模式的共同痛点是:智能体往往需要临时生成一段代码来处理数据、做计算或验证结果。
File-Based Apps 用"单文件 + 内嵌依赖指令 + 即编即跑"把执行门槛降到最低:每个智能体都能快速产出可运行的 C# 任务片段,减少传统项目结构带来的脚手架成本和交互延迟。同时借助完善的"智能体黄金三角",打通开发、观察和交互,例如DevUI + AG-UI + OpenTelemetry 的三角组合。
企业内部培训的"低代码模式"
此外,File-Based App模式也特别利于像Edison所在的制造业企业做Workshop工作坊培训,借助单文件启动Agent,业务人员不需要理解太多的代码内容,只需要了解如何启动和测试Agent项目,如何为Agent添加Skill文档即可。在这种模式下,培训的效果会好于之前需要工程化的.NET项目,大大降低学习门槛。
2 快速开始:HR Support Agent
假设你的企业有这样一个需求:HR部门需要自己动手开发一个Agent,为内部用户提供政策咨询等服务。
这时候,IT部同事给了HR部门一个C#文件,并告诉了HR修改系统提示词,如何添加skill文档,接下来HR就自己添加了两个Skill:
Skill1: 差旅政策
首先,我们创建这个SKILL.md,内容如下:
---
name: travel-policy
description: 公司差旅预订与审批政策。适用于航班预订、酒店预订、差旅审批流程或差旅安全指引等相关问题。
---
# 差旅政策(Travel Policy)
## 预订规则
| 项目 | 政策 | 审批 |
|------|--------|----------|
| 国内航班 | 仅限经济舱 | <$800自动审批 |
| 国际航班 | 经济舱;6小时以上可选高端经济舱 | 均需经理审批 |
| 酒店 | 优先公司协议酒店 | ≤$250/晚自动审批 |
| 租车 | 紧凑/标准车型 | ≤3天自动审批 |
| 火车/高铁 | 标准座 | 自动审批 |
## 预订流程
1. 所有预订须通过公司差旅平台(TravelHub)完成
2. 国内提前14天,国际提前21天预订
3. 总费用超$2,000需经理预先审批
4. 预订后24小时内取消可全额退款
## 安全指引
- 所有国际行程需向差旅安全团队报备
- 超过5天的行程需购买差旅保险
- 随身携带公司应急联系方式卡
Skill2: 报销政策
Skill.md内容:
---
name: expense-report
description: 按照 Contoso 公司政策填写和审核员工费用报销。适用于费用报销、报销规则、收据要求、支出限额或费用类别等相关问题。
---
# 费用报销(Expense Report)
## 费用类别与限额
| 类别 | 限额 | 收据要求 | 审批 |
|---|---|---|---|
| 单人用餐 | $50/天 | >$25 | 无需 |
| 团队/客户用餐 | $75/人 | 必须 | 总额>$200需经理 |
| 住宿 | $250/晚 | 必须 | 超过3晚需经理 |
| 地面交通 | $100/天 | >$15 | 无需 |
| 机票 | 经济舱 | 必须 | >$1,500需VP |
| 会议/培训 | $2,000/次 | 必须 | 经理+L&D |
| 办公用品 | $100 | 是 | 无需 |
| 软件/订阅 | $50/月 | 是 | >$200/年需经理 |
## 报销流程
1. 收集收据——需包含商家、日期、金额、支付方式。
2. 按上表分类。
3. 使用模板:[assets/expense-report-template.md](assets/expense-report-template.md)。
4. 团队/客户用餐需列出参与人及业务目的。
5. 提交——<$500自动审批;$500–$2,000需经理;>$2,000需VP。
6. 报销:10个工作日内通过银行转账。
## 政策规则
- 需在交易后30天内提交。
- 酒精类费用不予报销。
- 外币:按交易日汇率折算为美元,并注明原币种及金额。
- 混合个人/商务出行:仅报销商务部分,需提供对比报价。
- 丢失收据(>$25):需提交财务部的丢失收据声明,每季度最多2次。
- 如有未涵盖的问题,请查阅FAQ:[references/POLICY_FAQ.md](references/POLICY_FAQ.md)。答案应以本文件和FAQ为准。
reference:常见问题解答
# 费用政策常见问答(FAQ)
## 用餐
**问:工作日咖啡或零食可以报销吗?**
答:每日咖啡/零食低于$10不予报销(视为个人消费)。客户会议或团队协作期间购买的咖啡可作为团队用餐报销。
**问:团队晚餐超出人均限额怎么办?**
答:$75/人限额为指导标准。超出20%以内可书面说明(如“客户指定场地”),超出20%需VP预先批准。
**问:需要列出所有参与人吗?**
答:是。客户用餐需列明客户姓名及公司,团队用餐需列出所有员工姓名。10人以上可单独附名单。
## 差旅
**问:可以预订高端经济舱或商务舱吗?**
答:经济舱为标准。6小时以上可选高端经济舱,商务舱需VP预批,通常仅限10小时以上或医疗原因。
**问:打车(Uber/Lyft)和租车如何选择?**
答:往返30英里以内建议打车,多日或超$100/天建议租车。3人以上可选更大车型。
**问:小费可以报销吗?**
答:用餐、打车、酒店清洁小费20%以内可报销,超出需说明理由。
## 住宿
**问:部分城市$250/晚不够怎么办?**
答:纽约、旧金山、伦敦、东京、悉尼等高消费城市自动提升至$350/晚,无需额外审批。其他特殊情况请提前向经理申请。
**问:住亲友家能否领取补贴?**
答:不可以。公司仅报销实际住宿费用,不提供补贴。
## 订阅与软件
**问:个人效率工具可以报销吗?**
答:需与工作直接相关,如IDE、设计软件、项目管理工具可报销。一般效率类应用需经理书面确认。
## 收据与材料
**问:收据模糊/损坏怎么办?**
答:可向商家补打,如无法获取,需提交丢失收据声明(财务部网站下载),每季度限2次。
**问:停车/过路费需要收据吗?**
答:低于$15无需收据,注明日期、地点、金额即可;$15及以上需收据或银行流水。
## 审批与报销
**问:经理休假谁来审批?**
答:可由上级经理或系统指定的代理审批人审批。
**问:能否报销上季度的费用?**
答:标准为30天内,超期需书面说明并VP批准,超90天仅特殊情况经CFO批准。
asset:费用报销模板
# 费用报销模板(Expense Report Template)
| 日期 | 费用类别 | 商家 | 描述 | 金额(USD) | 原币种 | 原币金额 | 参与人 | 业务目的 | 已附收据 |
|------|----------|------|------|-------------|--------|----------|--------|----------|----------|
| | | | | | | | | | 是 / 否 |
主文件C#代码
这里,我们通过通过一个单文件就完成了Agent的定义 以及 Web Host托管:
#!/usr/bin/dotnet run
#:sdk Microsoft.NET.Sdk.Web
#:property PublishAot=false
#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc4
#:package Microsoft.Agents.AI.DevUI@1.0.0-preview.260225.1
#:package Microsoft.Agents.AI.Hosting@1.0.0-preview.260225.1
#:package Microsoft.Agents.AI.Hosting.OpenAI@1.0.0-alpha.260225.1
#:package Microsoft.Extensions.AI.OpenAI@10.3.0
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.DevUI;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;
using OpenAI;
using System.ClientModel;
var builder = WebApplication.CreateBuilder(args);
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Step0 准备工作 --- 创建注册 ChatClient
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
var config = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
var chatClient = new OpenAIClient(
new ApiKeyCredential(config["OpenAI:ApiKey"]!),
new OpenAIClientOptions { Endpoint = new Uri(config["OpenAI:EndPoint"]!) })
.GetChatClient(config["OpenAI:ModelId"]!)
.AsIChatClient();
builder.Services.AddChatClient(chatClient);
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Step1 创建 SkillsProvider --- 从文件系统发现和加载 Skills
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
#pragma warning disable MAAI001
var skillsProvider = new FileAgentSkillsProvider(
skillPath: Path.Combine(Directory.GetCurrentDirectory(), "skills")
);
#pragma warning restore MAAI001
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Step2 创建 Agent --- 注入 SkillsProvider
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
builder.Services.AddAIAgent("HRSupport", delegate (IServiceProvider sp, string key)
{
var client = sp.GetRequiredService<IChatClient>();
return new ChatClientAgent(client, new ChatClientAgentOptions
{
Name = "HRSupport",
ChatOptions = new()
{
Instructions = "你是一个专业的企业内部助手,使用和用户同样的语言回答用户提出的有关企业内部政策流程相关的问题。请优先使用对应系统的Skill进行处理,严格参考SKill对应的要求进行回答,不要进行多余的补充。",
},
AIContextProviders = [skillsProvider],
});
});
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Step3 注册 DevUI 相关服务
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
builder.Services.AddOpenAIResponses();
builder.Services.AddOpenAIConversations();
var app = builder.Build();
app.MapOpenAIResponses();
app.MapOpenAIConversations();
app.MapDevUI();
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Step4 开始运行 Agent
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Console.WriteLine("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
Console.WriteLine("🚀 HR Support Agent 已启动");
Console.WriteLine("📍 端点地址: https://localhost:8443/");
Console.WriteLine($"🤖 模型: {config["OpenAI:ModelId"]!}");
Console.WriteLine("💡 使用 Ctrl+C 停止服务");
Console.WriteLine("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
await app.RunAsync("https://localhost:8443");
在这个主文件中,我们完成了:
-
- Agent的定义 以及 Skill的加载
-
- DevUI组件的注册
-
- Web Host的启动运行
这里HR只需要知道在哪里修改系统提示词即可,如上述代码中的Instructions内容。
然后,通过一句简单的 dotnet run 命令就可以启动起来,效果如下图:

怎么样?是不是很nice。
3 小结
本文介绍了File-Based App模式的基本概念 和 优势,然后通过一个单文件的HR Support Agent案例解析如何快速开发一个MVP类型的Agent项目,相信会对你有所帮助。
示例源码
GitHub: https://github.com/EdisonTalk/MAFD
参考资料
圣杰,《.NET + AI 智能体开发进阶》(推荐指数:★★★★★)
Microsoft Learn,《Agent Framework Tutorials》

作者:爱迪生
出处:https://edisontalk.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。