部署至 Sandbox
@mastra/deployer-sandbox 會將包含 Studio 的完整 Mastra 伺服器部署至暫時性的 Workspace Sandbox,並傳回可用的公開 URL。由於部署器會略過相依性安裝,重複部署可以更快完成。
Sandbox 部署適用於:
- Agent 建置的應用程式:Agent 產生 Mastra 專案並部署,以驗證結果。
- 持續整合(CI):啟動實際伺服器執行檢查,完成後再將其關閉。
- 即時預覽:合併前與團隊分享可運作的 Agent。
- 多租戶不受信任程式碼:執行與基礎架構隔離的個別使用者 Mastra 執行個體。
Sandbox 有供應商強制規定的 runtime 上限,且會過期。正式環境代管請參閱部署概覽。
支援的 Sandbox「支援的 Sandbox」的直接連結
部署器可搭配任何支援網路功能(公開連接埠 URL)的 Workspace Sandbox:
- Vercel Sandbox (
@mastra/vercel) - E2B (
@mastra/e2b) - Daytona (
@mastra/daytona)
供應商作者可在 WorkspaceSandbox 上實作選用的 networking 能力,以加入支援。
快速開始「快速開始」的直接連結
安裝部署器與你選擇的 Sandbox Provider。此範例使用 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 用來識別部署,因此後續使用相同名稱的部署會重複使用現有 Sandbox。
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不得超過方案的 Sandbox 最長存續時間;Pro 方案為 45 分鐘。更高的值會讓部署收到 Vercel API 的 400 回應而失敗。- 在
ports中宣告伺服器連接埠。與 E2B 和 Daytona 不同,Vercel 只會公開建立時宣告的連接埠。
使用一個指令完成建置與部署:
mastra build
設定 SandboxDeployer() 後,mastra build 會打包專案並部署至 Sandbox。部署會印出 API 與 Studio URL,並將 sandbox-deployment.json manifest 寫入 .mastra/output:
API: https://<sandbox-id>-4111.vercel.run/api
Studio: https://<sandbox-id>-4111.vercel.run
Sandbox Provider 回報到期時間時,manifest 會包含 expiresAt。
重新部署至同一個 Sandbox 時,若輸入未變更,便會略過相依性安裝。這些輸入包括 package.json、打包的 lockfile 及安裝指令。
URL 提供的內容「URL 提供的內容」的直接連結
Studio URL 是不含 /api 的 Sandbox 根目錄。在瀏覽器中開啟即可使用 Studio。以 studio: false 執行部署時,根目錄會改為提供 Mastra 歡迎頁面。
API URL 只是其下方端點的前置路徑,例如 /api/agents。/api 本身沒有 handler,因此即使伺服器狀態正常,在瀏覽器中開啟仍會傳回「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'
Provider 認證資訊「Provider 認證資訊」的直接連結
每個 Provider 都使用各自的認證資訊進行驗證。請設定部署目標 Sandbox 所需的值:
# E2B
E2B_API_KEY=
# Daytona
DAYTONA_API_KEY=
# Vercel
VERCEL_TOKEN=
VERCEL_TEAM_ID=
VERCEL_PROJECT_ID=
每個 Provider 也接受以建構函式選項傳入這些值。自行代管的 E2B 與 Daytona 安裝會接受 E2B_DOMAIN 或 DAYTONA_API_URL。
與 mastra dev 不同,mastra build 不會載入 .env 檔案。部署發生於建置期間,因此從環境讀取認證資訊的 Sandbox Provider(例如使用 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 就會進行部署,因此 script 名稱應反映其用途。請將它與一般的 build script 分開,以免代管平台或 CI 工作執行 npm run build 時意外部署 Sandbox。
在持續整合(CI)中,請改為將認證資訊匯出為 secret。無論採用何種機制,變數都必須存在於 shell 環境中,而不能只存在 .env 檔案內。
以上適用於部署器在本機所需的認證資訊。已部署伺服器所需的變數會分開處理:部署器會讀取 .env、.env.production 及 .env.local,並將其注入 Sandbox。請參閱安全性。
使用 E2B「使用 E2B」的直接連結
對 E2B 而言,id 用來識別部署,因此後續使用相同值的部署會重新連線至現有 Sandbox,無論它正在執行或暫停。
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';若未傳入,Provider 會在首次使用時建置自訂的 Filesystem in Userspace(FUSE)template。E2B 會暫停而非停止:stop() 會建立整部虛擬機器(VM)的快照,包括記憶體與執行中的處理程序。暫停的 Sandbox 喚醒後,Mastra 伺服器會從原處繼續執行,不需要像 Vercel 一樣重新啟動。
使用 Daytona「使用 Daytona」的直接連結
對 Daytona 而言,id 用來識別部署,因此後續使用相同值的部署會重新連線至現有 Sandbox。設定 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 Sandbox 會保留檔案系統,但不保留執行中的處理程序,因此喚醒方式與 Vercel 相同:resolver 會在 wake: true 時重新啟動伺服器。
Daytona 會依目的地篩選對外流量。對某些主機的要求能正常透過 Transport Layer Security(TLS)連線,其他則會在交握期間重設,在 Agent 或 Tool 中顯示為 Node 的一般 fetch failed。除錯前,先從 Sandbox 內對相同主機執行 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 方案也會封鎖雲端儲存端點,掛載 helper 會以專用錯誤回報此情況。
以程式部署「以程式部署」的直接連結
deployToSandbox() 不經 bundler,直接部署預先建置的輸出目錄。與 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() export,取得現有部署。它會透過 Provider 特有的設定識別 Sandbox,例如 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,可在傳回前繼續已停止的 Sandbox。只有繼續後伺服器狀態不正常時,才會重新啟動伺服器。Provider Tool 也能使用,例如 vercel sandbox ls、vercel sandbox stop 及 vercel sandbox rm。
到期與 URL「到期與 URL」的直接連結
Sandbox 會依 Provider 的 runtime 限制到期。Provider 回報到期時間時,部署會記錄該時間,並透過 deployment.expiresAt 供程式存取。
Sandbox 停止再繼續時,URL 可能變更。請將 URL 視為連線細節,並將 Sandbox 識別資訊(例如 sandboxName)視為穩定控制碼。下列路由層級會處理 URL 輪替。
路由層級「路由層級」的直接連結
第 1 層:直接 URL「第 1 層:直接 URL」的直接連結
開發、示範與 CI 可直接使用印出的 URL,前提是每次部署使用全新 URL 沒有問題。
第 2 層:在 runtime 解析「第 2 層:在 runtime 解析」的直接連結
getDeployment() 會在 runtime 解析目前 URL,讓使用端不會持有過期 URL。任何知道 Sandbox 名稱的伺服器都能解析,包括與 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(預設值)時,不會啟動 Sandbox,而會取得 { url, status } 以便採取動作。解析 URL、stop() 與 destroy() 都會依名稱附加至現有 Sandbox,不會將其繼續,因此針對已停止 Sandbox 的生命週期操作絕不會喚醒它或開始計費。使用 wake: true 時,Sandbox 會繼續;若伺服器未回應,則會重新啟動。是否需要重新啟動取決於 Provider:Vercel 與 Daytona 會還原檔案系統,但不還原執行中的處理程序;E2B 則會繼續包含伺服器處理程序的整部 VM。
@mastra/deployer-sandbox/client 僅供伺服器使用。解析 Sandbox 會使用絕不能傳至瀏覽器的 Provider 認證資訊。在瀏覽器環境中匯入此模組會擲回錯誤。
第 3 層:提供終端使用者的穩定 URL「第 3 層:提供終端使用者的穩定 URL」的直接連結
在自己的網域提供穩定 URL,並在伺服器端轉送至 Sandbox;可使用 route handler proxy 或 Edge Config alias。
下列範例使用 Vercel 與 Next.js,但此概念適用於任何能轉送要求的伺服器端框架或 Provider。
-
Route handler proxy。
createSandboxHandler()會快取 Sandbox 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。 在部署器設定
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 中改寫要求:middleware.tsimport { createSandboxProxy } from '@mastra/deployer-sandbox/client'export const middleware = createSandboxProxy({ key: 'my-preview' })export const config = { matcher: '/api/:path*' }
CI 範例「CI 範例」的直接連結
為每個 pull request 部署預覽:
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"
安全性「安全性」的直接連結
- Sandbox URL 是公開的。任何擁有 URL 的人都能存取 Mastra 伺服器,包括 Studio。除拋棄式預覽外,請一律啟用伺服器驗證。
.env檔案中的環境變數會注入遠端 Sandbox VM,讓伺服器能夠執行。發生此情況時,部署會記錄警告。請勿部署你不願放在共用預覽伺服器上的 secret。- 若要將存取限制為第 3 層流量,請將
secret傳入createSandboxHandler()或createSandboxProxy()。這些 helper 會在轉送要求上附加x-mastra-sandbox-secretheader。設定伺服器驗證以要求該 header,如此直接存取 Sandbox URL 會遭拒絕,而透過你網域的流量則可正常運作。