Filesystem
Read, write, mount, and manage files inside agentOS.
Every VM comes with a persistent filesystem out of the box. Files written anywhere in the VM are automatically saved to the Rivet Actor’s built-in storage and restored on wake. No configuration needed.
- Persistent by default backed by Rivet Actor storage, up to 10 GB
- Full POSIX filesystem with read, write, mkdir, stat, move, delete
- Batch operations for reading and writing multiple files at once
- Mount backends for additional storage like S3, host directories, and overlays
Mounting filesystems
The default filesystem persists automatically across sleep/wake cycles with no setup required (up to 10 GB). For larger storage or external data, mount additional filesystem drivers via the options.mounts config.
Each mount takes a path (where to mount inside the VM), a driver (the filesystem implementation), and an optional readOnly flag.
In-memory
import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import { createInMemoryFileSystem } from "@rivet-dev/agent-os-core";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({
options: {
software: [common, pi],
mounts: [
{ path: "/mnt/scratch", driver: createInMemoryFileSystem() },
],
},
});
export const registry = setup({ use: { vm } });
registry.start();
Host directory
import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import { createHostDirBackend } from "@rivet-dev/agent-os-core";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({
options: {
software: [common, pi],
mounts: [
{ path: "/mnt/code", driver: createHostDirBackend({ hostPath: "/path/to/repo" }), readOnly: true },
],
},
});
export const registry = setup({ use: { vm } });
registry.start();
S3
Install @rivet-dev/agent-os-s3 for S3-compatible storage.
Per-agent storage (recommended)
Use createS3BackendForAgent to automatically scope S3 storage by agent key. Each agent instance gets its own prefix (agents/{key}/) within the bucket, so you don’t need to manage prefixes manually.
import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import { createS3BackendForAgent } from "@rivet-dev/agent-os-s3";
import type { AgentOsContext } from "@rivet-dev/agent-os-s3";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
function createVm(context: AgentOsContext) {
return agentOs({
options: {
software: [common, pi],
mounts: [
{
path: "/mnt/data",
driver: createS3BackendForAgent(context, {
bucket: "my-bucket",
region: "us-east-1",
}),
},
],
},
});
}
The AgentOsContext object contains:
key— unique identifier for the agent instance (e.g. actor ID, user ID, session ID). Used as the S3 prefix.metadata— optional key-value pairs with additional agent information.
Fixed prefix
For shared storage or custom prefix schemes, use createS3Backend with an explicit prefix.
import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import { createS3Backend } from "@rivet-dev/agent-os-s3";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({
options: {
software: [common, pi],
mounts: [
{
path: "/mnt/data",
driver: createS3Backend({
bucket: "my-bucket",
prefix: "agent-data/",
region: "us-east-1",
}),
},
],
},
});
export const registry = setup({ use: { vm } });
registry.start();
Google Drive
Install @rivet-dev/agent-os-google-drive for Google Drive storage.
import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import { GoogleDriveBlockStore } from "@rivet-dev/agent-os-google-drive";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({
options: {
software: [common, pi],
mounts: [
{
path: "/mnt/drive",
driver: new GoogleDriveBlockStore({
credentials: {
clientEmail: process.env.GOOGLE_DRIVE_CLIENT_EMAIL!,
privateKey: process.env.GOOGLE_DRIVE_PRIVATE_KEY!,
},
folderId: process.env.GOOGLE_DRIVE_FOLDER_ID!,
}),
},
],
},
});
export const registry = setup({ use: { vm } });
registry.start();
Filesystem operations
Read and write
// Write a file (string or Uint8Array)
await agent.writeFile("/home/user/hello.txt", "Hello, world!");
// Read a file (returns Uint8Array)
const content = await agent.readFile("/home/user/hello.txt");
console.log(new TextDecoder().decode(content));
Batch read and write
// Batch write (creates parent directories automatically)
const writeResults = await agent.writeFiles([
{ path: "/home/user/src/index.ts", content: "console.log('hello');" },
{ path: "/home/user/src/utils.ts", content: "export function add(a: number, b: number) { return a + b; }" },
]);
// Batch read
const readResults = await agent.readFiles([
"/home/user/src/index.ts",
"/home/user/src/utils.ts",
]);
for (const result of readResults) {
console.log(result.path, new TextDecoder().decode(result.content));
}
Directories
// Create a directory
await agent.mkdir("/home/user/projects");
// List directory contents
const entries = await agent.readdir("/home/user/projects");
// Recursive listing with metadata
const tree = await agent.readdirRecursive("/home/user", {
maxDepth: 3,
exclude: ["node_modules"],
});
for (const entry of tree) {
console.log(entry.type, entry.path, entry.size);
}
File metadata
// Check if a path exists
const fileExists = await agent.exists("/home/user/hello.txt");
// Get file metadata
const info = await agent.stat("/home/user/hello.txt");
console.log(info.size, info.isDirectory, info.mtimeMs);
Move and delete
// Move/rename
await agent.move("/home/user/old.txt", "/home/user/new.txt");
// Delete a file
await agent.deleteFile("/home/user/new.txt");
// Delete a directory recursively
await agent.deleteFile("/home/user/temp", { recursive: true });