说实话,AI Agent 最容易让人误判的地方,就是"能跑起来"和"能放进生产"之间,隔着一整套工程问题。
我最近持续关注 Microsoft Agent Framework,简称 MAF。站在 .NET 开发者的角度看,它真正有价值的地方并不是再提供一个"调用大模型"的 SDK,而是把 Agent、工具、工作流、状态、人工审批和可观测性,逐渐收敛到一套更适合企业应用的编程模型里。
本文不做 API 罗列,而是从架构和落地角度聊清楚:MAF 解决了什么问题,.NET 项目应该怎么开始,以及哪些地方不能只看 Demo。
作者说明:本文以微软最有价值专家(Microsoft MVP)的 .NET 开发视角撰写,代码和 API 以官方文档及当前版本为准,正式项目请结合实际 SDK 版本验证。
MAF 到底是什么
MAF 的全称是 Microsoft Agent Framework。它是微软将 Semantic Kernel 的企业级能力与 AutoGen 的多 Agent 编排思路进一步整合后的开放框架,同时提供 Python 和 .NET 支持。
可以把它理解成三层:
- Agent 层:负责理解指令、调用模型、使用工具并维护会话。
- Workflow 层:负责把多个 Agent 和普通函数组织成确定性的流程。
- 运行治理层:负责中间件、记忆、检查点、人工介入、遥测和部署。
这三层很关键。很多 Agent Demo 只有第一层,所以看起来很聪明;真正的业务系统必须把后两层补齐,否则一旦出现超时、重试、上下文过长或工具误调用,系统就会变得不可控。
为什么 .NET 开发者值得关注
如果只是发一条 Prompt,任何语言都能做到。但企业应用通常已经有成熟的 .NET 基础设施:ASP.NET Core、依赖注入、Options、日志、OpenTelemetry、身份认证、后台任务和 Azure 资源。
MAF 的优势在于,它没有要求 .NET 团队重新接受一套完全不同的运行方式。Agent 可以被当作应用服务的一部分,工具可以复用现有的 C# 方法和领域服务,工作流可以嵌入现有的 Web API、Worker Service 或 Durable 任务体系。
坦白讲,这比"单独搭一个 Python Agent 服务,再通过 HTTP 调用"更容易在大型 .NET 团队里推广。当然,Python 生态在 AI 实验和数据处理方面仍然很强,MAF 的价值不是让所有人改用 .NET,而是让 .NET 在生产级 Agent 开发上不再缺席。
先从一个最小 Agent 开始
以 Microsoft Foundry 为例,最小的 .NET Agent 可以这样创建:
csharp
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT")
?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
var model = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME")
?? "gpt-5.4-mini";
AIAgent agent = new AIProjectClient(
new Uri(endpoint),
new DefaultAzureCredential())
.AsAIAgent(
model: model,
name: "DotnetAssistant",
instructions: "你是一名严谨的 .NET 技术助手,回答要给出可执行的代码和边界条件。");
var response = await agent.RunAsync("解释一下 .NET 中的依赖注入生命周期。");
Console.WriteLine(response);
这段代码的重点不在于少,而在于抽象边界清楚:AIAgent 表示能力,具体模型服务由客户端适配。后面如果从 Foundry 切换到 Azure OpenAI、OpenAI、Anthropic 或其他提供商,业务层不应该到处散落模型调用代码。
实际项目中,我建议把 Agent 创建放进独立的工厂或注册扩展中,不要在 Controller 里直接 new。这样可以统一注入模型配置、工具集合、Middleware、遥测和超时策略。
Agent 不是工作流,别把两者混在一起
单 Agent 很适合问答、摘要、代码解释等任务,但业务流程往往更像这样:
text
用户需求
↓
需求分析 Agent
↓
并行执行:资料检索 + 数据校验
↓
汇总 Agent
↓
人工审批
↓
执行领域操作
这里如果完全交给一个 Agent 自由发挥,系统的可测试性会很差。MAF 的工作流模型更适合把"需要推理的部分"和"必须确定执行的部分"拆开。
一个实用原则是:让模型做选择,让代码做约束。
比如,模型可以判断用户想查询订单还是申请退款,但真正的退款操作应该经过参数校验、权限检查和人工审批,不能因为模型输出了一段看似合理的 JSON 就直接执行。
顺序、并行和交接:三种常用编排模式
在 MAF 的工作流里,最常见的三种模式分别是:
顺序编排
上一个 Agent 的输出作为下一个 Agent 的输入,适合"生成 → 审核 → 改写"这类链路。
csharp
var workflow = new SequentialBuilder(
participants: [writerAgent, reviewerAgent])
.Build();
顺序编排容易理解,也方便排查问题。内容生成、代码审查、数据清洗等流程,通常从它开始最稳。
并行编排
多个任务彼此独立时并行执行,例如同时查询知识库、订单系统和库存系统,最后再汇总。并行可以降低整体延迟,但要注意模型供应商的限流、下游系统连接数以及错误聚合策略。
Handoff 交接
让当前 Agent 根据上下文把任务交给更合适的 Agent。例如客服 Agent 发现用户要处理发票,就把对话交给财务 Agent;发现涉及退款,则交给售后 Agent。
交接模式更像真实组织协作,但也更容易出现"来回踢皮球"。生产环境要给交接次数、总耗时和最大 Token 消耗设上限。
工具调用:最容易被低估的工程边界
MAF 中的工具可以是一个普通的 C# 方法,但工具并不等于"把所有业务 API 暴露给模型"。我建议至少做四层保护:
- 输入层:使用强类型参数和数据注解,拒绝无法解析或超范围的值。
- 权限层:工具执行时重新获取当前用户身份,不要相信模型传入的 userId。
- 审批层:退款、删除、发消息、写入生产数据等操作使用人工确认。
- 审计层:记录调用者、参数摘要、审批人、结果和耗时。
示例中的工具描述应该清楚说明能力边界:
csharp
[Description("查询当前用户有权限访问的订单,只读,不会修改订单状态。")]
static async Task<OrderSummary> GetOrderAsync(
[Description("订单号,例如 ORD-20260902-001")] string orderId)
{
// 真实项目中还要做身份校验、租户隔离和超时控制
return await orderService.GetSummaryAsync(orderId);
}
工具描述写得越模糊,模型越容易误用。这个坑我建议大家一开始就重视,不要等到线上出现错误调用才补救。
Middleware、记忆和检查点,才是生产化的分水岭
MAF 的 Middleware 可以在 Agent 执行前后介入。常见用途包括内容安全、敏感信息脱敏、统一日志、Token 统计、重试和策略检查。
记忆也不要简单理解成"把所有历史消息一直塞回 Prompt"。对话历史、用户偏好、业务状态和向量检索文档,应该分开管理。历史消息适合短期上下文,业务状态应该进入明确的数据模型,知识检索则应该有独立的召回和权限过滤逻辑。
长流程还需要检查点。一个跨越数分钟甚至数小时的工作流,不能因为进程重启就从头调用模型。Checkpointing 和 hydration 的价值,就是保存工作流状态,在中断后恢复执行。
这也是 MAF 和普通 Chat Completion 封装的差异:它开始认真处理"Agent 运行过程中发生故障怎么办"。
MCP 和 A2A:连接外部能力,但别放松治理
MAF 支持 MCP,可以让 Agent 发现和调用外部工具;同时也在关注 A2A 等 Agent 间互操作协议。协议解决的是连接问题,不会自动解决安全问题。
接入第三方 MCP Server 时,我会重点确认:
- 工具能访问哪些数据;
- 是否支持租户隔离和最小权限;
- 输入输出是否会包含敏感信息;
- 失败、超时和重试怎么处理;
- 供应商是否会保存请求内容。
"能调用"只是第一关,"可审计、可撤销、可限制"才是企业真正关心的能力。
我认为 MAF 目前最适合的场景
MAF 很适合下面几类系统:
- 有明确业务流程的多 Agent 应用;
- 需要人工审批和长时间运行的任务;
- 已经使用 .NET、Azure 和 OpenTelemetry 的企业系统;
- 希望未来在多个模型供应商之间切换的团队;
- 需要把 Agent 能力和既有领域服务结合起来的项目。
如果你的需求只是"给网站加一个聊天框",直接使用模型 SDK 反而更简单。不要为了使用框架而使用框架,Agent 的编排、状态和治理复杂度是有成本的。
上线前的检查清单
在我看来,MAF 项目上线前至少要过这几关:
- 模型调用是否设置了超时、重试和 Token 上限?
- 工具是否做到最小权限,副作用操作是否需要审批?
- 每一次 Agent、Workflow 和 Tool 调用能否关联追踪?
- 长流程是否支持暂停、恢复和幂等重试?
- Prompt、工具描述和工作流定义是否纳入版本管理?
- 是否有真实业务数据下的评测集,而不只是 Demo?
- 是否明确了数据留存、跨境传输和第三方服务边界?
血泪教训是:Agent 系统最难调的通常不是模型回答得不够聪明,而是失败后没有留下足够的信息。
写在最后
MAF 的方向是对的:它没有把 Agent 只当成一个更会聊天的接口,而是试图把 Agent 放进真实的软件工程体系里。
对 .NET 开发者来说,最值得关注的不是某个具体 API,而是这套架构是否能让我们用熟悉的依赖注入、领域服务、工作流和可观测性,把 AI 能力变成可以维护的生产系统。
我的建议是:先用一个只读场景跑通单 Agent,再引入工具调用;随后把确定性步骤抽成 Workflow,最后补齐审批、检查点和遥测。不要一上来就做"全自动多 Agent 平台",那通常是复杂度的起点,不是成功的终点。
官方资料: