Loading...
Loading...
Use when creating cloud sandboxes (microVMs) to run code, start dev servers, and generate live preview URLs. Also covers deploying AI agents, MCP servers, batch jobs, and Agent Drives (shared filesystems) on Blaxel's serverless infrastructure. Reach for this skill when you need isolated compute environments, real-time app previews, shared file storage across sandboxes, or to deploy agentic workloads.
npx skill4agent add blaxel-ai/agent-skills blaxel@blaxel/coreblaxelbl.envBL_WORKSPACEBL_API_KEY~/.blaxel/config.yamlbl login YOUR-WORKSPACEexport BL_WORKSPACE=your-workspace
export BL_API_KEY=your-api-keyblaxel/base-image:latestblaxel/node:latestblaxel/nextjs:latestblaxel/vite:latestblaxel/expo:latestblaxel/py-app:latestimport { SandboxInstance } from "@blaxel/core";
const sandbox = await SandboxInstance.createIfNotExists({
name: "my-sandbox",
image: "blaxel/base-image:latest",
memory: 4096,
ports: [{ target: 3000, protocol: "HTTP" }],
});from blaxel.core import SandboxInstance
sandbox = await SandboxInstance.create_if_not_exists({
"name": "my-sandbox",
"image": "blaxel/base-image:latest",
"memory": 4096,
"ports": [{"target": 3000, "protocol": "HTTP"}],
})createIfNotExistscreate_if_not_exists// Write files
await sandbox.fs.write("/app/package.json", JSON.stringify({
name: "my-app",
scripts: { dev: "astro dev --host 0.0.0.0 --port 3000" },
dependencies: { "astro": "latest" }
}));
// Or write multiple files at once
await sandbox.fs.writeTree([
{ path: "src/pages/index.astro", content: "<h1>Hello</h1>" },
{ path: "astro.config.mjs", content: "import { defineConfig } from 'astro/config';\nexport default defineConfig({});" },
], "/app");
// Execute a command and wait for it to finish
const install = await sandbox.process.exec({
name: "install",
command: "npm install",
workingDir: "/app",
waitForCompletion: true,
timeout: 60000,
});
// Start a long-running dev server (don't wait for completion)
const devServer = await sandbox.process.exec({
name: "dev-server",
command: "npm run dev",
workingDir: "/app",
waitForPorts: [3000], // returns once port 3000 is open
});await sandbox.fs.write("/app/package.json", '{"name":"my-app","scripts":{"dev":"astro dev --host 0.0.0.0 --port 3000"},"dependencies":{"astro":"latest"}}')
await sandbox.fs.write_tree([
{"path": "src/pages/index.astro", "content": "<h1>Hello</h1>"},
{"path": "astro.config.mjs", "content": "import { defineConfig } from 'astro/config';\nexport default defineConfig({});"},
], "/app")
install = await sandbox.process.exec({
"name": "install",
"command": "npm install",
"working_dir": "/app",
"wait_for_completion": True,
"timeout": 60000,
})
dev_server = await sandbox.process.exec({
"name": "dev-server",
"command": "npm run dev",
"working_dir": "/app",
"wait_for_ports": [3000],
})0.0.0.0localhost--host 0.0.0.0HOSTconst preview = await sandbox.previews.createIfNotExists({
metadata: { name: "app-preview" },
spec: { port: 3000, public: true },
});
const url = preview.spec?.url;
// url => https://xxxx.us-pdx-1.preview.bl.runpreview = await sandbox.previews.create_if_not_exists({
"metadata": {"name": "app-preview"},
"spec": {"port": 3000, "public": True},
})
url = preview.spec.urlpublic: falseconst preview = await sandbox.previews.createIfNotExists({
metadata: { name: "private-preview" },
spec: { port: 3000, public: false },
});
const token = await preview.tokens.create(new Date(Date.now() + 10 * 60 * 1000));
// Access: preview.spec?.url + "?bl_preview_token=" + token.value// Reconnect to an existing sandbox
const sandbox = await SandboxInstance.get("my-sandbox");
// List files
const { subdirectories, files } = await sandbox.fs.ls("/app");
// Read a file
const content = await sandbox.fs.read("/app/src/pages/index.astro");
// Get process info / logs
const proc = await sandbox.process.get("dev-server");
const logs = proc.logs; // available if waitForCompletion was true
// Kill a process
await sandbox.process.kill("dev-server");
// Delete the sandbox (all data is erased)
await sandbox.delete();sandbox = await SandboxInstance.get("my-sandbox")
result = await sandbox.fs.ls("/app")
content = await sandbox.fs.read("/app/src/pages/index.astro")
proc = await sandbox.process.get("dev-server")
# proc.logs available if wait_for_completion was True
await sandbox.process.kill("dev-server")
await sandbox.delete()bl new sandbox my-astro-template
cd my-astro-templateblaxel.tomlDockerfileentrypoint.shMakefileFROM node:22-alpine
WORKDIR /app
COPY /sandbox-api /usr/local/bin/sandbox-api
RUN npm install -g astro
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]#!/bin/sh
/usr/local/bin/sandbox-api &
while ! nc -z 127.0.0.1 8080; do sleep 0.1; done
echo "Sandbox API ready"
# Optionally start a process via the sandbox API:
# curl http://127.0.0.1:8080/process -X POST -d '{"workingDir":"/app","command":"npm run dev","waitForCompletion":false}' -H "Content-Type: application/json"
waitbl deploybl get sandboxes my-astro-template -ojson | jq -r '.[0].spec.runtime.image'const sandbox = await SandboxInstance.createIfNotExists({
name: "project-sandbox",
image: "IMAGE_ID",
memory: 4096,
ports: [{ target: 3000, protocol: "HTTP" }],
});-y| Command | Purpose |
|---|---|
| Authenticate to workspace |
| Initialize new resource from template |
| Build and deploy resource to Blaxel |
| Deploy from a specific directory |
| Run resource locally for testing |
| Run locally with hot reload |
| List resources |
| Watch a sandbox deployment status |
| Remove resource |
| Open interactive terminal in sandbox |
| Interactive chat with deployed agent |
| Execute a deployed batch job |
name = "my-resource"
type = "sandbox" # sandbox, agent, function, job, volume-template
[env]
NODE_ENV = "development" # NOT for secrets — use Variables-and-secrets
[runtime]
memory = 4096 # MB
generation = "mk3"
# timeout = 900 # seconds (agents max 900, jobs max 86400)
# Ports (sandbox only)
[[runtime.ports]]
name = "dev-server"
target = 3000
protocol = "tcp"0.0.0.0localhostwaitForCompletionprocess.wait()maxWait[env]This feature is currently in private preview. During the preview, Agent Drive is only available in theregion. Both drive and sandbox must be in this region.us-was-1
import { DriveInstance } from "@blaxel/core";
const drive = await DriveInstance.createIfNotExists({
name: "my-drive",
region: "us-was-1",
displayName: "My Project Drive", // optional; defaults to name
labels: { env: "dev", project: "x" }, // optional
});from blaxel.core.drive import DriveInstance
drive = await DriveInstance.create_if_not_exists(
{
"name": "my-drive",
"region": "us-was-1",
"display_name": "My Project Drive",
"labels": {"env": "dev", "project": "x"},
}
)import { SandboxInstance } from "@blaxel/core";
const sandbox = await SandboxInstance.get("my-sandbox");
await sandbox.drives.mount({
driveName: "my-drive",
mountPath: "/mnt/data",
drivePath: "/", // optional; defaults to root of the drive
});from blaxel.core import SandboxInstance
sandbox = await SandboxInstance.get("my-sandbox")
await sandbox.drives.mount(
drive_name="my-drive",
mount_path="/mnt/data",
drive_path="/",
)await sandbox.drives.mount({
driveName: "my-drive",
mountPath: "/app/project",
drivePath: "/projects/alpha",
});await sandbox.drives.mount(
drive_name="my-drive",
mount_path="/app/project",
drive_path="/projects/alpha",
)// List mounted drives on a sandbox
const mounts = await sandbox.drives.list();
// List all drives
const drives = await DriveInstance.list();
// Unmount
await sandbox.drives.unmount("/mnt/data");
// Delete a drive
await DriveInstance.delete("my-drive");
// or instance-level:
const drive = await DriveInstance.get("my-drive");
await drive.delete();mounts = await sandbox.drives.list()
drives = await DriveInstance.list()
await sandbox.drives.unmount("/mnt/data")
await DriveInstance.delete("my-drive")
# or instance-level:
drive = await DriveInstance.get("my-drive")
await drive.delete()bl get drivesimport { SandboxInstance, DriveInstance } from "@blaxel/core";
// 1. Create a drive
const drive = await DriveInstance.createIfNotExists({
name: "agent-storage",
region: "us-was-1",
});
// 2. Create a sandbox (use image ID from custom template)
const sandbox = await SandboxInstance.createIfNotExists({
name: "my-agent-sandbox",
image: "my-sandbox-image-id",
memory: 2048,
region: "us-was-1",
});
// 3. Mount the drive
await sandbox.drives.mount({
driveName: "agent-storage",
mountPath: "/mnt/storage",
drivePath: "/",
});
// 4. Write a file to the mounted drive
await sandbox.fs.write("/mnt/storage/hello.txt", "Hello from the drive!");
// 5. Read it back
const content = await sandbox.fs.read("/mnt/storage/hello.txt");
console.log(content); // "Hello from the drive!"
// 6. List mounted drives
const mounts = await sandbox.drives.list();
console.log(mounts);import asyncio
from blaxel.core.drive import DriveInstance
from blaxel.core import SandboxInstance
async def main():
drive = await DriveInstance.create_if_not_exists(
{"name": "agent-storage", "region": "us-was-1"}
)
sandbox = await SandboxInstance.create_if_not_exists(
{
"name": "my-agent-sandbox",
"image": "my-sandbox-image-id",
"memory": 2048,
"region": "us-was-1",
}
)
await sandbox.drives.mount(
drive_name="agent-storage",
mount_path="/mnt/storage",
drive_path="/",
)
await sandbox.fs.write("/mnt/storage/hello.txt", "Hello from the drive!")
content = await sandbox.fs.read("/mnt/storage/hello.txt")
print(content)
mounts = await sandbox.drives.list()
print(mounts)
asyncio.run(main())bl new agent
# develop in src/agent.ts or src/agent.py
bl serve # test locally
bl deploy # deploy
bl chat AGENT-NAME # querybl new mcp
# implement in src/server.ts or src/server.py
bl serve --hotreload # test locally
bl deployconst tools = await blTools(["functions/my-mcp-server"]);https://<SANDBOX_URL>/mcpbl new job
# implement in src/index.ts or src/index.py
bl deploy
bl run job NAME --data '{"tasks": [...]}'maxConcurrentTasks