Aller au contenu principal

PlatformSandbox

Client permettant de provisionner des Sandboxes dans un environnement Mastra Platform. Chaque instance de PlatformSandbox possède une Sandbox distante : start() la provisionne, executeCommand() y exécute des commandes et destroy() la détruit. Construisez des instances supplémentaires pour posséder d'autres Sandboxes distantes. Utilisez clone() pour les dériver d'un template configuré (consultez Clonage).

Les Sandboxes démarrent depuis un checkpoint de recette préconstruit dans lequel Python 3, Node 22, TypeScript, tsx et les Tools de build courants sont déjà installés. Transmettez un id stable pour activer la récupération par checkpoint, afin qu'une nouvelle Sandbox démarre depuis le système de fichiers de la précédente.

Providers associés : RailwaySandbox pour les Sandboxes Railway auto-hébergées, LocalSandbox pour les Sandboxes locales.

info

Pour plus de détails sur l'interface, consultez l'interface WorkspaceSandbox.

Installation
Lien direct vers Installation

npm install @mastra/platform-workspace

Configurez les identifiants de la plateforme. Le token d'accès, l'identifiant du projet et celui de l'environnement utilisent par défaut des variables d'environnement ; un déploiement Mastra Platform peut donc n'utiliser aucune option du constructeur.

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

Dans un déploiement Mastra Platform, MASTRA_PLATFORM_ACCESS_TOKEN, MASTRA_PROJECT_ID et MASTRA_ENVIRONMENT_ID sont injectés automatiquement ; le constructeur peut donc être appelé sans options. Pour le développement local, MASTRA_PLATFORM_ACCESS_TOKEN peut contenir un token d'API sk_ provenant de la section Tokens d'API de la page des paramètres de votre organisation.

Utilisation
Lien direct vers Utilisation

Ajoutez une PlatformSandbox à un Workspace et attribuez-la à un 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)

Réseau privé
Lien direct vers Réseau privé

Définissez networkIsolation sur PRIVATE pour rejoindre le réseau privé de l'environnement et accéder aux autres services exécutés dans le même environnement Mastra Platform :

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

Le mode ISOLATED par défaut autorise uniquement l'accès sortant à Internet, sans connectivité au réseau privé.

Reconnexion à une Sandbox en cours d'exécution
Lien direct vers Reconnexion à une Sandbox en cours d'exécution

Transmettez un sandboxId existant pour vous reconnecter à une Sandbox active au lieu d'en créer une nouvelle :

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

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

Lorsque sandboxId est défini, environmentId n'est pas obligatoire, car la Sandbox existe déjà.

Récupération par checkpoint
Lien direct vers Récupération par checkpoint

La valeur id du constructeur (explicite ou générée automatiquement) est envoyée à la plateforme lors de POST /sandbox comme clé de récupération indicative :

  • Si la plateforme reconnaît le id d'une session précédente, la nouvelle Sandbox démarre depuis le checkpoint le plus récent du système de fichiers de cette ancienne Sandbox, plutôt que depuis la recette de base.
  • Si le id n'est pas reconnu, la plateforme démarre une nouvelle Sandbox depuis la recette de base. Les identifiants générés automatiquement ne correspondent jamais ; omettre id désactive donc la récupération par checkpoint.

Transmettez un id stable afin de préserver le système de fichiers d'une Sandbox entre les sessions ou pendant un cycle destroy()/start() :

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

La récupération par checkpoint est moins précise que la reconnexion au moyen de sandboxId. La reconnexion (via sandboxId) rejoint exactement la Sandbox active et ses processus en cours. La récupération par checkpoint construit une toute nouvelle Sandbox et restaure son système de fichiers depuis le dernier checkpoint capturé par la plateforme pour la Sandbox précédente portant ce id. Les processus en cours et les écritures effectuées après le dernier checkpoint ne sont pas restaurés.

Chaque id correspond à un système de fichiers indépendant. La réutilisation du même id pour des Sandboxes sans rapport amène la plateforme à les démarrer depuis le checkpoint les unes des autres.

Clonage pour une flotte de Sandboxes
Lien direct vers Clonage pour une flotte de Sandboxes

clone() renvoie une PlatformSandbox sœur indépendante qui hérite des identifiants et des valeurs par défaut (token d'accès, projet, environnement, isolation réseau, délai d'expiration, instructions, env et délai d'inactivité), avec des remplacements propres à l'instance. La Sandbox renvoyée n'est pas démarrée et se provisionne lors de son propre appel à start() ; clone() n'effectue donc aucune E/S :

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

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

Combinez clone() à un id stable pour chaque clone afin d'activer indépendamment la récupération par checkpoint sur chacun d'eux.

Exécution de commandes
Lien direct vers Exécution de commandes

executeCommand exécute une commande dans la Sandbox distante et renvoie sa sortie. Transmettez args afin que les arguments soient correctement échappés pour le 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)
attention

L'argument command est une chaîne shell concaténée telle quelle dans le shell distant. Cela permet d'utiliser des pipes, des redirections et des enchaînements (ls -la | grep foo), mais les entrées non fiables doivent être transmises au moyen de args (échappées en toute sécurité) ou échappées pour le shell par l'appelant. Les valeurs command non fiables permettent l'exécution de commandes shell arbitraires dans la Sandbox.

Paramètres du constructeur
Lien direct vers Paramètres du constructeur

accessToken?:

string
Token d'accès à la plateforme. Utilise par défaut la variable d'environnement MASTRA_PLATFORM_ACCESS_TOKEN.

