文件记忆支持 AI Agent 以文件方式读取长期上下文。应用既可以直接管理文件,也可以让记忆存储服务把对话消息转换为只读文件。
功能说明
记忆存储服务提供以下文件能力。
能力 | 记忆库类型 | 文件操作 | 适用场景 |
对话转文件 |
| 列出、读取和搜索服务生成的只读文件 | 继续通过消息写入,同时让 Agent 以文件方式读取记忆 |
直接管理文件 |
| 新增、读取、更新、重命名、删除和版本管理 | 已有 Markdown 记忆,或需要自行组织目录和版本 |
Dream 整理文件 |
| 跨 Scope 读取文本文件,自动写入一个确定的输出 Scope | 去重、归纳、纠错、合并或重组已有文件 |
Linux 环境还可以使用 agent-memory-fuse 将文件记忆挂载为本地目录,让 Agent 和应用通过普通文件操作访问记忆。
前提条件
已创建 AgentStorage 实例并获取访问地址(endpoint )和实例名
已安装Agent Storage SDK:Python ≥
1.0.10,TypeScript ≥0.0.13
快速开始
以下示例按安装 SDK、配置凭证、初始化客户端和使用文件功能的顺序,创建文件记忆库,写入一个 Markdown 文件,再读取验证。列出、更新、删除等更多操作参见下文常用文件操作。
Python
from tablestore_agent_storage import AgentStorageClient
client = AgentStorageClient(
api_key="your-api-key",
ots_endpoint="https://your-instance.cn-beijing.ots.aliyuncs.com",
ots_instance_name="your-instance-name",
)
scope = {
"appId": "app-001",
"tenantId": "user-001",
"agentId": "assistant",
"runId": "session-001",
}
client.create_memory_store({
"memoryStoreName": "agent_files",
"storageMode": "filemem",
})
client.add_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"content": "# 用户偏好\n\n- 喜欢美式咖啡\n- 偏好简洁回答\n",
})
item = client.get_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"view": "full",
})
print(item["content"])TypeScript
import { AgentStorageClient } from '@tablestore/agent-storage';
async function main() {
const client = new AgentStorageClient({
apiKey: 'your-api-key',
endpoint: 'https://your-instance.cn-beijing.ots.aliyuncs.com',
instanceName: 'your-instance-name',
});
const scope = {
appId: 'app-001',
tenantId: 'user-001',
agentId: 'assistant',
runId: 'session-001',
};
await client.createMemoryStore({
memoryStoreName: 'agent_files',
storageMode: 'filemem',
});
await client.addItem({
memoryStoreName: 'agent_files',
scope,
path: '/profile/preferences.md',
content: '# 用户偏好\n\n- 喜欢美式咖啡\n- 偏好简洁回答\n',
});
const item = await client.getItem({
memoryStoreName: 'agent_files',
scope,
path: '/profile/preferences.md',
view: 'full',
});
console.log(item.content);
}
void main();
storageMode 是创建记忆库时的必填参数,创建后不可变更。后续文件操作无需重复传入该参数,Agent Storage SDK 会自动补充 Item 接口所需的类型字段。
将对话转换为只读记忆文件
如果应用已经通过 AddMemories 写入对话,可以让服务异步生成只读记忆文件,无需由应用自行维护文件内容。
以下四个步骤均可在控制台或 SDK 中完成,每个步骤同时给出两种方式(SDK 以 Python 为例)。
1. 创建记忆库
创建同时输出结构化记忆和文件的记忆库:
控制台
登录 Agent Storage 控制台,进入记忆库管理,点击创建记忆库。
输入类型选择短期消息,输出类型勾选文件记忆(如需同时进行语义检索可加选结构记忆)。
点击确定完成创建。
SDK
from tablestore_agent_storage import AgentStorageClient
client = AgentStorageClient(
api_key="your-api-key",
ots_endpoint="https://your-instance.cn-beijing.ots.aliyuncs.com",
ots_instance_name="your-instance-name",
)
client.create_memory_store({
"memoryStoreName": "agent_memory",
"description": "Agent 对话记忆",
"inputType": "messages",
"outputTypes": ["structured", "file"],
})如果只需要文件,将 outputTypes 设置为 ["file"]。inputType 创建后不可修改;以 messages 作为输入的记忆库可以通过 UpdateMemoryStore 调整 outputTypes。
2. 写入对话
向记忆库写入对话消息,由服务异步生成只读文件。
控制台
打开文件记忆库,进入短期记忆页,点击写入记忆。
输入模式选择对话消息(JSON),填写完整的四级 Scope(应用 appId、租户/用户 tenantId、智能体 agentId、会话 runId)。
粘贴对话消息 JSON,点击确定提交。文件为异步生成,提交后可在请求日志页查看生成任务状态。
SDK
调用 AddMemories 写入消息。文件输出只支持异步生成,因此 sync 必须为 false 或省略。
resp = client.add_memories({
"memoryStoreName": "agent_memory",
"scope": {
"appId": "shopping-app",
"tenantId": "user-001",
"agentId": "shopping-assistant",
"runId": "session-001",
},
"messages": [
{"role": "user", "content": "我平时喝美式咖啡,不加糖。"},
{"role": "assistant", "content": "好的,我会记住你的饮品偏好。"},
],
"sync": False,
})
request_id = resp["requestId"]保存响应中的 requestId。传入 sync=true 会返回 400 INVALID_PARAMETER。
3. 等待文件生成完成
查询生成任务状态,确认服务已生成只读文件。
控制台
打开文件记忆库,进入请求日志页。
按写入时保存的
Request ID找到对应记录,查看状态列,等待状态变为completed。
SDK
使用 AddMemories 返回的requestId 调用 GetMemoryTask:
task = client.get_memory_task({
"memoryStoreName": "agent_memory",
"requestId": request_id,
})
print(task["task"]["status"])当 task.status 为 completed 时,配置的输出均已生成。双输出记忆库只有在结构化记忆和文件都生成完成后,整体任务才为 completed。
4. 列出并读取文件
使用写入时的精确四级 Scope 浏览服务生成的只读文件。服务生成的文件不支持通配 Scope。
控制台
登录 Agent Storage 控制台,打开文件记忆库,进入长期记忆页。
切换到文件记忆,选择写入时的完整 Scope。
在文件树浏览生成的只读文件,点击文件可查看内容及版本历史。
SDK
调用 ListItems 列出文件,再逐个读取内容。
scope = {
"appId": "shopping-app",
"tenantId": "user-001",
"agentId": "shopping-assistant",
"runId": "session-001",
}
page = client.list_items({
"type": "memoryfile",
"memoryStoreName": "agent_memory",
"scope": scope,
"limit": 20,
})
# 先从 items 取得实际 path,再读取内容
for entry in page["items"]:
item = client.get_item({
"type": "memoryfile",
"memoryStoreName": "agent_memory",
"scope": scope,
"path": entry["path"],
"view": "full",
})
print(item["path"], item["content"])响应顶层的 readOnly 为 true 表示这些文件由服务维护,读取内容需设置 view=full。
对这些文件调用新增、更新、重命名或删除接口会返回 409 READ_ONLY_STORE。需要修改内容时,应继续写入对话,或通过结构化记忆接口维护源记忆。
通过 FUSE 挂载为本地目录
agent-memory-fuse 可以把一个表格存储实例中的一个文件记忆库和一个精确 Scope 映射为 Linux 本地目录。挂载后,Agent 和应用可以使用 ls、cat、编辑器或文件 API 读写记忆,无需在应用中集成 Agent Storage SDK。
一次挂载只对应一个 (instance, memoryStoreName, scope)。该工具面向文件记忆,不是通用 POSIX 文件系统。
准备环境
获取与运行环境架构匹配的
agent-memory-fuseLinux 可执行文件,并为其添加执行权限。Linux 内核已启用 FUSE,当前用户或容器能够访问
/dev/fuse。已安装
fusermount3。部分系统中的命令名是fusermount。已创建
storageMode=filemem的文件记忆库,并准备实例的 HTTPS Endpoint、实例名称和完整四级 Scope。已准备 API Key、AccessKey 或 STS 临时凭证。API Key 必须配合 HTTPS Endpoint 使用。
容器内运行通常需要映射 /dev/fuse,并授予 CAP_SYS_ADMIN 或等效的用户命名空间挂载权限。应根据运行环境采用最小权限配置。
chmod +x ./agent-memory-fuse
mkdir -p /mnt/agent-memory挂载文件记忆
执行以下命令。示例中的 Scope 对应快速开始中的 scope 对象。使用引号包裹完整 Scope,避免 Shell 对特殊字符产生非预期解释。
./agent-memory-fuse mount \
--endpoint https://your-instance.cn-beijing.ots.aliyuncs.com \
--instance your-instance-name \
--credential apikey:your-api-key \
--store agent_files \
--scope 'app-001#user-001#assistant#session-001' \
--session fuse-session-001 \
/mnt/agent-memory挂载命令在前台运行,并负责维护挂载生命周期。看到以下日志表示初始目录加载和挂载成功。
mounted /mnt/agent-memory: store=agent_files files=1 readOnly=false保持该进程运行,在另一个终端或业务进程中访问挂载目录。生产环境可以使用 systemd 或容器编排系统托管进程,不要在挂载仍被使用时直接强制终止进程。
主要参数如下。
参数 | 说明 |
| 表格存储实例的 HTTPS Endpoint |
| 表格存储实例名称 |
|
|
|
|
| 以 |
| 本次挂载的会话标识,用于服务端版本归属;不同写入会话建议使用不同值 |
| 可选,将本次挂载限制为只读 |
最后一个位置参数 | 本地挂载目录 |
--credential 包含敏感信息。示例仅展示参数格式,不要把真实凭证写入代码、镜像、日志或可共享的脚本,并优先使用权限受限的短期凭证。
读写文件
挂载成功后,可以像访问普通目录一样读取、创建、修改、重命名和删除文件。
# 查看服务端已有文件
find /mnt/agent-memory -type f
cat /mnt/agent-memory/profile/preferences.md
# 创建或更新文件
mkdir -p /mnt/agent-memory/projects/alpha
printf '%s\n' '# 项目决策' '' '- 使用事件驱动架构' \
> /mnt/agent-memory/projects/alpha/decisions.md
cat /mnt/agent-memory/projects/alpha/decisions.md
# 重命名和删除文件
mv /mnt/agent-memory/projects/alpha/decisions.md \
/mnt/agent-memory/projects/alpha/architecture.md
rm /mnt/agent-memory/projects/alpha/architecture.md文件在 flush、fsync 或 close 时同步到服务端。生产应用必须检查 fsync 和 close 的返回值。部分 Shell 重定向不会显示 close 阶段的错误,重要写入应在完成后重新读取确认。
目录由文件路径前缀形成。包含文件的目录可以跨进程和重新挂载恢复;空目录只存在于当前挂载进程中。
只读挂载
如果 Agent 只需要读取记忆,在挂载目录参数之前增加 --read-only。
./agent-memory-fuse mount \
--endpoint https://your-instance.cn-beijing.ots.aliyuncs.com \
--instance your-instance-name \
--credential apikey:your-api-key \
--store agent_files \
--scope 'app-001#user-001#assistant#session-001' \
--session fuse-reader-001 \
--read-only \
/mnt/agent-memory对于结构化记忆生成的只读文件视图,服务端会自动把挂载切换为只读。对只读挂载执行写操作会返回 EROFS。
轮转 STS 凭证
使用 STS 凭证挂载时,可以在不卸载目录的情况下轮转完整的 AccessKey ID、AccessKey Secret 和 STS Token。凭证提供程序需要向标准输出写入以下 JSON,并通过管道交给轮转命令。
{"accessKeyId":"new-access-key-id","accessKeySecret":"new-access-key-secret","stsToken":"new-sts-token"}your-credential-provider | \
./agent-memory-fuse rotate-credential --mountpoint /mnt/agent-memory轮转命令从标准输入读取凭证,避免把新凭证放入命令行参数。命令成功表示新凭证已安装到本地挂载进程;凭证是否有效会在后续文件请求中确认。只有可信进程才能访问挂载点和执行凭证轮转。
卸载文件记忆
完成文件操作并关闭所有打开的文件后,执行以下命令。
./agent-memory-fuse umount /mnt/agent-memory卸载成功后,前台挂载进程会退出。如果系统缺少 fusermount3 和 fusermount,卸载命令会返回错误,需要先安装 FUSE 用户态工具。
使用限制与排查
仅支持有效的 UTF-8 文本,单个文件最大为 100 KiB。超过限制分别返回
EILSEQ或EFBIG。每个 Scope 默认最多保存 2000 个当前文件,达到配额后写入返回
ENOSPC。多个客户端并发修改同一文件时,过期的文件句柄可能返回
ESTALE。重新打开并读取最新内容后,再决定是否重试。凭证无效或 STS Token 过期时返回
EACCES。轮转凭证或使用有效凭证重新挂载。服务限流或短暂不可用可能返回
EAGAIN。工具会先执行有界重试,应用仍应采用退避策略处理最终错误。不支持符号链接、硬链接、ACL、业务扩展属性、稀疏文件和跨会话文件锁。
出现
operation not permitted或无法打开/dev/fuse时,检查设备映射、当前用户权限和容器挂载能力。出现
initial directory load错误时,检查 Endpoint、实例名称、凭证、记忆库名称和 Scope 是否匹配。
文件定位方式
一个文件由记忆库、Scope 和路径共同定位。
memoryStoreName:记忆库名称。scope:文件归属范围,必须完整填写appId、tenantId、agentId和runId,不支持通配符*。path:Scope 内的文件路径。建议使用带前导/的语义化路径,例如/profile/preferences.md、/projects/alpha/decisions.md。
不同 Scope 中可以使用相同路径,文件内容彼此隔离。列表接口返回的 itemId 是文件的稳定标识,查询历史版本时需要使用。
常用文件操作
以下操作可在控制台或 SDK 中完成。控制台操作均在文件记忆库的长期记忆页:先选择应用(appId) 和租户/用户(tenantId)(智能体、会话可选“全部”以浏览,新建或上传文件需指定完整四级 Scope),左侧按路径前缀浏览文件列表,点击文件在右侧查看内容、元数据与版本历史。SDK 示例沿用快速开始中的 Python client、scope 和 agent_files 记忆库。
仅读取元数据
控制台
在左侧文件列表选中目标文件,右侧详情面板直接显示文件内容以及创建时间、更新时间和当前版本 ID,无需额外操作即可查看元数据。
SDK
将 includeContent 设置为 False,响应不会包含 content,适合检查文件摘要和更新时间。
current = client.get_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"includeContent": False,
})
print(current["contentSha256"], current["updatedAt"])更新文件内容
控制台
选中文件,点击编辑或替换资料,修改文件内容后保存。控制台基于当前版本做并发校验,若文件已被其他请求修改则保存失败,需刷新后重试。
SDK
并发写入场景建议把上一次读取到的 contentSha256 作为 expectedSha256 传入。文件已被其他请求修改时,服务拒绝覆盖,应用重新读取后再决定是否重试。
updated = client.update_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"content": "# 用户偏好\n\n- 喜欢拿铁\n- 偏好简洁回答\n",
"expectedSha256": current["contentSha256"],
})重命名文件
控制台
选中文件,点击重命名,输入新的文件路径后确定。目标路径已存在时会提示冲突。
SDK
UpdateItem 同时承载内容更新和重命名。单次请求必须在 content 与 newPath 中恰好选择一个。
renamed = client.update_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"newPath": "/profile/user-preferences.md",
"expectedSha256": updated["contentSha256"],
})目标路径已经存在时,默认返回冲突。只有业务确认允许替换目标文件时,才设置 "overwrite": True。
分页列出文件
控制台
在长期记忆页选择 Scope 后,左侧文件列表按路径前缀筛选并分页浏览,点击刷新获取最新列表。
SDK
ListItems 默认每页返回 100 个文件,单页最多返回 500 个。响应包含 nextToken 时,将其原样传入下一次请求。
next_token = None
while True:
request = {
"memoryStoreName": "agent_files",
"scope": scope,
"pathPrefix": "/profile/",
"limit": 100,
}
if next_token:
request["nextToken"] = next_token
page = client.list_items(request)
for entry in page["items"]:
print(entry["path"])
next_token = page.get("nextToken")
if not next_token:
break删除文件
控制台
选中文件,点击删除并确认。删除会移除当前文件并产生一条删除版本,历史版本仍可在版本历史中查看。
SDK
client.delete_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/user-preferences.md",
"expectedSha256": renamed["contentSha256"],
})删除操作会移除当前文件,但历史版本仍可以按文件 ID 查询。
查询历史版本
每次新增、更新、重命名或删除都会形成不可变的历史版本。先从当前文件或之前保存的响应中取得 itemId,再列出版本。
versions = client.list_item_versions({
"memoryStoreName": "agent_files",
"scope": scope,
"itemId": renamed["itemId"],
"limit": 20,
})
version = versions["versions"][0]
snapshot = client.get_item_version({
"memoryStoreName": "agent_files",
"scope": scope,
"itemId": version["itemId"],
"versionId": version["versionId"],
"versionSeq": version["versionSeq"],
})
print(snapshot.get("content"))可以使用 operation 筛选 created、modified 或 deleted 版本。版本列表不返回内容,需要调用 GetItemVersion 读取指定快照。
脱敏历史版本
脱敏不可逆。执行前,请确认选中的是正确的历史版本。
RedactItemVersion 会清除一个历史快照的路径、内容、内容摘要和大小,保留操作类型、版本序号、创建时间以及脱敏审计信息。重复请求是幂等的,不会修改当前文件,也不会创建新版本。
redacted = client.redact_item_version({
"memoryStoreName": "agent_files",
"scope": scope,
"itemId": version["itemId"],
"versionId": version["versionId"],
"versionSeq": version["versionSeq"],
"sessionId": "privacy-job-001",
})
print(redacted["redacted"], redacted["redactedAt"])脱敏后再次调用 GetItemVersion 仍返回该版本,但不再包含 content。
读取结构化记忆的文件视图
如果应用向服务写入对话或文本,并使用结构化记忆接口进行语义检索,同一份记忆也可以文件方式供 Agent 浏览。
继续通过
AddMemories、UpdateMemory和DeleteMemory等结构化记忆接口写入和维护数据。通过 Agent Storage SDK 的
list_items和get_item列出、读取生成的文件。ListItems响应包含readOnly: true时,表示当前文件视图只读,不支持新增、更新、重命名、删除或版本操作。page = client.list_items({ "memoryStoreName": "agent_memory", "scope": scope, }) if page.get("readOnly"): for entry in page["items"]: item = client.get_item({ "memoryStoreName": "agent_memory", "scope": scope, "path": entry["path"], }) print(item["path"], item["content"])
对只读文件视图发起文件写操作会返回 READ_ONLY_STORE。此时应通过结构化记忆接口修改源记忆。
常见错误
错误码 | 常见原因 | 处理建议 |
| Scope 不完整、路径无效,或更新请求同时提供了 | 检查完整四级 Scope、路径和请求分支 |
| 记忆库、Scope、路径或版本不存在 | 核对文件定位信息,不要跨 Scope 复用文件标识 |
| 新建或重命名的目标路径已存在 | 更换路径,确认业务允许时再启用覆盖 |
| 文件已被其他请求修改 | 重新读取文件,基于最新内容决定是否重试 |
| 同一 Scope 正在发生并发变更 | 短暂退避后重试,并重新读取最新文件 |
| 尝试修改只读文件视图 | 改用结构化记忆接口更新源记忆 |
使用限制
仅支持有效的 UTF-8 文本,单个文件最大为 100 KiB。
规范化后的路径最长为 800 字节。路径不能指向根目录,不能包含空路径段、
.、..或 NUL 字符。每个 Scope 默认最多保存 2000 个当前文件。
所有 Item 接口均要求完整四级 Scope,不支持通配符。
历史版本脱敏后不可恢复。