关于 working-with-ms-agent-framework
这是一份使用 Microsoft Agent Framework 构建 Agent 的参考技能,涵盖状态管理、上下文提供程序、编排、持久化和开发界面,也介绍从 Semantic Kernel 或 AutoGen 迁移。
主要功能
- 01Agent 与线程架构
- 02基于策略的上下文与记忆
- 03五种编排模式
- 04线程序列化与工作流检查点
- 05DevUI 配置与追踪
- 06从 Semantic Kernel 和 AutoGen 迁移
适用场景
- 01设计多 Agent 工作流
- 02持久化并恢复 Agent 对话
- 03添加受策略控制的上下文
- 04将项目从 Semantic Kernel 或 AutoGen 迁移
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mhagrelius/ dotfiles --skill working-with-ms-agent-framework安装后在 Claude Code 中输入/working-with-ms-agent-framework确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
context-providers.mddesign-patterns.mdorchestration-patterns.md详细介绍
使用 Microsoft Agent Framework
Microsoft Agent Framework(2025 年 10 月)将 Semantic Kernel 和 AutoGen 整合到一个 SDK 中。这两个旧框架均处于维护模式。
核心原则: Agent 是无状态的。所有状态都存储在线程中。上下文提供程序会强制执行相关策略,决定哪些内容以何种方式、在何时进入提示词,以及何时衰减。
此技能中的其他参考文件:
context-providers.md- 基于策略的记忆、胶囊模式、Mem0 集成orchestration-patterns.md- 5 种编排模式及使用时机指南design-patterns.md- 生产模式、测试、迁移
适用场景
- 使用 Microsoft 的统一框架构建 AI Agent
- 使用上下文提供程序实现自定义记忆
- 创建支持检查点的多 Agent 工作流
- 从 Semantic Kernel 或 AutoGen 迁移
不适用场景
- 简单的单轮大模型调用(直接使用聊天客户端)
- 继续使用旧版 SK/AutoGen 的项目
- 非 Microsoft 框架(LangChain、CrewAI)
技术栈层级
官方指南(PM Jeremy Licknes): 从 ME AI 开始,仅在需要时升级。
| 层级 | 用途 | 何时升级 |
|---|---|---|
| ME AI(Microsoft.Extensions.AI) | 聊天客户端、结构化输出、嵌入、中间件 | 需要 Agent、工作流、记忆时 |
| Agent Framework | Agent、线程、编排、上下文提供程序 | 需要特定的 SK 适配器时 |
| Semantic Kernel | ME AI 中没有的特定适配器、实用工具 | 永远不要从这里开始 |
ME AI (foundation) → Agent Framework (agents/workflows) → SK (specific utilities only)
关键见解: ME AI 提供可用于 OpenAI、Ollama、Foundry Local 等平台的通用 API。Agent Framework 基于 ME AI 构建,提供 Agent 模式。SK 基础功能已迁移到 ME AI;仅在需要 ME AI 尚未提供的特定适配器时使用 SK。
ME AI 自动提供的功能:
- 结构化输出(通过扩展方法提供类型化响应)
- 中间件(OpenTelemetry、聊天内容缩减)
- 通用聊天客户端抽象
- 嵌入生成
架构速览
| 概念 | C# 类型 | 用途 |
|---|---|---|
| Agent | AIAgent | 无状态的大模型封装器 |
| 线程 | AgentThread | 有状态的对话容器 |
| 上下文提供程序 | AIContextBehavior | 基于策略的记忆/上下文注入 |
| 编排 | SequentialOrchestration 等 | 多 Agent 协调 |
安装
dotnet add package Microsoft.Agents.AI.OpenAI --prerelease
dotnet add package Azure.AI.OpenAI --version 2.1.0
创建 Agent
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
// Azure OpenAI
AIAgent agent = new AzureOpenAIClient(
new Uri("https://<resource>.openai.azure.com"),
new AzureCliCredential())
.GetChatClient("gpt-4o-mini")
.CreateAIAgent(
instructions: "You are a helpful assistant.",
name: "Assistant");
// Direct OpenAI
var agent = new OpenAIClient("api-key")
.GetChatClient("gpt-4o-mini")
.AsIChatClient()
.CreateAIAgent(instructions: "...", name: "Assistant");
// With tools
[Description("Gets weather for a location")]
static string GetWeather(string location) => $"Sunny in {location}";
AIAgent agent = chatClient.CreateAIAgent(
instructions: "You help with weather queries.",
tools: [AIFunctionFactory.Create(GetWeather)]
);
执行
// Simple
Console.WriteLine(await agent.RunAsync("Hello!"));
// With thread for multi-turn
AgentThread thread = agent.GetNewThread();
await agent.RunAsync("My name is Alice.", thread);
await agent.RunAsync("What's my name?", thread); // Remembers "Alice"
// Streaming
await foreach (var update in agent.RunStreamingAsync("Tell me a story.", thread))
{
Console.Write(update.Text);
}
具备弹性的流式处理
对于生产环境中的流式处理,请添加取消支持和弹性机制:
// Basic streaming with cancellation
await foreach (var update in agent.RunStreamingAsync("Tell me a story.", thread)
.WithCancellation(cancellationToken))
{
Console.Write(update.Text);
}
// With Polly resilience pipeline
var pipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions { MaxRetryAttempts = 3 })
.AddTimeout(TimeSpan.FromMinutes(2))
.Build();
await pipeline.ExecuteAsync(async token =>
{
await foreach (var chunk in agent.RunStreamingAsync(userMessage, thread)
.WithCancellation(token))
{
Console.Write(chunk.Text);
}
}, cancellationToken);
错误区分:
OperationCanceledException:用户取消TimeoutRejectedException:Polly 超时HttpRequestException:网络问题
开发界面(DevUI)
用于测试 Agent 和工作流的轻量级 Web 界面。仅用于开发,不适用于生产环境。
Python 设置
安装:
pip install agent-framework-devui --pre
选项 1:以编程方式注册
from agent_framework import ChatAgent
from agent_framework.openai import OpenAIChatClient
from agent_framework.devui import serve
agent = ChatAgent(
name="WeatherAgent",
chat_client=OpenAIChatClient(),
tools=[get_weather]
)
# Launch DevUI with tracing
serve(entities=[agent], auto_open=True, tracing_enabled=True)
# Opens browser to http://localhost:8080
选项 2:目录发现(CLI)
devui ./entities --port 8080 --tracing
用于发现的目录结构:
entities/
weather_agent/
__init__.py # Must export: agent = ChatAgent(...)
.env # Optional: API keys
my_workflow/
__init__.py # Must export: workflow = WorkflowBuilder()...
C# 设置
C# 将 DevUI 作为 SDK 组件嵌入(文档正在编写中):
var app = builder.Build();
app.MapOpenAIResponses();
app.MapConversation();
if (app.Environment.IsDevelopment())
{
app.MapAgentUI(); // Accessible at /ui
}
功能
| 功能 | 描述 |
|---|---|
| Web 界面 | 交互式测试 Agent/工作流 |
| 兼容 OpenAI 的 API | 使用 OpenAI SDK 调用本地 Agent |
| 追踪 | 在调试面板中查看 OpenTelemetry spans |
| 文件上传 | 多模态输入(图像、文档) |
| 自动生成输入 | 根据第一个执行器类型生成工作流输入 |
在 DevUI 中追踪
使用 --tracing 标志或 tracing_enabled=True 启用。在调试面板中查看:
Agent Execution
├── LLM Call (prompt → response)
├── Tool Call
│ ├── Tool Execution
│ └── Tool Result
└── LLM Call (prompt → response)
导出到外部工具(Jaeger、Azure Monitor):
export OTLP_ENDPOINT="http://localhost:4317"
devui ./entities --tracing
OpenAI SDK 集成
通过 OpenAI Python SDK 与 DevUI Agent 交互:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8080/v1", api_key="not-needed")
response = client.responses.create(
metadata={"entity_id": "weather_agent"},
input="What's the weather in Seattle?"
)
CLI 选项
devui [directory] [options]
--port, -p Port (default: 8080)
--tracing Enable OpenTelemetry tracing
--reload Auto-reload on file changes
--headless API only, no UI
--mode developer|user (default: developer)
线程序列化(关键模式)
// Serialize for persistence
JsonElement serialized = await thread.SerializeAsync();
await File.WriteAllTextAsync("thread.json", serialized.GetRawText());
// Later: restore and resume
string json = await File.ReadAllTextAsync("thread.json");
JsonElement element = JsonSerializer.Deserialize<JsonElement>(json);
AgentThread restored = agent.DeserializeThread(element, JsonSerializerOptions.Web);
await agent.RunAsync("Continue...", restored);
关键行为:
- 服务管理的线程:仅序列化线程 ID
- 内存中的线程:序列化所有消息
- 警告:使用不同的 Agent 配置进行反序列化可能会出错
上下文提供程序(基于策略的记忆)
上下文提供程序不是“记忆注入”,而是策略执行:
| 策略 | 决定内容 |
|---|---|
| 选择 | 什么内容成为记忆 |
| 门控 | 何时检索记忆 |
| 衰减 | 何时过期 |
| 避免噪声 | 何时不使用 |
ChatHistoryAgentThread thread = new();
// Long-term user memory
thread.AIContextProviders.Add(new Mem0Provider(httpClient, new() { UserId = "user123" }));
// Short-term conversation context
thread.AIContextProviders.Add(new WhiteboardProvider(chatClient));
// RAG integration
thread.AIContextProviders.Add(new TextSearchProvider(textSearch, new()
{
SearchTime = TextSearchProviderOptions.RagBehavior.OnDemandFunctionCalling
}));
自定义实现模式请参阅 context-providers.md。
编排模式
| 模式 | 适用场景 |
|---|---|
| 顺序 | 依赖关系明确(起草 → 审阅 → 润色) |
| 并发 | 独立视角、集成推理 |
| 交接 | 事先无法确定最佳 Agent,需要动态调度专业能力 |
| GroupChat | 协作构思、人在回路 |
| Magentic | 复杂的开放式问题 |
// Sequential
SequentialOrchestration orchestration = new(analystAgent, writerAgent);
// Handoff - CRITICAL: Always set termination conditions!
var workflow = AgentWorkflowBuilder.StartHandoffWith(triageAgent)
.WithHandoffs(triageAgent, [mathTutor, historyTutor])
.WithHandoff(mathTutor, triageAgent) // Allows routing back
.WithHandoff(historyTutor, triageAgent)
.WithMaxHandoffs(10) // REQUIRED: Prevent infinite loops
.Build();
// Execute
InProcessRuntime runtime = new();
await runtime.StartAsync();
var result = await orchestration.InvokeAsync(task, runtime);
交接的关键注意事项:缺少 .WithMaxHandoffs() 会导致无限循环。务必设置终止条件。
详细模式和适用场景指南请参阅 orchestration-patterns.md。
工作流检查点与持久性
对于必须在进程重启后继续运行的工作流:
// Basic checkpointing with CheckpointManager
var checkpointManager = CheckpointManager.Default;
await using Checkpointed<StreamingRun> checkpointedRun =
await InProcessExecution.StreamAsync(workflow, input, checkpointManager);
// Resume from checkpoint
await InProcessExecution.ResumeStreamAsync(savedCheckpoint, checkpointManager);
基于线程的持久化模式
对于长时间运行的工作流,在每个步骤后检查点保存线程状态:
// Save thread state after each workflow step
var serialized = await thread.SerializeAsync();
await checkpointStore.SaveAsync(workflowId, currentStep, serialized.GetRawText());
// Resume after restart
var json = await checkpointStore.GetAsync(workflowId);
var element = JsonSerializer.Deserialize<JsonElement>(json);
var restored = agent.DeserializeThread(element, JsonSerializerOptions.Web);
await agent.RunAsync(nextStep, restored);
启动时恢复
public class WorkflowRecoveryService : BackgroundService
{
private readonly ICheckpointStore _store;
private readonly AIAgent _agent;
protected override async Task ExecuteAsync(CancellationToken ct)
{
var pending = await _store.GetPendingWorkflowsAsync();
foreach (var workflow in pending)
{
var thread = _agent.DeserializeThread(workflow.State, JsonSerializerOptions.Web);
await _agent.RunAsync(workflow.NextStep, thread, cancellationToken: ct);
}
}
}
关键原则:每个步骤完成后再创建检查点,而不是之前。这样可确保从最后一个成功完成的步骤继续执行。
迁移速查
从 Semantic Kernel 迁移
| SK | Agent Framework |
|---|---|
Kernel | AIAgent |
ChatHistory | AgentThread |
方法上的 [KernelFunction] | [Description] |
IPromptFilter | AIContextBehavior |
KernelFunctionFactory.CreateFromMethod | AIFunctionFactory.Create |
从 AutoGen 迁移
| AutoGen | Agent Framework |
|---|---|
AssistantAgent | 通过 CreateAIAgent() 创建 AIAgent |
FunctionTool | AIFunctionFactory.Create() |
| GroupChat/Teams | WorkflowBuilder 模式 |
TopicSubscription | AgentWorkflowBuilder.WithHandoffs() |
BaseAgent, IHandle<> | 配备工具的 AIAgent |
从基于主题的模式迁移到交接模式:
// ❌ OLD AutoGen pattern (deprecated)
[TopicSubscription("queries")]
public class MyAgent : BaseAgent, IHandle<Query>
{
public async Task Handle(Query msg, CancellationToken ct)
{
// Process and publish to another topic
await PublishMessageAsync(new Response(...), "responses");
}
}
// ✅ NEW Agent Framework pattern
var triageAgent = chatClient.CreateAIAgent(
instructions: "Route queries to appropriate specialist.",
name: "Triage");
var mathAgent = chatClient.CreateAIAgent(
instructions: "Handle math queries.",
name: "Math");
var workflow = AgentWorkflowBuilder.StartHandoffWith(triageAgent)
.WithHandoffs(triageAgent, [mathAgent, otherAgent])
.WithMaxHandoffs(10) // REQUIRED
.Build();
await workflow.InvokeStreamingAsync(input, runtime);
反模式
| 不要这样做 | 应这样做 |
|---|---|
| 在 Agent 实例中存储状态 | 所有状态都使用 AgentThread 存储 |
| 仅序列化消息 | 序列化整个线程 |
| 在工作流中共享 Agent 实例 | 使用工厂模式 |
| 在服务之间混用线程类型 | 线程特定于各自的服务 |
| 顺序模式足以满足需求时仍使用 Magentic | 使用能解决问题的最简单模式 |
使用 ContextualFunctionProvider 时跳过 UseImmutableKernel | 始终设置 UseImmutableKernel = true |
| 新项目从 Semantic Kernel 入手 | 从 ME AI 入手,必要时再升级到 Agent Framework |
警示信号——停止
- 使用
Kernel而非AIAgent(旧版 SK) - 使用
AssistantAgent而非AIAgent(旧版 AutoGen) - 线程反序列化失败(上下文提供程序缺少序列化构造函数)
- 会话之间记忆丢失(序列化了消息而非线程)
- 交接陷入无限循环(需要设置终止条件)
已知限制
- 分布式运行时:仅支持进程内执行;计划支持分布式执行
- C# Magentic:大多数示例使用 Python
- C# 消息存储:Redis/数据库需要自定义实现
- Token 计数:提供程序中的预算计算没有文档说明
- DevUI C# 文档:Python 文档完整;C# DevUI 文档“即将推出”(嵌入式 SDK 的实现方式有所不同)
- GA 时间线:Agent Framework 稳定版“即将推出”(截至 2025 年 1 月)
资源
- GitHub:
github.com/microsoft/agent-framework - 文档:
learn.microsoft.com/en-us/agent-framework/ - 迁移指南:
learn.microsoft.com/en-us/agent-framework/migration-guide/