跳至主要內容

PlatformSandbox

用於在 Mastra Platform 環境中佈建 Sandbox 的用戶端。每個 PlatformSandbox 實例各自擁有一個遠端 Sandbox:start() 會佈建 Sandbox、executeCommand() 會在其中執行指令,而 destroy() 則會將其移除。如要擁有更多遠端 Sandbox,請建構更多實例。你亦可使用 clone(),從已設定的範本衍生實例(請參閱為一組 Sandbox 建立複本)。

Sandbox 會從預先建立的配方檢查點啟動,當中已安裝 Python 3、Node 22、TypeScript、tsx 及常用建構工具。傳入固定的 id 即可啟用檢查點復原,讓新 Sandbox 從上一個 Sandbox 的檔案系統啟動。

相關 Provider:適用於自行託管 Railway Sandbox 的 RailwaySandbox,以及適用於本機 Sandbox 的 LocalSandbox

資訊

介面詳情請參閱 WorkspaceSandbox 介面

安裝
安裝 的直接連結

npm install @mastra/platform-workspace

設定平台憑證。存取權杖、項目 ID 及環境 ID 會回退至環境變數,因此 Mastra Platform 部署可以不傳入任何建構函式選項。

MASTRA_PLATFORM_ACCESS_TOKEN=your-platform-access-token
MASTRA_PROJECT_ID=your-project-id
MASTRA_ENVIRONMENT_ID=your-environment-id

在 Mastra Platform 部署中,系統會自動注入 MASTRA_PLATFORM_ACCESS_TOKENMASTRA_PROJECT_IDMASTRA_ENVIRONMENT_ID,因此呼叫建構函式時毋須傳入選項。如在本機開發,MASTRA_PLATFORM_ACCESS_TOKEN 可使用你機構設定頁面中 API Tokens 下的 sk_ API 權杖。

用法
用法 的直接連結

PlatformSandbox 加入 Workspace,並指派給 Agent:

import { Agent } from '@mastra/core/agent'
import { Workspace } from '@mastra/core/workspace'
import { PlatformSandbox } from '@mastra/platform-workspace'

const workspace = new Workspace({
sandbox: new PlatformSandbox({
// accessToken, projectId, environmentId all fall back to env vars
idleTimeoutMinutes: 30,
}),
})

const agent = new Agent({
id: 'code-agent',
name: 'Code Agent',
instructions: 'You are a coding assistant working in this workspace.',
model: 'anthropic/claude-sonnet-4-6',
workspace,
})

const response = await agent.generate(
'Print "Hello, world!" and show the current working directory.',
)

console.log(response.text)

私人網絡
私人網絡 的直接連結

networkIsolation 設為 PRIVATE,即可加入環境的私人網絡,並連接同一 Mastra Platform 環境內執行的其他服務:

const workspace = new Workspace({
sandbox: new PlatformSandbox({
networkIsolation: 'PRIVATE',
}),
})

預設的 ISOLATED 模式只允許向外連接互聯網,不設私人網絡連線。

重新連接執行中的 Sandbox
重新連接執行中的 Sandbox 的直接連結

傳入現有的 sandboxId,即可重新連接運作中的 Sandbox,而非建立新 Sandbox:

const sandbox = new PlatformSandbox({
sandboxId: 'sbx_abc123',
})
await sandbox.start()

const result = await sandbox.executeCommand('cat', ['/workspace/state.json'])

設定 sandboxId 後,由於 Sandbox 已存在,因此毋須提供 environmentId

檢查點復原
檢查點復原 的直接連結

建構函式的 id(明確指定或自動產生)會在 POST /sandbox 時傳送至平台,作為建議復原鍵:

  • 如平台識別出上一個工作階段的 id,新 Sandbox 會從較早 Sandbox 檔案系統的最新檢查點啟動,而非基礎配方。
  • 如平台無法識別 id,便會從基礎配方啟動全新的 Sandbox。自動產生的 ID 永不會相符,因此省略 id 會停用檢查點復原。

傳入固定的 id,即可跨工作階段或 destroy()start() 週期保留 Sandbox 的檔案系統:

