Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions sandbox/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Sandbox Overview and Capabilities
description: Explore Sandbox creation, commands, files, pause and resume, and lifecycle events through the experimental Playground, with clear capability and resource boundaries.
description: Create sandboxes with the E2B SDK or SandBase Console, inspect status, logs, and metrics, and explore the separate experimental Playground.
---

# Sandbox overview and capabilities
Expand All @@ -9,7 +9,9 @@ Sandbox provides isolated environments for running commands, executing code, and

[Quickstart / E2B SDK](./quickstart) · [Open Playground (Experimental)](./playground)

## A five-minute walkthrough
Use the [official E2B SDK](./quickstart) to integrate Sandbox into your application. Sign in to the [Sandbox Console](https://www.sandbase.ai/console/sandboxes) to create sandboxes and view instance status, logs, and metrics. See the [Sandbox product overview](https://www.sandbase.ai/landing/sandbox) for an introduction. The walkthrough and support table below describe the separate Experimental Playground.

## A five-minute Playground walkthrough

1. Enter an [API key](/getting-started/api-keys) with Sandbox permissions. Connecting only reads templates and instances.
2. Choose an available template, acknowledge the resource notice, and create a short-lived instance.
Expand Down
2 changes: 2 additions & 0 deletions sandbox/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import SandboxPromo from '../.vitepress/theme/SandboxPromo.vue'

Use the official E2B SDK with your SandBase API key to create an isolated sandbox, run a command, and read and write files. This guide targets **E2B JavaScript and Python SDK 2.51.0**.

For browser-based creation and observation, sign in to the [Sandbox Console](https://www.sandbase.ai/console/sandboxes) to create an instance and view its status, logs, and metrics. Continue with the SDK steps below for application integration, or read the [Sandbox product overview](https://www.sandbase.ai/landing/sandbox).

## 1. Configure the official SDK

[Create a SandBase API key in the Console](https://www.sandbase.ai/console/keys), then configure the standard E2B environment variables. The official SDK reads these automatically in both JavaScript and Python.
Expand Down
53 changes: 53 additions & 0 deletions scripts/public-sandbox-page-links.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import assert from 'node:assert/strict'

// These are published product pages, not API endpoints. Match the complete href
// in Markdown, HTML or a compiled href property; never strip URL prefixes.
const approvedPage = String.raw`https:\/\/www\.sandbase\.ai\/(?:console\/sandboxes|landing\/sandbox)`
const markdownHref = new RegExp(String.raw`(\]\()${approvedPage}(\))`, 'g')
const renderedHref = new RegExp(String.raw`(\bhref["']?\s*[:=]\s*)(\\?["'])${approvedPage}\2`, 'g')

export const sandboxAPIPath = /\/(?:v1\/)?sandboxes?(?:\/|%7b|\{|:|\b)/i

export function maskApprovedSandboxPageHrefs(content) {
return content
.replace(markdownHref, '$1/approved-product-page$2')
.replace(renderedHref, '$1$2/approved-product-page$2')
}

// Both source and built validators import this module, so these regressions run
// in the existing CI commands without a separate test script.
for (const url of [
'https://www.sandbase.ai/console/sandboxes',
'https://www.sandbase.ai/landing/sandbox',
]) {
for (const wrap of [
value => `[Product](${value})`,
value => `<a href="${value}">Product</a>`,
value => `<a href='${value}'>Product</a>`,
value => `({href:"${value}"})`,
value => `({"href":"${value}"})`,
value => String.raw`<a href=\"${value}\">Product</a>`,
]) {
assert.doesNotMatch(maskApprovedSandboxPageHrefs(wrap(url)), sandboxAPIPath)
// An approved link must not exempt another API path in the same page.
assert.match(maskApprovedSandboxPageHrefs(`${wrap(url)} GET /v1/sandboxes`), sandboxAPIPath)
for (const suffix of ['/api', '/v1/sandboxes', '?next=/v1/sandboxes', '#/sandboxes']) {
const source = wrap(url + suffix)
assert.equal(maskApprovedSandboxPageHrefs(source), source)
if (url.includes('/sandboxes') || suffix.includes('/sandboxes')) {
assert.match(maskApprovedSandboxPageHrefs(source), sandboxAPIPath)
}
}
}
}
for (const source of [
'GET /sandboxes', 'POST /v1/sandboxes', 'GET /sandboxes/{id}/metrics',
'[API](https://api.sandbase.ai/sandboxes)',
'[API](https://www.sandbase.ai/v1/sandboxes)',
'<a href="https://other.example/console/sandboxes">API</a>',
'<a href="https://www.sandbase.ai.evil.example/console/sandboxes">API</a>',
'<a href="/console/sandboxes">Not an approved absolute href</a>',
'fetch("https://www.sandbase.ai/console/sandboxes")',
]) {
assert.match(maskApprovedSandboxPageHrefs(source), sandboxAPIPath)
}
5 changes: 3 additions & 2 deletions scripts/validate-built-public-surface.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { maskApprovedSandboxPageHrefs, sandboxAPIPath } from './public-sandbox-page-links.mjs'
import assert from 'node:assert/strict'
import { existsSync, readFileSync, readdirSync } from 'node:fs'
import path from 'node:path'
Expand Down Expand Up @@ -40,7 +41,7 @@ assert.match(legacySeedance, /<meta name="robots" content="noindex,follow">/, 'L
const forbidden = [
[/\/v1\/generations(?:\/|\b)/i, 'withdrawn generation API'],
[/\/v1\/blog\/assets(?:\/|\b)/i, 'internal Blog publishing storage API'],
[/\/(?:v1\/)?sandboxes?(?:\/|%7b|\{|:|\b)/i, 'Sandbox API'],
[sandboxAPIPath, 'Sandbox API'],
[/\/events\/webhooks(?:\/|\b)/i, 'Sandbox event webhook API'],
[/\/v1\/endpoints\/[A-Za-z0-9_{}%.-]+\/mcp\b/i, 'Endpoint MCP transport'],
[/\/v1\/endpoint_runtime_profiles\b/i, 'Endpoint runtime-profile discovery'],
Expand Down Expand Up @@ -86,7 +87,7 @@ function inspect(directory) {
// The experimental documentation routes and their dedicated lazy UI chunk are public.
// Keep all former Sandbox API reference pages and unrelated bundles protected.
if (/^assets\/(?:chunks\/)?SandboxPlayground\.[^/]+\.js$/.test(relative)) continue
const withoutGuideLinks = content.replace(/\/(?:docs\/)?sandbox\/(?:(?:playground|quickstart|index)(?:\.html)?)?(?=["'<\s?#])/g, '/experimental-guide')
const withoutGuideLinks = maskApprovedSandboxPageHrefs(content).replace(/\/(?:docs\/)?sandbox\/(?:(?:playground|quickstart|index)(?:\.html)?)?(?=["'<\s?#])/g, '/experimental-guide')
assert.doesNotMatch(withoutGuideLinks, pattern, `${relative} must not publish the hidden ${label}`)
continue
}
Expand Down
3 changes: 2 additions & 1 deletion scripts/validate-public-api-surface.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { maskApprovedSandboxPageHrefs, sandboxAPIPath } from './public-sandbox-page-links.mjs'
import assert from 'node:assert/strict'
import { readdirSync, readFileSync } from 'node:fs'
import path from 'node:path'
Expand Down Expand Up @@ -1131,7 +1132,7 @@ function inspectPublishedSources(directory) {
}
// Only the explicitly published experimental Sandbox guide/playground may link this section.
if (!['sandbox/index.md', 'sandbox/playground.md'].includes(relative)) {
assert.doesNotMatch(content, /\/(?:v1\/)?sandboxes?(?:\/|\{|:|\b)/i, `${relative} must not expose sandbox API paths`)
assert.doesNotMatch(maskApprovedSandboxPageHrefs(content), sandboxAPIPath, `${relative} must not expose sandbox API paths`)
}
if (!['api-reference/endpoints/index.md', 'api-reference/endpoints/mcp.md', 'agents/services.md'].includes(relative)) {
assert.doesNotMatch(content, /\/v1\/endpoints\/[^\s`"']+\/mcp\b/i, `${relative} must not expose Endpoint MCP transport`)
Expand Down
Loading