File memory enables AI agents to read long-term context as files. Applications can directly manage files, or let the memory store service convert conversation messages into read-only files.
Features
The memory store service provides the following file capabilities.
|
Capability |
Memory store type |
File operations |
Use cases |
|
Conversation-to-file |
|
List, read, and search service-generated read-only files |
Continue writing through messages while letting the agent read memory as files |
|
Direct file management |
|
Create, read, update, rename, delete, and manage versions |
Existing Markdown memory, or need to organize directories and versions independently |
|
Dream file organization |
|
Read text files across scopes and automatically write to a deterministic output scope |
Deduplicate, summarize, correct, merge, or reorganize existing files |
On Linux, you can also use agent-memory-fuse to mount file memory as a local directory, allowing agents and applications to access memory through standard file operations.
Prerequisites
-
You have created an AgentStorage instance and obtained the endpoint and instance name.
-
The Agent Storage SDK is installed: Python >=
1.0.10, TypeScript >=0.0.13
Quick start
The following examples walk through installing the SDK, configuring credentials, initializing the client, and using file features to create a file memory store, write a Markdown file, and read it back. For more operations such as listing, updating, and deleting, see Common file operations below.
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 is a required parameter when creating a memory store and cannot be changed after creation. Subsequent file operations do not need to pass this parameter again; the Agent Storage SDK automatically fills in the type fields required by Item interfaces.
Convert conversations to read-only memory files
If your application already writes conversations through AddMemories, you can let the service asynchronously generate read-only memory files without maintaining file content yourself.
The following four steps can all be completed in the console or SDK. Each step shows both methods (SDK examples use Python).
1. Create a memory store
Create a memory store that outputs both structured memory and files:
Console
-
Log on to the Agent Storage console, go to Memory store management, and click Create memory store.
-
For Input type, select Short-term messages. For Output type, select File memory (you can also select Structured memory if you need semantic retrieval at the same time).
-
Click OK to complete the creation.
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"],
})
If you only need files, set outputTypes to ["file"]. inputType cannot be modified after creation. Memory stores that use messages as input can adjust outputTypes through UpdateMemoryStore.
2. Write conversations
Write conversation messages to the memory store. The service generates read-only files asynchronously.
Console
-
Open the file memory store, go to the Short-term memory page, and click Write memory.
-
For Input mode, select Conversation messages (JSON). Fill in the complete four-level scope (Application appId, Tenant/User tenantId, Agent agentId, Session runId).
-
Paste the conversation messages JSON and click OK to submit. Files are generated asynchronously. After submission, you can check the generation task status on the Request log page.
SDK
Call AddMemories to write messages. File output only supports asynchronous generation, so sync must be false or omitted.
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"]
Save the requestId from the response. Passing sync=true returns 400 INVALID_PARAMETER.
3. Wait for file generation to complete
Query the generation task status to confirm that the service has generated the read-only files.
Console
-
Open the file memory store and go to the Request log page.
-
Find the corresponding record by the
Request IDsaved during writing, check the Status column, and wait for the status to becomecompleted.
SDK
Use the requestId returned by AddMemories to call GetMemoryTask:
task = client.get_memory_task({
"memoryStoreName": "agent_memory",
"requestId": request_id,
})
print(task["task"]["status"])
When task.status is completed, all configured outputs have been generated. For dual-output memory stores, the overall task is completed only after both structured memory and files have been generated.
4. List and read files
Use the exact four-level scope from the write operation to browse the service-generated read-only files. Service-generated files do not support wildcard scopes.
Console
-
Log on to the Agent Storage console, open the file memory store, and go to the Long-term memory page.
-
Switch to File memory and select the complete scope used during writing.
-
Browse the generated read-only files in the file tree. Click a file to view its content and version history.
SDK
Call ListItems to list files, then read each one.
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,
})
# Get the actual path from items, then read the content
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"])
When the top-level readOnly in the response is true, these files are maintained by the service. Reading content requires setting view=full.
Calling create, update, rename, or delete interfaces on these files returns 409 READ_ONLY_STORE. To modify content, continue writing conversations or maintain the source memory through structured memory interfaces.
Mount as a local directory through FUSE
agent-memory-fuse maps a file memory store and an exact scope in a Tablestore instance to a Linux local directory. After mounting, agents and applications can use ls, cat, editors, or file APIs to read and write memory without integrating the Agent Storage SDK into the application.
Each mount corresponds to a single (instance, memoryStoreName, scope). This tool is designed for file memory, not as a general-purpose POSIX file system.
Prepare the environment
-
Obtain the
agent-memory-fuseLinux executable that matches your runtime architecture, and add execute permissions. -
FUSE is enabled in the Linux kernel, and the current user or container can access
/dev/fuse. -
fusermount3is installed. On some systems, the command name isfusermount. -
A file memory store with
storageMode=filememhas been created. Prepare the instance HTTPS endpoint, instance name, and complete four-level scope. -
An API Key, AccessKey, or STS temporary credential is ready. API Keys must be used with HTTPS endpoints.
Running in a container typically requires mapping /dev/fuse and granting CAP_SYS_ADMIN or equivalent user namespace mount permissions. Use least-privilege configuration based on your runtime environment.
chmod +x ./agent-memory-fuse
mkdir -p /mnt/agent-memory
Mount file memory
Run the following command. The scope in the example corresponds to the scope object in the quick start. Use quotes to wrap the complete scope to prevent the shell from interpreting special characters unexpectedly.
./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
The mount command runs in the foreground and manages the mount lifecycle. The following log indicates that the initial directory load and mount succeeded.
mounted /mnt/agent-memory: store=agent_files files=1 readOnly=false
Keep this process running and access the mount directory from another terminal or business process. In production, use systemd or a container orchestration system to manage the process. Do not forcefully terminate the process while the mount is still in use.
The main parameters are as follows.
|
Parameter |
Description |
|
|
HTTPS endpoint of the Tablestore instance |
|
|
Tablestore instance name |
|
|
|
|
|
Name of the memory store with |
|
|
Exact scope separated by |
|
|
Session identifier for this mount, used for server-side version attribution. Different write sessions should use different values. |
|
|
Optional. Restricts this mount to read-only. |
|
Last positional argument |
Local mount directory |
--credential contains sensitive information. The example only shows the parameter format. Do not write real credentials into code, images, logs, or shared scripts. Prefer short-lived credentials with restricted permissions.
Read and write files
After the mount succeeds, you can read, create, modify, rename, and delete files as you would in a regular directory.
# View existing server-side files
find /mnt/agent-memory -type f
cat /mnt/agent-memory/profile/preferences.md
# Create or update files
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
# Rename and delete files
mv /mnt/agent-memory/projects/alpha/decisions.md \
/mnt/agent-memory/projects/alpha/architecture.md
rm /mnt/agent-memory/projects/alpha/architecture.md
Files are synced to the server on flush, fsync, or close. Production applications must check the return values of fsync and close. Some shell redirections do not surface errors during the close stage. For important writes, re-read the file after completion to confirm.
Directories are formed from file path prefixes. Directories that contain files can be restored across processes and remounts. Empty directories exist only within the current mount process.
Read-only mount
If the agent only needs to read memory, add --read-only before the mount directory argument.
./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
For read-only file views generated from structured memory, the server automatically switches the mount to read-only. Write operations on a read-only mount return EROFS.
Rotate STS credentials
When mounting with STS credentials, you can rotate the complete AccessKey ID, AccessKey Secret, and STS Token without unmounting the directory. The credential provider must write the following JSON to standard output and pipe it to the rotation command.
{"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
The rotation command reads credentials from standard input to avoid putting new credentials in command-line arguments. A successful command indicates that the new credentials have been installed in the local mount process. Whether the credentials are valid will be confirmed in subsequent file requests. Only trusted processes can access the mount point and perform credential rotation.
Unmount file memory
After completing file operations and closing all open files, run the following command.
./agent-memory-fuse umount /mnt/agent-memory
After unmounting succeeds, the foreground mount process exits. If the system lacks both fusermount3 and fusermount, the unmount command returns an error. Install FUSE userspace tools first.
Limits and troubleshooting
-
Only valid UTF-8 text is supported. The maximum size of a single file is 100 KiB. Exceeding these limits returns
EILSEQorEFBIG, respectively. -
Each scope supports a maximum of 2,000 current files by default. When the quota is reached, writes return
ENOSPC. -
When multiple clients concurrently modify the same file, stale file handles may return
ESTALE. Reopen and read the latest content before deciding whether to retry. -
Invalid credentials or an expired STS Token return
EACCES. Rotate credentials or remount with valid credentials. -
Service rate limiting or brief unavailability may return
EAGAIN. The tool performs bounded retries first. Applications should still use backoff strategies to handle final errors. -
Symbolic links, hard links, ACLs, extended attributes, sparse files, and cross-session file locks are not supported.
-
If you see
operation not permittedor cannot open/dev/fuse, check device mapping, current user permissions, and container mount capabilities. -
If you see an
initial directory loaderror, check whether the endpoint, instance name, credentials, memory store name, and scope match.
File location
A file is identified by the memory store, scope, and path together.
-
memoryStoreName: The memory store name. -
scope: The scope to which the file belongs. You must provide the completeappId,tenantId,agentId, andrunId. Wildcard*is not supported. -
path: The file path within the scope. We recommend using semantic paths with a leading/, such as/profile/preferences.mdor/projects/alpha/decisions.md.
The same path can be used in different scopes. File content is isolated between scopes. The itemId returned by the list interface is the stable identifier of the file and is required when querying historical versions.
Common file operations
The following operations can be completed in the console or SDK. All console operations are on the Long-term memory page of the file memory store: first select the Application (appId) and Tenant/User (tenantId) (Agent and Session can be set to "All" for browsing; creating or uploading files requires a complete four-level scope), browse the file list by Path prefix on the left, and click a file to view its content, metadata, and version history on the right. SDK examples use the Python client, scope, and agent_files memory store from the quick start.
Read metadata only
Console
Select the target file in the file list on the left. The details panel on the right directly displays the file content, Creation time, Update time, and current Version ID. No additional operation is needed to view metadata.
SDK
Set includeContent to False. The response will not include content, which is suitable for checking file summaries and update times.
current = client.get_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"includeContent": False,
})
print(current["contentSha256"], current["updatedAt"])
Update file content
Console
Select the file, click Edit or replace data, modify the File content, and save. The console performs concurrency validation based on the current version. If the file has been modified by another request, the save fails. Refresh and retry.
SDK
For concurrent write scenarios, we recommend passing the contentSha256 from the last read as expectedSha256. When the file has been modified by another request, the service rejects the overwrite. The application should re-read the file and then decide whether to retry.
updated = client.update_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"content": "# 用户偏好\n\n- 喜欢拿铁\n- 偏好简洁回答\n",
"expectedSha256": current["contentSha256"],
})
Rename a file
Console
Select the file, click Rename, enter the new File path, and confirm. If the target path already exists, a conflict is reported.
SDK
UpdateItem handles both content updates and renames. A single request must specify exactly one of content or newPath.
renamed = client.update_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"newPath": "/profile/user-preferences.md",
"expectedSha256": updated["contentSha256"],
})
When the target path already exists, a conflict is returned by default. Only set "overwrite": True when the business confirms that replacing the target file is allowed.
List files with pagination
Console
On the Long-term memory page, after selecting a scope, filter and browse the file list by Path prefix on the left with pagination. Click Refresh to get the latest list.
SDK
ListItems returns 100 files per page by default, with a maximum of 500 per page. When the response includes nextToken, pass it as-is in the next request.
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
Delete a file
Console
Select the file, click Delete, and confirm. Deletion removes the current file and creates a deletion version. Historical versions can still be viewed in Version history.
SDK
client.delete_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/user-preferences.md",
"expectedSha256": renamed["contentSha256"],
})
The delete operation removes the current file, but historical versions can still be queried by file ID.
Query historical versions
Each create, update, rename, or delete operation creates an immutable historical version. First, obtain the itemId from the current file or a previously saved response, then list the versions.
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"))
You can use operation to filter created, modified, or deleted versions. The version list does not return content. Call GetItemVersion to read a specific snapshot.
Redact historical versions
Redaction is irreversible. Before executing, confirm that you have selected the correct historical version.
RedactItemVersion clears the path, content, content hash, and size of a historical snapshot. It preserves the operation type, version sequence, creation time, and redaction audit information. Repeat requests are idempotent. Redaction does not modify the current file or create a new version.
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"])
After redaction, calling GetItemVersion still returns the version, but it no longer includes content.
Read the file view of structured memory
If your application writes conversations or text to the service and uses structured memory interfaces for semantic retrieval, the same memory can also be browsed as files by the agent.
-
Continue writing and maintaining data through structured memory interfaces such as
AddMemories,UpdateMemory, andDeleteMemory. -
Use the Agent Storage SDK's
list_itemsandget_itemto list and read generated files. -
When the
ListItemsresponse includesreadOnly: true, the current file view is read-only. Create, update, rename, delete, and version operations are not supported.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"])
File write operations on a read-only file view return READ_ONLY_STORE. In this case, modify the source memory through structured memory interfaces.
Common errors
|
Error code |
Common cause |
Suggested fix |
|
|
Incomplete scope, invalid path, or the update request provided both |
Check the complete four-level scope, path, and request branch |
|
|
The memory store, scope, path, or version does not exist |
Verify the file location information. Do not reuse file identifiers across scopes. |
|
|
The target path for creation or renaming already exists |
Use a different path. Only enable overwrite when the business confirms it is allowed. |
|
|
The file has been modified by another request |
Re-read the file and decide whether to retry based on the latest content |
|
|
Concurrent changes are occurring in the same scope |
Retry after a brief backoff and re-read the latest file |
|
|
Attempted to modify a read-only file view |
Use structured memory interfaces to update the source memory instead |
Limits
-
Only valid UTF-8 text is supported. The maximum size of a single file is 100 KiB.
-
The normalized path can be up to 800 bytes. Paths cannot point to the root directory and cannot contain empty path segments,
.,.., or NUL characters. -
Each scope supports a maximum of 2,000 current files by default.
-
All Item interfaces require a complete four-level scope. Wildcards are not supported.
-
Redacted historical versions cannot be restored.