目录一句话简介 核心价值 问题场景 解决方案三步实现记忆对话核心机制实现代码 流式多轮对话 多用户场景线程隔离实现代码 访问对话历史 API 速查表核心 API调用模式对比 企业级最佳实践✅ 推荐做法❌ 常见错误 总结上一篇一句话简介AgentThread 是 Microsoft Agent Framework 提供的对话线程管理机制通过显式创建并复用线程对象让 AI Agent 在多轮对话中拥有完整的上下文记忆能力。 核心价值✅多轮记忆Agent 自动记住所有对话历史✅线程隔离多用户场景下对话互不干扰✅简单易用三行代码实现带记忆的对话✅流式支持同时支持同步和流式多轮对话 问题场景很多开发者在使用 Agent 时会遇到失忆问题// ❌ 问题演示 await agent.RunAsync(我叫张三); await agent.RunAsync(你知道我叫什么吗?); // Agent: 抱歉,我不知道您的名字原因每次调用RunAsync()不传thread参数时MAF 会临时创建新线程并在调用结束后丢弃导致历史消息丢失。 解决方案三步实现记忆对话核心机制实现代码// 步骤1: 创建 Agent var chatClient AIClientHelper.GetDefaultChatClient(); AIAgent agent chatClient.CreateAIAgent( instructions: 你是专业助理记住用户所有信息并提供个性化服务, name: PersonalAssistant ); // 步骤2: 创建 Thread关键 AgentThread thread agent.GetNewThread(); // 步骤3: 多轮对话复用同一个 thread await agent.RunAsync(我叫李明是软件工程师喜欢咖啡, thread); await agent.RunAsync(你记得我叫什么吗?, thread); // ✅ 能准确回答 await agent.RunAsync(我喜欢什么饮料?, thread); // ✅ 能准确回答核心要点 使用GetNewThread()创建线程 所有调用都传入同一个thread对象 Thread 自动管理所有历史消息 流式多轮对话AgentThread 同样支持流式调用适合长文本生成场景。// 创建故事创作 Agent AIAgent storyWriter chatClient.CreateAIAgent( instructions: 你是创意写作助手记住所有故事元素保持一致性, name: StoryWriter ); // 创建线程 AgentThread storyThread storyWriter.GetNewThread(); // 第一轮设定背景 awaitforeach (var chunk in storyWriter.RunStreamingAsync( 科幻故事2150年火星殖民地主角阿尔法是工程师, storyThread)) { Console.Write(chunk); } // 第二轮引入冲突Agent 记得前面设定 awaitforeach (var chunk in storyWriter.RunStreamingAsync( 生命支持系统故障阿尔法需24小时内修复, storyThread)) { Console.Write(chunk); } // 第三轮添加转折Agent 记得所有情节 awaitforeach (var chunk in storyWriter.RunStreamingAsync( 阿尔法发现故障是人为破坏, storyThread)) { Console.Write(chunk); } 多用户场景线程隔离AgentThread 的重要特性是线程隔离每个用户应有独立线程。实现代码// 创建客服 Agent AIAgent customerService chatClient.CreateAIAgent( instructions: 电商客服记住每位客户信息提供个性化服务, name: CustomerService ); // 为两个用户创建独立线程 AgentThread threadZhangSan customerService.GetNewThread(); AgentThread threadLiSi customerService.GetNewThread(); // 张三的对话 await customerService.RunAsync(我叫张三想买笔记本电脑预算8000元, threadZhangSan); await customerService.RunAsync(主要用来做软件开发, threadZhangSan); // 李四的对话完全隔离 await customerService.RunAsync(我是李四想买游戏鼠标, threadLiSi); await customerService.RunAsync(价格300元以内, threadLiSi); // 验证隔离两个用户各自记得自己的信息 await customerService.RunAsync(你记得我的预算和用途吗?, threadZhangSan); await customerService.RunAsync(我刚才想买什么?, threadLiSi); 访问对话历史Thread 内部维护历史消息列表可用于统计、调试、导出等场景。// 获取历史消息 IListChatMessage? chatHistory thread.GetServiceIListChatMessage(); if (chatHistory ! null) { Console.WriteLine($总消息数: {chatHistory.Count}); // 统计不同角色的消息 var userMessages chatHistory.Where(m m.Role ChatRole.User).Count(); var assistantMessages chatHistory.Where(m m.Role ChatRole.Assistant).Count(); // 遍历显示 foreach (var message in chatHistory) { Console.WriteLine($[{message.Role}]: {message.Text}); } }使用场景 统计对话轮数 调试和日志记录 导出对话历史⚠️ 监控 Token 使用量注意事项⚠️ 历史消息只读访问不建议直接修改⚠️ 长对话需注意 Token 限制可用 ChatReducer 自动裁剪⚠️ 多用户场景务必线程隔离 API 速查表核心 APIAPI功能场景agent.GetNewThread()创建新线程用户会话开始RunAsync(msg, thread)同步多轮对话记忆上下文RunStreamingAsync(msg, thread)流式多轮对话长文本生成thread.ThreadId获取线程ID日志、调试thread.GetServiceIListChatMessage()获取历史消息统计、导出调用模式对比调用方式Thread 参数是否记忆使用场景RunAsync(消息)❌ 不传❌ 不记忆单次查询RunAsync(消息, thread)✅ 传入✅ 记忆多轮对话RunStreamingAsync(消息)❌ 不传❌ 不记忆单次流式RunStreamingAsync(消息, thread)✅ 传入✅ 记忆多轮流式 企业级最佳实践✅ 推荐做法1. 为每个用户会话创建独立 Thread// 用户登录时 var userThread agent.GetNewThread(); _userThreads[userId] userThread;2. 整个对话过程复用同一个 Threadvar thread _userThreads[userId]; await agent.RunAsync(message, thread);3. 添加元数据便于管理thread.Metadata[UserId] userId; thread.Metadata[SessionStartTime] DateTime.UtcNow;❌ 常见错误1. 忘记传入 Thread 参数// ❌ 错误每次都创建新线程 await agent.RunAsync(第一句话); await agent.RunAsync(第二句话); // 忘记了第一句话2. 每次调用都创建新 Thread// ❌ 错误不复用线程 var thread1 agent.GetNewThread(); await agent.RunAsync(第一句话, thread1); var thread2 agent.GetNewThread(); // ❌ 不应该创建新的 await agent.RunAsync(第二句话, thread2);3. 多用户共用一个 Thread// ❌ 错误会导致对话混乱 var sharedThread agent.GetNewThread(); await agent.RunAsync(用户A的消息, sharedThread); await agent.RunAsync(用户B的消息, sharedThread); // B能看到A的历史 总结✅AgentThread 核心作用管理对话历史实现多轮对话记忆✅使用方法创建 Thread → 复用 Thread → 自动记忆✅线程隔离每个用户独立 Thread多用户场景安全✅流式支持同步和流式调用都支持 Thread✅历史访问可获取历史消息用于统计、调试、导出核心原则一个用户会话 一个 Thread始终复用下一篇引入地址