Documentation Index Fetch the complete documentation index at: https://springaicommunity.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
GitHub • Maven Central
Overview
Agent Sandbox provides a unified API for isolated command execution across multiple backends. Whether you need local process isolation, Docker container security, or cloud-based E2B microVMs, the same interface works everywhere.
The library emphasizes clean design: interface segregation (separate concerns for execution vs file operations), Liskov substitution (backends are interchangeable), and a JDK 21 baseline for modern Java features.
Core API
Sandbox Main interface for isolated command execution with workspace management
ExecSpec Command specification with timeout, environment, and shell support
ExecResult Execution result with exit code, stdout, stderr, and utilities
SandboxFiles Fluent API for file operations within the sandbox workspace
Module Structure
Module Description Dependencies agent-sandbox-coreCore Sandbox API and LocalSandbox zt-exec agent-sandbox-dockerDocker container sandbox testcontainers agent-sandbox-e2bE2B cloud microVM sandbox jackson, awaitility agent-sandbox-bomBill of Materials N/A
Implementations
LocalSandbox Local process execution using zt-exec. Fast, no isolation overhead.
DockerSandbox Container-based isolation using Testcontainers. Full filesystem/network isolation.
E2BSandbox Cloud microVM execution via E2B. Maximum isolation with MCP support.
Quick Start
Maven Dependency
< dependency >
< groupId > org.springaicommunity.sandbox </ groupId >
< artifactId > agent-sandbox-core </ artifactId >
< version > 0.9.1 </ version >
</ dependency >
Basic Execution
try ( Sandbox sandbox = LocalSandbox . builder ()
. tempDirectory ( "test-" )
. build ()) {
ExecResult result = sandbox . exec ( ExecSpec . of ( "echo" , "Hello" ));
if ( result . success ()) {
System . out . println ( result . stdout ()); // "Hello"
}
}
Sandbox Interface
public interface Sandbox extends AutoCloseable {
ExecResult exec ( ExecSpec spec ); // Execute command
Process startInteractive ( ExecSpec spec ); // Start interactive process
Path workDir (); // Get working directory
SandboxFiles files (); // Access file operations
boolean isClosed (); // Check if closed
boolean shouldCleanupOnClose (); // Auto-delete on close?
}
ExecSpec (Command Specification)
Build command specifications with fluent API:
// Simple command
ExecSpec spec = ExecSpec . of ( "mvn" , "test" );
// Full builder
ExecSpec spec = ExecSpec . builder ()
. command ( "java" , "-jar" , "app.jar" )
. env ( "JAVA_OPTS" , "-Xmx512m" )
. env ( "DEBUG" , "true" )
. timeout ( Duration . ofMinutes ( 5 ))
. build ();
// Shell command (platform-aware: bash -c on Unix, cmd /c on Windows)
ExecSpec spec = ExecSpec . builder ()
. shellCommand ( "echo $HOME && ls -la" )
. timeout ( Duration . ofSeconds ( 30 ))
. build ();
// Modify existing spec
ExecSpec modified = spec . toBuilder ()
. timeout ( Duration . ofMinutes ( 10 ))
. build ();
ExecResult (Execution Result)
Rich result object with utilities for AI analysis:
ExecResult result = sandbox . exec (spec);
// Basic properties
int exitCode = result . exitCode ();
String stdout = result . stdout ();
String stderr = result . stderr ();
Duration duration = result . duration ();
// Convenience methods
boolean ok = result . success (); // exitCode == 0
boolean failed = result . failed (); // exitCode != 0
// Output utilities
String merged = result . mergedLog (); // stdout + stderr (for LLM analysis)
boolean hasOut = result . hasOutput (); // stdout or stderr non-empty
boolean hasStdout = result . hasStdout ();
boolean hasStderr = result . hasStderr ();
int length = result . outputLength (); // Combined length
// Logging-friendly summary (no full output)
String summary = result . summary (); // "ExecResult[exitCode=0, duration=PT1.234S]"
SandboxFiles (File Operations)
Fluent API for file management with .and() to chain back to sandbox:
try ( Sandbox sandbox = LocalSandbox . create ()) {
// Create files and directories
sandbox . files ()
. create ( "pom.xml" , pomContent)
. create ( "src/main/java/App.java" , sourceCode)
. createDirectory ( "target" )
. and () // Return to Sandbox
. exec ( ExecSpec . of ( "mvn" , "compile" ));
// Read files
String content = sandbox . files (). read ( "target/output.txt" );
// Check existence
boolean exists = sandbox . files (). exists ( "target/classes/App.class" );
// Delete files
sandbox . files ()
. delete ( "target/temp.txt" )
. delete ( "target/generated" , true ); // recursive
// List directory contents
List < FileEntry > entries = sandbox . files (). list ( "src" );
List < FileEntry > deep = sandbox . files (). list ( "src" , 3 ); // maxDepth=3
}
Batch File Setup
List < FileSpec > files = List . of (
FileSpec . of ( "pom.xml" , pomContent),
FileSpec . of ( "src/main/java/App.java" , code),
FileSpec . of ( "README.md" , docs)
);
sandbox . files (). setup (files);
FileEntry (File Metadata)
List < FileEntry > entries = sandbox . files (). list ( "src" );
for ( FileEntry entry : entries) {
String name = entry . name (); // Filename
String path = entry . path (); // Relative path
FileType type = entry . type (); // FILE or DIRECTORY
long size = entry . size (); // Bytes (0 for dirs)
Instant modified = entry . modifiedTime (); // Last modified
if ( entry . isFile ()) {
String content = sandbox . files (). read ( entry . path ());
}
}
ExecSpecCustomizer
Inject cross-cutting concerns (auth, logging, etc.) before every execution:
// Add authentication to all commands
ExecSpecCustomizer addAuth = spec -> spec . toBuilder ()
. env ( "AUTH_TOKEN" , System . getenv ( "TOKEN" ))
. build ();
// Conditional customization
ExecSpecCustomizer debugMode = ExecSpecCustomizer . when (
spec -> spec . command (). contains ( "test" ),
spec -> spec . toBuilder (). env ( "DEBUG" , "true" ). build ()
);
// Chain multiple customizers
ExecSpecCustomizer combined = ExecSpecCustomizer . chain (addAuth, debugMode);
// Apply to sandbox
LocalSandbox sandbox = LocalSandbox . builder ()
. customizer (combined)
. build ();
LocalSandbox
Fast local execution without container overhead:
// Use current directory
try ( Sandbox sandbox = LocalSandbox . create ()) {
sandbox . exec ( ExecSpec . of ( "ls" , "-la" ));
}
// Use specific directory
try ( Sandbox sandbox = new LocalSandbox ( Path . of ( "/project" ))) {
sandbox . exec ( ExecSpec . of ( "mvn" , "test" ));
}
// Builder with temp directory (auto-cleanup)
try ( Sandbox sandbox = LocalSandbox . builder ()
. tempDirectory ( "myapp-" )
. withFile ( "config.json" , configContent)
. withFiles ( List . of (
FileSpec . of ( "src/App.java" , code),
FileSpec . of ( "pom.xml" , pom)
))
. customizer (myCustomizer)
. build ()) {
sandbox . exec ( ExecSpec . of ( "mvn" , "compile" ));
}
// Temp directory deleted on close
Interactive Processes
For bidirectional I/O (stdin/stdout streaming):
Process proc = sandbox . startInteractive ( ExecSpec . of ( "bash" ));
try {
proc . getOutputStream (). write ( "echo hello \n " . getBytes ());
proc . getOutputStream (). flush ();
// Read from proc.getInputStream()
} finally {
proc . destroy ();
}
DockerSandbox
Container isolation for untrusted code:
// Default image
try ( Sandbox sandbox = DockerSandbox . create ()) {
sandbox . exec ( ExecSpec . of ( "python" , "--version" ));
}
// Custom image
try ( Sandbox sandbox = DockerSandbox . builder ()
. image ( "maven:3.9-eclipse-temurin-21" )
. withFile ( "pom.xml" , pomContent)
. customizer (myCustomizer)
. build ()) {
ExecResult result = sandbox . exec ( ExecSpec . of ( "mvn" , "test" ));
}
Default image: ghcr.io/spring-ai-community/agents-runtime:latest
Working directory: /work
E2BSandbox
Cloud-based Firecracker microVM for maximum isolation:
// Basic usage (uses E2B_API_KEY env var)
try ( Sandbox sandbox = E2BSandbox . builder ()
. template ( "base" )
. timeout ( Duration . ofMinutes ( 2 ))
. build ()) {
ExecResult result = sandbox . exec ( ExecSpec . of ( "python" , "script.py" ));
}
// Full configuration
try ( Sandbox sandbox = E2BSandbox . builder ( "your-api-key" )
. template ( "python-3.11" )
. timeout ( Duration . ofMinutes ( 5 ))
. env ( "API_KEY" , "secret" ) // Sandbox-level env
. env ( Map . of ( "DEBUG" , "true" ))
. withFile ( "script.py" , code)
. build ()) {
sandbox . exec ( ExecSpec . of ( "python" , "script.py" ));
}
Working directory: /home/user
Session Reconnection
Reconnect to existing E2B sandbox for persistent sessions:
// Create and get sandbox ID
E2BSandbox sandbox = E2BSandbox . builder (). build ();
String sandboxId = sandbox . getSandboxId ();
sandbox . close ();
// Later: reconnect to same sandbox
try ( Sandbox reconnected = E2BSandbox . connect (sandboxId)) {
// Files and state preserved
reconnected . exec ( ExecSpec . of ( "ls" , "-la" ));
}
E2B sandboxes support MCP (Model Context Protocol) for AI agent integration. See the E2B documentation for details.
Exceptions
try {
sandbox . exec ( ExecSpec . builder ()
. command ( "long-running-task" )
. timeout ( Duration . ofSeconds ( 5 ))
. build ());
} catch ( TimeoutException e ) {
Duration timeout = e . getTimeout (); // The timeout that was exceeded
// Handle timeout
} catch ( SandboxException e ) {
// General sandbox errors (I/O, process failures, etc.)
}
Design Principles
The Sandbox interface focuses on command execution, while SandboxFiles handles file operations. This separation allows implementations to optimize each concern independently. // Execution
ExecResult result = sandbox . exec (spec);
// File operations via accessor
sandbox . files (). create ( "test.txt" , content);
All sandbox implementations are interchangeable. Code written for LocalSandbox works identically with DockerSandbox or E2BSandbox: void runTests ( Sandbox sandbox) {
// Works with any implementation
ExecResult result = sandbox . exec ( ExecSpec . of ( "mvn" , "test" ));
}
// Choose isolation level at runtime
Sandbox sandbox = requiresIsolation
? DockerSandbox . create ()
: LocalSandbox . create ();
Built for modern Java with:
Virtual threads for concurrent operations
Pattern matching and sealed classes
Modern NIO file APIs
Try-with-resources for automatic cleanup
Used By
Agent Sandbox is used by:
Agent Judge - The agent-judge-exec module uses sandboxes for command-based evaluation
Agent Client - Provides isolated execution environments for autonomous agents
Resources
GitHub Repository Source code and contribution guidelines
E2B Documentation E2B cloud sandbox platform
License
Agent Sandbox is Open Source software released under the Apache 2.0 license .