const sandbox = new PlatformSandbox({
id: `project-${projectId}`,
})
await sandbox.start() // Boots from the most recent checkpoint for this id, or fresh if unknown

檢查點復原的粒度比透過 sandboxId 重新連接更粗。重新連接(透過 sandboxId)會接回確切的運作中 Sandbox 及其執行中的程序。檢查點復原則會建構全新 Sandbox,並從平台為上一個相同 id 的 Sandbox 擷取的最新檢查點復原其檔案系統。系統不會復原執行中的程序,也不會復原上次檢查點之後寫入檔案系統的內容。

每個 id 對應一個獨立檔案系統。在互不相關的 Sandbox 重複使用相同 id,會令平台從彼此的檢查點啟動這些 Sandbox。

為一組 Sandbox 建立複本
為一組 Sandbox 建立複本 的直接連結

clone() 會傳回獨立、同層的 PlatformSandbox,繼承憑證及預設值(存取權杖、項目、環境、網絡隔離、逾時、指示、環境變數、閒置逾時),並可按實例覆寫。傳回的 Sandbox 尚未啟動,會在自己的 start() 中佈建,因此 clone() 不會執行 I/O:

const template = new PlatformSandbox({
networkIsolation: 'PRIVATE',
idleTimeoutMinutes: 30,
})

const perProject = template.clone({ id: `project-${projectId}` })
await perProject.start()

clone() 與每個複本各自固定的 id 配合使用,即可讓每個複本獨立啟用檢查點復原

執行指令
執行指令 的直接連結

executeCommand 會在遠端 Sandbox 執行指令並傳回輸出。傳入 args 可安全地以 shell 引號括起引數:

const result = await sandbox.executeCommand('python', ['analyze.py'], {
timeout: 30_000,
cwd: '/workspace',
env: { INPUT: 'repo' },
})

console.log(result.stdout)
console.log(result.exitCode)
注意

command 引數是 shell 字串,並會原封不動地串接至遠端 shell。這讓你可以使用管道、重新導向及串接(ls -la | grep foo),但不受信任的輸入必須透過 args(安全加上引號)傳入,或由呼叫者以 shell 引號括起。不受信任的 command 值可在 Sandbox 任意執行 shell 指令。

建構函式參數
建構函式參數 的直接連結

accessToken?:

string
平台存取權杖。回退至 MASTRA_PLATFORM_ACCESS_TOKEN 環境變數。

projectId?:

string
平台項目 ID。回退至 MASTRA_PROJECT_ID 環境變數。

environmentId?:

string
Sandbox 所屬的平台環境 ID。回退至 MASTRA_ENVIRONMENT_ID 環境變數。除非傳入 sandboxId,否則為必填。

sandboxId?:

string
要重新連接的現有 Sandbox ID,而非建立新 Sandbox。設定後毋須提供 environmentId。

idleTimeoutMinutes?:

number
在平台銷毀 Sandbox 前,Sandbox 可在沒有活動的情況下維持運作多久。

networkIsolation?:

'ISOLATED' | 'PRIVATE'
網絡模式。'ISOLATED'(預設)只允許向外連接互聯網。'PRIVATE' 會加入平台環境的私人網絡。

env?:

Record<string, string>
建立 Sandbox 時寫入其中的環境變數。亦可將每項指令的環境變數傳給 executeCommand。

timeout?:

number
預設指令執行逾時(毫秒)。可透過 ExecuteCommandOptions.timeout 按呼叫覆寫。

instructions?:

string | ((opts: { defaultInstructions: string; requestContext?: RequestContext }) => string)
getInstructions() 傳回的自訂指示。字串會完全取代預設值;函式會接收預設值,並可按要求擴充或自訂。

id?:

string
= 自動產生
此 Sandbox 實例的唯一識別碼。會作為建議復原鍵傳送至平台:如平台識別出上一個 Sandbox 的 id,新 Sandbox 會從該 Sandbox 的最新檢查點啟動,而非基礎配方。無法識別的 id 會改為啟動全新 Sandbox。省略時自動產生,並會停用檢查點復原。

