Skip to main content

Filesystem

A filesystem gives an agent tools for reading, writing, listing, and searching files. Use it as a knowledge base or to persist files between ephemeral sandbox runs.

Configure files in two ways:

  • Direct filesystem access uses filesystem with one filesystem provider or a CompositeFilesystem that you create yourself.
  • Mounts uses mounts to create a CompositeFilesystem from path-prefixed providers. When a static sandbox and filesystem provider support mounting, Mastra automatically mounts the provider at its configured path. Remote sandbox mounts typically use Filesystem in Userspace (FUSE).

Configure either filesystem or mounts, not both. Configuring both throws a WorkspaceError with the code INVALID_CONFIG.

Both configurations give the agent file tools. Sandbox commands can only see a provider when the sandbox can mount it successfully.

Configuring a filesystem gives the agent these tools:

ToolDoes
read_fileReads all or part of a file.
write_fileCreates or overwrites a file.
edit_fileReplaces matching text in an existing file.
list_filesLists files and directories.
deleteDeletes a file or directory.
file_statReturns metadata about a file or directory.
mkdirCreates a directory and any missing parent directories.
grepSearches file contents with a regular expression.
ast_editApplies structural code edits. Available when @ast-grep/napi is installed.

Supported filesystems
Direct link to Supported filesystems

LocalFilesystem
Direct link to localfilesystem

LocalFilesystem connects to a directory on the same machine as your Mastra application. Use it for local development or files that already live on the application host.

Other filesystems
Direct link to Other filesystems

Use another provider when files live outside the application host or already exist in an external service:

Every provider supports file tools through filesystem. Sandbox mounting depends on both the filesystem provider and sandbox backend.

Direct filesystem access
Direct link to Direct filesystem access

Use filesystem when the agent should access a provider through file tools. It can also accept a resolver or a manually created CompositeFilesystem.

Give an agent file tools for a local knowledge base:

import { LocalFilesystem, Workspace } from '@mastra/core/workspace'

const workspace = new Workspace({
filesystem: new LocalFilesystem({
basePath: './knowledge-base',
}),
})

The agent receives tools such as read_file, write_file, list_files, and grep. Paths are resolved under ./knowledge-base, and no sandbox or command tools are required.

See Search to index the files for keyword or semantic retrieval. See the filesystem tools reference for every generated tool and its policies.

Mounts
Direct link to Mounts

Use mounts when programs inside a sandbox need to access persistent files by path. Mastra creates the mount automatically when the sandbox and filesystem provider support it. The agent still receives file tools, while command tools can run commands such as ls, cat, or python against the same files.

For example, mount an S3 bucket at /workspace inside a Daytona sandbox:

import { Mastra } from '@mastra/core'
import { Workspace } from '@mastra/core/workspace'
import { DaytonaSandbox } from '@mastra/daytona'
import { S3Filesystem } from '@mastra/s3'

const workspace = new Workspace({
mounts: {
'/workspace': new S3Filesystem({
bucket: process.env.S3_BUCKET!,
region: 'us-east-1',
}),
},
sandbox: new DaytonaSandbox(),
})

export const mastra = new Mastra({ workspace })

Using mounts
Direct link to Using mounts

Files already available through the provider appear under /workspace. The agent can call read_file('/workspace/report.md') or run cat /workspace/report.md. Files written through either interface are saved by the provider and remain available after the sandbox stops.

Without a mount, an agent can still combine file tools with sandbox commands by passing file contents between tool calls. This works for selected text files. Mounts are a better fit when programs expect a directory tree or need to process large or binary files.

warning

File-tool and command-tool policies are independent. Requiring approval for write_file, for example, doesn't stop the agent from using execute_command to write the same mounted path. If files must only be accessed through file tools, disable sandbox command tools.

Paths
Direct link to Paths

A mount path is the path exposed to file tools and, after a successful sandbox mount, commands. The underlying provider may store those files somewhere else.

For a remote provider mounted at /workspace:

  • File tools use paths such as /workspace/report.md.
  • Remote sandbox commands generally use the same path.
  • The provider maps the path to its configured bucket, prefix, or remote directory.

LocalSandbox creates a symlink inside its workingDirectory instead. A /workspace mount becomes <workingDirectory>/workspace on the host and is usually addressed as workspace by commands.

Composite filesystem
Direct link to Composite filesystem

The mounts option creates a CompositeFilesystem. This TypeScript path router presents several providers as one virtual directory tree.

Multiple filesystems
Direct link to Multiple filesystems

Configure each provider under its mount path:

