微软推出统一 AI agent 开发框架,整合 Semantic Kernel 企业功能与 AutoGen 多 agent 编排,提供从实验到生产的完整 SDK。
最初发布于 2025 年 12 月 27 日的 Medium。
如果你在 2025 年用 C#/.NET 构建 AI 智能体,最难的部分往往不是写提示词 —— 而是选择一个基础框架。你应该使用 Semantic Kernel?AutoGen?还是直接使用 OpenAI / Azure OpenAI SDK?如果你在 Python 中开发,选择菜单会更长。
Microsoft 创建了 Microsoft Agent Framework(MAF)来解决这个"框架轮盘赌"问题。根据 Microsoft 的公告文章,这个框架的核心思想是统一开发者们一直在选择的两个方向:
Semantic Kernel 的企业级友好 SDK 方法(连接器、平台集成、稳定的开发者界面)
AutoGen 风格的多智能体编排模式(协调、交接、更丰富的智能体间交互流程)
换句话说:一个开源 SDK + 运行时,旨在让你从本地实验一路带到生产系统,而无需在从"演示"切换到"部署"时重写智能体。
如果你想要 Microsoft 的官方框架说明和路线图,请阅读这两篇文章:
Semantic Kernel 团队的视角(包括 SK 支持预期)
Foundry 公告("为什么是现在"和支柱)
在本指南中,我们将通过我的代码仓库中的可运行演示专注于基础知识:调用函数、生成结构化输出、持久化线程、与 Azure AI Foundry 集成的智能体,以及使用 RAG。
Agent Framework 是一个用于构建 AI 智能体和将其编排成工作流的开源 SDK 和运行时。目前它处于公开预览阶段,Microsoft 将其定位为 Semantic Kernel 在智能体开发中的后继者 —— 实际上就是"Semantic Kernel v2"。
这并不意味着 Semantic Kernel 会立即消失。Microsoft 的声明意图是在可预见的未来继续支持 Semantic Kernel v1.x(重要的错误修复和安全修复,加上一些功能达到 GA),而大部分新的投资都投入到 Agent Framework 中。
该框架专注于两个核心功能:
AI 智能体:使用 LLM 处理输入、调用工具和生成响应的单个智能体
工作流:基于图的编排,连接多个智能体和函数来执行复杂的多步骤任务
为什么要重新开发?简短的答案是:智能体需要不仅仅是提示词模板。MAF 是围绕企业现实设计的 —— 长期运行智能体的耐久性、更丰富的可观测性、更好的可移植性/互操作性,以及从本地开发到托管服务的更清晰路径。
你可以在官方 Microsoft Agent Framework 文档中了解更多信息
在开始之前,确保你有:
.NET 10.0 SDK 或更高版本
Azure OpenAI 账户,包括:
大多数项目需要一个 appsettings.json 或 appsettings.Development.json 文件,包含你的 Azure OpenAI 配置:
{
"ModelName": "your-model-deployment-name",
"Endpoint": "https://your-resource.openai.azure.com/",
"ApiKey": "your-api-key",
"EmbeddingModel": "your-embedding-model-name"
}
⚠️ 注意:Agent Framework 目前处于公开预览阶段。API 可能在未来的版本中演变。
在我们跳入示例之前,让我们建立基础概念:
AIAgent:代表 AI 智能体的核心抽象。它封装了 LLM、指令和智能体可以使用的工具。
工具/函数:智能体可以执行的操作 —— 从简单的 C# 方法到复杂的 API 调用。Agent Framework 使用 AIFunctionFactory 将方法转换为 LLM 可以调用的工具。有关函数调用的深入讨论,请查看 OpenAI 的函数调用指南。
AgentThread:管理对话上下文和历史记录。将其视为智能体与用户交互的有状态容器。
记住这些构建块,让我们看看它们的实际应用。
让我们从基础开始:创建一个可以调用工具的智能体。
// 定义智能体可以调用的函数
[Description("Get the weather for a given location.")]
static string GetWeather([Description("The location to get the weather for.")] string location)
=> $"The weather in {location} is cloudy with a high of 15°C.";
// 将函数转换为工具
var weatherFunction = AIFunctionFactory.Create(GetWeather);
// 创建智能体
var agent = new AzureOpenAIClient(
new Uri(endpoint),
new AzureKeyCredential(apiKey))
.GetChatClient(modelName)
.CreateAIAgent(
instructions: "say 'just a second' before answering question",
tools: [weatherFunction],
name: "myagent");
// 为对话创建一个线程
var thread = agent.GetNewThread();
// 以流式方式运行智能体
var streamingResponse = agent.RunStreamingAsync(userInput, thread);
await foreach (var chunk in streamingResponse)
{
Console.Write(chunk);
}
函数定义:我们使用 [Description] 属性定义一个简单的 C# 方法。这些描述至关重要 —— 它们被发送到 LLM,以帮助其理解何时以及如何使用该工具。
工具注册:AIFunctionFactory.Create() 使用反射来分析你的方法签名和属性,然后生成 LLM 期望的工具模式。这个模式包括参数名称、类型和描述。
智能体创建:CreateAIAgent() 是一个扩展方法,包装了 ChatClient 并提供了智能体特定的功能。instructions 参数设置系统提示,用于指导智能体的行为。
线程管理:GetNewThread() 创建一个对话上下文,用于维护消息历史记录。每个线程都是隔离的,允许你独立管理多个对话。
流式执行:RunStreamingAsync() 将用户输入发送到 LLM,并以块的形式流式返回响应。这为用户提供即时反馈,而不是等待完整响应。
当用户问"巴黎的天气如何?"时,会发生以下情况:
LLM 接收问题和可用的工具模式
它决定调用 GetWeather,参数 location: "Paris"
Agent Framework 拦截此操作,执行你的 C# 方法
结果作为"工具消息"发送回 LLM
LLM 将结果整合到其最终响应中:"稍等… 巴黎的天气是阴天,最高气温 15°C。"
这种编排自动发生 —— 你只需定义函数,框架处理其余的。
与 Semantic Kernel 的插件注册仪式相比,这要简洁得多:
// Semantic Kernel 方法(更冗长)
var kernel = builder.Build();
kernel.ImportPluginFromFunctions("WeatherPlugin",
new[] { KernelFunctionFactory.CreateFromMethod(GetWeather) });
// Agent Framework 方法(简洁)
var weatherFunction = AIFunctionFactory.Create(GetWeather);
var agent = chatClient.CreateAIAgent(tools: [weatherFunction]);
你可以在 AgentFramework 项目中找到完整的实现。
结构化输出不是 Microsoft Agent Framework 独有的 —— 它是你在任何严肃的智能体应用中都想要的核心模式。
当你的智能体需要做一些具体的事情(创建票据、调用 API、路由请求)时,自由格式的文本就成了负担。你不想用正则表达式解析 LLM 响应 —— 你需要一个契约。
可靠的下游代码(类型化字段,而不是文本)
更少的提示词调整("仅有效 JSON"成为默认值)
更容易的测试/评估(对字段进行断言)
还有第二个被低估的效果:模式成为推理脚手架。模型不再产生听起来很好的段落,而是必须提交到特定的槽位(类别、实体、行动项等),这通常会使行为更具决定性。
权衡:如果你强制模型在输入缺少信息时填充字段,它可能会幻觉值来满足模式。通过为不确定性进行设计来缓解(可空字段、"未知"值或明确的说明,如"如果未说明,则将字段保留为空")。OpenAI 在其结构化输出指南中明确说明了这一点:https://platform.openai.com/docs/guides/structured-outputs
MAF 直接支持结构化输出:定义描述你想要的输出的 C# 类型,然后调用 RunAsync<T>()。框架从你的类型生成模式,要求模型生成与其匹配的响应,并将结果反序列化回 T。
下面是如何从会议记录中提取结构化信息:
// 使用嵌套类型定义输出结构
[Description("Structured meeting information")]
public class MeetingAnalysis
{
[JsonPropertyName("date")]
public string? Date { get; set; }
[JsonPropertyName("duration_minutes")]
public int? DurationMinutes { get; set; }
[JsonPropertyName("attendees")]
public List<string>? Attendees { get; set; }
[JsonPropertyName("decisions")]
public List<string>? Decisions { get; set; }
[JsonPropertyName("action_items")]
public List<ActionItem>? ActionItems { get; set; }
}
public class ActionItem
{
[JsonPropertyName("assignee")]
public string? Assignee { get; set; }
[JsonPropertyName("task")]
public string? Task { get; set; }
[JsonPropertyName("due_date")]
public string? DueDate { get; set; }
}
// 创建 AI 智能体
var agent = chatClient.CreateAIAgent(
name: "MeetingAnalyzer",
instructions: "You are an assistant that extracts structured information from meeting transcripts.");
// 使用结构化输出运行 - 注意泛型类型参数
var response = await agent.RunAsync<MeetingAnalysis>(
$"Please analyze this meeting transcript and extract key information:\n\n{meetingTranscript}",
thread
);
// 访问类型安全的属性 - 无需解析!
Console.WriteLine($"Meeting Date: {response.Result.Date}");
Console.WriteLine($"Duration: {response.Result.DurationMinutes} minutes");
Console.WriteLine($"Attendees: {string.Join(", ", response.Result.Attendees)}");
foreach (var item in response.Result.ActionItems)
{
Console.WriteLine($"- {item.Assignee}: {item.Task} (due: {item.DueDate})");
}
当你调用 RunAsync<MeetingAnalysis>() 时,Agent Framework 会:
你的类上的 [Description] 属性帮助 LLM 理解每个字段代表什么,提高提取精度。[JsonPropertyName] 属性控制 JSON 属性名称,这在与期望特定命名约定(如 snake_case)的 LLM 协作时特别有用。
在 AgentFrameworkStructuredOutput 项目中查看完整示例。
在生产场景中,你经常需要保存和恢复对话。Agent Framework 通过自定义存储提供者使这变得直接明了。
var agent = chatClient.CreateAIAgent(new ChatClientAgentOptions
{
Name = "Assistant",
ChatOptions = new() { Instructions = "You are a helpful assistant." },
// 关键点:你插入自己的消息存储。
// Agent Framework 将调用它来加载/保存聊天历史。
ChatMessageStoreFactory = ctx => new FileChatMessageStore(ctx.SerializedState)
});
var threadStore = new FileThreadStore(
storageDirectory: Path.Combine(Environment.CurrentDirectory, "ThreadStorage"));
AgentThread thread;
if (threadStore.Exists)
{
// 通过 agent 恢复线程状态(不是通过线程本身)
thread = threadStore.Load(serialized => agent.DeserializeThread(serialized));
// 聊天历史从消息存储中加载(见下文)
await DisplayHistoricalMessagesAsync(thread);
}
else
{
thread = agent.GetNewThread();
}
// 在每个用户转向后,保存线程状态
threadStore.Save(thread);
这个项目持久化两件事:
线程状态由 FileThreadStore 保存为 JSON。恢复由 agent 完成:
消息存储有意保持最小化。在 FileChatMessageStore 中,你主要覆盖 2–3 个成员:
如果你想要 Redis/SQL 等,你只需要创建你自己的 ChatMessageStore 实现。
在 AgentFrameworkThreadPersistancy 项目中探索完整实现。
Microsoft Foundry(旧名称:Azure AI Foundry)在云中提供托管 AI 智能体基础设施。你可以利用 Foundry 的持久化 AI 智能体,而不是自己管理 AI 智能体生命周期。
// 连接到 Azure AI Foundry
var credential = new AzureCliCredential();
var client = new PersistentAgentsClient(
new Uri(projectEndpoint),
credential
);
// 创建或检索一个托管 AI 智能体
var agent = await client.CreateAgentAsync(
model: modelName,
instructions: "You are a helpful assistant",
tools: tools
);
// 像使用任何其他 AI 智能体一样使用它
var thread = await client.CreateThreadAsync();
var response = await client.RunAsync(agent.Id, thread.Id, userMessage);
对于构建生产系统的团队,Foundry 消除了显著的运维开销。
在 AgentFrameworkFoundryAgent 项目中查看工作示例。
检索增强生成(RAG)用外部知识增强 AI 智能体。在这个演示中,Agent Framework 通过 TextSearchProvider 作为 AI 上下文提供者集成 RAG:AI 智能体可以按需触发检索,提供者将相关片段注入到提示中。
首先,使用向量存储属性定义你的文档 schema:
private sealed class SearchRecord
{
// 嵌入维度必须与你的模型匹配(例如,text-embedding-3-large 是 3072)
private const int EmbeddingDimensions = 3072;
[VectorStoreKey]
public required string SourceId { get; init; }
[VectorStoreData]
public string? SourceName { get; init; }
[VectorStoreData]
public string? SourceLink { get; init; }
[VectorStoreData(IsFullTextIndexed = true)]
public string? Text { get; init; }
[VectorStoreVector(EmbeddingDimensions)]
public ReadOnlyMemory<float> TextEmbedding { get; init; }
}
这些属性告诉向量存储什么是可搜索文本、什么是元数据,以及哪个字段包含嵌入。
var azureOpenAiClient = new AzureOpenAIClient(
new Uri(endpoint),
new AzureKeyCredential(apiKey));
// 在这个演示中,我们使用内存向量存储和 Azure OpenAI 嵌入。
var embeddingGenerator = azureOpenAiClient
.GetEmbeddingClient(embeddingModel)
.AsIEmbeddingGenerator();
VectorStore vectorStore = new InMemoryVectorStore(new InMemoryVectorStoreOptions
{
EmbeddingGenerator = embeddingGenerator
});
// 这个辅助程序创建集合并上传示例文档。
var knowledgeBase = await RagKnowledgeBase.CreateAsync(vectorStore, embeddingGenerator);
Func<string, CancellationToken, Task<IEnumerable<TextSearchProvider.TextSearchResult>>> searchAdapter =
knowledgeBase.SearchAsync;
TextSearchProviderOptions textSearchOptions = new()
{
SearchTime = TextSearchProviderOptions.TextSearchBehavior.OnDemandFunctionCalling,
RecentMessageMemoryLimit = 6,
};
var agent = azureOpenAiClient
.GetChatClient(modelName)
.CreateAIAgent(new ChatClientAgentOptions
{
Name = "myagent",
ChatOptions = new ChatOptions
{
Instructions = "Say 'just a second' before answering."
},
// RAG 作为上下文提供者连接(不是作为普通工具列表)。
AIContextProviderFactory = ctx => new TextSearchProvider(
searchAdapter,
ctx.SerializedState,
ctx.JsonSerializerOptions,
textSearchOptions)
});
var thread = agent.GetNewThread();
var response = await agent.RunAsync("What's your return policy?", thread);