projectId?:

string
Identifiant du projet de la plateforme. Utilise par défaut la variable d'environnement MASTRA_PROJECT_ID.

environmentId?:

string
Identifiant de l'environnement de plateforme auquel appartient la Sandbox. Utilise par défaut la variable d'environnement MASTRA_ENVIRONMENT_ID. Obligatoire sauf si sandboxId est transmis.

sandboxId?:

string
Identifiant d'une Sandbox existante à laquelle se reconnecter au lieu d'en créer une nouvelle. Lorsqu'il est défini, environmentId n'est pas obligatoire.

idleTimeoutMinutes?:

number
Durée pendant laquelle la Sandbox reste active sans activité avant que la plateforme ne la détruise.

networkIsolation?:

'ISOLATED' | 'PRIVATE'
Mode réseau. 'ISOLATED' (par défaut) autorise uniquement l'accès sortant à Internet. 'PRIVATE' rejoint le réseau privé de l'environnement de plateforme.

env?:

Record<string, string>
Variables d'environnement intégrées à la Sandbox lors de sa création. Des variables d'environnement propres à chaque commande peuvent également être transmises à executeCommand.

timeout?:

number
Délai d'expiration par défaut de l'exécution des commandes, en millisecondes. Peut être remplacé à chaque appel au moyen de ExecuteCommandOptions.timeout.

instructions?:

string | ((opts: { defaultInstructions: string; requestContext?: RequestContext }) => string)
Instructions personnalisées renvoyées par getInstructions(). Une chaîne remplace entièrement les valeurs par défaut ; une fonction reçoit ces valeurs et peut les étendre ou les personnaliser pour chaque requête.

id?:

string
= Généré automatiquement
Identifiant unique de cette instance de Sandbox. Envoyé à la plateforme comme clé de récupération indicative : si la plateforme reconnaît l'identifiant d'une Sandbox précédente, la nouvelle Sandbox démarre depuis le checkpoint le plus récent de cette Sandbox au lieu de la recette de base. Les identifiants inconnus produisent une nouvelle Sandbox. Généré automatiquement lorsqu'il est omis, ce qui désactive la récupération par checkpoint.

fetch?:

typeof fetch
Implémentation personnalisée de fetch, principalement destinée aux tests.

Propriétés
Lien direct vers Propriétés

id:

string
Identifiant de l'instance de Sandbox.

name:

string
Nom du Provider ('PlatformSandbox').

provider:

string
Identifiant du Provider ('platform').

status:

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

processes:

PlatformProcessManager
Gestionnaire de processus en arrière-plan. Consultez la référence de SandboxProcessManager.

Méthodes
Lien direct vers Méthodes

start:

() => Promise<void>
Provisionne la Sandbox distante, ou s'y reconnecte lorsque sandboxId a été transmis au constructeur. Idempotente une fois la Sandbox en cours d'exécution. Une cible de reconnexion détruite entraîne un nouveau provisionnement.

destroy:

() => Promise<void>
Détruit la Sandbox distante et efface le lease exec mis en cache. Un appel ultérieur à start() provisionne une nouvelle Sandbox (ou la restaure depuis un checkpoint lorsqu'un identifiant stable est défini).

stop:

() => Promise<void>
Alias de destroy().

executeCommand:

(command: string, args?: string[], options?: ExecuteCommandOptions) => Promise<CommandResult>
Exécute une commande dans la Sandbox distante et renvoie stdout, stderr, exitCode et executionTimeMs. command est une chaîne shell ; args est échappé en toute sécurité pour le shell.

clone:

(options?: SandboxCloneOptions) => PlatformSandbox
Construit une PlatformSandbox sœur non démarrée qui hérite des identifiants et des valeurs par défaut, avec des remplacements propres à l'instance (id, sandboxId, env, idleTimeoutMinutes). N'effectue aucune E/S. Utilisez-la pour créer une flotte de Sandboxes indépendantes depuis un template configuré.

getInfo:

() => Promise<SandboxInfo>
Renvoie l'identifiant de plateforme, le Provider, l'état, createdAt et les métadonnées de la Sandbox (sandboxId, providerResourceId, platformStatus).

getInstructions:

(opts?: { requestContext?: RequestContext }) => string
Renvoie les instructions de la Sandbox que le Workspace affiche dans les descriptions des Tools. Respecte l'option instructions du constructeur ; sinon, renvoie les instructions par défaut de la plateforme, qui comprennent l'identifiant actuel de la Sandbox distante lorsqu'elle est en cours d'exécution.

Erreurs
Lien direct vers Erreurs

Les échecs de l'API Platform lèvent PlatformApiError. Les réponses structurées { error: { message, type } } sont analysées dans .code (type lisible par une machine) et .proxyMessage (chaîne lisible par les utilisateurs) ; le corps brut de la réponse reste disponible dans .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)
}
}

code et proxyMessage valent undefined lorsque le corps de la réponse n'est pas au format JSON, par exemple pour une réponse HTML 502 provenant d'un répartiteur de charge.

executeCommand s'exécute sur le plan de données direct-exec (un WebSocket vers le tcp-proxy Railway) et peut également lever deux erreurs de Sandbox typées en cas d'échec irrécupérable :

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 contient des champs de diagnostic (opened, closeCode, closeReason, wsEndpoint, ainsi que sandboxId, command et attempts) afin que les opérateurs puissent distinguer un plan de données Railway défaillant d'une commande ayant échoué.