@mastra/mcp-docs-server 1.2.16 → 1.2.17-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/.docs/docs/agents/code-mode.md +2 -2
  2. package/.docs/docs/agents/skills.md +1 -1
  3. package/.docs/docs/agents/using-tools.md +1 -1
  4. package/.docs/docs/harness/agent-controller.md +1 -1
  5. package/.docs/docs/mcp/overview.md +4 -5
  6. package/.docs/docs/studio/overview.md +1 -1
  7. package/.docs/docs/workspace/filesystem.md +182 -153
  8. package/.docs/docs/workspace/lsp.md +4 -5
  9. package/.docs/docs/workspace/sandbox.md +234 -141
  10. package/.docs/docs/workspace/search.md +52 -4
  11. package/.docs/docs/workspace/skills.md +62 -33
  12. package/.docs/integrations/browsers/browser-viewer.md +2 -2
  13. package/.docs/integrations/file-storage/amazon-s3.md +1 -1
  14. package/.docs/integrations/file-storage/azure-blob.md +1 -1
  15. package/.docs/integrations/file-storage/google-cloud-storage.md +1 -1
  16. package/.docs/integrations/file-storage/mesa.md +1 -1
  17. package/.docs/integrations/file-storage/vercel-files.md +1 -1
  18. package/.docs/integrations/sandboxes/apple-container.md +1 -1
  19. package/.docs/integrations/sandboxes/daytona.md +1 -1
  20. package/.docs/integrations/sandboxes/docker.md +1 -1
  21. package/.docs/integrations/sandboxes/e2b.md +1 -1
  22. package/.docs/integrations/sandboxes/modal.md +1 -1
  23. package/.docs/models/environment-variables.md +1 -0
  24. package/.docs/models/gateways/vercel.md +3 -2
  25. package/.docs/models/index.md +1 -1
  26. package/.docs/models/providers/baseten.md +2 -1
  27. package/.docs/models/providers/crossmodel.md +2 -2
  28. package/.docs/models/providers/crusoe.md +80 -0
  29. package/.docs/models/providers/deepinfra.md +3 -1
  30. package/.docs/models/providers/fireworks-ai.md +26 -20
  31. package/.docs/models/providers/huggingface.md +5 -1
  32. package/.docs/models/providers/hyper.md +1 -1
  33. package/.docs/models/providers/kilo.md +4 -4
  34. package/.docs/models/providers/llmgateway.md +3 -2
  35. package/.docs/models/providers/merge-gateway.md +5 -2
  36. package/.docs/models/providers/nano-gpt.md +6 -6
  37. package/.docs/models/providers/ofox.md +5 -1
  38. package/.docs/models/providers/opencode-go.md +2 -1
  39. package/.docs/models/providers/opencode.md +3 -1
  40. package/.docs/models/providers/requesty.md +3 -1
  41. package/.docs/models/providers/zai-coding-plan.md +3 -2
  42. package/.docs/models/providers/zhipuai-coding-plan.md +2 -1
  43. package/.docs/models/providers.md +1 -0
  44. package/.docs/reference/agent-controller/agent-controller-class.md +26 -1
  45. package/.docs/reference/browser/browser-viewer.md +1 -1
  46. package/.docs/reference/configuration.md +1 -1
  47. package/.docs/reference/core/removeWorkspace.md +1 -1
  48. package/.docs/reference/file-based-agents/workspace.md +3 -3
  49. package/.docs/reference/observability/tracing/exporters/mastra-platform-exporter.md +2 -0
  50. package/.docs/reference/processors/skill-search-processor.md +1 -1
  51. package/.docs/reference/tools/create-code-mode.md +1 -1
  52. package/.docs/reference/tools/create-tool.md +11 -3
  53. package/.docs/reference/tools/mcp-server.md +4 -1
  54. package/.docs/reference/workspace/local-filesystem.md +1 -1
  55. package/.docs/reference/workspace/local-sandbox.md +1 -1
  56. package/.docs/reference/workspace/workspace-class.md +52 -15
  57. package/CHANGELOG.md +14 -0
  58. package/package.json +5 -5
  59. package/.docs/docs/workspace/overview.md +0 -416
@@ -2,187 +2,228 @@
2
2
 
3
3
  # Sandbox
4
4
 
5
- **Added in:** `@mastra/core@1.1.0`
5
+ Sandboxes give Mastra agents an environment for running commands and working with files. Agents can also start background processes when the selected backend supports process management; otherwise, background-process tools are unavailable.
6
6
 
7
- Sandbox providers give agents the ability to execute shell commands. When you configure a sandbox on a workspace, agents can run commands as part of their tasks.
7
+ In Mastra, you attach a sandbox backend to a `Workspace`. You can use one sandbox for an application or agent, or resolve separate environments for each user, tenant, or thread.
8
8
 
9
- A sandbox provider executes commands in a controlled environment:
9
+ Supported backends can FUSE-mount filesystems into the sandbox, letting you seed ephemeral environments with files and persist their output between runs.
10
10
 
11
- - **Command execution**: Run shell commands with arguments
12
- - **Background processes**: Spawn long-running processes like dev servers and watchers
13
- - **Working directory**: Commands run from a specific directory
14
- - **Environment variables**: Control what variables are available
15
- - **Timeouts**: Prevent long-running commands from hanging
16
- - **Isolation**: Optional OS-level sandboxing for security
11
+ ## When to use sandboxes?
17
12
 
18
- > **📹 Watch:** Watch [Mastra remote sandboxes overview](https://www.youtube.com/watch?v=Ix2X-sjVXjw) to see how remote sandboxes give agents an isolated computer to work in.
13
+ Sandboxes are useful for:
19
14
 
20
- ## Supported providers
15
+ - **Coding agents and software factories**: Clone repositories and run shell, Git, build, or test workflows without giving autonomous agents access to the host system.
16
+ - **Deep research and analysis**: Use specialized libraries to process downloaded PDFs or presentations and produce new artifacts.
17
+ - **Long-running and parallel tasks**: Run work in separate environments without tying it to one request or sharing files and processes.
21
18
 
22
- - [AgentCore](https://mastra.ai/integrations/sandboxes/agentcore)
23
- - [Apple Container](https://mastra.ai/integrations/sandboxes/apple-container)
24
- - [Blaxel](https://mastra.ai/integrations/sandboxes/blaxel)
25
- - [Daytona](https://mastra.ai/integrations/sandboxes/daytona)
26
- - [Docker](https://mastra.ai/integrations/sandboxes/docker)
27
- - [E2B](https://mastra.ai/integrations/sandboxes/e2b)
28
- - [LocalSandbox](https://mastra.ai/reference/workspace/local-sandbox)
29
- - [Mastra](https://mastra.ai/reference/workspace/platform-sandbox)
30
- - [Modal](https://mastra.ai/integrations/sandboxes/modal)
31
- - [Railway](https://mastra.ai/integrations/sandboxes/railway)
32
- - [Vercel](https://mastra.ai/integrations/sandboxes/vercel)
19
+ ## Quickstart
33
20
 
34
- ## Basic usage
21
+ In Mastra, a sandbox operates through a `Workspace`. Its `sandbox` backend defines where commands run.
35
22
 
36
- Create a workspace with a sandbox and assign it to an agent. The agent can then execute shell commands:
23
+ Create an agent with a workspace and sandbox:
37
24
 
38
25
  ```typescript
39
26
  import { Agent } from '@mastra/core/agent'
40
- import { Workspace, LocalFilesystem, LocalSandbox } from '@mastra/core/workspace'
41
-
42
- const workspace = new Workspace({
43
- filesystem: new LocalFilesystem({
44
- basePath: './workspace',
45
- }),
46
- sandbox: new LocalSandbox({
47
- workingDirectory: './workspace',
48
- }),
49
- })
27
+ import { LocalSandbox, Workspace } from '@mastra/core/workspace'
50
28
 
51
- const agent = new Agent({
52
- id: 'dev-agent',
29
+ export const codingAgent = new Agent({
30
+ id: 'coding-agent',
31
+ name: 'Coding agent',
32
+ instructions: 'Use the sandbox to complete coding tasks.',
53
33
  model: 'openai/gpt-5.6-sol',
54
- instructions: 'You are a helpful development assistant.',
55
- workspace,
34
+ workspace: new Workspace({
35
+ sandbox: new LocalSandbox({
36
+ workingDirectory: './workspace',
37
+ }),
38
+ }),
56
39
  })
57
40
 
58
- // The agent now has the execute_command tool available
59
- const response = await agent.generate('Run `ls -la` in the workspace directory')
41
+ await codingAgent.generate('List the files in the workspace directory')
60
42
  ```
61
43
 
62
- See [`LocalSandbox` reference](https://mastra.ai/reference/workspace/local-sandbox) for configuration options including environment isolation and native OS sandboxing.
44
+ > **Warning:** `LocalSandbox` is the quickest sandbox to set up, but commands run on the host by default. Enable [native isolation](#localsandbox) whenever possible. For applications exposed to untrusted users, use a remote or container backend with a stronger isolation boundary instead.
63
45
 
64
- ## Dynamic sandbox
46
+ To use a different sandbox for each user, tenant, or thread, configure a [sandbox resolver](#multi-tenant-sandboxes) instead.
65
47
 
66
- The `sandbox` option accepts a resolver function instead of a static instance. The resolver receives `requestContext` and returns a sandbox per request, allowing a single workspace to serve different sandboxes based on the caller's identity, role, or tenant.
48
+ ## Using the sandbox
67
49
 
68
- ```typescript
69
- import { Agent } from '@mastra/core/agent'
70
- import { Workspace, LocalSandbox } from '@mastra/core/workspace'
50
+ Agents receive tools for the capabilities supported by the sandbox backend:
71
51
 
72
- const workspace = new Workspace({
73
- sandbox: ({ requestContext }) => {
74
- const userId = requestContext.get('user-id') as string
75
- return new LocalSandbox({
76
- workingDirectory: `/workspaces/${userId}`,
77
- })
78
- },
79
- })
52
+ | Tool | Does |
53
+ | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
+ | `execute_command` | Runs a shell command and returns stdout, stderr, and the exit code. Supports `background: true` when the backend can spawn long-running processes. |
55
+ | `get_process_output` | Gets stdout, stderr, and status for a background process. Supports `tail` to limit output and `wait: true` to wait for the process to exit. This tool and `kill_process` are only added when the backend supports background processes. |
56
+ | `kill_process` | Stops a background process and returns its recent output. |
57
+
58
+ You can disable or rename each tool and require approval before it runs. You can also limit how much output it adds to the model's context. See the [workspace tool configuration reference](https://mastra.ai/reference/workspace/workspace-class).
80
59
 
81
- const agent = new Agent({
82
- id: 'multi-tenant-agent',
83
- model: 'your-provider/your-model',
84
- workspace,
60
+ Authored runtime functions, including tools and workflow steps, can get the live sandbox from their execution context. Start a server, watcher, notebook kernel, browser, or worker and interact with it across agent turns.
61
+
62
+ ```typescript
63
+ import type { ProcessHandle } from '@mastra/core/sandbox'
64
+ import { createTool } from '@mastra/core/tools'
65
+ import { z } from 'zod'
66
+
67
+ export const startServerTool = createTool({
68
+ id: 'start-server',
69
+ description: 'Starts a server in the sandbox',
70
+ inputSchema: z.object({
71
+ command: z.string(),
72
+ }),
73
+ execute: async ({ command }, ctx) => {
74
+ const sandbox = await ctx.getSandbox()
75
+ const server: ProcessHandle = await sandbox.spawn({ command })
76
+ return { pid: server.pid }
77
+ },
85
78
  })
86
79
  ```
87
80
 
88
- Each request resolves its own sandbox at tool execution time:
81
+ The authored function itself runs in your application process. Only operations called through the sandbox handle run inside the sandbox.
89
82
 
90
- ```typescript
91
- import { RequestContext } from '@mastra/core/request-context'
83
+ ## Supported backends
92
84
 
93
- // User Alice — commands run in /workspaces/alice
94
- const aliceCtx = new RequestContext([['user-id', 'alice']])
95
- await agent.generate('List files in cwd', { requestContext: aliceCtx })
85
+ ### `LocalSandbox`
96
86
 
97
- // User Bob commands run in /workspaces/bob
98
- const bobCtx = new RequestContext([['user-id', 'bob']])
99
- await agent.generate('List files in cwd', { requestContext: bobCtx })
100
- ```
87
+ [`LocalSandbox`](https://mastra.ai/reference/workspace/local-sandbox) executes commands on the same machine as your Mastra application. By default, commands run directly on the host with the permissions of the application process.
101
88
 
102
- By default, workspace instructions describe the runtime sandbox with stable placeholder text. See [Workspace instructions](#workspace-instructions) to include concrete per-request details.
89
+ Enable native isolation to restrict filesystem and network access at the operating-system level:
103
90
 
104
- The resolver can also be asynchronous, for example to look up tenant configuration from a database:
91
+ - **macOS**: Seatbelt (`sandbox-exec`)
92
+ - **Linux**: Bubblewrap (`bwrap`)
105
93
 
106
94
  ```typescript
107
- const workspace = new Workspace({
108
- sandbox: async ({ requestContext }) => {
109
- const tenant = await db.getTenant(requestContext.get('tenant-id'))
110
- return new LocalSandbox({ workingDirectory: tenant.workspacePath })
95
+ const sandbox = new LocalSandbox({
96
+ workingDirectory: './workspace',
97
+ isolation: 'seatbelt', // Use 'bwrap' on Linux
98
+ nativeSandbox: {
99
+ allowNetwork: false,
100
+ readOnlyPaths: ['./reference-data'],
111
101
  },
112
102
  })
113
103
  ```
114
104
 
115
- ### Lifecycle ownership
116
-
117
- When the sandbox is a static instance, `workspace.init()` calls its `start()` method and `workspace.destroy()` calls its `destroy()` method. With a resolver, the workspace has no instance to manage at construction time, the caller owns the returned sandbox's lifecycle.
105
+ Use `LocalSandbox.detectIsolation()` to check whether Seatbelt or Bubblewrap is available on the current operating system. The `nativeSandbox` options control network access, read-only or writable paths, workspace write access, and system binaries. You can also provide a custom Seatbelt profile or Bubblewrap arguments. See [`LocalSandbox`](https://mastra.ai/reference/workspace/local-sandbox) for the full configuration.
118
106
 
119
- The resolver must return a sandbox that's ready to use, either already started or able to handle calls without explicit startup. The caller also owns cleanup timing for returned sandboxes.
107
+ ### Other backends
120
108
 
121
- Cleanup can happen per request, tenant, or user. It can also be part of a long-lived sandbox pool. `workspace.destroy()` doesn't destroy resolver-returned sandboxes.
109
+ Use a remote or container backend when commands need a stronger boundary from the host application. Each backend has its own isolation, persistence, networking, and mount behavior:
122
110
 
123
- > **Note:** `sandbox` resolvers are incompatible with `mounts` and `lsp: true`. Both require a concrete sandbox instance at construction time, so combining them with a resolver throws an `INVALID_CONFIG` error (for `mounts`) or disables LSP with a warning (for `lsp: true`).
111
+ - [AgentCore](https://mastra.ai/integrations/sandboxes/agentcore)
112
+ - [Apple Container](https://mastra.ai/integrations/sandboxes/apple-container)
113
+ - [Blaxel](https://mastra.ai/integrations/sandboxes/blaxel)
114
+ - [Daytona](https://mastra.ai/integrations/sandboxes/daytona)
115
+ - [Docker](https://mastra.ai/integrations/sandboxes/docker)
116
+ - [E2B](https://mastra.ai/integrations/sandboxes/e2b)
117
+ - [Mastra](https://mastra.ai/reference/workspace/platform-sandbox)
118
+ - [Modal](https://mastra.ai/integrations/sandboxes/modal)
119
+ - [Railway](https://mastra.ai/integrations/sandboxes/railway)
120
+ - [Vercel](https://mastra.ai/integrations/sandboxes/vercel)
124
121
 
125
- ### Tool registration
122
+ If Mastra doesn't support your execution backend, implement [`WorkspaceSandbox`](https://mastra.ai/reference/workspace/sandbox) to add it.
126
123
 
127
- With a static sandbox, the workspace inspects the instance to decide which tools to register. With a resolver, the workspace assumes full capabilities and registers `execute_command` (with `background` support), `get_process_output`, and `kill_process`. If the resolved sandbox doesn't implement a capability, the runtime throws a clear `SandboxFeatureNotSupportedError`.
124
+ ## Persistent storage
128
125
 
129
- ### Background process continuity
126
+ Some execution backends can also mount cloud filesystems through FUSE. Mounted files appear as local directories inside the sandbox, so commands such as `cat /data/report.md` or `python /data/analyze.py` can use them directly.
130
127
 
131
- Background processes can outlive a single tool call, so `get_process_output` and `kill_process` must reach the same sandbox that started the process. By default, a resolved sandbox is cached per request. For continuity across follow-up requests, such as a later conversation turn, set `sandboxCacheKey` to a stable identifier. The resolved sandbox is then cached by that key instead of by request:
128
+ Configure mounts on the workspace alongside the sandbox:
132
129
 
133
130
  ```typescript
131
+ import { Workspace } from '@mastra/core/workspace'
132
+ import { DaytonaSandbox } from '@mastra/daytona'
133
+ import { S3Filesystem } from '@mastra/s3'
134
+
134
135
  const workspace = new Workspace({
135
- sandbox: ({ requestContext }) => resolveSandbox(requestContext),
136
- sandboxCacheKey: ({ requestContext }) => requestContext.get('thread-id') as string,
136
+ mounts: {
137
+ '/data': new S3Filesystem({
138
+ bucket: 'agent-data',
139
+ region: 'us-east-1',
140
+ }),
141
+ },
142
+ sandbox: new DaytonaSandbox(),
137
143
  })
138
144
  ```
139
145
 
140
- Without a `sandboxCacheKey`, the resolver must return the same sandbox itself for follow-up calls that share a tenant, user, or session.
146
+ The agent receives filesystem tools for the mounted storage, and commands in the sandbox can access the same files under `/data`. This lets you seed an ephemeral sandbox with existing files and persist its output after the sandbox stops.
141
147
 
142
- When a cached sandbox is no longer needed, destroy the sandbox in your own lifecycle code and call `workspace.clearSandboxCache(cacheKey)` to drop the workspace cache entry. Call `workspace.clearSandboxCache()` to clear all keyed sandbox entries.
148
+ Mount support varies by sandbox backend. See [Filesystem](https://mastra.ai/docs/workspace/filesystem) for supported storage backends, detailed mount configuration, and how to mount multiple filesystems.
143
149
 
144
- ### Workspace instructions
150
+ ## Multi-tenant sandboxes
145
151
 
146
- Workspace instructions describe the environment in the agent's system message. With a sandbox resolver, the workspace doesn't call the resolver to build these instructions. It emits stable placeholder text, so constructing the prompt never provisions a caller-owned sandbox and the system message stays consistent across requests, which keeps prompt caching effective.
152
+ Use a **resolver** when each user, tenant, or thread needs a separate sandbox. Set `sandboxCacheKey` to the identity that owns the sandbox so later requests reuse the same live environment.
147
153
 
148
- To include concrete per-request sandbox details, set `instructions.dynamicSandbox` to `'resolve'`:
154
+ This example creates one Daytona sandbox and one S3 storage prefix per memory thread. The S3 filesystem is also mounted at `/workspace` inside the sandbox:
149
155
 
150
156
  ```typescript
151
- const workspace = new Workspace({
152
- sandbox: ({ requestContext }) => resolveSandbox(requestContext),
153
- instructions: { dynamicSandbox: 'resolve' },
154
- })
155
- ```
156
-
157
- `'resolve'` calls the resolver on every request, which may provision the sandbox and makes the system message request-specific. Pass a function instead to return custom text from `requestContext` without resolving the sandbox:
157
+ import { MASTRA_THREAD_ID_KEY, type RequestContext } from '@mastra/core/request-context'
158
+ import { Workspace } from '@mastra/core/workspace'
159
+ import { DaytonaSandbox } from '@mastra/daytona'
160
+ import { S3Filesystem } from '@mastra/s3'
161
+
162
+ const getThreadId = (requestContext: RequestContext) => {
163
+ const threadId = requestContext.get(MASTRA_THREAD_ID_KEY)
164
+ if (typeof threadId !== 'string' || !threadId) {
165
+ throw new Error('A memory thread is required to use this workspace')
166
+ }
167
+
168
+ return threadId
169
+ }
170
+
171
+ const createThreadFilesystem = (threadId: string) =>
172
+ new S3Filesystem({
173
+ bucket: process.env.S3_BUCKET!,
174
+ region: process.env.S3_REGION!,
175
+ prefix: `threads/${threadId}`,
176
+ })
158
177
 
159
- ```typescript
160
178
  const workspace = new Workspace({
161
- sandbox: ({ requestContext }) => resolveSandbox(requestContext),
162
- instructions: {
163
- dynamicSandbox: ({ requestContext }) =>
164
- `Sandbox scoped to tenant ${requestContext.get('tenant-id')}.`,
179
+ filesystem: ({ requestContext }) => createThreadFilesystem(getThreadId(requestContext)),
180
+ sandbox: async ({ requestContext }) => {
181
+ const threadId = getThreadId(requestContext)
182
+ const sandbox = new DaytonaSandbox({
183
+ id: `thread-${threadId}`,
184
+ language: 'typescript',
185
+ })
186
+
187
+ await sandbox.start()
188
+ await sandbox.mount(createThreadFilesystem(threadId), '/workspace')
189
+ return sandbox
165
190
  },
191
+ sandboxCacheKey: ({ requestContext }) => getThreadId(requestContext),
166
192
  })
167
193
  ```
168
194
 
169
- ## Agent tools
195
+ The first request in a thread runs the resolver and starts the sandbox. Later requests with the same thread ID reuse the cached sandbox. A different thread ID creates a different sandbox and storage prefix.
170
196
 
171
- When you configure a sandbox on a workspace, agents receive the `execute_command` tool for running shell commands.
197
+ Workspace-level `mounts` can't be combined with a sandbox resolver. This is a known limitation, so the example mounts the filesystem inside the resolver instead. Workspace tools resolve the filesystem and sandbox from the request context automatically.
172
198
 
173
- If your sandbox provider supports running processes in the background, the `execute_command` tool also accepts `background: true` for starting long-running processes, and two additional tools are registered:
199
+ ### Resolver ownership
174
200
 
175
- | Tool | Description |
176
- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
177
- | `execute_command` | Run a shell command. Returns stdout, stderr, and exit code. Supports `background: true` to spawn a long-running process and return a PID. |
178
- | `get_process_output` | Get stdout, stderr, and status of a background process by PID. Supports `tail` to limit output lines and `wait: true` to block until exit. |
179
- | `kill_process` | Stop a background process by PID. Returns recent output. |
201
+ The workspace doesn't own sandboxes returned by a resolver. Return a sandbox that's ready to use, and destroy it through your application's lifecycle code when it's no longer needed. `workspace.destroy()` doesn't destroy resolver-returned sandboxes.
180
202
 
181
- These tools are registered automatically. See [Workspace class reference](https://mastra.ai/reference/workspace/workspace-class) for the full tool name list.
203
+ Resolvers are incompatible with `mounts` and [`lsp: true`](https://mastra.ai/docs/workspace/lsp), because both require a static sandbox when the workspace is constructed. Using a resolver with `mounts` throws an `INVALID_CONFIG` error. With `lsp: true`, Mastra disables LSP and logs a warning.
182
204
 
183
- ## Background process callbacks
205
+ ### Tool availability
184
206
 
185
- When agents start background processes through the `execute_command` tool, you can receive lifecycle callbacks for stdout, stderr, and process exit. Configure these through the `backgroundProcesses` option on the `execute_command` tool:
207
+ With a static sandbox, Mastra knows which capabilities the backend supports and only gives the agent the corresponding tools. With a resolver-backed sandbox, the backend isn't known until a request runs, so Mastra initially makes all sandbox tools available. If the resolved backend doesn't support the tool the agent calls, the call fails with `SandboxFeatureNotSupportedError`.
208
+
209
+ For example, this resolver returns a Daytona sandbox for development requests and an AgentCore sandbox for other requests:
210
+
211
+ ```typescript
212
+ const workspace = new Workspace({
213
+ sandbox: ({ requestContext }) =>
214
+ requestContext.get('environment') === 'development'
215
+ ? new DaytonaSandbox()
216
+ : new AgentCoreRuntimeSandbox({
217
+ agentRuntimeArn: process.env.AGENTCORE_RUNTIME_ARN!,
218
+ }),
219
+ })
220
+ ```
221
+
222
+ Mastra exposes the process tools because `DaytonaSandbox` supports background processes. If a request resolves to `AgentCoreRuntimeSandbox`, one-shot commands still work, but calling `get_process_output` or `kill_process` fails with `SandboxFeatureNotSupportedError` because that backend doesn't support background processes.
223
+
224
+ ## Background processes
225
+
226
+ When agents start background processes through `execute_command`, you can receive lifecycle callbacks for stdout, stderr, and process exit. Configure these through the `backgroundProcesses` option on its `WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND` entry:
186
227
 
187
228
  ```typescript
188
229
  import { Workspace, LocalSandbox, WORKSPACE_TOOLS } from '@mastra/core/workspace'
@@ -201,45 +242,97 @@ const workspace = new Workspace({
201
242
  })
202
243
  ```
203
244
 
204
- These callbacks fire for all background processes started by the agent through the `execute_command` tool.
245
+ These callbacks fire for all background processes started by the agent through `execute_command`.
246
+
247
+ By default, background processes inherit the agent's abort signal and stop when the agent disconnects. Set `abortSignal` to a custom signal, or use `null` or `false` when the process should continue after the request ends.
248
+
249
+ For the full `SandboxProcessManager` API (spawning processes programmatically and reading output, plus sending stdin), see the [`SandboxProcessManager` reference](https://mastra.ai/reference/workspace/process-manager).
250
+
251
+ ## Lifecycle and persistence
252
+
253
+ Sandbox scope depends on where you assign the workspace and whether you use a resolver:
205
254
 
206
- ### Abort signal
255
+ | Configuration | Sandbox scope |
256
+ | ------------------------ | -------------------------------------------------------------------------------- |
257
+ | Mastra-level workspace | Agents that inherit the workspace from the Mastra instance use the same sandbox. |
258
+ | Agent-level workspace | Every request handled by that agent instance uses the same sandbox. |
259
+ | Resource-scoped resolver | The resolver caches one sandbox for each resource ID. |
260
+ | Thread-scoped resolver | A memory thread keeps its sandbox across requests in that thread. |
207
261
 
208
- By default, background processes inherit the agent's abort signal and are killed when the agent disconnects. Control this behavior with the `abortSignal` option:
262
+ A static sandbox isn't automatically scoped to the current resource or memory thread. For resource or thread scope, use a resolver and set `sandboxCacheKey` to the corresponding ID. See [Multi-tenant sandboxes](#multi-tenant-sandboxes).
209
263
 
210
- - **`undefined`** (default): Uses the agent's abort signal
211
- - **`AbortSignal`**: Uses a custom signal
212
- - **`null` or `false`**: Disables abort: processes persist after agent shutdown
264
+ ### Start
265
+
266
+ Static sandbox backends are instantiated with your application, but their execution environment usually starts lazily on the first command. Call `workspace.init()` when you want to provision it during application startup instead.
267
+
268
+ Resolver-backed sandboxes aren't started by `workspace.init()` because no backend is selected until the resolver runs. Return a sandbox that's already started or can start itself on first use.
269
+
270
+ ### Hooks
271
+
272
+ Use `onStart`, `onStop`, and `onDestroy` to run application code during lifecycle transitions. Hooks receive the live sandbox instance:
213
273
 
214
274
  ```typescript
215
- import { Workspace, LocalSandbox, WORKSPACE_TOOLS } from '@mastra/core/workspace'
275
+ const sandbox = new LocalSandbox({
276
+ workingDirectory: './workspace',
277
+ onStart: ({ sandbox }) => console.log(`Started ${sandbox.id}`),
278
+ onStop: ({ sandbox }) => console.log(`Stopping ${sandbox.id}`),
279
+ onDestroy: ({ sandbox }) => console.log(`Destroying ${sandbox.id}`),
280
+ })
281
+ ```
216
282
 
217
- const workspace = new Workspace({
218
- sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
219
- tools: {
220
- [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
221
- backgroundProcesses: {
222
- abortSignal: null, // Processes survive agent disconnection
223
- },
224
- },
225
- },
283
+ `onStart` runs after the sandbox starts. `onStop` and `onDestroy` run before their corresponding operation.
284
+
285
+ ### Cleanup
286
+
287
+ Sandboxes passed directly to a workspace are owned by that workspace. `mastra dev` and the generated Mastra server handle shutdown signals and destroy registered workspaces automatically. If you embed Mastra in a custom server or process, call `mastra.shutdown()` from its shutdown hook. For a standalone workspace, call `workspace.destroy()` directly. The effect of stopping or destroying the underlying environment depends on the backend.
288
+
289
+ Sandboxes returned by a resolver are owned by your application. `workspace.destroy()` and `mastra.shutdown()` clear workspace references but don't destroy those resolved sandboxes. Your resolver or application lifecycle must keep track of them, call `destroy()` when their user, thread, or session ends, and then call `workspace.clearSandboxCache(cacheKey)` for keyed entries. This prevents unused compute from continuing to run and later requests from reusing a stale sandbox.
290
+
291
+ ### Persistence
292
+
293
+ Persistence is backend-specific. Files and processes aren't guaranteed to survive when a sandbox stops or the application restarts. An idle timeout may also discard them. Some backends reconnect by sandbox ID or preserve snapshots and volumes. Others create a fresh environment.
294
+
295
+ Every sandbox has an `id`, but the ID isn't a cross-backend persistence guarantee. Read the selected backend's reference before relying on reconnection or persisted state.
296
+
297
+ ## Network and credential safety
298
+
299
+ Mastra doesn't define one network policy that applies to every sandbox backend. Defaults and supported controls vary, so check the selected backend before running untrusted code. For sensitive or production workloads, prefer blocking outbound access or allowing only the destinations the task needs. Apply that policy when you create the sandbox so it takes effect before commands run.
300
+
301
+ If an agent starts a web server inside a remote sandbox, that server initially listens on a port inside the sandbox. Backends that support port exposure implement `sandbox.networking.getPortUrl()` to return a URL you can use to preview or test the server from outside the sandbox:
302
+
303
+ ```typescript
304
+ const url = await sandbox.networking?.getPortUrl(8000)
305
+ ```
306
+
307
+ Depending on the backend's access controls, the URL may make the service reachable to others. This inbound exposure is separate from outbound sandbox access. `LocalSandbox` with native isolation blocks network access by default unless `allowNetwork` is enabled. Without native isolation, local commands use the host network.
308
+
309
+ For example, `DaytonaSandbox` allows outbound access unless you configure a restriction. Set `networkBlockAll` with a domain allowlist when the task only needs specific services:
310
+
311
+ ```typescript
312
+ import { DaytonaSandbox } from '@mastra/daytona'
313
+
314
+ const sandbox = new DaytonaSandbox({
315
+ networkBlockAll: true,
316
+ domainAllowList: 'registry.npmjs.org,api.github.com',
226
317
  })
227
318
  ```
228
319
 
229
- Use `null` or `false` for cloud sandboxes (for example, E2B, Daytona, or Modal) where processes should outlive the agent.
320
+ Daytona applies these settings when it creates the sandbox. It also supports CIDR rules through `networkAllowList`. See the [Daytona integration page](https://mastra.ai/integrations/sandboxes/daytona) for full configuration details.
230
321
 
231
- > **Note:** For the full `SandboxProcessManager` API (spawning processes programmatically and reading output, plus sending stdin), see the [`SandboxProcessManager` reference](https://mastra.ai/reference/workspace/process-manager).
322
+ Environment variables passed to a sandbox or command are available to code running there. Mastra doesn't provide a backend-neutral credential broker that keeps secrets outside the sandbox while authorizing its requests. Give the command only the credentials it needs, scoped to the task. Follow the selected backend's secret-management guidance.
323
+
324
+ For example, pass a read-only token to the command that needs it instead of configuring it for every command in the sandbox:
325
+
326
+ ```typescript
327
+ await sandbox.executeCommand('node', ['scripts/download-reports.js'], {
328
+ env: {
329
+ REPORTS_READ_TOKEN: process.env.REPORTS_READ_TOKEN,
330
+ },
331
+ })
332
+ ```
232
333
 
233
334
  ## Related
234
335
 
235
336
  - [`SandboxProcessManager` reference](https://mastra.ai/reference/workspace/process-manager)
236
- - [`AgentCoreRuntimeSandbox` reference](https://mastra.ai/integrations/sandboxes/agentcore)
237
- - [`AppleContainerSandbox` reference](https://mastra.ai/integrations/sandboxes/apple-container)
238
- - [`DaytonaSandbox` reference](https://mastra.ai/integrations/sandboxes/daytona)
239
- - [`E2BSandbox` reference](https://mastra.ai/integrations/sandboxes/e2b)
240
- - [`LocalSandbox` reference](https://mastra.ai/reference/workspace/local-sandbox)
241
- - [`ModalSandbox` reference](https://mastra.ai/integrations/sandboxes/modal)
242
- - [`VercelSandbox` reference](https://mastra.ai/integrations/sandboxes/vercel)
243
- - [`VercelServerlessSandbox` reference](https://mastra.ai/integrations/sandboxes/vercel)
244
- - [Workspace overview](https://mastra.ai/docs/workspace/overview)
337
+ - [`WorkspaceSandbox` reference](https://mastra.ai/reference/workspace/sandbox)
245
338
  - [Filesystem](https://mastra.ai/docs/workspace/filesystem)
@@ -2,10 +2,40 @@
2
2
 
3
3
  # Search and indexing
4
4
 
5
- **Added in:** `@mastra/core@1.1.0`
6
-
7
5
  Search lets agents find relevant content in indexed workspace files. When an agent needs to answer a question or find information, it can search the indexed content instead of reading every file.
8
6
 
7
+ Search works with both [`mounts`](https://mastra.ai/docs/workspace/filesystem) and a [workspace-only filesystem](https://mastra.ai/docs/workspace/filesystem). With `mounts`, paths from every mounted filesystem are available through one composite filesystem. With `filesystem`, search uses that provider directly. In both cases, queries search the workspace index rather than reading live files on demand.
8
+
9
+ ## When to use search
10
+
11
+ Use workspace search when your agent needs to:
12
+
13
+ - Find exact terms, filenames, or error messages with BM25 keyword search
14
+ - Find conceptually related content with vector search
15
+ - Combine keyword and semantic results with hybrid search
16
+ - Search a large set of files without reading each file in full
17
+ - Index content from files, databases, or APIs
18
+
19
+ ## Quickstart
20
+
21
+ Enable BM25 search, index content, and query it through the workspace:
22
+
23
+ ```typescript
24
+ import { Workspace, LocalFilesystem } from '@mastra/core/workspace'
25
+
26
+ const workspace = new Workspace({
27
+ filesystem: new LocalFilesystem({ basePath: './workspace' }),
28
+ bm25: true,
29
+ })
30
+
31
+ await workspace.index('/docs/guide.md', 'Reset passwords from the account settings page.')
32
+
33
+ const results = await workspace.search('password reset')
34
+ console.log(results)
35
+ ```
36
+
37
+ This configuration also gives agents tools for searching and indexing workspace content.
38
+
9
39
  ## How it works
10
40
 
11
41
  Workspace search has two phases: indexing and querying.
@@ -180,6 +210,8 @@ Manual indexing is useful when:
180
210
 
181
211
  Configure `autoIndexPaths` to automatically index files when the workspace initializes. Each entry can be a directory path (indexed recursively) or a glob pattern for selective indexing.
182
212
 
213
+ `autoIndexPaths` works with a static `filesystem` or with `mounts`. For mounts, include the mount prefix in each path, such as `/docs/**/*.md`. Resolver-backed filesystems aren't auto-indexed during workspace initialization because the provider is only selected for a request; index their content manually instead.
214
+
183
215
  ```typescript
184
216
  const workspace = new Workspace({
185
217
  filesystem: new LocalFilesystem({ basePath: './workspace' }),
@@ -275,10 +307,26 @@ interface SearchResult {
275
307
 
276
308
  ## Agent tools
277
309
 
278
- When you configure search on a workspace, agents receive tools for searching and indexing content. See [workspace class reference](https://mastra.ai/reference/workspace/workspace-class) for details.
310
+ When you configure search on a workspace, agents receive `mastra_workspace_search` and `mastra_workspace_index` tools. Use `WORKSPACE_TOOLS.SEARCH` constants to configure them independently. For example, remove indexing when the agent should search existing content without changing the index:
311
+
312
+ ```typescript
313
+ import { LocalFilesystem, Workspace, WORKSPACE_TOOLS } from '@mastra/core/workspace'
314
+
315
+ const workspace = new Workspace({
316
+ filesystem: new LocalFilesystem({ basePath: './workspace' }),
317
+ bm25: true,
318
+ tools: {
319
+ [WORKSPACE_TOOLS.SEARCH.INDEX]: {
320
+ enabled: false,
321
+ },
322
+ },
323
+ })
324
+ ```
325
+
326
+ See [workspace class reference](https://mastra.ai/reference/workspace/workspace-class) for the complete tool list and [`WorkspaceToolsConfig`](https://mastra.ai/reference/workspace/workspace-class) for shared settings.
279
327
 
280
328
  ## Related
281
329
 
282
- - [Workspace overview](https://mastra.ai/docs/workspace/overview)
330
+ - [Sandbox](https://mastra.ai/docs/workspace/sandbox)
283
331
  - [RAG overview](https://mastra.ai/reference/rag/overview)
284
332
  - [Workspace class reference](https://mastra.ai/reference/workspace/workspace-class)