fetch?:

typeof fetch
自訂 fetch 實作,主要用於測試。

屬性
屬性 的直接連結

id:

string
Sandbox 實例識別碼。

name:

string
Provider 名稱('PlatformSandbox')。

provider:

string
Provider 識別碼('platform')。

status:

ProviderStatus
'pending' | 'initializing' | 'ready' | 'starting' | 'running' | 'stopping' | 'stopped' | 'destroying' | 'destroyed' | 'error'.

processes:

PlatformProcessManager
背景程序管理器。請參閱 SandboxProcessManager 參考

方法
方法 的直接連結

start:

() => Promise<void>
佈建遠端 Sandbox;如建構函式收到 sandboxId,則重新連接。Sandbox 運作後可重複安全呼叫。如重新連接的目標已銷毀,便會改為全新佈建。

destroy:

() => Promise<void>
移除遠端 Sandbox 並清除快取的 exec 租約。之後呼叫 start() 會佈建全新 Sandbox(如設定固定 id,則從檢查點復原)。

stop:

() => Promise<void>
destroy() 的別名。

executeCommand:

(command: string, args?: string[], options?: ExecuteCommandOptions) => Promise<CommandResult>
在遠端 Sandbox 執行指令,並傳回其 stdout、stderr、exitCode 及 executionTimeMs。command 是 shell 字串,args 會安全地以 shell 引號括起。

clone:

(options?: SandboxCloneOptions) => PlatformSandbox
建構尚未啟動的同層 PlatformSandbox,繼承憑證及預設值,並可按實例覆寫(id、sandboxId、env、idleTimeoutMinutes)。不會執行 I/O。可用於從一個已設定的範本建立一組獨立 Sandbox。

getInfo:

() => Promise<SandboxInfo>
傳回 Sandbox 的平台 id、provider、status、createdAt 及中繼資料(sandboxId、providerResourceId、platformStatus)。

getInstructions:

(opts?: { requestContext?: RequestContext }) => string
傳回 Workspace 在 Tool 說明中顯示的 Sandbox 指示。遵從建構函式的 instructions 選項;否則傳回平台預設指示,Sandbox 運作時亦會包含目前的遠端 Sandbox id。

錯誤
錯誤 的直接連結

Platform API 失敗會引發 PlatformApiError。結構化的 { error: { message, type } } 回應會剖析為 .code(機器可讀類別)及 .proxyMessage(人類可讀字串);原始回應內容仍可在 .body 取得:

import { PlatformApiError } from '@mastra/platform-workspace'

try {
await sandbox.executeCommand('cat', ['/missing.txt'])
} catch (err) {
if (err instanceof PlatformApiError) {
if (err.code === 'not_found') {
// handle missing resource
} else if (err.code === 'authentication_error') {
// refresh token
}
console.error(err.status, err.code, err.proxyMessage)
}
}

如回應內容並非 JSON(例如負載平衡器傳回 HTML 502),codeproxyMessage 會是 undefined

executeCommand 會透過 direct-exec 資料平面(連接 Railway tcp-proxy 的 WebSocket)執行;遇到無法復原的失敗時,亦可能引發兩種具類型的 Sandbox 錯誤:

import { SandboxDestroyedError, SandboxExecTransportError } from '@mastra/platform-workspace'

try {
await sandbox.executeCommand('pytest')
} catch (err) {
if (err instanceof SandboxDestroyedError) {
// /exec-lease returned 410; the sandbox has been destroyed.
// The cached sandbox id and lease have already been cleared,
// so reusing the instance will reprovision on the next call.
} else if (err instanceof SandboxExecTransportError) {
// Both the initial WebSocket attempt and the built-in retry
// closed without an exit frame against a live sandbox.
console.error(err.closeCode, err.closeReason, err.wsEndpoint)
}
}

SandboxExecTransportError 帶有診斷欄位(openedcloseCodecloseReasonwsEndpoint,以及 sandboxIdcommandattempts),讓操作人員可分辨 Railway 資料平面故障與指令執行失敗。