> For the complete documentation index, see [llms.txt](https://docs.convai.com/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/unity-plugin-beta-overview/features/long-term-memory/memory-management-api.md).

# 记忆管理 API

## 程序化记忆记录管理

记忆管理 API 让你的应用能够为特定的用户–角色对读取、添加和删除单条记忆记录。在正常使用中，记忆会在对话过程中由 Convai 后端自动累积——无需编写代码。这个 API 适用于你需要有意控制的场景：在首次会话前预置事实、审核角色已知内容，或在不清空用户整个历史记录的情况下重置特定记忆。

所有记忆操作都通过 `ConvaiRestClient.Memory`，并公开 `MemoryService`.

{% hint style="info" %}
**Beta API 注意：** 所有长期记忆端点在 Convai 后端都使用 beta API 标志。截至本文撰写时，方法签名和响应结构是稳定的，但在未来的 SDK 或后端更新中可能会发生变化。上线到生产环境时，请锁定你的 SDK 版本。
{% endhint %}

## 什么是记忆记录？

角色对某个用户所知道的每条事实都会存储为一个 `MemoryRecord`。该 `Memory` 字段中包含一个自然语言字符串——而不是结构化数据。后端会自动从对话中写入这些内容，它们看起来像笔记：

> `"用户的名字是 Alex，他们在夜班担任安全员。"` `"Alex 在灭火器分类方面遇到困难，并且更喜欢逐步讲解。"`

当会话开始时，角色会将这些字符串作为上下文接收，并可以在回复中自然地引用它们。你也可以通过 `AddAsync` —— 任何角色应该知道的事实性句子都可以。

| 字段          | 类型                           | 说明                        |
| ----------- | ---------------------------- | ------------------------- |
| `Id`        | `string`                     | 此记忆记录的唯一标识符。              |
| `Memory`    | `string`                     | 事实文本——角色将用作上下文的自然语言句子。    |
| `CreatedAt` | `string`                     | 记录首次存储时的 ISO 8601 时间戳。    |
| `UpdatedAt` | `string`                     | 最近一次更新的 ISO 8601 时间戳。     |
| `Metadata`  | `Dictionary<string, object>` | 附加到记录上的任意键值数据。可以为 `null`. |

## 设置 ConvaiRestClient

记忆操作需要一个 `ConvaiRestClient` 已使用你的 API 密钥完成身份验证的。

```csharp
using System;
using Convai.RestAPI;
using UnityEngine;

public class MemoryManager : MonoBehaviour
{
    private ConvaiRestClient _client;

    private void Awake()
    {
        _client = new ConvaiRestClient(ConvaiSettings.Instance.ApiKey);
    }

    private void OnDestroy()
    {
        _client?.Dispose();
    }
}
```

{% hint style="info" %}
`ConvaiSettings` 是用于存储你的 API 密钥的 ScriptableObject，配置在 **工具 → Convai → 配置**. `ConvaiRestClient` 实现 `IDisposable` —— 用完后务必释放它，或者将其作为长期存在的单例来管理。
{% endhint %}

{% hint style="info" %}
**查找你的 Character ID 和 end\_user\_id：** Character ID 位于 **角色 ID** 你在 `ConvaiCharacter` 检视器。接下来 `end_user_id` 是你的身份提供程序返回的值——如果你使用默认的 `DeviceEndUserIdProvider`，你可以通过调用 `new DeviceEndUserIdProvider().GetEndUserId()` 在主线程上。
{% endhint %}

{% hint style="info" %}
本页中的所有示例都使用 `async void` 以兼容 Unity。务必如图所示将异步调用包装在 `try/catch` 中—— `async void` 不会将未处理的异常传播给调用方。
{% endhint %}

## 列出记忆

检索角色为给定用户拥有的所有记忆。结果是分页的——一直迭代直到 `HasMore` 为 `false`.

```csharp
using System;
using System.Threading;
using Convai.RestAPI.Internal;
using UnityEngine;

public async void ListAllMemories(
    string characterId,
    string endUserId,
    CancellationToken cancellationToken = default)
{
    try
    {
        int page = 1;
        const int pageSize = 50;

        do
        {
            MemoryListResponse response = await _client.Memory.ListAsync(
                characterId,
                endUserId,
                page,
                pageSize,
                cancellationToken);

            foreach (MemoryRecord record in response.Memories)
            {
                Debug.Log($"[{record.Id}] {record.Memory}");
            }

            if (!response.HasMore) break;
            page++;

        } while (true);
    }
    catch (Exception e)
    {
        Debug.LogError($"[LTM] 列出记忆失败：{e.Message}");
    }
}
```

### ListAsync 参数

| 参数                  | 类型                  | 默认值  | 说明             |
| ------------------- | ------------------- | ---- | -------------- |
| `characterId`       | `string`            | 必需   | 要列出其记忆的角色。     |
| `endUserId`         | `string`            | 必需   | 要读取其记忆分区的最终用户。 |
| `page`              | `int`               | `1`  | 从 1 开始的页码。     |
| `pageSize`          | `int`               | `50` | 每页记录数。         |
| `cancellationToken` | `CancellationToken` | `默认` | 可选的取消支持。       |

### MemoryListResponse 字段

| 字段           | 类型                   | 说明          |
| ------------ | -------------------- | ----------- |
| `Memories`   | `List<MemoryRecord>` | 当前页上的记录。    |
| `TotalCount` | `int`                | 跨所有页面的记录总数。 |
| `Page`       | `int`                | 当前页码。       |
| `PageSize`   | `int`                | 此响应使用的页大小。  |
| `HasMore`    | `bool`               | 是否存在更多页面。   |

## 获取单条记忆

通过 ID 检索一条特定记录。当你已经从之前的 `ListAsync` 调用的这三个参数。

```csharp
public async void GetMemory(
    string characterId,
    string endUserId,
    string memoryId,
    CancellationToken cancellationToken = default)
{
    try
    {
        MemoryRecord record = await _client.Memory.GetAsync(
            characterId,
            endUserId,
            memoryId,
            cancellationToken);

        Debug.Log($"记忆：{record.Memory}（创建于 {record.CreatedAt}）");
    }
    catch (Exception e)
    {
        Debug.LogError($"[LTM] 获取记忆失败：{e.Message}");
    }
}
```

## 添加记忆

以编程方式注入一个或多个事实。传入自然语言字符串列表——服务器会将每一条都存储为单独的 `MemoryRecord`.

```csharp
using System;
using System.Collections.Generic;
using System.Threading;
using Convai.RestAPI.Internal;
using UnityEngine;

public async void AddMemories(
    string characterId,
    string endUserId,
    CancellationToken cancellationToken = default)
{
    try
    {
        var facts = new List<string>
        {
            "学员以 88% 的分数完成了模块 1。",
            "学员在模块 1 中对灭火器分类感到困难。",
            "学员更喜欢逐步讲解，而不是摘要。"
        };

        AddMemoriesResponse response = await _client.Memory.AddAsync(
            characterId,
            endUserId,
            facts,
            metadata: null,
            cancellationToken);

        foreach (MemoryAddResult result in response.Memories)
        {
            Debug.Log($"[{result.Event}] {result.Memory}");
        }
    }
    catch (Exception e)
    {
        Debug.LogError($"[LTM] 添加记忆失败：{e.Message}");
    }
}
```

### AddAsync 参数

| 参数                  | 类型                                     | 默认值    | 说明               |
| ------------------- | -------------------------------------- | ------ | ---------------- |
| `characterId`       | `string`                               | 必需     | 要向其添加记忆的角色。      |
| `endUserId`         | `string`                               | 必需     | 要写入其分区的最终用户。     |
| `memories`          | `IReadOnlyList<string>`                | 必需     | 一条或多条自然语言事实字符串。  |
| `metadata`          | `IReadOnlyDictionary<string, object>?` | `null` | 应用于所有添加记录的可选元数据。 |
| `cancellationToken` | `CancellationToken`                    | `默认`   | 可选的取消支持。         |

### MemoryAddResult 字段

| 字段       | 说明                                        |
| -------- | ----------------------------------------- |
| `Id`     | 新创建或更新记录的 ID。                             |
| `事件`     | 服务器执行的操作： `"ADD"`, `"UPDATE"`，或 `"NONE"`. |
| `Memory` | 最终存储的文本。服务器可能会为保持一致性而重新表述输入。              |

{% hint style="info" %}
服务器会去重并合并与现有记录重叠的事实。当这种情况发生时， `事件` 为 `"UPDATE"` 或 `"NONE"` 而不是 `"ADD"`，以及 `Id` 指的是现有记录。最终存储的文本可能与你传入的内容略有不同。
{% endhint %}

## 删除单条记忆

通过 ID 删除一条特定记录。用于纠正错误事实，而无需清空全部内容。

```csharp
public async void DeleteMemory(
    string characterId,
    string endUserId,
    string memoryId,
    CancellationToken cancellationToken = default)
{
    try
    {
        MemoryDeleteResponse response = await _client.Memory.DeleteAsync(
            characterId,
            endUserId,
            memoryId,
            cancellationToken);

        Debug.Log($"已删除：{response.Deleted} — 记忆 ID：{response.MemoryId}");
    }
    catch (Exception e)
    {
        Debug.LogError($"[LTM] 删除记忆失败：{e.Message}");
    }
}
```

## 删除某个用户的所有记忆

一次性移除用户–角色分区中的每条记忆记录。最终用户记录本身会被保留。

```csharp
public async void DeleteAllMemories(
    string characterId,
    string endUserId,
    CancellationToken cancellationToken = default)
{
    try
    {
        MemoryDeleteAllResponse response = await _client.Memory.DeleteAllAsync(
            characterId,
            endUserId,
            cancellationToken);

        Debug.Log($"用户 {response.EndUserId} 在角色 {response.CharacterId} 上的所有记忆已清除。");
    }
    catch (Exception e)
    {
        Debug.LogError($"[LTM] 删除所有记忆失败：{e.Message}");
    }
}
```

{% hint style="danger" %}
`DeleteAllAsync` 为 **不可逆**。指定用户–角色对的所有记忆记录将被永久移除。该角色在未来会话中将不再记得该用户。API 中没有确认对话框——在调用此方法之前，请在你的应用中实现确认。
{% endhint %}

## 完整 API 参考

所有方法都在 `ConvaiRestClient.Memory` (`MemoryService`）。所有 `CancellationToken` 参数都默认为 `默认`.

| 方法               | 签名                                                                                                                                            | 返回                              |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
| `AddAsync`       | `(string characterId, string endUserId, IReadOnlyList<string> memories, IReadOnlyDictionary<string, object>? metadata, CancellationToken ct)` | `Task<AddMemoriesResponse>`     |
| `ListAsync`      | `(string characterId, string endUserId, int page, int pageSize, CancellationToken ct)`                                                        | `Task<MemoryListResponse>`      |
| `GetAsync`       | `(string characterId, string endUserId, string memoryId, CancellationToken ct)`                                                               | `Task<MemoryRecord>`            |
| `DeleteAsync`    | `(string characterId, string endUserId, string memoryId, CancellationToken ct)`                                                               | `Task<MemoryDeleteResponse>`    |
| `DeleteAllAsync` | `(string characterId, string endUserId, CancellationToken ct)`                                                                                | `Task<MemoryDeleteAllResponse>` |

## 结论

记忆管理 API 让你可以完全以编程方式控制角色对每个用户所知道的内容——你可以在不接触 Convai 仪表板的情况下查看、初始化、纠正和清空记忆记录。要管理用户本身（列出有哪些用户拥有记忆、更新元数据，或彻底删除用户记录），请参见下一页：最终用户管理。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/unity-plugin-beta-overview/features/long-term-memory/memory-management-api.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.
