File memory lets AI agents read and maintain long-term context as files. Applications can manage memory files directly or use read-only file views generated from structured memories.
File access options
Memory Store provides the following file access options.
|
Option |
Input |
File operations |
Use case |
|
Structured memories and file views |
Write conversation messages or text for the service to extract long-term memories |
List and read service-generated, read-only files |
Use semantic search and file-based access for agents |
|
File memory |
Write Markdown or UTF-8 text files directly |
Create, read, update, rename, delete, and manage versions |
Use existing memory files or organize memories in custom directories |
On Linux, agent-memory-fuse can mount file memory as a local directory. Agents and applications can then access memories with standard file operations.
Prerequisites
A Tablestore instance with its HTTPS endpoint and instance name
An API Key generated for the instance, or an AccessKey ID and AccessKey secret
An Agent Storage SDK version that supports file memory: Python SDK
1.0.10or later, or TypeScript SDK0.0.11or later
Quick start
The following examples install the SDK, configure credentials, initialize a client, create a file memory store, and write a Markdown file. The examples then list and read the file.
For client initialization and common settings, see Agent Storage SDK.
Python
Install the Python SDK.
pip install "tablestore-agent-storage>=1.0.10"
In the following program, specify the API Key, HTTPS endpoint, and instance name.
Create and run the program to initialize the client and use file memory.
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": "# User preferences\n\n- Likes Americano coffee\n- Prefers concise answers\n",
})
listed = client.list_items({
"memoryStoreName": "agent_files",
"scope": scope,
"pathPrefix": "/profile/",
})
for entry in listed["items"]:
print(entry["path"], entry["contentSizeBytes"])
item = client.get_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
})
print(item["content"])
TypeScript
Install the TypeScript SDK.
npm install "@tablestore/agent-storage@^0.0.11"
In the following program, specify the API Key, HTTPS endpoint, and instance name.
Create and run the program to initialize the client and use file memory.
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: '# User preferences\n\n- Likes Americano coffee\n- Prefers concise answers\n',
});
const listed = await client.listItems({
memoryStoreName: 'agent_files',
scope,
pathPrefix: '/profile/',
});
const item = await client.getItem({
memoryStoreName: 'agent_files',
scope,
path: '/profile/preferences.md',
});
console.log(listed.items, item.content);
}
void main();
storageMode is required when you create a memory store and cannot be changed later. File operations do not require this parameter. Agent Storage SDK automatically adds the type field required by Item APIs.
Mount file memory as a local directory with FUSE
agent-memory-fuse maps one file memory store and one exact scope in a Tablestore instance to a local Linux directory. After mounting, agents and applications can read and write memories with ls, cat, editors, or file APIs without integrating Agent Storage SDK.
Each mount maps one (instance, memoryStoreName, scope) combination. The tool is designed for file memory and is not a general-purpose POSIX file system.
Prepare the environment
Download the
agent-memory-fuseLinux executable that matches the runtime architecture, and make the file executable.Enable FUSE in the Linux kernel, and grant the current user or container access to
/dev/fuse.Install
fusermount3. On some systems, the command is namedfusermount.Create a file memory store with
storageMode=filemem, and obtain the HTTPS endpoint, instance name, and all four scope fields.Prepare an API Key, AccessKey, or Security Token Service (STS) temporary credential. API Key authentication requires an HTTPS endpoint.
Running the tool in a container typically requires mapping /dev/fuse and granting CAP_SYS_ADMIN or equivalent user-namespace mount permissions. Use the minimum permissions required by the runtime environment.
chmod +x ./agent-memory-fuse
mkdir -p /mnt/agent-memory
Mount file memory
Run the following command. The scope matches the scope object in Quick start. Enclose the complete scope in quotation marks to prevent the shell from interpreting special characters.
./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 maintains the mount lifecycle. The following log indicates that the initial directory was loaded and mounted.
mounted /mnt/agent-memory: store=agent_files files=1 readOnly=false
Keep the process running and access the mounted directory from another terminal or application process. In production, use systemd or a container orchestrator to manage the process. Do not forcibly terminate the process while the mount is in use.
The following table describes the main parameters.
|
Parameter |
Description |
|
|
HTTPS endpoint of the Tablestore instance |
|
|
Tablestore instance name |
|
|
|
|
|
Name of a memory store with |
|
|
Exact |
|
|
Session identifier for the mount, used to associate versions on the server. Use a different value for each write session. |
|
|
Optional. Mount the directory as read-only. |
|
Final positional argument |
Local mount directory |
--credential contains sensitive information. The example shows only the parameter format. Do not store real credentials in source code, container images, logs, or shared scripts. Prefer short-lived credentials with restricted permissions.
Read and write files
After mounting, read, create, modify, rename, and delete files as you would in a regular directory.
# View files stored on the server
find /mnt/agent-memory -type f
cat /mnt/agent-memory/profile/preferences.md
# Create or update a file
mkdir -p /mnt/agent-memory/projects/alpha
printf '%s\n' '# Project decisions' '' '- Use an event-driven architecture' \
> /mnt/agent-memory/projects/alpha/decisions.md
cat /mnt/agent-memory/projects/alpha/decisions.md
# Rename and delete a file
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 synchronized to the server during flush, fsync, or close operations. Production applications must check the return values of fsync and close. Some shell redirections do not display errors raised during close. Read critical writes back to confirm that they succeeded.
Directories are derived from file path prefixes. Directories that contain files persist across processes and remounts. Empty directories exist only in the current mount process.
Use a read-only mount
If an agent only needs to read memories, 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 a read-only file view generated from structured memories, the service automatically switches the mount to read-only. Write operations on a read-only mount return EROFS.
Rotate STS credentials
When a mount uses STS credentials, rotate the 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 so that new credentials are not exposed in command-line arguments. A successful command installs the credentials in the local mount process. Subsequent file requests verify the credentials. Only trusted processes can access the mount point and rotate credentials.
Unmount file memory
After all file operations finish and all open files are closed, run the following command.
./agent-memory-fuse umount /mnt/agent-memory
After the directory is unmounted, the foreground mount process exits. If fusermount3 and fusermount are unavailable, the unmount command returns an error. Install the FUSE user-space tools before you retry.
Limitations and troubleshooting
Only valid UTF-8 text is supported, and each file can be up to 100 KiB. Content and size violations return
EILSEQandEFBIG, respectively.Each scope stores up to 2,000 current files by default. Writes return
ENOSPCwhen the quota is reached.When multiple clients modify the same file concurrently, stale file handles might return
ESTALE. Reopen the file, read the latest content, and then decide whether to retry.Invalid credentials or an expired STS token return
EACCES. Rotate the credentials or remount with valid credentials.Throttling or temporary service unavailability might return
EAGAIN. The tool first performs bounded retries. Applications must use backoff to handle the final error.Symbolic links, hard links, access control lists (ACLs), application-defined extended attributes, sparse files, and cross-session file locks are not supported.
For an
operation not permittederror or failure to open/dev/fuse, check device mapping, current-user permissions, and container mount capabilities.For an
initial directory loaderror, verify that the endpoint, instance name, credentials, memory store name, and scope match.
File identification
A memory store, a scope, and a path together identify a file.
memoryStoreName: The memory store name.scope: The scope that owns the file. SpecifyappId,tenantId,agentId, andrunId. The*wildcard is not supported.path: The file path within the scope. Use a meaningful path with a leading/, such as/profile/preferences.mdor/projects/alpha/decisions.md.
The same path can be used in different scopes because their file contents are isolated. The itemId returned by ListItems is the stable file identifier and is required to query version history.
Common file operations
The following examples use the Python client, scope, and agent_files memory store from Quick start.
Read file metadata only
Set includeContent to False to omit content from the response. Use this option to inspect the content digest and update time.
current = client.get_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"includeContent": False,
})
print(current["contentSha256"], current["updatedAt"])
Update file content
For concurrent writes, pass the most recently read contentSha256 value as expectedSha256. If another request has modified the file, the service rejects the overwrite. Read the file again before deciding whether to retry.
updated = client.update_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"content": "# User preferences\n\n- Likes latte\n- Prefers concise answers\n",
"expectedSha256": current["contentSha256"],
})
Rename a file
UpdateItem updates content or renames a file. Each request must specify exactly one of content and newPath.
renamed = client.update_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/preferences.md",
"newPath": "/profile/user-preferences.md",
"expectedSha256": updated["contentSha256"],
})
If the destination path exists, the request returns a conflict by default. Set "overwrite": True only when replacing the destination file is acceptable.
List files by page
ListItems returns 100 files per page by default and up to 500 files per page. If the response contains nextToken, pass it unchanged 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
client.delete_item({
"memoryStoreName": "agent_files",
"scope": scope,
"path": "/profile/user-preferences.md",
"expectedSha256": renamed["contentSha256"],
})
Deleting a file removes the current file. Historical versions remain available by file ID.
View version history
Each create, update, rename, or delete operation creates an immutable historical version. Get the itemId from the current file or a previously saved response, and 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"))
Use operation to filter created, modified, or deleted versions. Version lists do not include content. Call GetItemVersion to read a specific snapshot.
Redact a historical version
Redaction is irreversible. Before you continue, verify that you selected the correct historical version.
RedactItemVersion removes the path, content, digest, and size from a historical snapshot. The operation type, version sequence, creation time, and redaction audit information remain. Repeated requests are idempotent. Redaction does not modify the current file or create a 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, GetItemVersion still returns the version without the content field.
Read file views of structured memories
If an application writes conversations or text to the service and uses structured memory APIs for semantic search, agents can also browse the same memories as files.
Continue to write and maintain data with structured memory APIs such as
AddMemories,UpdateMemory, andDeleteMemory.Use Agent Storage SDK
list_itemsandget_itemto list and read generated files.-
If a
ListItemsresponse containsreadOnly: true, the 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 against a read-only file view return READ_ONLY_STORE. Modify the source memories through structured memory APIs instead.
Common errors
|
Error code |
Cause |
Solution |
|
|
The scope is incomplete, the path is invalid, or the update request contains both |
Check all four scope fields, the path, and the update operation. |
|
|
The memory store, scope, path, or version does not exist. |
Check the file identifiers. Do not reuse a file identifier across scopes. |
|
|
The destination path for a create or rename operation already exists. |
Use a different path, or enable overwrite only when replacing the destination is acceptable. |
|
|
Another request modified the file. |
Read the latest content before deciding whether to retry. |
|
|
A concurrent change is in progress in the same scope. |
Retry with a short backoff, and then read the latest file. |
|
|
A request attempted to modify a read-only file view. |
Update the source memories through structured memory APIs. |
Limitations
Only valid UTF-8 text is supported. Each file can be up to 100 KiB.
A normalized path can be up to 800 bytes. A path cannot point to the root directory or contain empty path segments,
.,.., or NUL characters.Each scope stores up to 2,000 current files by default.
All Item APIs require all four scope fields. Wildcards are not supported.
Historical version redaction cannot be undone.