Sandbox
@mastra/deployer-sandbox 会将完整的 Mastra 服务器(包括 Studio)部署到临时工作区沙箱中,并返回一个可访问的公共 URL。重复部署可以更快完成,因为部署器会跳过依赖安装。
沙箱部署适用于:
- Agent 构建的应用:agent 生成 Mastra 项目并部署它来验证结果。
- 持续集成(CI):启动真实服务器进行检查,然后将其销毁。
- 即时预览:在合并前与团队分享可用的 agent。
- 多租户不受信任代码:运行与你的基础设施隔离的每用户 Mastra 实例。
沙箱有提供方强制的运行时上限,并且会过期。生产托管请参阅部署概览。
支持的沙箱支持的沙箱的直接链接
该部署器适用于任何支持网络连接(公共端口 URL)的工作区沙箱:
- Vercel Sandbox(
@mastra/vercel) - E2B(
@mastra/e2b) - Daytona(
@mastra/daytona)
提供方作者可以在 WorkspaceSandbox 上实现可选的 networking 能力来添加支持。
快速开始快速开始的直接链接
安装部署器和你选择的沙箱提供方。本例使用 Vercel Sandbox:
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/deployer-sandbox @mastra/vercel
pnpm add @mastra/deployer-sandbox @mastra/vercel
yarn add @mastra/deployer-sandbox @mastra/vercel
bun add @mastra/deployer-sandbox @mastra/vercel
在 src/mastra/index.ts 文件中配置部署器。sandboxName 标识该部署,因此使用相同名称的后续部署会复用现有沙箱。
import { Mastra } from '@mastra/core/mastra'
import { SandboxDeployer } from '@mastra/deployer-sandbox'
import { VercelSandbox } from '@mastra/vercel'
export const mastra = new Mastra({
deployer: new SandboxDeployer({
sandbox: new VercelSandbox({
sandboxName: 'my-preview',
timeout: 2_400_000, // 40 minutes
ports: [4111],
}),
}),
})
Vercel 有两个额外要求:
timeout不能超过你套餐允许的最大沙箱生命周期,Pro 套餐为 45 分钟。更高的值会导致部署失败,Vercel API 返回 400。- 在
ports中声明服务器端口。与 E2B 和 Daytona 不同,Vercel 只暴露创建时声明的端口。
使用一条命令构建并部署:
mastra build
配置 SandboxDeployer() 后,mastra build 会打包你的项目并将其部署到沙箱中。部署会打印 API 和 Studio URL,并将 sandbox-deployment.json 清单写入 .mastra/output:
API: https://<sandbox-id>-4111.vercel.run/api
Studio: https://<sandbox-id>-4111.vercel.run
当沙箱提供方报告过期时间时,清单会包含 expiresAt。
当输入未发生变化时,重新部署到同一沙箱会跳过依赖安装。输入哈希涵盖 package.json 和安装命令,以及打包的 lockfile。
URL 提供的内容URL 提供的内容的直接链接
Studio URL 是沙箱根路径,不带 /api。在浏览器中打开即可使用 Studio。当部署使用 studio: false 运行时,根路径会改为提供 Mastra 欢迎页面。
API URL 只是其下端点(例如 /api/agents)的前缀。/api 本身没有处理器,因此即使在服务器健康的情况下,在浏览器中打开它也会返回 "Not Found"。
要检查部署,可以直接调用端点:
curl -s -X POST https://4111-<sandbox-id>.e2b.app/api/agents/weatherAgent/generate \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"Weather in London"}]}' | jq -r '.text'
提供方凭据提供方凭据的直接链接
每个提供方使用自己的凭据进行认证。请设置你要部署到的沙箱对应的凭据:
# E2B
E2B_API_KEY=
# Daytona
DAYTONA_API_KEY=
# Vercel
VERCEL_TOKEN=
VERCEL_TEAM_ID=
VERCEL_PROJECT_ID=
每个提供方也接受将这些作为构造函数选项。自托管的 E2B 和 Daytona 安装使用 E2B_DOMAIN 或 DAYTONA_API_URL。
与 mastra dev 不同,mastra build 不会加载 .env 文件。部署发生在构建内部,因此从环境读取凭据的沙箱提供方(例如使用 E2B_API_KEY 的 E2B)会看到空值,导致部署因认证错误而失败。
在 src/mastra/index.ts 中添加 import 'dotenv/config' 并不能解决此问题。为了找到部署器,构建过程只会从入口文件中提取 deployer 选项,并将其他内容(包括该导入)通过 tree-shaking 移除。
请在构建运行前将 .env 文件加载到 shell 环境中。dotenv-cli 是一种实现方式:
- npm
- pnpm
- Yarn
- Bun
npm install --save-dev dotenv-cli
pnpm add --save-dev dotenv-cli
yarn add --dev dotenv-cli
bun add --dev dotenv-cli
{
"scripts": {
"deploy": "dotenv -e .env -- mastra build"
}
}
然后运行 npm run deploy。该脚本按其功能命名,因为配置 SandboxDeployer() 后,mastra build 会执行部署。请将其与普通的 build 脚本分开,以免运行 npm run build 的托管平台或 CI 任务意外部署沙箱。
在持续集成(CI)中,请改用密钥方式导出凭据。无论使用何种机制,变量都必须存在于 shell 环境中,而不仅仅在 .env 文件中。
这适用于部署器在你的机器上需要的凭据。已部署服务器需要的变量另行处理:部署器会读取 .env、.env.production 和 .env.local,并将它们注入沙箱。参见安全。
使用 E2B使用 E2B的直接链接
对于 E2B,id 标识该部署,因此使用相同值的后续部署会重新连接到现有沙箱,无论它正在运行还是已暂停。
import { SandboxDeployer } from '@mastra/deployer-sandbox'
import { E2BSandbox } from '@mastra/e2b'
const deployer = new SandboxDeployer({
sandbox: new E2BSandbox({
id: 'my-preview',
template: 'base',
timeout: 3_600_000, // 1 hour
}),
})
除非你需要文件系统挂载,否则请传入 template: 'base';否则提供方会在首次使用时构建自定义的用户空间文件系统(FUSE)模板。E2B 会暂停而不是停止:stop() 会对整个虚拟机(VM)进行快照,包括内存和运行中的进程。暂停的沙箱唤醒后,Mastra 服务器会从离开的地方继续运行,不需要像 Vercel 那样重新启动。
使用 Daytona使用 Daytona的直接链接
对于 Daytona,id 标识该部署,因此使用相同值的后续部署会重新连接到现有沙箱。设置 public: true 可使预览 URL 无需 Token 即可访问。
import { SandboxDeployer } from '@mastra/deployer-sandbox'
import { DaytonaSandbox } from '@mastra/daytona'
const deployer = new SandboxDeployer({
sandbox: new DaytonaSandbox({
id: 'my-preview',
public: true,
autoStopInterval: 30, // minutes
}),
})
停止 Daytona 沙箱会保留其文件系统,但不会保留运行中的进程,因此唤醒方式与 Vercel 类似:解析器会在 wake: true 时重新启动服务器。
Daytona 会按目的地过滤出站流量。发往某些主机的请求会通过传输层安全(TLS)正常连接,而其他请求会在握手期间被重置,这在 agent 或工具中表现为 Node 通用的 fetch failed。在调试代码之前,请先在沙箱内对同一主机运行 curl 以排除问题:
const sandbox = new DaytonaSandbox({ id: 'my-preview' })
await sandbox.start()
const result = await sandbox.executeCommand('curl -v --max-time 10 https://api.example.com')
console.info(result.stdout, result.stderr)
TLS 握手期间出现 Connection reset by peer 表明是过滤导致的问题,而不是你的 agent 问题。请联系 Daytona 支持以允许该目的地。受限的 Daytona 套餐还会阻止云存储端点,挂载辅助函数会以专用错误报告该情况。
以编程方式部署以编程方式部署的直接链接
deployToSandbox() 在不使用打包器的情况下部署预构建的输出目录。与 SandboxDeployer() 不同,除非传入 studio: true,否则它不包含 Studio。可在 CI 中或从 agent 代码中使用:
import { deployToSandbox } from '@mastra/deployer-sandbox'
import { VercelSandbox } from '@mastra/vercel'
const deployment = await deployToSandbox({
sandbox: new VercelSandbox({ sandboxName: 'ci-smoke', ports: [4111] }),
dir: '.mastra/output',
})
console.info(deployment.url) // https://<sandbox-id>-4111.vercel.run
await deployment.logs() // tail the server log
await deployment.stop() // stop the sandbox (resumable)
await deployment.destroy() // permanently delete the sandbox
生命周期生命周期的直接链接
管理部署管理部署的直接链接
使用 @mastra/deployer-sandbox/client 中仅限服务端的 getDeployment() 导出来获取现有部署。它通过提供方特定的配置(例如 Vercel 的 sandboxName,或 E2B 和 Daytona 的 id)识别沙箱。该查找不依赖于创建部署的进程,因此你可以在另一个服务端服务或 CI 中使用它。
import { getDeployment } from '@mastra/deployer-sandbox/client'
import { VercelSandbox } from '@mastra/vercel'
const deployment = await getDeployment({
sandbox: new VercelSandbox({ sandboxName: 'my-preview', ports: [4111] }),
port: 4111,
})
console.info(deployment.status, deployment.url)
await deployment.logs() // tail the server log
await deployment.stop() // stop the sandbox (resumable)
await deployment.destroy() // permanently delete the sandbox
传入 wake: true 可在返回前恢复已停止的沙箱。只有在恢复后服务器仍不健康时才会重新启动它。也可以使用提供方工具,例如 vercel sandbox ls、vercel sandbox stop 和 vercel sandbox rm。
过期与 URL过期与 URL的直接链接
沙箱会根据提供方的运行时限制过期。当提供方报告过期时间时,部署会记录该时间,deployment.expiresAt 会以编程方式暴露它。
沙箱停止并恢复时,URL 可能会变化。请将 URL 视为管道细节,将沙箱身份(例如 sandboxName)视为稳定的句柄。下面的路由层级用于处理 URL 轮换。
路由层级路由层级的直接链接
层级 1:直接 URL层级 1:直接 URL的直接链接
在开发、演示和 CI 中可直接使用打印出的 URL,此时每次部署使用新 URL 是可以接受的。
层级 2:运行时解析层级 2:运行时解析的直接链接
getDeployment() 在运行时解析当前 URL,因此使用方永远不会持有过期 URL。任何知道沙箱名称的服务器都可以解析它,包括与 Mastra 项目位于不同代码库的服务器:
import { getDeployment } from '@mastra/deployer-sandbox/client'
import { VercelSandbox } from '@mastra/vercel'
const deployment = await getDeployment({
sandbox: new VercelSandbox({ sandboxName: 'my-preview', ports: [4111] }),
wake: true,
})
console.info(deployment.url, deployment.status)
使用 wake: false(默认值)时,沙箱不会启动,你会得到 { url, status } 以便采取行动。解析 URL、stop() 和 destroy() 会按名称附加到现有沙箱而不恢复它,因此对已停止沙箱的生命周期操作永远不会唤醒它或开始计费。使用 wake: true 时,沙箱会恢复,如果服务器没有响应则会重新启动。是否需要重新启动取决于提供方:Vercel 和 Daytona 会恢复文件系统但不恢复运行中的进程,而 E2B 会恢复整个 VM,包括服务器进程。
@mastra/deployer-sandbox/client 仅限服务端使用。解析沙箱会使用绝不能到达浏览器的提供方凭据。该模块在浏览器上下文中被导入时会抛出异常。
层级 3:面向最终用户的稳定 URL层级 3:面向最终用户的稳定 URL的直接链接
为最终用户提供你自己的域名上的稳定 URL,并在服务端转发到沙箱,可以使用路由处理器代理或 Edge Config 别名。
下面的示例展示了 Vercel + Next.js 的设置,但该概念适用于任何可以转发请求的服务端框架或提供方。
-
路由处理器代理。
createSandboxHandler()会缓存沙箱 URL,并在连接级故障后重新解析,从而覆盖 URL 轮换和冷唤醒:app/api/[...path]/route.tsimport { createSandboxHandler, getDeployment } from '@mastra/deployer-sandbox/client'import { VercelSandbox } from '@mastra/vercel'const handler = createSandboxHandler({resolve: async () => {const deployment = await getDeployment({sandbox: new VercelSandbox({ sandboxName: 'my-preview', ports: [4111] }),wake: true,})return deployment.url!},})export { handler as GET, handler as POST } -
Edge Config 别名。 在部署器上设置
alias选项,以便每次部署时保持一个 Vercel Edge Config 条目指向当前 URL:src/mastra/index.tsconst deployer = new SandboxDeployer({sandbox: new VercelSandbox({ sandboxName: 'my-preview', ports: [4111] }),alias: { edgeConfigId: 'ecfg_...', key: 'my-preview', token: process.env.VERCEL_TOKEN! },})然后使用
createSandboxProxy()在 Next.js 中间件中重写请求:middleware.tsimport { createSandboxProxy } from '@mastra/deployer-sandbox/client'export const middleware = createSandboxProxy({ key: 'my-preview' })export const config = { matcher: '/api/:path*' }
CI 示例CI 示例的直接链接
在每个拉取请求上部署预览:
name: Sandbox preview
on: pull_request
jobs:
preview:
runs-on: ubuntu-latest
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_TEAM_ID: ${{ secrets.VERCEL_TEAM_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npx mastra build
- run: curl --fail "$(jq -r .url .mastra/output/sandbox-deployment.json)/api"
安全安全的直接链接
- 沙箱 URL 是公开的。任何拥有 URL 的人都可以访问你的 Mastra 服务器,包括 Studio。对于任何不仅仅是临时预览的场景,请启用服务器认证。
.env文件中的环境变量会被注入远程沙箱 VM,以便服务器可以运行。发生这种情况时,部署会记录警告。不要部署你不愿意放在共享预览服务器上的机密。- 要限制层级 3 流量的访问,请向
createSandboxHandler()或createSandboxProxy()传入secret。这些辅助函数会将该值附加到转发请求的x-mastra-sandbox-secret请求头中。配置服务器认证以要求该请求头,从而拒绝直接访问沙箱 URL 的请求,同时保持通过你域名的流量正常工作。