Mastra Workspaces

Trust: ★★★☆☆ (0.90) · 0 validations · developer_reference

Published: 2026-05-11 · Source: crawler_authoritative

Tình huống

Configuration and usage guide for Mastra workspaces — a persistent environment giving agents filesystem access, shell command execution, semantic code inspection, and indexed search capabilities.

Insight

A Mastra workspace provides agents with a persistent environment for storing files and executing commands. The workspace class supports five main features: Filesystem (read, write, list, delete, copy, move, grep operations), Sandbox (shell commands and background processes), LSP inspection (hover, definition, and implementation queries through language servers), Search (BM25, vector, or hybrid search over indexed content), and Skills (reusable instruction definitions). Workspaces are instantiated from @mastra/core/workspace using the Workspace class with configurable feature providers. The two primary building blocks are filesystem (file tools) and sandbox (command execution), with mounts serving as a FUSE-based bridge to connect cloud storage providers into sandboxes. For local development, LocalFilesystem and LocalSandbox are paired pointing at the same directory. Cloud storage integration uses mounts with providers like S3Filesystem or GCSFilesystem mounted at specific paths inside a sandbox. The filesystem and mounts options are mutually exclusive. Tool configuration through the tools option supports enabled (boolean or function), requireApproval (boolean or function with args access), requireReadBeforeWrite (boolean or function), name (custom tool name), and maxOutputTokens (default 2000) per tool. Tool names can be remapped using WORKSPACE_TOOLS constants like WORKSPACE_TOOLS.FILESYSTEM.READ_FILE, WORKSPACE_TOOLS.FILESYSTEM.GREP, WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND, and WORKSPACE_TOOLS.LSP.LSP_INSPECT. Dynamic filesystem is supported via a resolver function receiving requestContext. Read-before-write enforcement uses FileReadRequiredError at the tool layer and StaleFileError at the filesystem layer, with expectedMtime passed through write options. LSP inspection adds the mastra_workspace_lsp_inspect tool. Output truncation applies line-based tail (last 200 lines default) and token-based limits (2000 tokens default). ANSI escape codes are stripped automatically.

Hành động

Import Workspace and desired providers from @mastra/core/workspace. Create a workspace instance with configuration options, then assign it either globally to the Mastra instance or directly to individual agents. For local development, use LocalFilesystem and LocalSandbox both pointing to the same directory. For cloud storage in sandboxes, use mounts with S3Filesystem or GCSFilesystem at specific mount paths inside an E2BSandbox. For filesystem-only scenarios without commands, use a single filesystem provider. For sandbox-only, omit filesystem and mounts. Call optional init() method before first use in standalone scripts or when pre-provisioning resources. Configure tool behavior using the tools option with WORKSPACE_TOOLS constants for per-tool overrides. Enable requireApproval for write operations, requireReadBeforeWrite to prevent overwriting unseen files, and maxOutputTokens to adjust token limits. Remap tool names using the name option to match agent expectations.

Kết quả

Agents receive the corresponding tools in their toolset based on configured features. Files written through filesystem are immediately available to sandbox commands when both use the same local directory. Cloud-mounted paths are accessible directly via standard shell commands (e.g., ls /data). Read-before-write enforcement throws FileReadRequiredError for modified files and StaleFileError for externally changed files. Large outputs are automatically truncated to configured line and token limits. LSP inspection returns hover information, definition locations, and implementations for code symbols.

Điều kiện áp dụng

@mastra/[email protected] or later. filesystem and mounts are mutually exclusive. Tool names must be unique when remapping.


Nội dung gốc (Original)

Workspaces

Added in: @mastra/[email protected]

A Mastra workspace gives agents a persistent environment for storing files and executing commands. Agents use workspace tools to read and write files, run shell commands, and search indexed content.

A workspace supports the following features:

  • Filesystem: File storage (read, write, list, delete, copy, move, grep)
  • Sandbox: Command execution (shell commands) and background processes
  • LSP inspection: Hover, definition, and implementation queries through language servers
  • Search: BM25, vector, or hybrid search over indexed content
  • Skills: Reusable instructions for agents

When to use workspaces

Use a workspace when your agent needs access to the local filesystem, shell commands, semantic code inspection, indexed search, or reusable skill instructions.

How it works

When you assign a workspace to an agent, Mastra includes the corresponding tools in the agent’s toolset. The agent can then use these tools to interact with files and execute commands.

You can create a workspace with any combination of the supported features. The agent receives only the tools relevant to what’s configured.

Usage

Creating a workspace

Create a workspace by instantiating the Workspace class with your desired features:

import { Workspace, LocalFilesystem, LocalSandbox } from '@mastra/core/workspace'
 
const workspace = new Workspace({
  filesystem: new LocalFilesystem({
    basePath: './workspace',
  }),
  sandbox: new LocalSandbox({
    workingDirectory: './workspace',
  }),
  skills: ['skills'],
})

The skills array specifies paths to directories containing skill definitions, see Skills.

Global workspace

Set a workspace on the Mastra instance. All agents inherit this workspace unless they define their own:

import { Mastra } from '@mastra/core'
import { Workspace, LocalFilesystem } from '@mastra/core/workspace'
 
const workspace = new Workspace({
  filesystem: new LocalFilesystem({ basePath: './workspace' }),
})
 
const mastra = new Mastra({
  workspace,
})

Agent-level workspace

Assign a workspace directly to an agent to override the global workspace:

import { Agent } from '@mastra/core/agent'
import { Workspace, LocalFilesystem } from '@mastra/core/workspace'
 
const workspace = new Workspace({
  filesystem: new LocalFilesystem({ basePath: './agent-workspace' }),
})
 
export const myAgent = new Agent({
  id: 'my-agent',
  model: 'openai/gpt-5.4',
  workspace,
})

Configuration patterns

Workspaces support several configuration patterns depending on what capabilities your agent needs. The two main building blocks are filesystem (file tools) and sandbox (command execution), with mounts as the way to bridge cloud storage into sandboxes.

Filesystem + sandbox (local)

For local development, pair a LocalFilesystem and LocalSandbox pointed at the same directory. Since both operate on the local machine, files written through the filesystem are immediately available to commands in the sandbox:

const workspace = new Workspace({
  filesystem: new LocalFilesystem({ basePath: './workspace' }),
  sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
})

The agent receives both file tools and execute_command. This is the simplest full-featured setup.

Mounts + sandbox (cloud storage)

When you need cloud storage accessible inside a sandbox, use mounts. This FUSE-mounts the cloud filesystem into the sandbox so commands can read and write files at the mount path:

const workspace = new Workspace({
  mounts: {
    '/data': new S3Filesystem({
      bucket: 'my-bucket',
      region: 'us-east-1',
      accessKeyId: process.env.AWS_ACCESS_KEY_ID,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    }),
    '/skills': new GCSFilesystem({
      bucket: 'agent-skills',
    }),
  },
  sandbox: new E2BSandbox({ id: 'dev-sandbox' }),
})

Under the hood, mounts creates a CompositeFilesystem that routes file tool operations to the correct provider based on path prefix. Commands in the sandbox access the mounted paths directly (e.g., ls /data).

You can mount multiple providers at different paths. Each mount path must be unique and non-overlapping.

Note: filesystem and mounts are mutually exclusive — you can’t use both in the same workspace. Use filesystem for a single provider without a sandbox, or mounts when you need to combine cloud storage with a sandbox.

Filesystem only

Use a single filesystem when agents only need to read and write files. No command execution is available.

const workspace = new Workspace({
  filesystem: new S3Filesystem({
    bucket: 'my-bucket',
    region: 'us-east-1',
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  }),
})

The agent receives file tools (read_file, write_file, list_directory, grep, etc.) that operate directly against the storage provider.

Sandbox only

Use a single sandbox when agents only need to execute commands. No file tools are added.

const workspace = new Workspace({
  sandbox: new E2BSandbox({ id: 'dev-sandbox' }),
})

The agent receives the execute_command tool.

Dynamic filesystem (per-request)

Pass a resolver function to filesystem to return a different filesystem per request. This is useful for multi-tenant applications or multi-role agents where each request needs a different storage root or different permissions.

const workspace = new Workspace({
  filesystem: ({ requestContext }) => {
    const role = requestContext.get('agent-role') || 'guest'
    return new LocalFilesystem({
      basePath: `/workspaces/${role}`,
      readOnly: role !== 'admin',
    })
  },
})

One workspace instance serves all requests. The resolver runs at tool execution time, so each request gets its own filesystem. See dynamic filesystem for details.

Which pattern should I use?

ScenarioPattern
Local development with files and commandsfilesystem + sandbox (both local, same directory)
Cloud storage accessible inside a cloud sandboxmounts + sandbox
Multiple cloud providers in one sandboxmounts + sandbox (one mount per provider)
Agent reads/writes files, no command execution neededfilesystem only
Agent runs commands, no file tools neededsandbox only
Multi-role or multi-tenant agent with per-request storagefilesystem with resolver function

Tool configuration

Configure tool behavior through the tools option on the workspace. This controls which tools are enabled and how they behave.

import { Workspace, LocalFilesystem, LocalSandbox, WORKSPACE_TOOLS } from '@mastra/core/workspace'
 
const workspace = new Workspace({
  filesystem: new LocalFilesystem({ basePath: './workspace' }),
  sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
  tools: {
    // Global defaults
    enabled: true,
    requireApproval: false,
 
    // Per-tool overrides
    [WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: {
      requireApproval: true,
      requireReadBeforeWrite: true,
    },
    [WORKSPACE_TOOLS.FILESYSTEM.DELETE]: {
      enabled: false,
    },
    [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
      requireApproval: true,
    },
  },
})

Tool options

OptionTypeDescription
enabledboolean | (context) => booleanWhether the tool is available (default: true). When a function, evaluated at tool-listing time.
requireApprovalboolean | (context) => booleanWhether the tool requires user approval before execution (default: false). When a function, evaluated at execution time with access to args.
requireReadBeforeWriteboolean | (context) => booleanFor write tools: require reading the file first (default: false). When a function, evaluated at execution time with access to args.
namestringCustom name for the tool. Replaces the default mastra_workspace_* name.
maxOutputTokensnumberMaximum tokens for tool output (default: 2000). Output exceeding this limit is truncated using tiktoken.

Dynamic tool configuration

Tool options that accept functions receive a context object and return a boolean. This enables context-aware tool behavior.

const workspace = new Workspace({
  filesystem: new LocalFilesystem({ basePath: './workspace' }),
  tools: {
    // Dynamic enabled: disable command execution unless explicitly allowed
    [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
      enabled: async ({ requestContext }) => {
        return requestContext['allowExecution'] === 'true'
      },
    },
 
    // Dynamic requireApproval: only require approval for protected paths
    [WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: {
      requireApproval: async ({ args }) => {
        return (args.path as string).startsWith('/protected')
      },
      requireReadBeforeWrite: true,
    },
  },
})

Functions for enabled receive { requestContext, workspace }. Functions for requireApproval and requireReadBeforeWrite also receive args since they are evaluated when the tool is called.

Tool name remapping

Rename workspace tools to match the conventions your agent expects. The config key remains the original WORKSPACE_TOOLS constant — only the exposed name changes.

import { Workspace, LocalFilesystem, LocalSandbox, WORKSPACE_TOOLS } from '@mastra/core/workspace'
 
const workspace = new Workspace({
  filesystem: new LocalFilesystem({ basePath: './workspace' }),
  sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
  lsp: true,
  tools: {
    [WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]: { name: 'view' },
    [WORKSPACE_TOOLS.FILESYSTEM.GREP]: { name: 'search_content' },
    [WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES]: { name: 'find_files' },
    [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: { name: 'execute_command' },
    [WORKSPACE_TOOLS.LSP.LSP_INSPECT]: { name: 'lsp_inspect' },
  },
})

The agent sees view, search_content, find_files, execute_command, and lsp_inspect instead of the default mastra_workspace_* names. Tool names must be unique — duplicate names or conflicts with other default names throw an error.

LSP inspection

Enable lsp on a workspace to add semantic code inspection through language servers. This adds the mastra_workspace_lsp_inspect tool by default, which can return hover information, definition locations, and implementations for a symbol at a specific cursor position.

See LSP inspection for configuration, examples, and tool name remapping.

Output truncation

Workspace tools automatically truncate large outputs to avoid exceeding LLM context limits. Two layers of truncation apply:

  1. Line-based tail: Command output is limited to the last 200 lines by default (configurable per-command via the tail parameter)
  2. Token-based limit: Tool output is capped at 2000 tokens by default

Set maxOutputTokens per tool to adjust the token limit:

const workspace = new Workspace({
  // ...
  tools: {
    [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
      maxOutputTokens: 5000,
    },
  },
})

ANSI escape codes (colors, cursor sequences) are automatically stripped from command output before it reaches the model.

Read-before-write

When requireReadBeforeWrite is enabled on write tools, agents must read a file before writing to it. This prevents overwriting files the agent hasn’t seen:

  • New files: Can be written without reading (they don’t exist yet)
  • Existing files: Must be read first
  • Externally modified files: If a file changed since the agent read it, the write fails

File write safety is enforced at two layers:

  1. Tool layer: Before a write tool runs, the read tracker checks whether the file was modified since it was last read. If it was, the tool throws a FileReadRequiredError.
  2. Filesystem layer: At write time, writeFile() compares the file’s current modification time against the expected value (passed via expectedMtime in write options). If they don’t match, it throws a StaleFileError. This catches external modifications (for example, an editor saving the file) that happen between the tool-level check and the actual write.

When requireReadBeforeWrite is enabled, workspace tools pass the recorded modification time through automatically. You can also use expectedMtime directly when calling filesystem.writeFile() outside of tools:

const stat = await filesystem.stat('/docs/file.md')
// ... later ...
await filesystem.writeFile('/docs/file.md', newContent, {
  expectedMtime: stat.modifiedAt,
})

Initialization

Calling init() is optional in most cases—some providers initialize on first operation. Call init() manually when using a workspace outside of Mastra (standalone scripts, tests) or when you need to pre-provision resources before the first agent interaction.

import { Workspace, LocalFilesystem, LocalSandbox } from '@mastra/core/workspace'
 
const workspace = new Workspace({
  filesystem: new LocalFilesystem({ basePath: './workspace' }),
  sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
})
 
// Optional: pre-create directories and sandbox before first use
await workspace.init()

What init() does

Initialization runs setup logic for each configured provider:

  • LocalFilesystem: Creates the base directory if it doesn’t exist
  • LocalSandbox: Creates the working directory
  • Search (if configured): Indexes files from autoIndexPaths, see Search and Indexing

External providers may perform additional setup like establishing connections or authenticating.

Liên kết

Xem thêm: