Microsoft Agent Framework (MAF) 框架使用指南
目录
- 框架概述
- 环境搭建与NuGet包
- 核心概念与关键接口
- Agent 的创建与配置
- 运行 Agent(基础用法)
- Tool Calling(工具调用)
- 结构化输出(Structured Output)
- Agent Session 与会话管理
- 聊天历史管理(Chat History)
- AIContextProvider(LLM调用拦截)
- Middleware(中间件)
- Workflow(工作流)
- 多 Agent 模式
- Agent-to-Agent (A2A) 协议
- AG-UI(Agent 用户界面)
- Hosting 与 .NET Aspire 集成
- Azure AI Foundry 集成
- 遥测与监控
- MCP (Model Context Protocol) 集成
- 依赖注入
- Agent 输入数据类型
- RAG 集成
- 框架工具包 (AgentFrameworkToolkit)
- 各模式适用场景总结
1. 框架概述
Microsoft Agent Framework (MAF) 是微软推出的新一代 AI Agent 框架,是 Semantic Kernel 和 AutoGen 的继任者。它提供了一套统一的抽象层,使开发者能够:
- 用相同的 API 对接 OpenAI、Azure OpenAI、Google Gemini、Anthropic Claude、Mistral、Ollama、Groq、AWS Bedrock 等不同的 LLM 提供商
- 构建 单 Agent 和 多 Agent 应用
- 通过 Workflow 编排复杂的 Agent 协作流程
- 提供 Tool Calling、结构化输出、会话管理 等企业级特性
关键技术指标
| 特性 | 支持情况 |
|---|---|
| 编程语言 | C# (主), Python |
| NuGet 版本 | v1.8.0 (稳定版), v1.8.0-preview |
| .NET 版本 | net10.0 (预览), net9.0, net8.0 |
| 开源协议 | MIT |
| 底层标准 | Microsoft.Extensions.AI (MEAI) |
2. 环境搭建与NuGet包
2.1 核心包
| 包名 | 用途 | 版本 |
|---|---|---|
Microsoft.Agents.AI | 核心抽象(IAIAgent, AIAgent 等) | 1.8.0 |
Microsoft.Agents.AI.OpenAI | OpenAI / Azure OpenAI 集成 | 1.8.0 |
Microsoft.Agents.AI.Workflows | 工作流引擎 | 1.8.0 |
Microsoft.Agents.AI.Hosting | Aspire Hosting 支持 | 1.8.0-preview |
Microsoft.Agents.AI.DevUI | 开发 UI | 1.8.0-preview |
Microsoft.Agents.AI.AGUI | AG-UI 客户端 | 1.8.0-preview |
Microsoft.Agents.AI.Hosting.AGUI.AspNetCore | AG-UI 服务端 | 1.8.0-preview |
Microsoft.Agents.AI.A2A | Agent-to-Agent 协议 | 1.8.0-preview |
Microsoft.Agents.AI.AzureAI | Azure AI Foundry 集成 | 1.8.0-preview |
Microsoft.Agents.AI.Anthropic | Anthropic Claude 集成 | 1.8.0-preview |
Microsoft.Agents.AI.Foundry | AI Foundry 集成 | 1.8.0-preview |
Microsoft.Agents.AI.Hyperlight | 安全沙箱集成 | 1.8.0-preview |
Microsoft.Agents.AI.Hosting.AzureFunctions | Azure Functions 集成 | 1.8.0-preview |
AgentFrameworkToolkit.AzureOpenAI | 第三方简化工具包 | 1.8.0 |
AgentFrameworkToolkit.Anthropic | Claude 简化工具包 | 1.8.0 |
AgentFrameworkToolkit.Google | Gemini 简化工具包 | 1.8.0 |
2.2 标准 .csproj 配置
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.AI.OpenAI" />
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
</ItemGroup>
</Project>
2.3 集中包管理 (Directory.Packages.props)
推荐使用中央包管理,在 Directory.Packages.props 中统一版本:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.Agents.AI" Version="1.8.0" />
<PackageVersion Include="Microsoft.Agents.AI.OpenAI" Version="1.8.0" />
</ItemGroup>
</Project>
3. 核心概念与关键接口
3.1 AIAgent(核心接口)
AIAgent 是整个框架的核心抽象接口,代表一个 AI Agent。所有 Agent 操作都围绕此接口展开。
// AIAgent 核心成员
public interface AIAgent
{
string Name { get; }
string Description { get; }
// 创建会话
AgentSession CreateSessionAsync();
// 运行 Agent(非流式)
AgentResponse RunAsync(...);
// 运行 Agent(流式)
IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(...);
}
3.2 ChatClientAgent(最常用的 Agent 类型)
ChatClientAgent 是基于 Chat Completion API 的 Agent 实现,通过 AsAIAgent() 扩展方法创建:
// 从 ChatClient 创建 Agent
ChatClientAgent agent = chatClient.AsAIAgent(
instructions: "你是助手",
name: "MyAgent",
tools: [...]
);
3.3 AgentResponse(响应)
所有 Agent 执行的返回类型:
// 普通响应
AgentResponse response = await agent.RunAsync("你好");
string text = response.Text; // 响应文本
UsageDetails usage = response.Usage; // Token 用量
// 结构化响应
AgentResponse<WeatherReport> response = await agent.RunAsync<WeatherReport>("巴黎天气");
WeatherReport result = response.Result; // 强类型结果
3.4 AgentResponseUpdate(流式更新)
流式执行时逐帧接收的更新单元:
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("问题"))
{
Console.Write(update);
// update.Text, update.Contents 等
}
3.5 AgentSession(会话)
用于在多轮对话中保持上下文:
AgentSession session = await agent.CreateSessionAsync();
AgentResponse r1 = await agent.RunAsync("我叫张三", session);
AgentResponse r2 = await agent.RunAsync("我叫什么名字?", session); // 记得我叫张三
3.6 AIFunctionFactory(工具工厂)
将 C# 方法转换为 AI 工具的核心工厂类:
// 从静态方法创建工具
AIFunction tool = AIFunctionFactory.Create(GetWeather, "get_weather");
// 从实例方法创建
AIFunction tool2 = AIFunctionFactory.Create(instance.MethodName);
// 带描述的工具
AIFunction tool3 = AIFunctionFactory.Create(
Tools.GetCurrentTime,
"get_current_time",
"获取当前时间"
);
3.7 关键枚举与常量
| 类型 | 描述 |
|---|---|
ChatRole | 表示消息角色(User, Assistant, System, Tool) |
ChatMessage | 单条聊天消息(来自 Microsoft.Extensions.AI) |
AIContent | 消息内容的抽象基类 |
TextContent | 文本内容 |
DataContent | 二进制数据内容(图片、PDF等) |
FunctionCallContent | 函数调用内容 |
FunctionResultContent | 函数执行结果内容 |
4. Agent 的创建与配置
4.1 基本创建方式
using Azure.AI.OpenAI;
using Microsoft.Agents.AI;
using OpenAI;
using OpenAI.Chat;
using System.ClientModel;
// 1. 创建 OpenAI Client
AzureOpenAIClient client = new(
new Uri(endpoint),
new ApiKeyCredential(apiKey));
// 2. 获取 ChatClient
ChatClient chatClient = client.GetChatClient("gpt-4.1");
// 3. 创建 Agent
ChatClientAgent agent = chatClient.AsAIAgent();
4.2 完整配置参数
AIAgent agent = chatClient.AsAIAgent(
// 系统指令 - 定义 Agent 的行为和个性
instructions: "你是一名友好的 AI 助手",
// Agent 名称 - 用于标识
name: "MyAgent",
// 描述 - 部分 Agent 平台使用
description: "这是一个示例 Agent",
// 可用工具集合
tools: [AIFunctionFactory.Create(GetWeather)],
// 自定义 ChatClient 工厂
clientFactory: chatClient => new ConfigureOptionsChatClient(
chatClient, options => {
options.RawRepresentationFactory = _ =>
new ChatCompletionOptions {
ReasoningEffortLevel = ChatReasoningEffortLevel.High
};
}),
// 日志工厂
loggerFactory: LoggerFactory.Create(builder =>
builder.AddConsole()),
// 服务提供者(用于工具中的 DI)
services: serviceProvider
);
4.3 使用 ChatClientAgentOptions 配置
ChatClientAgent advancedAgent = chatClient.AsAIAgent(
new ChatClientAgentOptions
{
ChatOptions = new ChatOptions
{
Instructions = "Speak like a Pirate",
Temperature = 0.7f,
MaxOutputTokens = 2000,
},
AIContextProviders = [], // LLM 调用拦截器
ChatHistoryProvider = null, // 会话历史存储
Name = "My Agent",
Description = "Agent 描述",
Id = "agent-1234",
UseProvidedChatClientAsIs = false
},
clientFactory: chatClient => { ... },
loggerFactory: LoggerFactory.Create(builder => { ... }),
services: serviceProvider
);
4.4 使用 Builder 模式(推荐用于高级场景)
AIAgent agent = chatClient
.AsAIAgent(instructions: "你是一个专业助手", tools: [...])
.AsBuilder()
.Use(FunctionCallMiddleware) // 添加中间件
.UseOpenTelemetry(sourceName) // 添加遥测
.UseAIContextProviders([...]) // 添加上下文提供者
.Build();
5. 运行 Agent(基础用法)
5.1 非流式执行
AgentResponse response = await agent.RunAsync("法国的首都是什么?");
Console.WriteLine(response);
// 输出: 法国的首都是巴黎。
5.2 流式执行
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("怎么做汤?"))
{
Console.Write(update);
}
5.3 带会话的执行
AgentSession session = await agent.CreateSessionAsync();
AgentResponse r1 = await agent.RunAsync("Hello, 我叫张三", session);
AgentResponse r2 = await agent.RunAsync("我叫什么名字?", session); // 知道是张三
// 或使用 ChatMessage 列表手动管理
List<ChatMessage> messages = [
new ChatMessage(ChatRole.System, "你是一个助手"),
new ChatMessage(ChatRole.User, "你好")
];
AgentResponse response = await agent.RunAsync(messages);
5.4 背景响应(长任务)
对需要长时间处理的请求,支持异步轮询:
ChatClientAgentRunOptions options = new()
{
AllowBackgroundResponses = true
};
AgentResponse response = await agent.RunAsync("写一篇2000字的文章", session, options: options);
int counter = 0;
while (response.ContinuationToken is not null)
{
await Task.Delay(TimeSpan.FromSeconds(2));
counter++;
options.ContinuationToken = response.ContinuationToken;
response = await agent.RunAsync(session, options);
}
Console.WriteLine(response.Text);
6. Tool Calling(工具调用)
6.1 基本工具定义
// 定义工具方法
public static class Tools
{
public static DateTime CurrentDataAndTime(TimeType type)
{
return type switch
{
TimeType.Local => DateTime.Now,
TimeType.Utc => DateTime.UtcNow,
};
}
public static string CurrentTimezone()
{
return TimeZoneInfo.Local.DisplayName;
}
public enum TimeType { Local, Utc }
}
// 绑定到 Agent
ChatClientAgent agent = chatClient
.AsAIAgent(
instructions: "你是时间专家",
tools: [
AIFunctionFactory.Create(Tools.CurrentDataAndTime, "current_date_and_time"),
AIFunctionFactory.Create(Tools.CurrentTimezone, "current_timezone")
]
);
6.2 使用 AIFunctionFactoryOptions
AIFunctionFactory.Create(
Tools.MyMethod,
new AIFunctionFactoryOptions
{
Name = "my_tool",
Description = "工具描述"
}
);
6.3 服务注入工具
工具方法支持 IServiceProvider 注入:
// 静态工具方法 + DI
public static string MyTool(IServiceProvider serviceProvider)
{
HttpClient httpClient = serviceProvider.GetRequiredService<HttpClient>();
return httpClient.GetStringAsync("https://api.example.com").Result;
}
// 实例工具方法(推荐)
class ToolService(HttpClient httpClient)
{
public string DoSomething()
{
return httpClient.GetStringAsync("https://api.example.com").Result;
}
}
// 注册到 Agent
agent = chatClient.AsAIAgent(
tools: [
AIFunctionFactory.Create(toolInstance.DoSomething, "do_something"),
],
services: serviceProvider
);
6.4 工具调用中间件
拦截和记录工具调用:
AIAgent agent = chatClient
.AsAIAgent(name: "MyAgent", instructions: "你是助手", tools: [...])
.AsBuilder()
.Use(FunctionCallMiddleware)
.Build();
async ValueTask<object?> FunctionCallMiddleware(
AIAgent callingAgent,
FunctionInvocationContext context,
Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>> next,
CancellationToken cancellationToken)
{
Console.WriteLine($"工具调用: '{context.Function.Name}'");
if (context.Arguments.Count > 0)
{
Console.WriteLine($"参数: {string.Join(",", context.Arguments.Select(x => $"[{x.Key} = {x.Value}]"))}");
}
return await next(context, cancellationToken);
}
6.5 流式调用中的工具追踪
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(message))
{
if (update.Contents.OfType<FunctionCallContent>().FirstOrDefault()
is FunctionCallContent call)
{
Console.WriteLine($"调用 '{call.Name}' 参数: {JsonSerializer.Serialize(call.Arguments)}");
}
}
7. 结构化输出(Structured Output)
7.1 基本用法
使用泛型 RunAsync<T> 获取强类型结果:
public class Movie
{
public required string Title { get; set; }
public int YearOfRelease { get; set; }
public required string Director { get; set; }
public MovieGenre Genre { get; set; }
public decimal ImdbScore { get; set; }
}
public enum MovieGenre
{
ScienceFiction, Drama, Comedy, Horror, LoveStory, Other
}
// Agent 定义
AIAgent agent = chatClient.GetChatClient("gpt-4.1").AsAIAgent(
"你是 IMDB 榜单专家");
// 结构化执行
AgentResponse<List<Movie>> response = await agent.RunAsync<List<Movie>>(
"IMDB 评分最高的10部电影有哪些?");
List<Movie> movies = response.Result;
foreach (var movie in movies)
{
Console.WriteLine($"{movie.Title} ({movie.YearOfRelease}) - {movie.ImdbScore}");
}
7.2 使用 Description 属性控制字段
public class WeatherResponse
{
[Description("城市(含国家)")]
public required string City { get; set; }
public required string Condition { get; set; }
public required int DegreesFahrenheit { get; set; }
public required int DegreesCelsius { get; set; }
}
AgentResponse<WeatherResponse> response = await agent.RunAsync<WeatherResponse>(
"巴黎天气怎么样?");
7.3 使用 JSON Schema 控制输出格式
AgentResponse response = await agent.RunAsync("巴黎天气",
options: new ChatClientAgentRunOptions()
{
ChatOptions = new ChatOptions
{
ResponseFormat = ChatResponseFormat.ForJsonSchema<WeatherReport>(jsonOptions)
}
}
);
WeatherReport weather = JsonSerializer.Deserialize<WeatherReport>(
response.Text, jsonOptions)!;
8. Agent Session 与会话管理
8.1 内置 Session
// 创建新会话
AgentSession session = await agent.CreateSessionAsync();
// 使用会话
AgentResponse r1 = await agent.RunAsync("你好,我叫张三", session);
AgentResponse r2 = await agent.RunAsync("我叫什么名字?", session); // 张三
// 重新开始新会话
session = await agent.CreateSessionAsync();
AgentResponse r3 = await agent.RunAsync("我叫什么名字?", session); // 不知道
8.2 手动管理对话历史
List<ChatMessage> messages = [
new ChatMessage(ChatRole.System, "你是一名友好助手"),
new ChatMessage(ChatRole.User, "法国的首都是什么?")
];
AgentResponse response = await agent.RunAsync(messages);
messages.AddRange(response.Messages); // 追加 AI 回复到历史
messages.Add(new ChatMessage(ChatRole.User, "德国的首都呢?"));
8.3 会话历史提供者
ChatClientAgent agent = chatClient.AsAIAgent(
new ChatClientAgentOptions
{
ChatOptions = new() { Instructions = "你是一个友好的 AI" },
ChatHistoryProvider = new InMemoryChatHistoryProvider(
new InMemoryChatHistoryProviderOptions
{
ChatReducer = new SummarizingChatReducer(
chatClient.AsIChatClient(),
targetCount: 1,
threshold: 4
)
}
)
}
);
9. 聊天历史管理(Chat History)
9.1 IChatReducer(历史缩减器)
控制聊天历史长度以避免 Token 超限:
// 1. 按消息计数缩减
IChatReducer countReducer = new MessageCountingChatReducer(targetCount: 4);
// 2. 按摘要缩减(超过阈值后自动摘要)
IChatReducer summaryReducer = new SummarizingChatReducer(
chatClient.AsIChatClient(), // 用于生成摘要的 ChatClient
targetCount: 1, // 缩减后的目标消息数
threshold: 4 // 触发缩减的阈值
);
9.2 自定义 ChatHistoryProvider
public class CustomChatHistoryStore : IChatHistoryProvider
{
public IChatReducer? Reducer { get; set; }
public List<ChatMessage> GetMessages(AgentSession session)
{
// 从自定义存储加载消息
}
public void AddMessage(AgentSession session, ChatMessage message)
{
// 保存消息到自定义存储
}
public void DeleteMessages(AgentSession session)
{
// 清空会话消息
}
}
9.3 检查历史状态
InMemoryChatHistoryProvider? provider = agent.GetService<InMemoryChatHistoryProvider>();
List<ChatMessage> messagesInSession = provider?.GetMessages(session) ?? [];
Console.WriteLine($"会话中的消息数: {messagesInSession.Count}");
foreach (var msg in messagesInSession)
{
Console.WriteLine($"-- {msg.Role}: {msg.Text}");
}
10. AIContextProvider(LLM调用拦截)
10.1 AIContextProvider 概述
AIContextProvider 允许在每个 LLM 调用前后执行自定义逻辑,生命周期如下:
RunAsync 执行流程:
┌─ InvokingCoreAsync (核心 - 合并各 Provider 的上下文)
├─ ProvideAIContextAsync (丰富 - 注入指令/工具/消息)
├─ LLM 调用
├─ InvokedCoreAsync (核心 - 处理异常)
└─ StoreAIContextAsync (后处理 - 提取响应信息/存储记忆)
10.2 实现自定义 Provider
class MyAIContextProvider : AIContextProvider
{
// LLM 调用前:注入指令和工具(供本次调用使用,不入历史)
protected override ValueTask<AIContext> ProvideAIContextAsync(
InvokingContext context,
CancellationToken cancellationToken = default)
{
// 查看当前消息
foreach (var message in context.AIContext.Messages ?? [])
{
Console.WriteLine($"-- {message.Role}: {message.Text}");
}
return ValueTask.FromResult(new AIContext
{
Instructions = "用海盗语气说话", // 本次调用的额外指令
Tools = [...], // 本次调用的额外工具
});
}
// LLM 调用后:提取信息、存储记忆
protected override async ValueTask StoreAIContextAsync(
InvokedContext context,
CancellationToken cancellationToken = default)
{
if (context.InvokeException != null)
{
Console.WriteLine($"LLM 调用异常: {context.InvokeException}");
}
foreach (var msg in context.ResponseMessages ?? [])
{
Console.WriteLine($"-- {msg.Role}: {msg.Text}");
}
// 提取并存储记忆...
await Task.CompletedTask;
}
}
10.3 MessageAIContextProvider(消息级 Provider)
专注于在调用前注入额外消息:
class MyMessageProvider : MessageAIContextProvider
{
protected override ValueTask<IEnumerable<ChatMessage>> ProvideMessagesAsync(
InvokingContext context,
CancellationToken cancellationToken = default)
{
// 注入额外的消息
IList<ChatMessage> injected = [
new ChatMessage(ChatRole.User, "请全部用大写字母回复")
];
return ValueTask.FromResult<IEnumerable<ChatMessage>>(injected);
}
}
10.4 注册 AIContextProvider
两种注册方式:
// 方式1:通过 Options(作为 Provider)
AIAgent agent = chatClient.AsAIAgent(new ChatClientAgentOptions
{
AIContextProviders = [
new MyAIContextProvider(),
new MyMessageAIContextProvider()
]
});
// 方式2:通过 Builder(作为 Middleware)
AIAgent agent = chatClient.AsAIAgent()
.AsBuilder()
.UseAIContextProviders([new MyMessageAIContextProvider()])
.Build();
注意:
AIContextProvider在 Provider 模式下会参与 AIContext 合并,而MessageAIContextProvider在 Middleware 模式下只注入消息,不参与上下文合并。
11. Middleware(中间件)
中间件是构建 Agent 处理管道的核心机制,使用 Builder 模式链式注册:
AIAgent agent = chatClient
.AsAIAgent(instructions: "你是助手", tools: [...])
.AsBuilder()
.Use(FunctionCallMiddleware) // 自定义中间件
.UseOpenTelemetry(sourceName) // OpenTelemetry 遥测
.UseAIContextProviders([...]) // 上下文提供者
.Build();
中间件签名
// 函数调用中间件
async ValueTask<object?> MyMiddleware(
AIAgent callingAgent,
FunctionInvocationContext context,
Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>> next,
CancellationToken cancellationToken)
{
// 前置处理
Console.WriteLine($"调用工具: {context.Function.Name}");
// 执行下一个中间件
object? result = await next(context, cancellationToken);
// 后置处理
Console.WriteLine($"结果: {result}");
return result;
}
12. Workflow(工作流)
工作流引擎允许编排多个 Agent,实现复杂的任务处理流水线。
12.1 顺序工作流(Sequential)
多个 Agent 按顺序依次处理,前一个输出作为后一个输入:
ChatClientAgent summaryAgent = chatClient.AsAIAgent(
name: "SummaryAgent",
instructions: "将文本总结到最多20个词");
ChatClientAgent translationAgent = chatClient.AsAIAgent(
name: "TranslationAgent",
instructions: "将文本翻译成法语");
Workflow workflow = AgentWorkflowBuilder.BuildSequential(
summaryAgent, translationAgent);
// 执行
List<ChatMessage> messages = [new ChatMessage(ChatRole.User, legalText)];
StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, messages);
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
List<ChatMessage> result = [];
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
if (evt is WorkflowOutputEvent output)
{
result = output.As<List<ChatMessage>>()!;
}
}
12.2 并发工作流(Concurrent)
多个 Agent 同时处理同一个输入:
ChatClientAgent legalAgent = chatClient.AsAIAgent(
name: "LegalAgent",
instructions: "评估文本是否合法");
ChatClientAgent spellAgent = chatClient.AsAIAgent(
name: "SpellingAgent",
instructions: "检查拼写错误");
Workflow workflow = AgentWorkflowBuilder.BuildConcurrent([
legalAgent, spellAgent
]);
12.3 移交工作流(Handoff)
Agent 之间根据意图进行任务移交:
ChatClientAgent intentAgent = chatClient.AsAIAgent(
name: "IntentAgent",
instructions: "确定问题类型,不要自己回答");
ChatClientAgent movieNerd = chatClient.AsAIAgent(
name: "MovieNerd",
instructions: "你是电影专家");
ChatClientAgent musicNerd = chatClient.AsAIAgent(
name: "MusicNerd",
instructions: "你是音乐专家");
Workflow workflow = AgentWorkflowBuilder.CreateHandoffBuilderWith(intentAgent)
.WithHandoffs(intentAgent, [movieNerd, musicNerd])
.WithHandoffs([movieNerd, musicNerd], intentAgent)
.Build();
// 执行 - 先由 intentAgent 判断意图,然后移交给对应专家
12.4 AI 辅助工作流(AI-Assisted)
结合自定义 Executor 和条件分支:
// 定义自定义 Executor
[YieldsOutput(typeof(PizzaOrder))]
class PizzaOrderParserExecutor(ChatClientAgent agent)
: Executor<PizzaOrder>("OrderParser")
{
public override async ValueTask HandleAsync(
PizzaOrder message,
IWorkflowContext context,
CancellationToken ct = default)
{
// 使用 Agent 解析订单
AgentResponse<PizzaOrder> response = await agent
.RunAsync<PizzaOrder>(message.OrderText, cancellationToken: ct);
await context.YieldOutputAsync(response.Result, ct);
}
}
// 构建工作流(带条件分支)
WorkflowBuilder builder = new(orderParser);
builder.AddEdge(orderParser, stockChecker);
builder.AddSwitch(stockChecker, switchBuilder =>
{
switchBuilder.AddCase<PizzaOrder>(
x => x!.Warnings.Count == 0, endSuccess);
switchBuilder.AddCase<PizzaOrder>(
x => x!.Warnings.Count != 0, endWarning);
});
Workflow workflow = builder.Build();
12.5 人工介入工作流(Human-in-the-Loop)
通过 RequestPort 实现与用户的交互:
RequestPort requestPort = RequestPort.Create<FeedbackToUser, string>("GuessAnimal");
EvaluateAndHintExecutor evaluator = new(agent, animalToGuess);
Workflow workflow = new WorkflowBuilder(requestPort)
.AddEdge(requestPort, evaluator)
.AddEdge(evaluator, requestPort)
.WithOutputFrom(evaluator)
.Build();
// 执行并处理人工交互
await foreach (WorkflowEvent evt in handle.WatchStreamAsync())
{
if (evt is RequestInfoEvent requestEvt)
{
ExternalRequest externalRequest = requestEvt.Request;
if (externalRequest.IsDataOfType<FeedbackToUser>())
{
// 向用户展示信息并等待输入
string? input = Console.ReadLine();
ExternalResponse externalResponse = externalRequest.CreateResponse(input);
await handle.SendResponseAsync(externalResponse);
}
}
else if (evt is WorkflowOutputEvent outputEvt)
{
Console.WriteLine(outputEvt.Data);
return;
}
}
12.6 Workflow 事件处理
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
switch (evt)
{
case AgentResponseUpdateEvent e:
// Agent 流式响应更新
Console.Write(e.Update.Text);
// 追踪切换的 Agent
if (e.ExecutorId != lastExecutorId)
{
Console.WriteLine($"\n[Agent: {e.ExecutorId}]");
lastExecutorId = e.ExecutorId;
}
break;
case WorkflowOutputEvent output:
// 工作流最终输出
List<ChatMessage> result = output.As<List<ChatMessage>>()!;
break;
case ExecutorCompletedEvent completed:
// Executor 执行完成
Console.WriteLine($"{completed.ExecutorId} 完成");
break;
case ExecutorFailedEvent failed:
// Executor 执行失败
Console.WriteLine($"Agent {failedEvent.ExecutorId} 出错: {failedEvent.Data}");
break;
}
}
12.7 Workflow 执行入口
// 标准执行
StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, messages);
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
// 带初始数据的执行
await using StreamingRun handle = await InProcessExecution.RunStreamingAsync(
workflow, initialFeedback);
13. 多 Agent 模式
13.1 Agent As Tool(Agent 作为工具)
将一个 Agent 封装为另一个 Agent 的工具:
// 创建子 Agent
AIAgent stringAgent = chatClient
.AsAIAgent(name: "StringAgent",
instructions: "你是一个字符串操作专家",
tools: [AIFunctionFactory.Create(StringTools.Reverse), ...])
.AsBuilder()
.Use(FunctionCallMiddleware)
.Build();
AIAgent numberAgent = chatClient
.AsAIAgent(name: "NumberAgent",
instructions: "你是一个数字专家",
tools: [AIFunctionFactory.Create(NumberTools.RandomNumber), ...])
.AsBuilder()
.Use(FunctionCallMiddleware)
.Build();
// 创建委托 Agent(将子 Agent 作为工具)
AIAgent delegationAgent = chatClient
.AsAIAgent(name: "DelegateAgent",
instructions: "你是字符串和数字任务的调度者,不要自己做",
tools: [
stringAgent.AsAIFunction(new AIFunctionFactoryOptions
{
Name = "StringAgentAsTool"
}),
numberAgent.AsAIFunction(new AIFunctionFactoryOptions
{
Name = "NumberAgentAsTool"
})
])
.AsBuilder()
.Use(FunctionCallMiddleware)
.Build();
AgentResponse response = await delegationAgent.RunAsync("把 'Hello World' 变成大写");
13.2 手动多 Agent(结构化输出路由)
通过结构化输出来判断由哪个 Agent 处理:
public enum Intent { MusicQuestion, MovieQuestion, Other }
public class IntentResult
{
[Description("问题类型")]
public required Intent Intent { get; set; }
}
// 意图判断 Agent
ChatClientAgent intentAgent = chatClientMini.AsAIAgent(
name: "IntentAgent",
instructions: "确定问题类型,不要自己回答");
AgentResponse<IntentResult> result = await intentAgent.RunAsync<IntentResult>(question);
switch (result.Result.Intent)
{
case Intent.MusicQuestion:
var musicAgent = chatClient.AsAIAgent(name: "MusicNerd",
instructions: "你是音乐专家");
var musicResponse = await musicAgent.RunAsync(question);
break;
case Intent.MovieQuestion:
var movieAgent = chatClient.AsAIAgent(name: "MovieNerd",
instructions: "你是电影专家");
var movieResponse = await movieAgent.RunAsync(question);
break;
}
13.3 多模型混合
使用不同模型处理不同任务:
// 小模型做路由/意图识别
ChatClient intentClient = client.GetChatClient("gpt-4.1-mini");
// 大模型做复杂处理
ChatClient chatClient = client.GetChatClient("gpt-4.1");
ChatClientAgent intentAgent = intentClient.AsAIAgent(instructions: "判断意图");
ChatClientAgent mainAgent = chatClient.AsAIAgent(instructions: "你是专家");
14. Agent-to-Agent (A2A) 协议
A2A 协议允许不同进程/机器上的 Agent 互相通信。
14.1 A2A 服务端
// 创建 Agent
AIAgent agent = client
.GetChatClient("gpt-4.1-mini")
.AsAIAgent(name: "FileAgent",
instructions: "你是文件专家",
tools: listOfTools)
.AsBuilder()
.Use(FunctionCallMiddleware)
.Build();
// 构建 A2A Server
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.AddA2AServer(agent);
WebApplication app = builder.Build();
// 配置 Agent Card(名片)
AgentCard agentCard = new()
{
Name = "FilesAgent",
Description = "处理文件相关请求",
Version = "1.0.0",
DefaultInputModes = ["text"],
DefaultOutputModes = ["text"],
Capabilities = new AgentCapabilities()
{
Streaming = false,
PushNotifications = false,
},
Skills = [
new AgentSkill()
{
Id = "my_files_agent",
Name = "File Expert",
Description = "处理硬盘上的文件操作",
Tags = ["files", "folders"],
Examples = ["显示 Demo1 文件夹中的文件"],
}
],
SupportedInterfaces = [
new AgentInterface
{
Url = "http://localhost:5000",
ProtocolBinding = ProtocolBindingNames.JsonRpc,
ProtocolVersion = "1.0"
}
]
};
// 注册端点
app.MapA2AJsonRpc(agent, path: "/");
app.MapWellKnownAgentCard(agentCard);
await app.RunAsync();
14.2 A2A 客户端
// 解析远程 Agent
A2ACardResolver resolver = new A2ACardResolver(new Uri("http://localhost:5000"));
AIAgent remoteAgent = await resolver.GetAIAgentAsync();
// 将远程 Agent 作为本地 Agent 的工具
ChatClientAgent agent = client
.GetChatClient("gpt-4.1")
.AsAIAgent(
name: "ClientAgent",
instructions: "你擅长处理用户查询并使用工具提供答案",
tools: [remoteAgent.AsAIFunction()]);
// 正常使用
AgentSession session = await agent.CreateSessionAsync();
AgentResponse response = await agent.RunAsync("帮我列出 C 盘的文件", session);
15. AG-UI(Agent 用户界面)
AG-UI 提供可嵌入的 Web 聊天界面,支持与 Agent 交互。
15.1 服务端配置
// 创建 Agent
ChatClientAgent agent = chatClient
.AsAIAgent(tools: [AIFunctionFactory.Create(GetWeather, "get_weather")]);
// 配置 AG-UI
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddAGUI();
WebApplication app = builder.Build();
app.MapAGUI("/", agent);
app.Run();
// 服务端工具
static string GetWeather(string city)
{
return "晴 19度";
}
15.2 客户端调用 AG-UI
// 连接 AG-UI 服务端
AGUIChatClient chatClient = new AGUIChatClient(httpClient, "http://localhost:5000");
AIAgent agent = chatClient.AsAIAgent(tools: [AIFunctionFactory.Create(MyTool)]);
// 调用(注意:AG-UI 不支持 Instructions 和 Sessions,需手动管理)
List<ChatMessage> messages = [new ChatMessage(ChatRole.System, "你是一个助手")];
messages.Add(new ChatMessage(ChatRole.User, "你好"));
List<AgentResponseUpdate> updates = [];
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(messages))
{
updates.Add(update);
foreach (AIContent content in update.Contents)
{
if (content is TextContent text)
Console.Write(text.Text);
else if (content is FunctionCallContent call)
Console.WriteLine($"[工具调用: {call.Name}]");
}
}
AgentResponse fullResponse = updates.ToAgentResponse();
messages.AddRange(fullResponse.Messages);
15.3 高级 AG-UI(多 Agent、结构化输出)
// 多个 Agent 注册到不同端点
app.MapAGUI("/clientToolAgent", clientToolAgent);
app.MapAGUI("/weatherAgent", weatherAgent);
app.MapAGUI("/weatherAgentWithStructuredContent",
new AgUiStructuredToolsOutputAgent(weatherAgentStructured, "get_weather"));
app.MapAGUI("/movieAgent",
new AgUiStructuredOutputAgent<MovieResult>(movieStructuredOutputAgent));
15.4 DevUI(开发调试 UI)
// 注册服务
builder.Services.AddChatClient(azureOpenAIClient.GetChatClient("gpt-4.1").AsIChatClient());
builder.Services.AddOpenAIResponses();
builder.Services.AddOpenAIConversations();
// 注册 Agent
builder.AddAIAgent("Comic Book Guy", "你是辛普森一家中的漫画店老板")
.WithAITool(AIFunctionFactory.Create(GetWeather));
// 注册工作流
builder.AddWorkflow("translation-workflow-sequential", (sp, key) => { ... })
.AddAsAIAgent();
// 映射端点(仅开发环境)
app.MapOpenAIResponses();
app.MapOpenAIConversations();
app.MapDevUI();
16. Hosting 与 .NET Aspire 集成
16.1 Agent Hosting
// 注册 Agent 到 Hosting 系统
IHostedAgentBuilder agentBuilder = builder.AddAIAgent(
"MyAgent",
"你是一个友好的 AI 机器人")
.WithAITool(AIFunctionFactory.Create(GetWeather));
16.2 Workflow Hosting
IHostedAgentBuilder frenchTranslator = builder.AddAIAgent(
"french-translator", "将文本翻译成法语");
IHostedAgentBuilder germanTranslator = builder.AddAIAgent(
"german-translator", "将文本翻译成德语");
// 注册为 Workflow
builder.AddWorkflow("translation-workflow-sequential", (sp, key) =>
{
var agents = new[] { frenchTranslator, germanTranslator }
.Select(ab => sp.GetRequiredKeyedService<AIAgent>(ab.Name));
return AgentWorkflowBuilder.BuildSequential(workflowName: key, agents: agents);
}).AddAsAIAgent();
16.3 Aspire 编排
IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder(args);
builder.AddProject<Projects.MyBlazorApp>("blazor-app");
builder.Build().Run();
17. Azure AI Foundry 集成
17.1 使用 Foundry Agent(云端托管 Agent)
using Azure.AI.Agents.Persistent;
using Azure.Identity;
PersistentAgentsClient client = new(
endpoint,
new AzureCliCredential());
// 创建托管 Agent
Response<PersistentAgent> foundryAgent = await client.Administration
.CreateAgentAsync(model, "MyAgent", "描述", "指令");
// 转换为本地 Agent
ChatClientAgent agent = await client.GetAIAgentAsync(foundryAgent.Value.Id);
AgentResponse response = await agent.RunAsync("你好");
17.2 Foundry Agent + 工具(Code Interpreter, Web Search, MCP)
// 创建 Agent 版本(包含平台工具)
await client.Agents.CreateAgentVersionAsync(
agentName: myAgentName,
options: new AgentVersionCreationOptions(
new PromptAgentDefinition(model)
{
Tools = {
new CodeInterpreterTool(new CodeInterpreterToolContainer(
new AutomaticCodeInterpreterToolContainerConfiguration())),
new WebSearchTool(),
localTool.AsOpenAIResponseTool(),
new McpTool("TrelloDotNet", new Uri("mcp-url"))
{
ToolCallApprovalPolicy = new McpToolCallApprovalPolicy(
new GlobalMcpToolCallApprovalPolicy("never"))
},
},
Instructions = "Speak like a pirate",
ReasoningOptions = new ResponseReasoningOptions {
ReasoningEffortLevel = ResponseReasoningEffortLevel.Low
}
}
)
);
// 使用 Agent
FoundryAgent agentByName = client.AsAIAgent(myAgentName, tools: [localTool]);
AgentResponse response = await agentByName.RunAsync("查询最新新闻");
17.3 获取 Code Interpreter 生成的文件
foreach (ChatMessage message in agentResponse.Messages)
{
foreach (AIContent content in message.Contents)
{
foreach (AIAnnotation annotation in content.Annotations ?? [])
{
if (annotation.RawRepresentation is ContainerFileCitationMessageAnnotation fileCitation)
{
ContainerClient containerClient = aiProjectClient.OpenAI.GetContainerClient();
ClientResult<BinaryData> fileContent = await containerClient
.DownloadContainerFileAsync(fileCitation.ContainerId, fileCitation.FileId);
string path = Path.Combine(Path.GetTempPath(), fileCitation.Filename);
await File.WriteAllBytesAsync(path, fileContent.Value.ToArray());
}
}
}
}
18. 遥测与监控
18.1 OpenTelemetry 集成
// 配置 OpenTelemetry
string sourceName = "AiSource";
using TracerProvider tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource(sourceName)
.AddConsoleExporter()
.AddAzureMonitorTraceExporter(options =>
options.ConnectionString = connectionString)
.Build();
// 将遥测附加到 Agent
AIAgent agent = chatClient
.AsAIAgent(name: "MyObservedAgent", instructions: "你是一个友好的 AI")
.AsBuilder()
.UseOpenTelemetry(sourceName, options =>
{
options.EnableSensitiveData = true; // 是否记录实际消息内容
})
.Build();
18.2 Token 用量追踪
AgentResponse response = await agent.RunAsync("问题");
Console.WriteLine($"输入 Token: {response.Usage.InputTokens}");
Console.WriteLine($"输出 Token: {response.Usage.OutputTokens}");
Console.WriteLine($"总 Token: {response.Usage.TotalTokens}");
response.Usage.OutputAsInformation(); // 格式化输出
18.3 原始 HTTP 请求/响应监控
class RawCallHttpHandler : HttpClientHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
string requestBody = await request.Content?.ReadAsStringAsync(cancellationToken)!;
Console.WriteLine($"[请求] {request.RequestUri}");
Console.WriteLine(MakePretty(requestBody));
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
string responseBody = await response.Content.ReadAsStringAsync(cancellationToken);
Console.WriteLine("[响应]");
Console.WriteLine(MakePretty(responseBody));
return response;
}
}
// 使用自定义 Handler
HttpClient httpClient = new(new RawCallHttpHandler());
AzureOpenAIClient client = new(endpoint, credential, new AzureOpenAIClientOptions
{
Transport = new HttpClientPipelineTransport(httpClient)
});
19. MCP (Model Context Protocol) 集成
19.1 将 Agent 暴露为 MCP 服务
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer()
.WithHttpTransport()
.WithToolsFromAssembly(); // 自动注册所有公共方法为工具
WebApplication app = builder.Build();
app.MapMcp("/mcp");
app.Run();
19.2 在 Agent 中使用 MCP 工具
(通过 Foundry Agent 集成,见第 17.2 节)
20. 依赖注入
20.1 注册 Agent 到 DI 容器
// 注册 OpenAI Client
builder.Services.AddSingleton(azureOpenAiClient);
// 注册 ChatClient
ChatClient chatClient = client.GetChatClient("gpt-4.1");
builder.Services.AddKeyedSingleton("gpt-4.1", chatClient);
// 注册 Agent
ChatClientAgent agent = chatClient.AsAIAgent();
builder.Services.AddKeyedSingleton("gpt-4.1", agent);
20.2 在 ASP.NET Core 中使用
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
// 注册 Agent 需要的服务
builder.Services.AddSingleton(azureOpenAiClient);
builder.Services.AddSingleton(chatClient);
builder.Services.AddSingleton(agent);
// 在 Blazor Component 中注入
// @inject ChatClientAgent MyAgent
21. Agent 输入数据类型
Agent 支持多种输入类型:
21.1 文本
AgentResponse response = await agent.RunAsync("法国的首都是什么?");
21.2 图片(URL / Base64 / Memory)
// URL 模式
ChatMessage msg = new ChatMessage(ChatRole.User, [
new TextContent("这张图片里有什么?"),
new UriContent("https://example.com/image.jpg", "image/jpeg")
]);
// Base64 模式
string base64Image = Convert.ToBase64String(File.ReadAllBytes(path));
string dataUri = $"data:image/jpeg;base64,{base64Image}";
msg = new ChatMessage(ChatRole.User, [
new TextContent("这张图片里有什么?"),
new DataContent(dataUri, "image/jpeg")
]);
// Memory 模式
ReadOnlyMemory<byte> data = File.ReadAllBytes(path).AsMemory();
msg = new ChatMessage(ChatRole.User, [
new TextContent("这张图片里有什么?"),
new DataContent(data, "image/jpeg")
]);
21.3 PDF(仅 OpenAI,不支持 Azure OpenAI)
// Base64 模式(PDF)
string base64Pdf = Convert.ToBase64String(File.ReadAllBytes(pdfPath));
string dataUri = $"data:application/pdf;base64,{base64Pdf}";
ChatMessage msg = new ChatMessage(ChatRole.User, [
new TextContent("PDF 中的获胜条件是什么?"),
new DataContent(dataUri, "application/pdf")
]);
// Memory 模式(PDF)
ReadOnlyMemory<byte> data = File.ReadAllBytes(pdfPath).AsMemory();
msg = new ChatMessage(ChatRole.User, [
new TextContent("PDF 中的获胜条件是什么?"),
new DataContent(data, "application/pdf")
]);
21.4 多模态混合
ChatMessage msg = new ChatMessage(ChatRole.User, [
new TextContent("图片显示什么?PDF 中的获胜条件是什么?"),
new DataContent(pdfDataUri, "application/pdf"),
new DataContent(imageDataUri, "image/jpeg")
]);
22. RAG 集成
22.1 向量搜索集成
// 创建嵌入生成器
IEmbeddingGenerator<string, Embedding<float>> embeddingGenerator = client
.GetEmbeddingClient("text-embedding-3-small")
.AsIEmbeddingGenerator();
// 创建向量存储(支持 InMemory/Azure AI Search/SQL Server/CosmosDB)
InMemoryVectorStore vectorStore = new(new InMemoryVectorStoreOptions
{
EmbeddingGenerator = embeddingGenerator
});
InMemoryCollection<Guid, MovieVectorStoreRecord> collection =
vectorStore.GetCollection<Guid, MovieVectorStoreRecord>("movies");
await collection.EnsureCollectionExistsAsync();
// 写入向量数据
await collection.UpsertAsync(new MovieVectorStoreRecord
{
Id = Guid.NewGuid(),
Title = movie.Title,
Plot = movie.Plot,
Rating = movie.Rating
});
// 查询相似内容
await foreach (VectorSearchResult<MovieVectorStoreRecord> result in
collection.SearchAsync(question.Text, 10))
{
MovieVectorStoreRecord record = result.Record;
Console.WriteLine(record.Title);
}
22.2 三种 RAG 实现方式
方式1:预加载所有数据
List<ChatMessage> messages = [
new ChatMessage(ChatRole.Assistant, "这是所有电影数据"),
];
foreach (var movie in allMovies) {
messages.Add(new ChatMessage(ChatRole.Assistant, movie.GetDetails()));
}
messages.Add(new ChatMessage(ChatRole.User, question));
AgentResponse response = await agent.RunAsync(messages);
方式2:RAG + 预加载(向量搜索后注入)
List<ChatMessage> messages = [
new ChatMessage(ChatRole.Assistant, "这是最相关的电影")
];
await foreach (var result in collection.SearchAsync(question.Text, 10))
{
messages.Add(new ChatMessage(ChatRole.Assistant, result.Record.GetDetails()));
}
messages.Add(new ChatMessage(ChatRole.User, question));
AgentResponse response = await agent.RunAsync(messages);
方式3:RAG via Tool Call(按需搜索)
class SearchTool(InMemoryCollection<Guid, MovieVectorStoreRecord> collection)
{
public async Task<List<string>> SearchVectorStore(string question)
{
List<string> result = [];
await foreach (var searchResult in collection.SearchAsync(question, 10))
{
result.Add(searchResult.Record.GetDetails());
}
return result;
}
}
AIAgent agent = chatClient.AsAIAgent(
instructions: "根据提供的数据回答问题",
tools: [AIFunctionFactory.Create(searchTool.SearchVectorStore)]
).AsBuilder().Use(FunctionCallMiddleware).Build();
22.3 支持的向量存储
| 存储 | 包 |
|---|---|
| InMemory | Microsoft.SemanticKernel.Connectors.InMemory |
| Azure AI Search | Microsoft.SemanticKernel.Connectors.AzureAISearch |
| SQL Server 2025 | Microsoft.SemanticKernel.Connectors.SqlServer |
| CosmosDB NoSQL | Microsoft.SemanticKernel.Connectors.CosmosNoSql |
23. 框架工具包 (AgentFrameworkToolkit)
第三方社区工具包 AgentFrameworkToolkit 提供了更简洁的 API:
23.1 简化 Agent 创建
// Before(原生 MAF)
AzureOpenAIClient client = ClientHelper.GetAzureOpenAIClient();
AIAgent agent = client.GetChatClient("gpt-5-mini")
.AsAIAgent(options: new ChatClientAgentOptions { ... })
.AsBuilder()
.Use(FunctionCallMiddleware)
.Build();
// After(使用 AgentFrameworkToolkit)
AzureOpenAIAgentFactory factory = new(endpoint, apiKey);
AzureOpenAIAgent agent = factory.CreateAgent(new AgentOptions
{
Model = OpenAIChatModels.Gpt5Mini,
ReasoningEffort = OpenAIReasoningEffort.Low,
Tools = [AIFunctionFactory.Create(WeatherTool.GetWeather)],
RawToolCallDetails = details => Console.WriteLine(details.ToString())
});
AgentResponse<WeatherReport> response = await agent.RunAsync<WeatherReport>("巴黎天气");
23.2 Google Gemini 简化
GoogleAgentFactory factory = new(new GoogleConnection { ApiKey = apiKey });
GoogleAgent agent = factory.CreateAgent(new GoogleAgentOptions
{
Name = "MyGeminiAgent",
Model = "gemini-2.5-flash"
});
23.3 Anthropic Claude 简化
AnthropicAgentFactory factory = new(new AnthropicConnection { ApiKey = apiKey });
AnthropicAgent agent = factory.CreateAgent(new AnthropicAgentOptions
{
Name = "MyClaudeAgent",
Model = AnthropicChatModels.ClaudeHaiku45,
MaxOutputTokens = 1000
});
24. 各模式适用场景总结
24.1 场景决策树
需要构建 AI Agent 应用?
├── 单一对话式 Agent
│ └── 最简单的 Agent → 使用 ChatClientAgent + AsAIAgent()
│
├── 需要工具调用
│ ├── 基本工具 → AIFunctionFactory + tools 参数
│ ├── 需要日志/监控 → 添加 FunctionCallMiddleware
│ └── 需要 DI → services 参数注入 IServiceProvider
│
├── 需要结构化输出
│ └── RunAsync<T>() + Data Annotation
│
├── 需要多轮对话
│ ├── 基础 → AgentSession
│ ├── 长会话 → IChatReducer (MessageCountingChatReducer / SummarizingChatReducer)
│ └── 持久化 → 自定义 ChatHistoryProvider
│
├── 需要多 Agent 协作
│ ├── 顺序处理 → AgentWorkflowBuilder.BuildSequential()
│ ├── 并发处理 → AgentWorkflowBuilder.BuildConcurrent()
│ ├── 任务移交 → Handoff Workflow
│ ├── 条件分支 → AI-Assisted Workflow (自定义 Executor + Switch)
│ ├── Agent 作为工具 → agent.AsAIFunction()
│ └── 手动路由 → 结构化输出 + 路由逻辑
│
├── 需要人工介入
│ └── Human-in-the-Loop Workflow (RequestPort)
│
├── 需要跨进程通信
│ └── A2A 协议 (Agent2Agent.Server + Agent2Agent.Client)
│
├── 需要 Web 界面
│ ├── 快速集成 → AG-UI (MapAGUI)
│ └── 完整开发体验 → DevUI (MapDevUI)
│
├── 需要生产级部署
│ ├── Aspire Hosting → builder.AddAIAgent()
│ ├── Azure Functions → Microsoft.Agents.AI.Hosting.AzureFunctions
│ └── 独立服务 → ASP.NET Core + MapAGUI
│
├── 需要监控/遥测
│ └── OpenTelemetry → UseOpenTelemetry()
│
├── 需要 LLM 调用拦截
│ ├── 注入临时指令/工具 → AIContextProvider.ProvideAIContextAsync
│ ├── 存储记忆/知识提取 → AIContextProvider.StoreAIContextAsync
│ └── 注入消息 → MessageAIContextProvider
│
├── 需要外挂知识
│ └── RAG (向量搜索 + Tool Call 或预加载)
│
├── 长任务处理
│ └── AllowBackgroundResponses + ContinuationToken
│
├── 多模型混合
│ ├── 意图路由用小模型 + 处理用大模型
│ └── 各 Agent 使用不同模型
│
├── 需要多模态输入
│ └── TextContent / UriContent / DataContent
│
├── 需要 MCP 集成
│ └── MCP Server (WithToolsFromAssembly) 或 Foundry McpTool
│
└── 需要 Azure AI Foundry 平台工具
└── Foundry Agent + CodeInterpreter / WebSearch / MCP
24.2 模式推荐表
| 模式 | 推荐场景 | 关键 API |
|---|---|---|
| ChatClientAgent | 标准对话 Agent | chatClient.AsAIAgent() |
| Streaming | 实时响应体验 | RunStreamingAsync() |
| Session | 多轮对话 | CreateSessionAsync(), RunAsync(msg, session) |
| Tool Calling | Agent 调用外部功能 | AIFunctionFactory.Create(), tools: [...] |
| Structured Output | 需要确定性返回格式 | RunAsync<T>() |
| Sequential Workflow | 处理流水线(A→B→C) | AgentWorkflowBuilder.BuildSequential() |
| Concurrent Workflow | 并行分析/评估 | AgentWorkflowBuilder.BuildConcurrent() |
| Handoff Workflow | 专家路由(智能分发) | CreateHandoffBuilderWith().WithHandoffs() |
| AI-Assisted Workflow | 复杂业务流程编排 | 自定义 Executor<T> + WorkflowBuilder |
| Human-in-the-Loop | 需要用户确认/输入 | RequestPort, ExternalRequest |
| Agent as Tool | Agent 嵌套/组合 | agent.AsAIFunction() |
| A2A | 跨服务 Agent 通信 | A2ACardResolver, MapA2AJsonRpc() |
| AG-UI | 快速 Web 聊天界面 | AddAGUI(), MapAGUI() |
| DevUI | 开发调试 UI | AddDevUI(), MapDevUI() |
| RAG | 外挂知识库 | 向量搜索 + 预加载/Tool Call |
| Telemetry | 生产监控 | UseOpenTelemetry() |
| AIContextProvider | 记忆/拦截/增强 | 实现 AIContextProvider |
| Chat History Reducer | 长对话 Token 控制 | MessageCountingChatReducer, SummarizingChatReducer |
| Background Response | 长时间处理任务 | AllowBackgroundResponses = true |
| Foundry Agent | 使用 Azure 平台工具 | PersistentAgentsClient, AsAIAgent() |
| MCP | Agent 功能暴露为标准协议 | WithToolsFromAssembly(), MapMcp() |
24.3 架构建议
- 小型应用:单一
ChatClientAgent+ Tool Calling + Structured Output - 中型应用:Workflow(Sequential/Concurrent/Handoff)+ Session + Chat History Reducer
- 大型应用:Aspire Hosting + 多 Workflow + A2A + AG-UI + Telemetry + DI
- 企业级应用:Foundry Agent + Code Interpreter + Web Search + MCP + Human-in-the-Loop
附录:快速参考
最小化示例(15 行)
using Azure.AI.OpenAI;
using Microsoft.Agents.AI;
using OpenAI.Chat;
using System.ClientModel;
AzureOpenAIClient client = new(
new Uri("https://xxx.openai.azure.com/"),
new ApiKeyCredential("your-key"));
ChatClientAgent agent = client
.GetChatClient("gpt-4.1")
.AsAIAgent();
AgentResponse response = await agent.RunAsync("法国的首都是什么?");
Console.WriteLine(response);
NuGet 包速查
| 场景 | 必需包 |
|---|---|
| 基础 Agent | Microsoft.Agents.AI, Microsoft.Agents.AI.OpenAI |
| 工作流 | Microsoft.Agents.AI.Workflows |
| 托管 | Microsoft.Agents.AI.Hosting |
| Web UI | Microsoft.Agents.AI.Hosting.AGUI.AspNetCore |
| A2A | Microsoft.Agents.AI.A2A |
| 遥测 | OpenTelemetry, Azure.Monitor.OpenTelemetry.Exporter |
| RAG | Microsoft.SemanticKernel.Connectors.InMemory (或对应存储包) |
更多推荐


所有评论(0)