一、前言
Microsoft Agent Framework(简称 Agent Framework)发布已有一段时间。在"观望"(摸鱼)一阵后,在老板的"鼓励"下,我们果断将多个 AI 微服务从 Semantic Kernel(SK) 迁移至 Agent Framework。
本文记录迁移过程中总结的工程化用法与实践经验,供同行参考。
二、Agent Framework 是什么?
Agent Framework 是微软在 Semantic Kernel 之后推出的新一代智能体(Agent)开发框架,可视为 SK 的"进化版":
-
核心理念相似,但 API 更直观、更现代化;
-
原生支持 多智能体协作(Multi-Agent);
-
更契合当前 LLM 应用向"智能体系统"演进的趋势。
💡 如果你曾被 SK 的
Kernel/Skill/Function/Context嵌套结构折磨过,Agent Framework 会让你眼前一亮。
三、与 Semantic Kernel 的关键对比
| 维度 | Semantic Kernel | Agent Framework |
|---|---|---|
| 结构设计 | 抽象层级多(Skill/Function),复用困难 | 直接定义 Agent 类,职责清晰 |
| Prompt 管理 | 依赖 YAML/JSON 模板 + Template Function | 直接传入 instructions,逻辑与提示分离自然 |
| 多 Agent 协作 | 需手动实现消息传递 | 内置线程(Thread)机制,天然支持多 Agent 通信 |
| 工具集成 | 手动注册函数为插件 | 支持 MCP 工具、自定义 AITool,开箱即用 |
四、工程化使用姿势
4.1 单一职责:每个任务一个 Agent
摒弃 SK 中"一个 Kernel 打天下"的模式,采用 一个任务对应一个 Agent 的设计:
-
职责单一,便于测试与维护;
-
通过 IOC 容器注册,像普通服务一样注入使用。
示例:公司名称抽取 Agent
csharp
public class CompanyExtractionAgent : BaseAgentFunction, ICompanyExtractionAgent
{
private readonly AIAgent _agent;
public CompanyExtractionAgent(IOptions<LLMConfiguration> config)
{
var client = new OpenAIClient(...);
var chatClient = client.GetChatClient(config.Value.Model);
_agent = chatClient.CreateAIAgent(instructions:
"你是一个信息抽取助手,请从文本中提取所有公司名称,必须返回合法 JSON 数组...");
}
public async Task<List<string>> ExtractCompanyNamesAsync(string filePath)
{
// 分块处理文档 → 调用 Agent → 解析 JSON → 合并结果
}
}
4.2 给 Agent 装上"手和眼":集成 MCP 工具
4.2.1 注册 MCP 客户端(如 Playwright 浏览器)
csharp
public static async Task AddMcpClientAsync(this IServiceCollection services, bool headless)
{
var transport = new StdioClientTransport(new StdioClientTransportOptions
{
Name = "PlaywrightMCP",
Command = "npx",
Arguments = new List<string> { "@playwright/mcp", "--headless", ... }
});
var mcpClient = await McpClient.CreateAsync(transport);
services.AddSingleton(mcpClient);
}
4.2.2 使用 MCP 工具的 Agent
csharp
public class CompanyInfoQueryAgent : BaseAgentFunction, ICompanyInfoQueryAgent
{
public CompanyInfoQueryAgent(IOptions<LLMConfiguration> config, McpClient mcpClient)
{
var tools = (await mcpClient.ListToolsAsync()).Cast<AITool>().ToList();
_agent = chatClient.CreateAIAgent(
instructions: "你拥有网络访问能力,请使用 MCP 工具查询公司公开信息...",
tools: tools
);
}
public async Task<CompanyInfo?> QueryCompanyInfoAsync(string companyName) { ... }
}
4.3 自定义函数工具(Function Tool)
4.3.1 编写工具类
csharp
public class CompanyInfoTool : AITool
{
public async Task<string> QueryCompanyInfoAsync(string companyName)
{
return await _httpClient.GetStringAsync($"https://api.example.com/company/{companyName}");
}
}
4.3.2 注册到 Agent
csharp
_agent = chatClient.CreateAIAgent(
instructions: "请使用工具查询公司信息",
tools: new List<AITool> { _companyInfoTool }
);
4.4 记忆功能(Memory / Thread)
Agent Framework 通过 Thread 实现对话记忆:
csharp
// 保存对话状态
var serialized = thread.Serialize(JsonSerializerOptions.Web).GetRawText();
await File.WriteAllTextAsync("thread.json", serialized);
// 恢复对话
var json = await File.ReadAllTextAsync("thread.json");
var restoredThread = _agent.DeserializeThread(JsonSerializer.Deserialize<JsonElement>(json));
var response = await _agent.RunAsync("继续...", restoredThread);
✅ 支持持久化到数据库、Redis 等,实现跨会话记忆。
五、踩坑与注意事项
5.1 Endpoint 配置差异
| 框架 | 正确 Endpoint 格式 |
|---|---|
| Semantic Kernel | https://api.deepseek.com/v1 |
| Agent Framework | https://api.deepseek.com (无 /v1) |
⚠️ 多数国产模型 API(如 DeepSeek、Moonshot)在 Agent Framework 中需去掉路径后缀。
5.2 结构化输出(Structured Output)
推荐使用 ChatResponseFormat.ForJsonSchema 强制模型输出合规 JSON:
csharp
var schema = AIJsonUtilities.CreateJsonSchema(typeof(CompanyInfo));
var chatOptions = new ChatOptions
{
ResponseFormat = ChatResponseFormat.ForJsonSchema(schema, "CompanyInfo", "结构化公司信息"),
Tools = tools
};
_agent = chatClient.CreateAIAgent(new ChatClientAgentOptions
{
Instructions = "...",
ChatOptions = chatOptions
});
❗ 注意:部分国产模型(如 DeepSeek)虽文档声称支持
response_format: { "type": "json_object" },但实际调用可能报错。建议先验证模型兼容性。
六、总结
Agent Framework 相比 Semantic Kernel:
-
结构更清晰:Agent 即服务,天然契合微服务架构;
-
开发更高效:减少模板代码,Prompt 与逻辑解耦;
-
扩展更灵活:MCP、自定义工具、记忆、多 Agent 协作一应俱全。
尽管在国产模型适配上仍有小坑,但整体体验显著优于 SK,强烈推荐新项目直接采用 Agent Framework。
最佳实践
-
一个任务 = 一个 Agent
-
工具解耦、通过 DI 注入
-
利用 Thread 实现上下文记忆
-
优先使用结构化输出保障数据可靠性
关键词
Microsoft Agent Framework、Semantic Kernel、AI Agent、MCP、多智能体、结构化输出、.NET AI 开发
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。
也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
优秀是一种习惯,欢迎大家留言学习!