> Discover all available pages from the documentation index: https://mastra.ai/llms.txt

# Workspace class

**Added in:** `@mastra/core@1.1.0`

The `Workspace` class combines a filesystem and sandbox to provide agents with file storage and command execution capabilities. It also supports BM25 and vector search for indexed content.

## Usage example

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

const workspace = new Workspace({
  id: 'my-workspace',
  name: 'My Workspace',
  filesystem: new LocalFilesystem({
    basePath: './workspace',
  }),
  sandbox: new LocalSandbox({
    workingDirectory: './workspace',
  }),
  bm25: true,
  autoIndexPaths: ['docs'],
})
```

## Constructor parameters

**id** (`string`): Unique identifier for the workspace (Default: `Auto-generated`)

**name** (`string`): Human-readable name (Default: `workspace-{id}`)

**filesystem** (`WorkspaceFilesystem | WorkspaceFilesystemResolver`): Filesystem provider instance, or a resolver function that receives requestContext and returns a filesystem per request. See filesystems per user or thread.

**sandbox** (`WorkspaceSandbox | WorkspaceSandboxResolver`): Sandbox provider instance, or a resolver function that receives requestContext and returns a sandbox per request. See sandboxes per user or thread.

**instructions.dynamicSandbox** (`'placeholder' | 'resolve' | (({ requestContext }) => string)`): Controls how a resolver-backed sandbox contributes to workspace instructions. 'placeholder' (default) emits stable text without calling the resolver. 'resolve' calls the resolver and uses the sandbox's own instructions. A function returns custom text without resolving. Has no effect on a static sandbox. (Default: `'placeholder'`)

**sandboxCacheKey** (`({ requestContext }) => string | undefined`): Stable cache key for a resolver-backed sandbox. When set, resolved sandboxes are memoized per key instead of per RequestContext instance, so background-process tools reach the same sandbox across follow-up requests. Has no effect on a static sandbox.

**bm25** (`boolean | BM25Config`): Enable BM25 keyword search. Pass true for defaults or a config object. (Default: `undefined`)

**vectorStore** (`MastraVector`): Vector store for semantic search

**embedder** (`Embedder`): Function that turns text into vectors. Required when vectorStore is set. Accepts either a single-text function (text: string) => Promise\<number\[]> or a batch-capable function (texts: string\[]) => Promise\<number\[]\[]> that has a batch: true property and an optional maxBatchSize. See Batch embedding.

**autoIndexPaths** (`string[]`): Paths or glob patterns to auto-index on init(). Supports glob patterns like '\*\*/\*.md' for selective indexing.

**skills** (`string[] | ((context: SkillsContext) => string[] | Promise<string[]>)`): Paths where SKILL.md files are located. This can be a static array or an async function that resolves paths dynamically. Supports glob patterns like './\*\*/skills' for discovery.

**skillSource** (`SkillSource`): Custom skill source for skill discovery. When provided, this source is used instead of the workspace filesystem. Use VersionedSkillSource to serve published skill versions from a content-addressable blob store.

**onMount** (`OnMountHook`): Pre-mount hook called for each filesystem before mounting into a sandbox. Return false to skip mounting, or return { success: true } if the hook handled the mount. Return undefined to use the default mount behavior.

**searchIndexName** (`string`): Custom index name for the vector store. Must be a valid SQL identifier (start with a letter or underscore, contain only letters, numbers, or underscores, max 63 characters). Defaults to a sanitized version of '{id}\_search'.

**tools** (`WorkspaceToolsConfig`): Per-tool configuration for enabling tools and setting safety options

**tools.enabled** (`boolean | ((context: ToolConfigContext) => boolean | Promise<boolean>)`): Default availability for all workspace tools. Per-tool settings take precedence.

**tools.requireApproval** (`boolean | ((context: ToolConfigWithArgsContext) => boolean | Promise<boolean>)`): Default approval policy for all workspace tools. Per-tool settings take precedence.

**tools.writeLockTimeoutMs** (`number`): Maximum time in milliseconds a write tool waits to acquire the per-file write lock before failing. Raise this for slow or cold-starting filesystems (e.g. remote sandboxes).

**tools.hooks** (`WorkspaceToolHooks`): Hooks that run before and after every enabled workspace tool call. See Tool hooks below.

**operationTimeout** (`number`): Timeout for operations in milliseconds

For a resolver-backed sandbox, the default `'placeholder'` mode avoids provisioning a sandbox while workspace instructions are built. Set `instructions.dynamicSandbox` to `'resolve'` when the instructions must come from the resolved sandbox:

```typescript
const workspace = new Workspace({
  sandbox: ({ requestContext }) => resolveSandbox(requestContext),
  instructions: { dynamicSandbox: 'resolve' },
})
```

This calls the resolver while building instructions. To describe a request-specific environment without provisioning it, pass a function that returns instruction text from `requestContext` instead.

## Tool configuration

The `tools` option accepts a `WorkspaceToolsConfig` object that controls which workspace tools are enabled and their safety settings.

```typescript
import { Workspace } from '@mastra/core/workspace'
import { WORKSPACE_TOOLS } from '@mastra/core/workspace'

const workspace = new Workspace({
  id: 'my-workspace',
  name: 'My Workspace',
  tools: {
    // Global defaults (apply to all tools)
    enabled: true,
    requireApproval: false,

    // Per-tool overrides using WORKSPACE_TOOLS constants
    [WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: {
      requireApproval: true,
    },
  },
})
```

The config object has two types of settings:

- **Global settings**: `enabled` and `requireApproval` apply to all workspace tools unless overridden. `hooks` and `writeLockTimeoutMs` are global-only and can't be configured per tool.
- **Per-tool overrides**: Use `WORKSPACE_TOOLS` constants as keys to configure individual tools

Per-tool overrides accept the following options:

**enabled** (`boolean | ((context: ToolConfigContext) => boolean | Promise<boolean>)`): Whether the tool is available. Functions are evaluated when Mastra lists tools. (Default: `true`)

**requireApproval** (`boolean | ((context: ToolConfigWithArgsContext) => boolean | Promise<boolean>)`): Whether the tool requires approval. Functions are evaluated when the tool executes. (Default: `false`)

**name** (`string`): Name exposed to the model instead of the default mastra\_workspace\_\* name.

**requireReadBeforeWrite** (`boolean | ((context: ToolConfigWithArgsContext) => boolean | Promise<boolean>)`): For write tools, require the agent to read an existing file before changing it. (Default: `false`)

**maxOutputTokens** (`number`): Maximum output tokens for tools that support token-based truncation.

`ToolConfigContext` contains `{ requestContext, workspace }`. Execution-time policies use `ToolConfigWithArgsContext`, which also contains the tool's `args`.

```typescript
import { Workspace, WORKSPACE_TOOLS } from '@mastra/core/workspace'

const workspace = new Workspace({
  id: 'my-workspace',
  tools: {
    enabled: ({ requestContext }) => requestContext.get('workspace-tools') === true,
    [WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: {
      requireApproval: ({ args }) => (args.path as string).startsWith('/protected'),
      requireReadBeforeWrite: true,
    },
    [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
      maxOutputTokens: 5000,
    },
  },
})
```

See [Filesystem tools](https://mastra.ai/docs/sandbox/filesystem), [Sandbox tools](https://mastra.ai/docs/sandbox/overview), [LSP inspection](https://mastra.ai/docs/sandbox/lsp), and [Search tools](https://mastra.ai/docs/sandbox/search) for capability-specific configuration.

### Tool name remapping

Rename workspace tools by setting the `name` property on individual tool configs. The config key remains the original constant: only the name exposed to the agent changes.

```typescript
import { Workspace } from '@mastra/core/workspace'
import { WORKSPACE_TOOLS } from '@mastra/core/workspace'

const workspace = new Workspace({
  id: 'my-workspace',
  name: 'My Workspace',
  tools: {
    [WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]: { name: 'view' },
    [WORKSPACE_TOOLS.FILESYSTEM.GREP]: { name: 'search_content' },
  },
})
```

Tool names must be unique across all workspace tools. Setting a custom name that conflicts with another tool's default or custom name throws an error.

### Tool hooks

Set `tools.hooks` to run logic before and after every enabled workspace tool call. Hooks run after name remapping, so the context includes both the exposed `toolName` and the original `workspaceToolName`.

```typescript
import { Workspace } from '@mastra/core/workspace'

const workspace = new Workspace({
  id: 'my-workspace',
  tools: {
    hooks: {
      beforeToolCall: ({ toolName, workspaceToolName, input }) => {
        console.log(`Running ${toolName} (${workspaceToolName})`, input)
      },
      afterToolCall: ({ toolName, output, error }) => {
        console.log(`Finished ${toolName}`, { output, error })
      },
    },
  },
})
```

**beforeToolCall** (`(context: WorkspaceToolHookContext) => void | WorkspaceToolBeforeHookResult | Promise<void | WorkspaceToolBeforeHookResult>`): Runs before a workspace tool executes. Receives { toolName, workspaceToolName, input, context }. Return { proceed: false, output } to skip the tool call and use output as its result.

**afterToolCall** (`(context: WorkspaceToolAfterHookContext) => void | Promise<void>`): Runs after a workspace tool executes. Receives { toolName, workspaceToolName, input, context, output, error }. output is undefined when the tool throws, and error is set instead.

If the owning agent also defines [tool hooks](https://mastra.ai/reference/agents/agent), workspace hooks run inside the agent hook wrapper. The order is agent `beforeToolCall` → workspace `beforeToolCall` → tool → workspace `afterToolCall` → agent `afterToolCall`.

## Properties

**id** (`string`): Workspace identifier

**name** (`string`): Workspace name

**status** (`WorkspaceStatus`): 'pending' | 'initializing' | 'ready' | 'paused' | 'error' | 'destroying' | 'destroyed'

**filesystem** (`WorkspaceFilesystem | undefined`): The static filesystem provider. Returns undefined when a resolver function is configured — use hasFilesystemConfig() to check availability.

**sandbox** (`WorkspaceSandbox | undefined`): The static sandbox provider. Returns undefined when a resolver function is configured — use hasSandboxConfig() to check availability.

**skills** (`WorkspaceSkills | undefined`): Skills interface for accessing SKILL.md files

**canBM25** (`boolean`): Whether BM25 search is available

**canVector** (`boolean`): Whether vector search is available

**canHybrid** (`boolean`): Whether hybrid search is available

## Methods

### Lifecycle

#### `init()`

Initialize the workspace and prepare resources.

```typescript
await workspace.init()
```

Calling `init()` is optional in most cases:

- **Sandbox**: Auto-starts on first `executeCommand()` call. Use `init()` to avoid first-command latency.
- **Filesystem**: Creates the base directory and runs any provider-specific setup. Some providers auto-create the directory on first operation.
- **Search**: Required only if using `autoIndexPaths` for auto-indexing.

Initialization performs:

- Starts the filesystem provider (creates base directory if needed)
- Starts the sandbox provider (creates working directory, sets up isolation if configured)
- Indexes files from `autoIndexPaths` for search

#### `stop()`

Stop the workspace's live resources without destroying them.

```typescript
await workspace.stop()
```

`stop()` shuts down language servers and closes the browser, then stops the sandbox provider. Remote sandbox providers suspend or pause the sandbox so it can resume later. `LocalSandbox` kills its background processes and unmounts filesystems. Stopping isn't a teardown. The filesystem, search index, and skills keep working, and the next sandbox operation starts the sandbox again.

`mastra.shutdown()` calls `stop()` for registered workspaces, so a process restart suspends remote sandboxes instead of deleting them. To fully tear a workspace down, call `destroy()` or `mastra.removeWorkspace(id, { destroy: true })` explicitly.

#### `destroy()`

Destroy the workspace and clean up resources.

```typescript
await workspace.destroy()
```

`destroy()` closes workspace-owned resources in order: language servers, browsers, sandbox providers, and filesystem providers. It also clears cached sandbox references.

Call `destroy()` when your application is done with a workspace and its sandbox. To remove a workspace from the Mastra registry, use [`mastra.removeWorkspace()`](https://mastra.ai/reference/core/removeWorkspace).

`LocalFilesystem.destroy()` doesn't delete files on disk. Resolver-backed filesystem and sandbox providers are owned by your application and must be cleaned up by your application.

### Search operations

#### `index(path, content, options?)`

Index content for search.

```typescript
await workspace.index('/docs/guide.md', 'Guide content...')
```

#### `search(query, options?)`

Search indexed content.

```typescript
const results = await workspace.search('password reset', {
  topK: 10,
  mode: 'hybrid',
})
```

### Utility

#### `getInfo()`

Get workspace information.

```typescript
const info = await workspace.getInfo()
// { id, name, status, createdAt, lastAccessedAt, filesystem?, sandbox? }
```

Pass `resolveDynamicProviders: false` to report resolver-backed providers as runtime-defined without invoking their resolver.

```typescript
const info = await workspace.getInfo({ resolveDynamicProviders: false })
```

**Parameters:**

**options.includeFileCount** (`boolean`): Whether to count total files. This can be slow for large workspaces.

**options.requestContext** (`RequestContext`): Passed to dynamic provider resolvers when resolveDynamicProviders is enabled.

**options.resolveDynamicProviders** (`boolean`): Whether to invoke dynamic provider resolvers. Set to false when you only need metadata and want resolver-backed providers reported as dynamic. (Default: `true`)

#### `getInstructions(opts?)`

Returns combined instructions from the filesystem and sandbox providers. Injected into the agent's system message to help it understand the execution context.

```typescript
const instructions = workspace.getInstructions()
```

Pass `requestContext` to enable per-request customization when a provider's `instructions` option is a function:

```typescript
const instructions = workspace.getInstructions({ requestContext })
```

**Parameters:**

**opts.requestContext** (`RequestContext`): Forwarded to the instructions function on the filesystem or sandbox provider, if one is configured.

**Returns:** `string`

#### `getInstructionsAsync(opts?)`

Returns combined workspace instructions. Use this when the workspace uses resolver-backed providers. A runtime-defined filesystem is resolved per request. A runtime-defined sandbox contributes stable placeholder text unless `instructions.dynamicSandbox` is set to `'resolve'`.

```typescript
const instructions = await workspace.getInstructionsAsync({ requestContext })
```

**Parameters:**

**opts.requestContext** (`RequestContext`): Passed to the dynamic filesystem resolver, and to the dynamic sandbox resolver when instructions.dynamicSandbox is 'resolve'.

**Returns:** `Promise<string>`

To override the default output, pass an `instructions` option to [LocalFilesystem](https://mastra.ai/reference/workspace/local-filesystem) or [LocalSandbox](https://mastra.ai/reference/workspace/local-sandbox).

#### `getToolsConfig()`

Get the current tools configuration.

```typescript
const config = workspace.getToolsConfig()
```

**Returns:** `WorkspaceToolsConfig | undefined`

#### `setToolsConfig(config?)`

Replace the per-tool configuration at runtime. This performs a full replacement: it doesn't merge with the previous config. Pass `undefined` to reset to defaults. Changes take effect on the next agent interaction (the next `createWorkspaceTools()` call).

```typescript
import { WORKSPACE_TOOLS } from '@mastra/core/workspace'

// Disable write tools for read-only mode
workspace.setToolsConfig({
  [WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: { enabled: false },
  [WORKSPACE_TOOLS.FILESYSTEM.EDIT_FILE]: { enabled: false },
})

// Reset to defaults
workspace.setToolsConfig(undefined)
```

**Parameters:**

**config** (`WorkspaceToolsConfig | undefined`): New tool configuration to apply. Pass undefined to reset to defaults.

### Dynamic filesystem

#### `hasFilesystemConfig()`

Check whether a filesystem is configured, either as a static instance or a resolver function. Use this instead of checking `workspace.filesystem` directly, because a resolver-based workspace returns `undefined` from the `filesystem` property.

```typescript
if (workspace.hasFilesystemConfig()) {
  // Filesystem tools are available
}
```

**Returns:** `boolean`

#### `resolveFilesystem({ requestContext })`

Resolve the filesystem for a request context. When a resolver function is configured, calls it with the provided `requestContext`. When a static filesystem is configured, returns it directly. Returns `undefined` if no filesystem is configured.

```typescript
import { RequestContext } from '@mastra/core/request-context'

const ctx = new RequestContext([['agent-role', 'admin']])
const fs = await workspace.resolveFilesystem({ requestContext: ctx })
```

**Parameters:**

**requestContext** (`RequestContext`): The request context to pass to the resolver function.

**Returns:** `Promise<WorkspaceFilesystem | undefined>`

### Dynamic sandbox

#### `hasSandboxConfig()`

Check whether a sandbox is configured, either as a static instance or a resolver function. Use this instead of checking `workspace.sandbox` directly, because a resolver-based workspace returns `undefined` from the `sandbox` property.

```typescript
if (workspace.hasSandboxConfig()) {
  // Sandbox tools are available
}
```

**Returns:** `boolean`

#### `resolveSandbox({ requestContext })`

Resolve the sandbox for a request context. When a resolver function is configured, calls it with the provided `requestContext`. When a static sandbox is configured, returns it directly. Returns `undefined` if no sandbox is configured.

```typescript
import { RequestContext } from '@mastra/core/request-context'

const ctx = new RequestContext([['user-id', 'alice']])
const sandbox = await workspace.resolveSandbox({ requestContext: ctx })
```

**Parameters:**

**requestContext** (`RequestContext`): The request context to pass to the resolver function.

**Returns:** `Promise<WorkspaceSandbox | undefined>`

#### `clearSandboxCache(cacheKey?)`

Clear resolver-backed sandboxes cached by `sandboxCacheKey`. Pass a cache key to clear one entry, or omit it to clear all keyed sandbox entries.

This method doesn't clear the per-`RequestContext` weak cache. Those entries are garbage-collection managed.

The workspace doesn't own resolver-returned sandboxes. This method only drops workspace references. Destroy the sandbox in your own lifecycle code.

```typescript
workspace.clearSandboxCache('thread-123')
workspace.clearSandboxCache()
```

**Parameters:**

**cacheKey** (`string`): The cache key to clear. Omit this value to clear all keyed sandbox entries.

**Returns:** `void`

## Agent tools

A workspace provides tools to agents based on what's configured.

### Filesystem tools

Added when a filesystem is configured:

| Tool                          | Description                                                                                                                                                                                                                      |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mastra_workspace_read_file`  | Read file contents. Text files return as text (with optional line range). Images and PDFs return as native media parts the model can view directly. Other binaries return metadata only unless an explicit `encoding` is passed. |
| `mastra_workspace_write_file` | Create or overwrite a file with new content. Creates parent directories automatically.                                                                                                                                           |
| `mastra_workspace_edit_file`  | Edit an existing file by finding and replacing text. Useful for targeted changes without rewriting the entire file.                                                                                                              |
| `mastra_workspace_list_files` | List directory contents as a tree structure. Supports recursive listing with depth limits, glob patterns, and `.gitignore` filtering (enabled by default).                                                                       |
| `mastra_workspace_delete`     | Delete a file or directory. Supports recursive deletion for directories.                                                                                                                                                         |
| `mastra_workspace_file_stat`  | Get metadata about a file or directory including size, type, and modification time.                                                                                                                                              |
| `mastra_workspace_mkdir`      | Create a directory. Creates parent directories automatically if they don't exist.                                                                                                                                                |
| `mastra_workspace_grep`       | Search file contents using regex patterns. Supports glob filtering, context lines, and case-insensitive search.                                                                                                                  |

With a static filesystem, write tools (`write_file`, `edit_file`, `delete`, `mkdir`) are excluded when the filesystem is in read-only mode. With a [runtime-defined filesystem](https://mastra.ai/docs/sandbox/filesystem), write tools are always included and read-only is enforced at runtime.

The `read_file` tool accepts `mediaTypes` and `maxMediaBytes` options to control which mime types are surfaced to the model as native media parts and how large those files can be:

**mediaTypes** (`string[] | ((mimeType: string) => boolean) | false`): Which mime types to surface to the model as media parts (file/image parts) rather than as text. Accepts an array of globs (e.g. \['image/\*']), a custom predicate function, or false to disable media detection. Defaults to the cross-provider-safe intersection of image formats plus PDF. Only applies when the caller doesn't pass an explicit encoding. (Default: `['image/png', 'image/jpeg', 'image/webp', 'application/pdf']`)

**maxMediaBytes** (`number`): Maximum file size (in bytes) to inline as a media part. Files larger than this fall back to metadata-only output rather than being fully base64-encoded into context and persisted in storage on rehydration. (Default: `10 * 1024 * 1024 (10 MiB)`)

```typescript
const workspace = new Workspace({
  filesystem: new LocalFilesystem({ basePath: './workspace' }),
  tools: {
    [WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]: {
      // Broaden to any image (including SVG, BMP, HEIC) — may fail on some providers
      mediaTypes: ['image/*'],
      // Raise the inline-media cap to 25 MiB
      maxMediaBytes: 25 * 1024 * 1024,
    },
  },
})
```

### Sandbox tools

Added when a sandbox is configured:

| Tool                                  | Description                                                                                                                                                                                      |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `mastra_workspace_execute_command`    | Execute a shell command. Returns stdout, stderr, and exit code. When the sandbox has a process manager, accepts `background: true` to spawn a long-running process and return a PID.             |
| `mastra_workspace_get_process_output` | Get stdout, stderr, and status of a background process by PID. Accepts `tail` to limit output lines and `wait: true` to block until exit. Only available when the sandbox has a process manager. |
| `mastra_workspace_kill_process`       | Kill a background process by PID. Returns the last 50 lines of output. Only available when the sandbox has a process manager.                                                                    |

With a static sandbox, capability checks (`executeCommand`, `processes`) decide which tool variants are exposed. With a [runtime-defined sandbox](https://mastra.ai/docs/sandbox/overview), all sandbox tools are registered and the runtime throws a clear error if the resolved sandbox doesn't implement a requested capability.

The `execute_command` tool accepts a `backgroundProcesses` option for lifecycle callbacks on background processes:

**backgroundProcesses** (`BackgroundProcessesConfig`): Configuration for handling background processes. Only applicable if the sandbox supports background execution.

**backgroundProcesses.onStdout** (`(data: string, meta: BackgroundProcessMeta) => void`): Callback for stdout chunks from background processes.

**backgroundProcesses.onStderr** (`(data: string, meta: BackgroundProcessMeta) => void`): Callback for stderr chunks from background processes.

**backgroundProcesses.onExit** (`(meta: BackgroundProcessExitMeta) => void`): Callback when a background process exits. Meta includes pid, exitCode, stdout, and stderr.

**backgroundProcesses.abortSignal** (`AbortSignal | null | false`): Abort signal for background processes. undefined (default) uses the agent's signal. null or false disables abort — processes persist after agent shutdown.

See [Background processes](https://mastra.ai/docs/sandbox/overview) for callback examples.

### Search tools

Added when BM25 or vector search is configured:

| Tool                      | Description                                                                                                           |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `mastra_workspace_search` | Search indexed content using keyword (BM25), semantic (vector), or hybrid search. Returns ranked results with scores. |
| `mastra_workspace_index`  | Index content for search. Associates content with a path for later retrieval.                                         |

The `index` tool is excluded when the filesystem is in read-only mode.

### Skill tools

Added when skills are configured:

| Tool           | Description                                                                                               |
| -------------- | --------------------------------------------------------------------------------------------------------- |
| `skill`        | Activate a skill by name or path. Returns the skill's full instructions, references, scripts, and assets. |
| `skill_search` | Search across skill content. Accepts an optional list of skill names to filter and a `topK` parameter.    |
| `skill_read`   | Read a specific file (reference, script, or asset) from a skill directory.                                |

When multiple skills share the same name, `list()` returns all of them. `get()` with a name applies tie-breaking (local > managed > external). If two skills share the same name and source type, `get()` throws an error. Pass a skill's full path to `get()` to bypass tie-breaking. See [Skills with the same name](https://mastra.ai/docs/sandbox/skills) for details.