LLM Sandbox
Securely Execute LLM-Generated Code with Ease


LLM Sandbox is a lightweight and portable sandbox environment designed to run Large Language Model (LLM) generated code in a safe and isolated mode. It provides a secure execution environment for AI-generated code while offering flexibility in container backends and comprehensive language support, simplifying the process of running code generated by LLMs.
Documentation: https://vndee.github.io/llm-sandbox/

β¨ New: This project now supports the Model Context Protocol (MCP) server, which allows your MCP clients (e.g. Claude Desktop) to run code generated by LLMs in a secure sandbox environment.
π Key Features
π‘οΈ Security First
- Isolated Execution: Code runs in isolated containers with no access to host system
- Security Policies: Define custom security policies to control code execution
- Resource Limits: Set CPU, memory, and execution time limits
- Network Isolation: Control network access for sandboxed code
ποΈ Flexible Container Backends
- Docker: Most popular and widely supported option
- Kubernetes: Enterprise-grade orchestration for scalable deployments
- Podman: Rootless containers for enhanced security
π Multi-Language Support
Execute code in multiple programming languages with automatic dependency management:
- Python - Full ecosystem support with pip packages
- JavaScript/Node.js - npm package installation
- Java - Maven and Gradle dependency management
- C++ - Compilation and execution
- Go - Module support and compilation
- R - Statistical computing and data analysis with CRAN packages
π LLM Framework Integration
Runnable examples for eleven agent frameworks β OpenAI Agents SDK, Claude Agent SDK, LangChain, DeepAgents, LlamaIndex, Google ADK, CrewAI, Pydantic AI, smolagents, Strands and AG2. See examples/agent_sdks/.
π Advanced Features
- Artifact Extraction: Automatically capture plots and visualizations
- Library Management: Install dependencies on-the-fly
- File Operations: Copy files to/from sandbox environments
- Custom Images: Use your own container images
- Fast Production Mode: Skip environment setup for faster container startup
- Container Pooling: Pre-warm and reuse containers for improved performance (NEW!)
π¦ Installation
Basic Installation
With Specific Backend Support
# For Docker support (most common)
pip install 'llm-sandbox[docker]'
# For Kubernetes support
pip install 'llm-sandbox[k8s]'
# For Podman support
pip install 'llm-sandbox[podman]'
# All backends
pip install 'llm-sandbox[docker,k8s,podman]'
Development Installation
Dev dependencies live in the dev uv dependency group, so install them with uv (or the make install shortcut):
git clone https://github.com/vndee/llm-sandbox.git
cd llm-sandbox
make install # uv sync + pre-commit install
See CONTRIBUTING.md for the full workflow.
πββοΈ Quick Start
Basic Usage
from llm_sandbox import SandboxSession
# Create and use a sandbox session
with SandboxSession(lang="python") as session:
result = session.run("""
print("Hello from LLM Sandbox!")
print("I'm running in a secure container.")
""")
print(result.stdout)
Installing Libraries
from llm_sandbox import SandboxSession
with SandboxSession(lang="python") as session:
result = session.run("""
import numpy as np
# Create an array
arr = np.array([1, 2, 3, 4, 5])
print(f"Array: {arr}")
print(f"Mean: {np.mean(arr)}")
""", libraries=["numpy"])
print(result.stdout)
Multi-Language Support
JavaScript
with SandboxSession(lang="javascript") as session:
result = session.run("""
const greeting = "Hello from Node.js!";
console.log(greeting);
const axios = require('axios');
console.log("Axios loaded successfully!");
""", libraries=["axios"])
Java
with SandboxSession(lang="java") as session:
result = session.run("""
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello from Java!");
}
}
""")
C++
with SandboxSession(lang="cpp") as session:
result = session.run("""
#include <iostream>
int main() {
std::cout << "Hello from C++!" << std::endl;
return 0;
}
""")
Go
with SandboxSession(lang="go") as session:
result = session.run("""
package main
import "fmt"
func main() {
fmt.Println("Hello from Go!")
}
""")
R
with SandboxSession(
lang="r",
image="ghcr.io/vndee/sandbox-r-451-bullseye",
verbose=True,
) as session:
result = session.run(
"""
# Basic R operations
print("=== Basic R Demo ===")
# Create some data
numbers <- c(1, 2, 3, 4, 5, 10, 15, 20)
print(paste("Numbers:", paste(numbers, collapse=", ")))
# Basic statistics
print(paste("Mean:", mean(numbers)))
print(paste("Median:", median(numbers)))
print(paste("Standard Deviation:", sd(numbers)))
# Work with data frames
df <- data.frame(
name = c("Alice", "Bob", "Charlie", "Diana"),
age = c(25, 30, 35, 28),
score = c(85, 92, 78, 96)
)
print("=== Data Frame ===")
print(df)
# Calculate average score
avg_score <- mean(df$score)
print(paste("Average Score:", avg_score))
"""
)
Interactive Sessions
For notebook-style workflows you can use InteractiveSandboxSession, which keeps the Python interpreter state across multiple run calls.
from llm_sandbox import InteractiveSandboxSession
with InteractiveSandboxSession(
lang="python",
kernel_type="ipython",
history_size=200,
) as session:
session.run("value = 21 * 2")
result = session.run("print(f'Result: {value}')")
print(result.stdout) # -> Result: 42
# Use magic command to install libraries
session.run("%pip install pandas")
result = session.run("import pandas as pd; print(pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}))")
print(result.stdout)
Interactive sessions support Docker, Podman, and Kubernetes backends and currently target Python language. They spin up a long-running IPython kernel inside the sandbox, so each run() behaves like a notebook cellβstate, imports, and magic commands stay alive until the context manager exits, without any extra networking or manual serialization.
Capturing Plots and Visualizations
Python Plots
from llm_sandbox import ArtifactSandboxSession
import base64
from pathlib import Path
with ArtifactSandboxSession(lang="python") as session:
result = session.run("""
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y)
plt.title("Sine Wave")
plt.xlabel("x")
plt.ylabel("sin(x)")
plt.grid(True)
plt.savefig("sine_wave.png", dpi=150, bbox_inches="tight")
plt.show()
""", libraries=["matplotlib", "numpy"])
# Extract the generated plots
print(f"Generated {len(result.plots)} plots")
# Save plots to files
for i, plot in enumerate(result.plots):
plot_path = Path(f"plot_{i + 1}.{plot.format.value}")
with plot_path.open("wb") as f:
f.write(base64.b64decode(plot.content_base64))
R Plots
from llm_sandbox import ArtifactSandboxSession
import base64
from pathlib import Path
with ArtifactSandboxSession(lang="r") as session:
result = session.run("""
library(ggplot2)
# Create sample data
data <- data.frame(
x = rnorm(100),
y = rnorm(100)
)
# Create ggplot2 visualization
p <- ggplot(data, aes(x = x, y = y)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE) +
labs(title = "Scatter Plot with Trend Line",
x = "X values", y = "Y values") +
theme_minimal()
print(p)
# Base R plot
hist(data$x, main = "Distribution of X",
xlab = "X values", col = "lightblue", breaks = 20)
""", libraries=["ggplot2"])
# Extract the generated plots
print(f"Generated {len(result.plots)} R plots")
# Save plots to files
for i, plot in enumerate(result.plots):
plot_path = Path(f"r_plot_{i + 1}.{plot.format.value}")
with plot_path.open("wb") as f:
f.write(base64.b64decode(plot.content_base64))