import { Workspace } from '@mastra/core/workspace'
import { E2BSandbox } from '@mastra/e2b'
import { GCSFilesystem } from '@mastra/gcs'
import { S3Filesystem } from '@mastra/s3'

const workspace = new Workspace({
mounts: {
'/data': new S3Filesystem({
bucket: 'agent-data',
region: 'us-east-1',
}),
'/reports': new GCSFilesystem({
bucket: 'agent-reports',
}),
},
sandbox: new E2BSandbox({ id: 'analysis-sandbox' }),
})

With this configuration:

  • list_files('/') returns the virtual directories data and reports.
  • read_file('/data/input.csv') routes to the S3 provider.
  • write_file('/reports/summary.md') routes to the Google Cloud Storage provider.
  • Sandbox commands use the same paths when each sandbox mount succeeds.

The composite strips the mount prefix before passing the remaining path to its provider. Mount paths can't be nested, so the same composite can't contain both /data and /data/archive.

Without a sandbox
Direct link to Without a sandbox

You can configure mounts without a sandbox. Mastra still creates the CompositeFilesystem, and all file tools work with mount-prefixed paths. The agent receives no command or process tools because no sandbox is configured.

Manual composition
Direct link to Manual composition

You can also create a CompositeFilesystem yourself and pass it through filesystem for path routing without automatic sandbox mount wiring:

import { CompositeFilesystem, LocalFilesystem, Workspace } from '@mastra/core/workspace'
import { S3Filesystem } from '@mastra/s3'

const filesystem = new CompositeFilesystem({
mounts: {
'/local': new LocalFilesystem({ basePath: './data' }),
'/archive': new S3Filesystem({
bucket: 'agent-archive',
region: 'us-east-1',
}),
},
})

const workspace = new Workspace({ filesystem })

Use manual composition when another part of your application needs the composite as a filesystem provider. For normal sandbox mounting, the mounts option performs the same routing setup with less configuration.

Mount availability
Direct link to Mount availability

File tools and composite routing work without a sandbox mount. When a remote sandbox and filesystem provider support mounting, mounts automatically uses FUSE to make the files visible to commands. LocalSandbox uses symlinks instead.

Built-in sandbox mounting currently includes:

Sandbox backendFilesystem providers
LocalSandboxLocalFilesystem
E2BAmazon S3, Google Cloud Storage, Azure Blob Storage
DaytonaAmazon S3, Google Cloud Storage, Azure Blob Storage
BlaxelAmazon S3, Google Cloud Storage

Remote mounts may require s3fs, gcsfuse, or blobfuse2 inside the sandbox. Some backends install missing software during startup, which can require network access and additional startup time. Other combinations require an onMount hook or provider-specific setup.

If a sandbox mount is unavailable or fails, the workspace remains usable. File tools continue to access the provider through its SDK, but commands can't see that path. Mastra describes these providers to the agent as available through file tools only.

Filesystems per user or thread
Direct link to Filesystems per user or thread

The filesystem option accepts a resolver when storage should vary by request, user, role, or tenant:

const workspace = new Workspace({
filesystem: ({ requestContext }) => {
const userId = requestContext.get('user-id') as string

return new S3Filesystem({
bucket: process.env.S3_BUCKET!,
region: process.env.S3_REGION!,
prefix: `users/${userId}`,
})
},
})

Each user gets a separate filesystem view, and file tools resolve the provider from the request context automatically.

mounts doesn't accept a resolver and can't be combined with a sandbox resolver. When each user or thread needs separate storage inside a separate sandbox, create and mount the provider inside the sandbox resolver. See Sandboxes per user or thread.

Policies and containment
Direct link to Policies and containment

Use individual constants under WORKSPACE_TOOLS.FILESYSTEM, such as WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE, to configure each file tool. Set approval globally or per tool. Configure read-before-write and output limits on individual filesystem tool entries. See the filesystem tool configuration reference.

LocalFilesystem contains access within basePath by default. Use allowedPaths when the agent needs specific directories outside that root:

const workspace = new Workspace({
filesystem: new LocalFilesystem({
basePath: './knowledge-base',
allowedPaths: ['../shared-policies'],
}),
})

Containment applies to filesystem operations, including file tools and search indexing. It doesn't restrict shell commands.

Set readOnly: true when the agent should use files without changing them. For a static provider, Mastra removes write-related file tools.

With a filesystem resolver, write tools remain registered because the provider isn't known until the request runs. The provider rejects write attempts at runtime.

For LocalFilesystem entries in a composite, keep contained: true, which is the default. Set contained: false only when unrestricted host filesystem access is intentional.