Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/opensandbox-group/OpenSandbox/llms.txt

Use this file to discover all available pages before exploring further.

The OpenSandbox Kotlin/Java SDK provides a builder-style API for creating and managing secure sandbox environments from JVM applications. It supports shell command execution with real-time streaming, comprehensive file management, egress policy control, Credential Vault integration, and a client-side SandboxPool for pre-warming idle instances. All examples below use Java syntax, which is fully compatible with the Kotlin builder API.

Installation

dependencies {
    implementation("com.alibaba.opensandbox:sandbox:{latest_version}")
}

Quick Start

The Sandbox class implements AutoCloseable, so use try-with-resources to ensure close() is called automatically.
import com.alibaba.opensandbox.sandbox.Sandbox;
import com.alibaba.opensandbox.sandbox.config.ConnectionConfig;
import com.alibaba.opensandbox.sandbox.domain.exceptions.SandboxException;
import com.alibaba.opensandbox.sandbox.domain.models.execd.executions.Execution;

public class QuickStart {
    public static void main(String[] args) {
        // 1. Configure connection
        ConnectionConfig config = ConnectionConfig.builder()
            .domain("api.opensandbox.io")
            .apiKey("your-api-key")
            .build();

        // 2. Create a sandbox using try-with-resources
        try (Sandbox sandbox = Sandbox.builder()
                .connectionConfig(config)
                .image("ubuntu")
                .build()) {

            // 3. Execute a shell command
            Execution execution = sandbox
                    .commands()
                    .run("echo 'Hello Sandbox!'");

            // 4. Print output
            System.out.println(execution.getLogs().getStdout().get(0).getText());

            // 5. Terminate the remote instance explicitly
            // sandbox.close() is called automatically by try-with-resources
            sandbox.kill();
        } catch (SandboxException e) {
            System.err.println("Sandbox Error: [" + e.getError().getCode() + "] " + e.getError().getMessage());
            System.err.println("Request ID: " + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

ConnectionConfig Parameters

ParameterDescriptionDefaultEnvironment Variable
apiKeyAPI key for authenticationRequiredOPEN_SANDBOX_API_KEY
domainEndpoint domain of the sandbox serviceRequired (or localhost:8080)OPEN_SANDBOX_DOMAIN
protocolHTTP protocol (http/https)http
requestTimeoutTimeout for API requests30 seconds
debugEnable debug logging for HTTP requestsfalse
headersCustom HTTP headersEmpty
connectionPoolShared OkHttp ConnectionPoolSDK-created per instance
useServerProxyRoute execd/endpoint calls through the server proxyfalse
import okhttp3.ConnectionPool;
import java.util.concurrent.TimeUnit;

// Basic configuration
ConnectionConfig config = ConnectionConfig.builder()
    .apiKey("your-key")
    .domain("api.opensandbox.io")
    .requestTimeout(Duration.ofSeconds(60))
    .build();

// Advanced: shared connection pool (recommended for many sandbox instances)
ConnectionPool sharedPool = new ConnectionPool(50, 30, TimeUnit.SECONDS);

ConnectionConfig sharedConfig = ConnectionConfig.builder()
    .apiKey("your-key")
    .domain("api.opensandbox.io")
    .headers(Map.of("X-Custom-Header", "value", "X-Request-ID", "trace-123"))
    .connectionPool(sharedPool)
    .build();

Sandbox.builder() Parameters

ParameterDescriptionDefault
imageDocker image to useRequired
timeoutAutomatic termination TTL (null = no expiry)10 minutes
entrypointContainer entrypoint command["tail", "-f", "/dev/null"]
resourceCPU and memory limits{"cpu": "1", "memory": "2Gi"}
envEnvironment variablesEmpty
metadataCustom metadata tagsEmpty
extensionsOpaque server-side extension parametersEmpty
networkPolicyOptional outbound egress policy
credentialProxyCredential Vault proxy startup settings
readyTimeoutMax time to wait for sandbox readiness30 seconds
Metadata keys under opensandbox.io/ are reserved for system-managed labels and will be rejected by the server.
import com.alibaba.opensandbox.sandbox.domain.models.sandboxes.NetworkPolicy;
import com.alibaba.opensandbox.sandbox.domain.models.sandboxes.NetworkRule;

Sandbox sandbox = Sandbox.builder()
    .connectionConfig(config)
    .image("python:3.11")
    .timeout(Duration.ofMinutes(30))
    .resource(map -> {
        map.put("cpu", "2");
        map.put("memory", "4Gi");
    })
    .env("PYTHONPATH", "/app")
    .metadata("project", "demo")
    .extension("storage.id", "dataset-001")
    .networkPolicy(
        NetworkPolicy.builder()
            .defaultAction(NetworkPolicy.DefaultAction.DENY)
            .addEgress(
                NetworkRule.builder()
                    .action(NetworkRule.Action.ALLOW)
                    .target("pypi.org")
                    .build()
            )
            .build()
    )
    .build();

Key Operations

Lifecycle

// Renew the sandbox TTL
sandbox.renew(Duration.ofMinutes(30));

// Suspend all processes
sandbox.pause();

// Resume a paused sandbox
sandbox.resume();

// Inspect current status
SandboxInfo info = sandbox.getInfo();
System.out.println("State: " + info.getStatus().getState());
System.out.println("Expires: " + info.getExpiresAt());
Create a non-expiring sandbox with timeout(null):
Sandbox manual = Sandbox.builder()
    .connectionConfig(config)
    .image("ubuntu")
    .timeout(null)
    .build();

Custom Health Check

Sandbox sandbox = Sandbox.builder()
    .connectionConfig(config)
    .image("nginx:latest")
    .healthCheck(sbx -> {
        try {
            SandboxEndpoint endpoint = sbx.getEndpoint(80);
            // return checkConnection(endpoint.getEndpoint());
            return true;
        } catch (Exception e) {
            return false;
        }
    })
    .build();

Command Execution with Streaming

ExecutionHandlers handlers = ExecutionHandlers.builder()
    .onStdout(msg -> System.out.println("STDOUT: " + msg.getText()))
    .onStderr(msg -> System.err.println("STDERR: " + msg.getText()))
    .onExecutionComplete(complete ->
        System.out.println("Command finished in " + complete.getExecutionTimeInMillis() + "ms")
    )
    .build();

RunCommandRequest request = RunCommandRequest.builder()
    .command("for i in {1..5}; do echo \"Count $i\"; sleep 0.5; done")
    .handlers(handlers)
    .build();

sandbox.commands().run(request);

File Operations

// Write a file
sandbox.files().write(List.of(
    WriteEntry.builder()
        .path("/tmp/hello.txt")
        .data("Hello World")
        .mode(644)
        .build()
));

// Read a file
String content = sandbox.files().readFile("/tmp/hello.txt", "UTF-8", null);
System.out.println("Content: " + content);

// Search files
List<EntryInfo> files = sandbox.files().search(
    SearchEntry.builder()
        .path("/tmp")
        .pattern("*.txt")
        .build()
);
files.forEach(f -> System.out.println("Found: " + f.getPath()));

// Delete files
sandbox.files().deleteFiles(List.of("/tmp/hello.txt"));

Egress Policy

NetworkPolicy policy = sandbox.getEgressPolicy();

sandbox.patchEgressRules(
    List.of(
        NetworkRule.builder().action(NetworkRule.Action.ALLOW).target("www.github.com").build(),
        NetworkRule.builder().action(NetworkRule.Action.DENY).target("pypi.org").build()
    )
);

Credential Vault

import com.alibaba.opensandbox.sandbox.domain.models.sandboxes.*;
import java.util.List;

Sandbox sandbox = Sandbox.builder()
    .connectionConfig(config)
    .image("python:3.11")
    .networkPolicy(
        NetworkPolicy.builder()
            .defaultAction(NetworkPolicy.DefaultAction.DENY)
            .addEgress(
                NetworkRule.builder()
                    .action(NetworkRule.Action.ALLOW)
                    .target("api.example.com")
                    .build()
            )
            .build()
    )
    .credentialProxyEnabled(true)
    .build();

sandbox.credentialVault().create(
    CredentialVaultCreateRequest.builder()
        .credentials(List.of(
            Credential.builder()
                .name("api-token")
                .inlineSource("<token>")
                .build()
        ))
        .bindings(List.of(
            CredentialBinding.builder()
                .name("api-token")
                .match(
                    CredentialMatch.builder()
                        .schemes(CredentialMatch.Scheme.HTTPS)
                        .ports(443)
                        .hosts("api.example.com")
                        .paths("/v1/*")
                        .build()
                )
                .auth(CredentialAuth.apiKey("x-api-key", "api-token"))
                .build()
        ))
        .build()
);

Sandbox Pool

SandboxPool keeps an idle buffer of ready sandboxes to reduce acquire latency.
SandboxPool is experimental and may introduce breaking changes in future releases based on production feedback.
import com.alibaba.opensandbox.sandbox.pool.SandboxPool;
import com.alibaba.opensandbox.sandbox.domain.pool.PoolCreationSpec;
import com.alibaba.opensandbox.sandbox.domain.pool.AcquirePolicy;
import com.alibaba.opensandbox.sandbox.infrastructure.pool.InMemoryPoolStateStore;

SandboxPool pool = SandboxPool.builder()
    .poolName("demo-pool")
    .ownerId("worker-1")
    .maxIdle(3)
    .warmupReadyTimeout(Duration.ofSeconds(45))
    .stateStore(new InMemoryPoolStateStore())
    .connectionConfig(config)
    .creationSpec(
        PoolCreationSpec.builder()
            .image("ubuntu:22.04")
            .entrypoint(java.util.List.of("tail", "-f", "/dev/null"))
            .extension("storage.id", "dataset-001")
            .build()
    )
    .build();

pool.start();
Sandbox sb = pool.acquire(Duration.ofMinutes(10), AcquirePolicy.FAIL_FAST);
try {
    sb.commands().run("echo pool-ok");
} finally {
    sb.kill();
    sb.close();
}
pool.shutdown(true);
For distributed deployments, add the com.alibaba.opensandbox:sandbox-pool-redis module or implement PoolStateStore yourself. The Redis module accepts a caller-managed Jedis client. Configure primaryLockTtl greater than warmupReadyTimeout plus expected preparer time to avoid leadership expiry during sandbox creation. Call resize(0) to drain a distributed idle buffer before decommissioning a pool.

SandboxManager (Admin)

SandboxManager manager = SandboxManager.builder()
    .connectionConfig(config)
    .build();

PagedSandboxInfos sandboxes = manager.listSandboxInfos(
    SandboxFilter.builder()
        .states(SandboxState.RUNNING)
        .pageSize(10)
        .page(1)
        .build()
);

sandboxes.getSandboxInfos().forEach(info -> {
    System.out.println("Found sandbox: " + info.getId());
    manager.killSandbox(info.getId());
});

Build docs developers (and LLMs) love