蝗曝植莆重要说明:
Microsoft Agent Framework 目前处于公开预览版(Public Preview)阶段
本文档中的代码示例基于 Azure OpenAI SDK 实现,展示 Function Calling 和 AI 代理的核心概念
部分工作流(Workflow)示例为概念性设计,展示多代理协作的思路
概述
什么是Microsoft Agent Framework
Microsoft Agent Framework 是微软开源的AI代理开发工具包,用于构建智能AI代理和多代理工作流系统。它支持 .NET 和 Python 两种开发语言,是 Semantic Kernel 和 AutoGen 项目的直接继承者和统一版本。
项目背景
设计理念:结合 AutoGen 的简洁抽象和 Semantic Kernel 的企业级特性
开源地址:https://github.com/microsoft/agent-framework
当前状态:公开预览版(Public Preview)
核心价值
统一框架:整合了Semantic Kernel和AutoGen的最佳特性
企业级特性:提供会话状态管理、类型安全、过滤器、遥测等
灵活架构:支持单代理和多代理编排模式
显式控制:通过工作流提供对多代理执行路径的精确控制
长期运行:强大的状态管理系统支持长时间运行和人机协作场景
核心概念
- AI代理(AI Agents)
定义
AI代理是使用大型语言模型(LLM)处理用户输入、做出决策、调用工具和MCP服务器执行操作,并生成响应的智能实体。
核心组件
用户输入 → AI代理 → 工具调用 → 外部服务
↓ ↓
LLM处理 MCP服务器
↓ ↓
决策逻辑 ← 执行结果 ←
↓
响应生成
增强组件
会话(Session):管理多轮对话状态
上下文提供者(Context Provider):提供代理记忆能力
中间件(Middleware):拦截和增强代理行为
工具集成:通过MCP客户端集成外部工具
适用场景
? 适合使用AI代理的场景:
客户支持:处理多模态查询(文本、语音、图像)
教育辅导:利用外部知识库提供个性化辅导
代码生成与调试:辅助开发者进行实现、代码审查和调试
研究助手:搜索网络、总结文档、整合多源信息
动态任务处理:需要自主决策、临时规划和试错探索的场景
? 不适合使用AI代理的场景:
高度结构化且需要严格遵循预定义规则的任务
可以直接编写函数处理的确定性任务
简单的CRUD操作
需要100%确定性结果的场景
关键原则:如果可以编写函数来处理任务,就直接编写函数,而不是使用AI代理。可以用AI辅助编写函数。
- 工作流(Workflows)
定义
工作流是一种图形化的执行流程,它可以连接多个AI代理和函数来执行复杂的多步骤任务,同时保持一致性和可靠性。
工作流结构
开始节点
↓
AI代理1 → 决策节点 → AI代理2
↓ ↓ ↓
函数调用 ← 条件路由 → 并行处理
↓ ↓
结束节点 ← 汇总结果 ←
核心特性
模块化:可分解为更小的可重用组件
代理集成:可整合多个AI代理和非代理组件
类型安全:强类型确保组件间消息正确流转
灵活控制流:支持条件路由、并行处理和动态执行路径
外部集成:内置请求/响应模式用于系统集成
检查点机制:保存工作流状态,支持恢复和续接
多代理编排:内置顺序、并发、移交等编排模式
可组合性:工作流可嵌套或组合创建更复杂流程
AI代理 vs 工作流对比
特性 AI代理 工作流
执行方式 LLM驱动的动态步骤 预定义的操作序列
决策方式 基于对话上下文和可用工具自动决定 明确定义的流程路径
适用任务 非结构化、需要探索的任务 结构化、多步骤的复杂任务
控制程度 较低(LLM自主决策) 较高(显式定义)
可预测性 较低 较高
安装与配置
.NET环境要求
前置条件
-
.NET 8.0 SDK 或更高版本
-
Azure OpenAI 资源(已部署模型,如 gpt-4o-mini)
-
Azure CLI(已安装并认证,可选)
创建项目
创建新控制台应用
dotnet new console -o AgentFrameworkDemo
cd AgentFrameworkDemo
安装NuGet包
安装核心包(实际使用的包)
dotnet add package Azure.AI.OpenAI --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Configuration.Json
注意:Microsoft.Agents.AI 包仍在开发中
当前示例使用 Azure.AI.OpenAI 实现相同功能
配置Azure认证
使用Azure CLI登录(可选)
az login
确保账户具有以下角色之一:
- Cognitive Services OpenAI User
- Cognitive Services OpenAI Contributor
创建配置文件
创建 appsettings.json 文件:
{
"AzureOpenAI": {
"Endpoint": "https://your-resource.openai.azure.com/",
"DeploymentName": "gpt-4o-mini",
"ApiKey": ""
}
}
注意:
Endpoint: 你的 Azure OpenAI 资源端点
DeploymentName: 部署的模型名称(如 gpt-4o-mini, gpt-4o)
ApiKey: 可留空使用 Azure CLI 认证,或填入 API 密钥
快速入门
基础AI代理示例(C#)
注意:Microsoft Agent Framework 目前仍在预览阶段,本示例使用 Azure OpenAI SDK 实现相同的功能。
using System;
using Azure;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Extensions.Configuration;
using OpenAI.Chat;
// 加载配置
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var endpoint = configuration["AzureOpenAI:Endpoint"];
var deploymentName = configuration["AzureOpenAI:DeploymentName"];
var apiKey = configuration["AzureOpenAI:ApiKey"];
// 创建Azure OpenAI客户端
AzureOpenAIClient openAIClient;
if (!string.IsNullOrEmpty(apiKey))
{
// 使用API Key认证
openAIClient = new AzureOpenAIClient(
new Uri(endpoint),
new AzureKeyCredential(apiKey)
);
}
else
{
// 使用Azure CLI认证
openAIClient = new AzureOpenAIClient(
new Uri(endpoint),
new AzureCliCredential()
);
}
// 获取聊天客户端
var chatClient = openAIClient.GetChatClient(deploymentName);
// 创建对话
var messages = new List
{
new SystemChatMessage("You are good at telling jokes."),
new UserChatMessage("Tell me a joke about a pirate.")
};
var response = await chatClient.CompleteChatAsync(messages);
Console.WriteLine(response.Value.Content[0].Text);
配置文件示例
创建 appsettings.json 文件:
{
"AzureOpenAI": {
"Endpoint": "https://your-resource.openai.azure.com/",
"DeploymentName": "gpt-4o-mini",
"ApiKey": ""
}
}
Python快速示例
import asyncio
from agent_framework.azure import AzureAIClient
from azure.identity.aio import AzureCliCredential
async def main():
async with (
AzureCliCredential() as credential,
AzureAIClient(async_credential=credential).as_agent(
name="JokeAgent",
instructions="You are good at telling jokes.",
) as agent,
):
result = await agent.run("Tell me a joke about a pirate.")
print(result.text)
if name == "main":
asyncio.run(main())
AI代理详解
代理工具(Agent Tools / Function Calling)
定义工具函数
using System.ComponentModel;
public class CustomerServiceTools
{
Description("Search for customer order by order ID")
public async Task GetOrderInfoAsync(
Description("Order ID to search, format like ORD-12345")\] string orderId) { // 模拟数据库查询 await Task.Delay(100); return $@"订单信息查询成功: - 订单号:{orderId} - 客户姓名:张三 - 产品:Surface Laptop 5 - 状态:已发货 - 物流单号:SF1234567890"; } \[Description("Process refund request for an order")
public async Task ProcessRefundAsync(
Description("Order ID to refund")\] string orderId, \[Description("Refund reason provided by customer")\] string reason) { await Task.Delay(200); var refundId = $"RF-{DateTime.Now:yyyyMMddHHmmss}"; return $@"退款申请已成功提交: - 退款单号:{refundId} - 订单号:{orderId} - 退款原因:{reason} - 预计处理时间:3-5个工作日"; } } 使用 Function Calling using OpenAI.Chat; // 创建工具实例 var tools = new CustomerServiceTools(); // 定义工具(Function Calling) var chatOptions = new ChatCompletionOptions(); chatOptions.Tools.Add(ChatTool.CreateFunctionTool( "GetOrderInfo", "Search for customer order by order ID", BinaryData.FromString(""" { "type": "object", "properties": { "orderId": { "type": "string", "description": "Order ID to search, format like ORD-12345" } }, "required": \["orderId"
}
""")
));
chatOptions.Tools.Add(ChatTool.CreateFunctionTool(
"ProcessRefund",
"Process refund request for an order",
BinaryData.FromString("""
{
"type": "object",
"properties": {
"orderId": {
"type": "string",
"description": "Order ID to refund"
},
"reason": {
"type": "string",
"description": "Refund reason provided by customer"
}
},
"required": ["orderId", "reason"]
}
""")
));
// 调用AI并处理工具调用
var messages = new List
{
new SystemChatMessage("你是专业的客户服务助手"),
new UserChatMessage("查询订单 ORD-12345")
};
var completion = await chatClient.CompleteChatAsync(messages, chatOptions);
// 检查是否需要调用工具
if (completion.Value.FinishReason == ChatFinishReason.ToolCalls)
{
// 添加助手消息到历史
messages.Add(new AssistantChatMessage(completion.Value));
// 执行工具调用
foreach (var toolCall in completion.Value.ToolCalls)
{
var functionName = toolCall.FunctionName;
var arguments = JsonDocument.Parse(toolCall.FunctionArguments.ToString());
string result = functionName switch
{
"GetOrderInfo" => await tools.GetOrderInfoAsync(
arguments.RootElement.GetProperty("orderId").GetString()!
),
"ProcessRefund" => await tools.ProcessRefundAsync(
arguments.RootElement.GetProperty("orderId").GetString()!,
arguments.RootElement.GetProperty("reason").GetString()!
),
_ => "未知工具"
};
// 添加工具结果到历史
messages.Add(new ToolChatMessage(toolCall.Id, result));
}
// 再次调用AI生成最终响应
var finalResponse = await chatClient.CompleteChatAsync(messages, chatOptions);
Console.WriteLine(finalResponse.Value.Content[0].Text);
}
多轮对话(Multi-turn Conversation)
using OpenAI.Chat;
// 创建对话历史以保持上下文
var conversationHistory = new List
{
new SystemChatMessage("You are a helpful assistant.")
};
// 第一轮对话
conversationHistory.Add(new UserChatMessage("My name is John."));
var response1 = await chatClient.CompleteChatAsync(conversationHistory);
var assistantMessage1 = response1.Value.Content[0].Text;
Console.WriteLine(assistantMessage1);
// 将助手响应添加到历史
conversationHistory.Add(new AssistantChatMessage(assistantMessage1));
// 第二轮对话(AI记得之前的上下文)
conversationHistory.Add(new UserChatMessage("What's my name?"));
var response2 = await chatClient.CompleteChatAsync(conversationHistory);
var assistantMessage2 = response2.Value.Content[0].Text;
Console.WriteLine(assistantMessage2); // 输出:Your name is John.
// 将响应添加到历史
conversationHistory.Add(new AssistantChatMessage(assistantMessage2));
// 第三轮对话
conversationHistory.Add(new UserChatMessage("Tell me a joke about my name."));
var response3 = await chatClient.CompleteChatAsync(conversationHistory);
Console.WriteLine(response3.Value.Content[0].Text);
代理记忆(Agent Memory)
注意:此示例展示记忆管理概念,实际实现通过维护对话历史来管理上下文。
using OpenAI.Chat;
// 使用对话历史实现记忆功能
var conversationHistory = new List
{
new SystemChatMessage("You are a personal assistant. Remember user preferences.")
};
// 用户设置偏好
conversationHistory.Add(new UserChatMessage("Remember that I prefer meetings in the morning."));
var response1 = await chatClient.CompleteChatAsync(conversationHistory);
conversationHistory.Add(new AssistantChatMessage(response1.Value.Content[0].Text));
conversationHistory.Add(new UserChatMessage("My favorite programming language is C#."));
var response2 = await chatClient.CompleteChatAsync(conversationHistory);
conversationHistory.Add(new AssistantChatMessage(response2.Value.Content[0].Text));
// 稍后查询 - AI会从对话历史中回忆
conversationHistory.Add(new UserChatMessage("When do I prefer meetings?"));
var response3 = await chatClient.CompleteChatAsync(conversationHistory);
Console.WriteLine(response3.Value.Content[0].Text); // 输出:You prefer meetings in the morning.
代理中间件(Agent Middleware)
注意:此示例展示中间件概念,实际实现可以通过包装函数来实现类似功能。
using OpenAI.Chat;
// 创建包装类实现日志和过滤功能
public class ChatClientWrapper
{
private readonly ChatClient _chatClient;
public ChatClientWrapper(ChatClient chatClient)
{
_chatClient = chatClient;
}
public async Task CompleteChatWithLoggingAsync(
List messages,
ChatCompletionOptions? options = null)
{
// 日志记录请求
var userMessage = messages.LastOrDefault(m => m is UserChatMessage);
if (userMessage != null)
{
Console.WriteLine($"[Request] {((UserChatMessage)userMessage).Content[0].Text}");
}
// 检查敏感内容
if (userMessage != null && ContainsSensitiveInfo(((UserChatMessage)userMessage).Content[0].Text))
{
Console.WriteLine("[Filter] Sensitive information detected");
return "I cannot process sensitive information.";
}
// 调用实际的API
var response = await _chatClient.CompleteChatAsync(messages, options);
var responseText = response.Value.Content[0].Text;
// 日志记录响应
Console.WriteLine($"[Response] {responseText}");
return responseText;
}
private bool ContainsSensitiveInfo(string message)
{
// 实现敏感信息检测逻辑
return message.Contains("password") || message.Contains("credit card");
}
}
// 使用示例
var wrapper = new ChatClientWrapper(chatClient);
var messages = new List
{
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage("Tell me a joke.")
};
var response = await wrapper.CompleteChatWithLoggingAsync(messages);
工作流详解
重要说明:以下工作流示例为概念性设计,展示多代理协作的思路。Microsoft Agent Framework 的工作流 API 仍在开发中,实际实现需要通过组合多个 ChatClient 调用来完成。
基础工作流结构(概念性示例)
using OpenAI.Chat;
using System.Text.Json;
// 概念性的客户支持工作流实现
public class CustomerSupportWorkflow
{
private readonly ChatClient _chatClient;
public CustomerSupportWorkflow(ChatClient chatClient)
{
_chatClient = chatClient;
}
public async Task ExecuteAsync(string userQuery)
{
// 步骤1: 意图识别
var intent = await TriageAsync(userQuery);
// 步骤2: 根据意图路由到专门的处理逻辑
return intent switch
{
"technical" => await HandleTechnicalIssueAsync(userQuery),
"billing" => await HandleBillingIssueAsync(userQuery),
_ => await HandleGeneralQueryAsync(userQuery)
};
}
private async Task TriageAsync(string query)
{
var messages = new List
{
new SystemChatMessage(@"你是客户服务分类助手。分析用户问题并返回以下类别之一:
-
technical: 技术问题
-
billing: 账单问题
-
general: 一般咨询
只返回类别名称,不要其他内容。"),
new UserChatMessage(query)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text.Trim().ToLower();
}
private async Task HandleTechnicalIssueAsync(string query)
{
var messages = new List
{
new SystemChatMessage("你是技术支持专家,负责解决技术问题。"),
new UserChatMessage(query)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task HandleBillingIssueAsync(string query)
{
var messages = new List
{
new SystemChatMessage("你是账单支持专家,负责处理账单相关问题。"),
new UserChatMessage(query)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task HandleGeneralQueryAsync(string query)
{
var messages = new List
{
new SystemChatMessage("你是客户服务代表,负责回答一般性问题。"),
new UserChatMessage(query)
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}
条件路由(概念性示例)
using OpenAI.Chat;
public class OrderProcessingWorkflow
{
private readonly ChatClient _chatClient;
public async Task ExecuteAsync(string orderId)
{
// 步骤1: 验证订单
var isValid = await ValidateOrderAsync(orderId);
if (isValid)
{
// 步骤2: 处理支付
await ProcessPaymentAsync(orderId);
// 步骤3: 发货
return await ShipOrderAsync(orderId);
}
else
{
// 通知客户
return await NotifyCustomerAsync(orderId, "订单验证失败");
}
}
private async Task ValidateOrderAsync(string orderId)
{
// 实现订单验证逻辑
await Task.Delay(100);
return orderId.StartsWith("ORD-");
}
private async Task ProcessPaymentAsync(string orderId)
{
// 实现支付处理逻辑
await Task.Delay(200);
}
private async Task ShipOrderAsync(string orderId)
{
// 实现发货逻辑
await Task.Delay(150);
return $"订单 {orderId} 已发货";
}
private async Task NotifyCustomerAsync(string orderId, string reason)
{
// 实现客户通知逻辑
await Task.Delay(100);
return $"订单 {orderId} 处理失败: {reason}";
}
}
并行处理(概念性示例)
using OpenAI.Chat;
public class DataAnalysisWorkflow
{
private readonly ChatClient _chatClient;
public async Task ExecuteAsync(string data)
{
// 步骤1: 加载数据
var loadedData = await LoadDataAsync(data);
// 步骤2: 并行执行三种分析
var statisticalTask = StatisticalAnalysisAsync(loadedData);
var sentimentTask = SentimentAnalysisAsync(loadedData);
var trendTask = TrendAnalysisAsync(loadedData);
await Task.WhenAll(statisticalTask, sentimentTask, trendTask);
// 步骤3: 汇总结果
return await AggregateResultsAsync(
statisticalTask.Result,
sentimentTask.Result,
trendTask.Result
);
}
private async Task LoadDataAsync(string data)
{
await Task.Delay(100);
return data;
}
private async Task StatisticalAnalysisAsync(string data)
{
var messages = new List
{
new SystemChatMessage("你是统计分析专家。"),
new UserChatMessage($"对以下数据进行统计分析:{data}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task SentimentAnalysisAsync(string data)
{
var messages = new List
{
new SystemChatMessage("你是情感分析专家。"),
new UserChatMessage($"对以下数据进行情感分析:{data}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task TrendAnalysisAsync(string data)
{
var messages = new List
{
new SystemChatMessage("你是趋势分析专家。"),
new UserChatMessage($"对以下数据进行趋势分析:{data}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task AggregateResultsAsync(
string statistical,
string sentiment,
string trend)
{
var messages = new List
{
new SystemChatMessage("你是数据分析总结专家。"),
new UserChatMessage($@"汇总以下分析结果:
统计分析:{statistical}
情感分析:{sentiment}
趋势分析:{trend}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}
多代理编排模式
- 顺序编排(Sequential)(概念性示例)
using OpenAI.Chat;
public class ResearchWorkflow
{
private readonly ChatClient _chatClient;
public async Task ExecuteAsync(string topic)
{
// 步骤1: 搜索信息
var searchResults = await SearchAsync(topic);
// 步骤2: 分析数据
var analysis = await AnalyzeAsync(searchResults);
// 步骤3: 生成摘要
var summary = await SummarizeAsync(analysis);
// 步骤4: 审查结果
return await ReviewAsync(summary);
}
private async Task SearchAsync(string topic)
{
var messages = new List
{
new SystemChatMessage("你是信息搜索专家。"),
new UserChatMessage($"搜索关于 '{topic}' 的相关信息")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task AnalyzeAsync(string data)
{
var messages = new List
{
new SystemChatMessage("你是数据分析专家。"),
new UserChatMessage($"分析以下数据:{data}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task SummarizeAsync(string analysis)
{
var messages = new List
{
new SystemChatMessage("你是内容摘要专家。"),
new UserChatMessage($"总结以下分析:{analysis}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task ReviewAsync(string summary)
{
var messages = new List
{
new SystemChatMessage("你是质量审查专家。"),
new UserChatMessage($"审查以下摘要:{summary}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}
- 并发编排(Concurrent)(概念性示例)
using OpenAI.Chat;
public class ContentCreationWorkflow
{
private readonly ChatClient _chatClient;
public async Task ExecuteAsync(string topic)
{
// 步骤1: 生成大纲
var outline = await CreateOutlineAsync(topic);
// 步骤2: 并行撰写各部分
var section1Task = WriteSectionAsync(outline, "section1");
var section2Task = WriteSectionAsync(outline, "section2");
var section3Task = WriteSectionAsync(outline, "section3");
await Task.WhenAll(section1Task, section2Task, section3Task);
// 步骤3: 编辑整合
return await EditAsync(section1Task.Result, section2Task.Result, section3Task.Result);
}
private async Task CreateOutlineAsync(string topic)
{
var messages = new List
{
new SystemChatMessage("你是内容大纲设计专家。"),
new UserChatMessage($"为主题 '{topic}' 创建详细大纲")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task WriteSectionAsync(string outline, string sectionName)
{
var messages = new List
{
new SystemChatMessage($"你是内容撰写专家,专注于撰写 {sectionName}。"),
new UserChatMessage($"根据以下大纲撰写 {sectionName}:\n{outline}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
private async Task EditAsync(string section1, string section2, string section3)
{
var messages = new List
{
new SystemChatMessage("你是内容编辑专家。"),
new UserChatMessage($@"整合并编辑以下内容:
部分1:{section1}
部分2:{section2}
部分3:{section3}")
};
var response = await _chatClient.CompleteChatAsync(messages);
return response.Value.Content[0].Text;
}
}