在生产中,你通常会将内存存储交换为持久向量后端,但连接保持不变。
额外福利:Python 支持
Agent Framework 不仅仅面向 C# 开发者。Microsoft 提供了 Python 支持,能够实现跨语言的智能体开发。
from azure.ai.agents import AIAgent from azure.ai.openai import AzureOpenAIClient
client = AzureOpenAIClient(endpoint=endpoint, credential=credential) agent = client.create_agent( model=model_name, instructions="You are a helpful assistant", tools=[weather_tool] )
thread = agent.create_thread() response = agent.run(user_input, thread)
Python API 镜像了 C# 的设计,使得跨语言工作或将现有 Python 项目迁移到 Agent Framework 变得轻而易举。
请查看 AgentFrameworkPython 目录中的 Python 示例。
我们已经介绍了基础知识——具有各种能力的单个智能体。但当你需要将多个智能体和确定性逻辑编排成复杂工作流时会发生什么呢?
这就是 Agent Framework 的工作流系统发挥作用的地方。工作流允许你构建基于图的流程,将 LLM 智能体与业务规则、条件路由和共享状态管理相结合。
在下一篇文章中,我们将探索如何构建一个真实的客户支持邮件分类系统,该系统可以自动对邮件进行分类、应用业务策略,并路由到自动响应或人工升级。
Microsoft Agent Framework 代表了 AI 智能体开发的重大进步。通过学习 Semantic Kernel 和 AutoGen,它提供了更简洁、更直观的 API,在不牺牲功能的情况下加速开发。
无论你是在构建简单的聊天机器人还是复杂的多智能体系统,Agent Framework 都提供了你需要的构建块——作为 SK 和 AutoGen 的继任者,它是 Microsoft AI 智能体生态系统的未来方向。
🔗 浏览完整演示仓库:GitHub 上的 AgentFrameworkPlayground
🤝 你的反馈弥足珍贵!请随时留下评论、提出问题或分享你的见解和优化方案。每个贡献都有助于增进我们的集体知识并构建一个有用的开发者社区。
如有进一步的行动,你可以考虑屏蔽此人和/或举报滥用。