# 第6篇-Agent-Framework实现Agent会话持久化

在开发 AI Agent（智能体）应用时，我们经常遇到一个痛点：**如何让 AI 记住之前的对话？**

如果每次运行程序，AI 都像初次见面一样问候“你好”，那体验就太差了。在实际业务中，用户可能今天聊了一半， 明天想接着聊。这就涉及到 **Agent 状态的持久化（Persistence）**。

今天，我们使用微软的 `microsoft/agent-framework`，来看看如何在 .NET 环境下，轻松实现对话状态的“存档”和“读档”。

### 🎬 场景设定

想象一下，你创建了一个擅长讲笑话的 AI 助手，代号“Joker”。

1. 你让它讲个海盗笑话。
2. **（模拟程序关闭/崩溃/暂停）** 保存当前对话进度。
3. **（模拟程序重启）** 读取进度，让它用海盗的语气复述刚才的笑话。

如果它能接得上，说明我们的"记忆植入"成功了！

### 🛠️ 代码实战

我们直接看核心代码。

#### 1. 初始化 Agent

首先，我们需要创建一个Agent。这里使用了 `AzureOpenAI` 作为后端模型（GPT-4o-mini），并配置了 `AzureCliCredential` 进行安全认证。

```csharp
// 引入必要的命名空间
using System.Text.Json;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using OpenAI;

// 配置环境变量（Endpoint 和 部署名）
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";

// 创建一个“爱讲笑话”的 Agent
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
    .GetChatClient(deploymentName)
    .CreateAIAgent(instructions: "你是一位江湖说书人，擅长用幽默、接地气的方式讲笑话和故事。", name: "Joker");
```

💡 这里给 Agent 的指令（Instructions）很简单：你是一位江湖说书人，擅长用幽默、接地气的方式讲笑话和故事。

#### 2. 开启对话并存档

接下来，我们要开启一段新的对话线程（Thread），并让 AI 讲第一个笑话。

```csharp
// 开启一个新的对话线程
AgentThread thread = agent.GetNewThread();
// 运行 Agent，要求讲一个海盗笑话
Console.WriteLine(await agent.RunAsync("给我讲一个发生在茶馆里的段子，轻松一点的那种。", thread));
// 重点来了！序列化线程状态
JsonElement serializedThread = thread.Serialize();
// 将状态保存到本地文件（模拟存入数据库或缓存）
string tempFilePath = Path.GetTempFileName();
await File.WriteAllTextAsync(tempFilePath, JsonSerializer.Serialize(serializedThread));
Console.WriteLine($"\n[系统提示]：对话状态已保存至 {tempFilePath}，程序模拟退出...");
```

核心解析： thread.Serialize() 是关键。它将当前对话上下文（包括用户的提问、AI 的回答、Token 使用情况等）打包成了一个 JSON 对象。你可以把这个 JSON 存到 SQL Server、Redis 或者像本例一样存到本地文件里。

#### 3. 读档与“记忆唤醒”

现在，假设过了一段时间，用户回来了。我们需要从文件里读取刚才的 JSON，并“复活”这个线程。

```csharp
// 从文件中读取 JSON 数据
JsonElement reloadedSerializedThread = JsonElement.Parse(await File.ReadAllTextAsync(tempFilePath));
// 反序列化，恢复线程对象
AgentThread resumedThread = agent.DeserializeThread(reloadedSerializedThread);
// 继续对话！要求 AI 基于刚才的上下文做进一步处理
Console.WriteLine(await agent.RunAsync("现在把这个段子加上一些表情符号，并用说书人的语气再讲一遍。",    resumedThread));
```

核心解析： agent.DeserializeThread(...) 方法接收之前保存的 JSON，重新构建出 AgentThread 对象。注意看最后一次 RunAsync 的参数，我们传入的是 resumedThread（恢复后的线程）。

### 运行效果

当你运行这段代码时，控制台可能会输出：

\[系统提示]：对话状态已保存...

这证明 Agent 完美继承了之前的记忆！

### 💡 总结

在构建复杂的 AI 应用（如客服机器人、RPG 游戏 NPC、个人助理）时，状态管理是绕不开的话题。

利用 Microsoft.Agents.AI 框架提供的 Serialize() 和 DeserializeThread() 方法，我们可以：

节省 Token：不需要每次都把历史聊天记录重新发给 LLM（视具体实现机制而定）。 跨设备同步：用户在手机上聊一半，回家在电脑上接着聊。 灾备恢复：服务器重启，用户的对话状态不丢失。 今天的代码虽然短，但却是构建生产级 AI 应用的基石。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bingbing-gui.gitbook.io/blog/ai-agent/agent-framework/di-6-pian-agentframework-shi-xian-agent-hui-hua-chi-jiu-hua.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
