-
Notifications
You must be signed in to change notification settings - Fork 2.4k
feat(core): support dynamic sandbox resolution via requestContext #16048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
intojhanurag
merged 24 commits into
mastra-ai:main
from
intojhanurag:feat/dynamic-sandbox-resolver
Jun 4, 2026
Merged
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
5c49fa4
feat(core): support dynamic sandbox resolution via requestContext in …
intojhanurag d7f1345
fix(core): resolve dynamic workspace instructions
intojhanurag 00b4956
fix(core): forward synthesized requestContext to provider instruction…
intojhanurag d7c6d86
perf(core): memoize workspace resolvers per requestContext
intojhanurag a3f4be8
fix(core): wire dynamic workspace instructions into durable agent pre…
intojhanurag 9028811
test(core): cover durable workspace instructions
intojhanurag 1929718
test(core): cover dynamic sandbox capability errors
intojhanurag baebd85
chore(core): drop sandbox class-constructor guard
intojhanurag cf038ad
fix(core): avoid resolving dynamic providers for metadata
intojhanurag d4b0e54
fix(core): report request-resolved provider in workspace metadata
intojhanurag 6cf3f20
refactor(core): drop unused getPathContextAsync from Workspace
intojhanurag 8dca207
fix(core): resolve dynamic filesystem for the lsp_inspect tool
intojhanurag 88363e5
test(core): tidy dynamic sandbox/filesystem test organization
intojhanurag b859b20
Merge branch 'main' into feat/dynamic-sandbox-resolver
abhiaiyer91 9a994b0
feat(core): make dynamic sandbox instructions opt-in, add sandboxCach…
intojhanurag cc195aa
docs(core): correct dynamic-sandbox instruction docs, trim comments
intojhanurag 6c9f088
Merge branch 'main' into feat/dynamic-sandbox-resolver
abhiaiyer91 8ca508c
fix(core): clear dynamic sandbox cache
intojhanurag 694c8ba
Merge branch 'main' into feat/dynamic-sandbox-resolver
abhiaiyer91 5f42344
Merge branch 'main' into feat/dynamic-sandbox-resolver
intojhanurag d799b83
Merge branch 'main' into feat/dynamic-sandbox-resolver
intojhanurag e28e015
Merge branch 'main' into feat/dynamic-sandbox-resolver
NikAiyer 45940b2
fix(core): retry failed sandbox resolvers and hint sandboxCacheKey
intojhanurag 62fd2fd
Merge branch 'main' into feat/dynamic-sandbox-resolver
NikAiyer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| --- | ||
| '@mastra/core': minor | ||
| --- | ||
|
|
||
| Workspace `sandbox` now accepts a resolver function for per-request sandboxes. | ||
|
|
||
| **Before:** `sandbox: WorkspaceSandbox` (static, same sandbox for every request) | ||
| **After:** `sandbox: WorkspaceSandbox | (({ requestContext }) => WorkspaceSandbox)` (static or per-request) | ||
|
|
||
| This enables per-request sandbox routing from a single Workspace — useful for multi-tenant deployments where each user/role needs an isolated working directory or different execution permissions. | ||
|
|
||
| ```ts | ||
| const workspace = new Workspace({ | ||
| sandbox: ({ requestContext }) => { | ||
| const userId = requestContext.get('user-id') as string; | ||
| return new LocalSandbox({ workingDirectory: `/workspaces/${userId}` }); | ||
| }, | ||
| }); | ||
| ``` | ||
|
|
||
| When using a resolver, the caller owns the returned sandbox's lifecycle — the Workspace will not call `start()` or `destroy()` on it. `mounts` throws an `INVALID_CONFIG` error with a resolver, and `lsp: true` is disabled with a warning because both require a concrete sandbox instance up front. | ||
|
|
||
| **Stable prompts by default** | ||
|
|
||
| Building workspace instructions no longer calls a sandbox resolver. Resolver-backed sandboxes contribute stable placeholder text to the agent's system message, so constructing the prompt never provisions a caller-owned sandbox and the prompt stays cache-friendly. Opt into concrete per-request instructions with `instructions.dynamicSandbox`: | ||
|
|
||
| ```ts | ||
| const workspace = new Workspace({ | ||
| sandbox: ({ requestContext }) => resolveSandbox(requestContext), | ||
| instructions: { dynamicSandbox: 'resolve' }, // or a ({ requestContext }) => string function | ||
| }); | ||
| ``` | ||
|
|
||
| **Background process continuity** | ||
|
|
||
| Set `sandboxCacheKey` to keep `execute_command({ background: true })`, `get_process_output`, and `kill_process` on the same sandbox across follow-up requests — continuity is keyed by a stable id rather than the `RequestContext` instance: | ||
|
|
||
| ```ts | ||
| const workspace = new Workspace({ | ||
| sandbox: ({ requestContext }) => resolveSandbox(requestContext), | ||
| sandboxCacheKey: ({ requestContext }) => requestContext.get('thread-id') as string, | ||
| }); | ||
| ``` | ||
|
|
||
| Failed sandbox resolver calls are removed from the cache so later calls can retry. Use `workspace.clearSandboxCache(cacheKey)` to drop a keyed sandbox reference when your own lifecycle code has destroyed or replaced that sandbox. | ||
|
|
||
| When background process tools cannot find a PID on a dynamic sandbox without `sandboxCacheKey`, the tool output now points to `sandboxCacheKey` so callers can fix continuity across follow-up requests. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.