mcpField
L
LLM Sandbox

LLM Sandbox

本地服务
vndee.github.io开发工具1.1k2 天前更新

关于 LLM Sandbox

LLM Sandbox 为需要安全执行 LLM 生成代码的开发者提供统一 API,可使用容器或本地隔离后端,并配置资源、网络和访问策略。它支持多种语言、文件操作及制品提取。

主要功能

  1. 01容器与本地隔离后端
  2. 02配置安全策略和资源限制
  3. 03控制沙箱网络访问
  4. 04多语言代码执行与依赖安装
  5. 05主机与沙箱间文件操作
  6. 06提取图表等运行制品

适用场景

  1. 01在隔离环境运行 LLM 生成代码
  2. 02限制代码执行的资源和网络权限
  3. 03在执行环境中安装库并运行多语言代码
  4. 04复制输入文件并收集生成的图表

MCP 相关

项目提供 MCP 服务,让 MCP 客户端能够在安全沙箱中运行代码。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"vndee-llm-sandbox": {
"command": "uvx",
"args": [
"llm-sandbox"
],
"env": {
"BACKEND": "<BACKEND>",
"DOCKER_HOST": "<DOCKER_HOST>",
"KUBECONFIG": "<KUBECONFIG>",
"NAMESPACE": "<NAMESPACE>",
"COMMIT_CONTAINER": "<COMMIT_CONTAINER>",
"KEEP_TEMPLATE": "<KEEP_TEMPLATE>",
"SANDBOX_NETWORK_MODE": "<SANDBOX_NETWORK_MODE>",
"SANDBOX_READ_ONLY": "<SANDBOX_READ_ONLY>",
"SANDBOX_CAP_DROP": "<SANDBOX_CAP_DROP>",
"SANDBOX_SECURITY_OPT": "<SANDBOX_SECURITY_OPT>",
"SANDBOX_MEMORY": "<SANDBOX_MEMORY>",
"SANDBOX_CPUS": "<SANDBOX_CPUS>"
}
}
}
}
启动命令uvx llm-sandbox
需要配置的环境变量
BACKENDContainer backend to use. Must match the installed extra: mcp-docker, mcp-podman, or mcp-k8s.
DOCKER_HOSTDocker or Podman socket URL, e.g. unix:///var/run/docker.sock
KUBECONFIGPath to kubeconfig file when BACKEND=kubernetes.
NAMESPACEKubernetes namespace used for sandbox pods when BACKEND=kubernetes.
COMMIT_CONTAINERCommit the container after a run so installed libraries persist between sessions.
KEEP_TEMPLATEKeep the base image after the session ends to avoid re-pulling it on the next run.
SANDBOX_NETWORK_MODENetwork mode for the sandbox container. Set to 'none' for hardened isolation. Docker and Podman backends only.
SANDBOX_READ_ONLYMount the sandbox root filesystem read-only. Recommended: true. Docker and Podman backends only.
SANDBOX_CAP_DROPComma-separated Linux capabilities to drop. Recommended: ALL. Docker and Podman backends only.
SANDBOX_SECURITY_OPTComma-separated container security options, e.g. no-new-privileges. Docker and Podman backends only.
SANDBOX_MEMORYMemory limit for the sandbox container, e.g. 4g. Docker and Podman backends only.
SANDBOX_CPUSFractional CPU allocation for the sandbox container, e.g. 1.5. Docker and Podman backends only.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypillm-sandbox0.3.43

工具

3

收录的工具列表 · 更新于 2 周前

参数类型必填说明
codestring是
timeoutinteger否
languagestring否
librariesany否

详细介绍

LLM Sandbox

轻松安全地执行 LLM 生成的代码

SonarQube Cloud

Quality Gate Status PyPI Downloads Release Build status CodeFactor codecov MCP Enabled DOI

LLM Sandbox 通过统一的 API,在容器和本地 Linux、Windows 沙箱后端中运行大模型(LLM)生成的代码。选择适合部署环境的隔离后端,配置其安全控制,并重复使用相同的代码执行和文件 API。

文档:https://vndee.github.io/llm-sandbox/

后端基准测试比较 Docker、Bubblewrap 和 NsJail 在启动、执行、文件传输和并发方面的表现,并提供置信区间和可复现的证据。

README 配图

✨ **新增:**本项目现已支持 Model Context Protocol(MCP) 服务,让 MCP 客户端(例如 Claude Desktop)能够在安全的沙箱环境中运行 LLM 生成的代码。

🚀 主要功能

🛡️ 安全至上
  • 隔离执行:通过容器或本地 OS 沙箱隔离,并显式配置主机访问权限
  • 安全策略:定义自定义安全策略以控制代码执行
  • 资源限制:设置 CPU、内存和执行时间限制
  • 网络隔离:控制沙箱代码的网络访问
🏗️ 灵活的沙箱后端
  • Docker:最受欢迎且支持广泛的选项
  • Kubernetes:适用于可扩展部署的企业级编排
  • Podman:通过无根容器增强安全性
  • Bubblewrap:无需 Docker 或守护进程的本地 Linux 命名空间和 seccomp
  • NsJail:无需守护进程的本地 Linux 命名空间和原生 seccomp 策略
  • Windows MXC:通过 Microsoft 的 MXC/PSEC API 实现原生 Windows 进程隔离
  • WSL2 Bubblewrap:在显式选定的 WSL2 发行版中使用 Linux 命名空间和 seccomp
  • 后端注册表:注册其他适配器并检查其支持的功能
🌐 多语言支持

通过自动依赖管理执行多种编程语言的代码:

  • Python - 完整生态系统支持,可使用 pip 包
  • JavaScript/Node.js - npm 包安装
  • Java - Maven 和 Gradle 依赖管理
  • C++ - 编译和执行
  • Go - 模块支持和编译
  • R - 使用 CRAN 包进行统计计算和数据分析
🔌 大模型框架集成

提供十一个 Agent 框架的可运行示例——OpenAI Agents SDK、Claude Agent SDK、LangChain、DeepAgents、LlamaIndex、Google ADK、CrewAI、Pydantic AI、smolagents、Strands 和 AG2。参见 examples/agent_sdks/。

📊 高级功能
  • 产物提取:自动捕获绘图和可视化内容
  • 库管理:即时安装依赖项
  • 文件操作:在沙箱环境之间复制文件
  • 自定义镜像:使用你自己的容器镜像
  • 快速生产模式:跳过环境设置,加快容器启动速度
  • 容器池:预热并重复使用容器,以提升性能(新功能!)

📦 安装

基本安装
pip install llm-sandbox
安装特定后端支持
# 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 optional container SDKs
pip install 'llm-sandbox[docker,k8s,podman]'

Bubblewrap 和 NsJail 使用基础 Python 软件包和系统可执行文件;无需额外安装容器 SDK。Linux 先决条件请参阅本地后端要求。

Windows 适配器也无需容器 SDK。windows-mxc 需要兼容的 Windows 主机和原生辅助程序;wsl2-bubblewrap 需要已配置的 WSL2 发行版,并安装相应的 Python 软件包和 Linux 先决条件。请参阅 Windows 要求;这两个适配器都不会安装操作系统运行时,也不会回退到无沙箱执行。

开发安装

开发依赖项位于 dev uv 依赖组中,因此请使用 uv 安装(或使用 make install 快捷命令):

git clone https://github.com/vndee/llm-sandbox.git
cd llm-sandbox
make install   # uv sync + pre-commit install

完整工作流请参阅 CONTRIBUTING.md。

🏃‍♂️ 快速开始

基本用法
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)
不使用 Docker 的本地 Linux 用法

在 Debian/Ubuntu 上,使用 sudo apt install bubblewrap libseccomp2 python3-venv 安装系统先决条件。Bubblewrap 必须为 0.8.0 或更高版本,并支持 --disable-userns;Ubuntu 22.04 等较旧发行版需要更新的软件包或上游版本。主机必须允许非特权用户命名空间;发行版的安全策略可能会限制此功能。

from llm_sandbox import SandboxSession

with SandboxSession(backend="bubblewrap", lang="python") as session:
    result = session.run("print('Hello from a local Linux sandbox!')")
    print(result.stdout)

本地默认配置结合了命名空间隔离和 seccomp 系统调用拒绝列表、禁用网络访问、以只读方式公开运行时路径,并提供私有可写工作区和临时目录。Python 设置过程会离线创建虚拟环境。请先安装主机运行时及其 venv 支持。选择 backend="nsjail" 可改用已安装的 NsJail 二进制文件。

Linux 适配器支持 run()、execute_command()、install()、文件复制和产物包装器。它们不支持容器镜像、容器池或交互式会话。文件会在会话中的命令之间保留;后台进程则不会。这些后端共用主机内核,不构成虚拟机级别的隔离边界。请参阅配置、安全性和后端路线图。

不使用 Docker 的 Windows 用法

如需使用原生 Windows Python 执行,请在安装了辅助程序的兼容 Windows 主机上使用 MXC 适配器:

from llm_sandbox import SandboxSession

with SandboxSession(backend="windows-mxc", lang="python") as session:
    print(session.run("import platform; print(platform.system())").stdout)

如需从 Windows Python 应用运行 Linux 工具,请明确选择 WSL2 发行版:

from llm_sandbox import SandboxSession

with SandboxSession(
    backend="wsl2-bubblewrap",
    distribution="Ubuntu",
    lang="python",
) as session:
    print(session.run("import platform; print(platform.system())").stdout)

这些实验性适配器的先决条件和 API 限制各不相同。MXC 起初支持 Python 和 JavaScript,并预装了依赖项。WSL2 复用 Linux Bubblewrap 运行时,需要 seccomp,并将挂载限制为内置 Linux 运行时路径,以确保无法访问 Windows 互操作功能。两者默认都禁用网络。请参阅后端设置和限制。

安装库
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)
多语言支持
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))
        """
    )
交互式会话

对于笔记本式工作流,可以使用 InteractiveSandboxSession,它会在多次 run 调用之间保留 Python 解释器状态。

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)

交互式会话支持 Docker、Podman 和 Kubernetes 后端,目前面向 Python 语言。它们会在沙盒中启动一个长期运行的 IPython 内核,因此每次 run() 的行为都像笔记本单元格一样——状态、导入和魔术命令会一直保留,直到上下文管理器退出,无需额外网络连接或手动序列化。

捕获绘图和可视化内容
Python 绘图
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 绘图
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))

🔧 配置

基本配置
from llm_sandbox import SandboxSession

# Create a new sandbox session
with SandboxSession(image="python:3.9.19-bullseye", keep_template=True, lang="python") as session:
    result = session.run("print('Hello, World!')")
    print(result)

# With custom Dockerfile
with SandboxSession(dockerfile="Dockerfile", keep_template=True, lang="python") as session:
    result = session.run("print('Hello, World!')")
    print(result)

# Or default image
with SandboxSession(lang="python", keep_template=True) as session:
    result = session.run("print('Hello, World!')")
    print(result)

LLM Sandbox 还支持在主机与沙盒之间复制文件:

from llm_sandbox import SandboxSession

with SandboxSession(lang="python", keep_template=True) as session:
    # Copy a file from the host to the sandbox
    session.copy_to_runtime("test.py", "/sandbox/test.py")

    # Run the copied Python code in the sandbox
    result = session.execute_command("python /sandbox/test.py")
    print(result)

    # Copy a file from the sandbox to the host
    session.copy_from_runtime("/sandbox/output.txt", "output.txt")
自定义运行时配置
from llm_sandbox import SandboxSession

pod_manifest = {
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        "name": "test",
        "namespace": "test",
        "labels": {"app": "sandbox"},
    },
    "spec": {
        "containers": [
            {
                "name": "sandbox-container",
                "image": "test",
                "tty": True,
                "volumeMounts": {
                    "name": "tmp",
                    "mountPath": "/tmp",
                },
            }
        ],
        "volumes": [{"name": "tmp", "emptyDir": {"sizeLimit": "5Gi"}}],
    },
}
with SandboxSession(
    backend="kubernetes",
    image="python:3.9.19-bullseye",
    dockerfile=None,
    lang="python",
    keep_template=False,
    verbose=False,
    pod_manifest=pod_manifest,
) as session:
    result = session.run("print('Hello, World!')")
    print(result)
远程 Docker 主机
import docker
from llm_sandbox import SandboxSession

tls_config = docker.tls.TLSConfig(
    client_cert=("path/to/cert.pem", "path/to/key.pem"),
    ca_cert="path/to/ca.pem",
    verify=True
)
docker_client = docker.DockerClient(base_url="tcp://<your_host>:<port>", tls=tls_config)

with SandboxSession(
    client=docker_client,
    image="python:3.9.19-bullseye",
    keep_template=True,
    lang="python",
) as session:
    result = session.run("print('Hello, World!')")
    print(result)
Kubernetes 支持
from kubernetes import client, config
from llm_sandbox import SandboxSession

# Use local kubeconfig
config.load_kube_config()
k8s_client = client.CoreV1Api()

with SandboxSession(
    client=k8s_client,
    backend="kubernetes",
    image="python:3.9.19-bullseye",
    lang="python",
    pod_manifest=pod_manifest, # None by default
) as session:
    result = session.run("print('Hello from Kubernetes!')")
    print(result)

⚠️ 自定义 Pod 清单的重要提示:

使用自定义 Pod 清单时,请确保容器配置包含:

  • "tty": True(保持容器运行)
  • 在 Pod 和容器两级设置正确的 securityContext
  • 容器名称可以是任何有效名称(没有限制)

有关完整要求,请参阅配置指南。

Podman 支持
from llm_sandbox import SandboxSession

with SandboxSession(
    backend="podman",
    lang="python",
    image="python:3.9.19-bullseye"
) as session:
    result = session.run("print('Hello from Podman!')")
    print(result)

⚡ 容器池化(性能优化)

容器池化通过重复使用预热容器,而不是每次执行都创建新容器,可显著提升性能。这对频繁执行代码的应用尤其有益。

主要优势
  • 执行更快:消除创建容器的开销(速度最高可提升 10 倍)
  • 预热环境:容器会预先安装依赖项
  • 线程安全:安全处理并发请求
  • 资源高效:自动管理容器生命周期
  • 配置灵活:可控制池大小、超时和行为
基本池用法
from llm_sandbox import SandboxSession
from llm_sandbox.pool import PoolConfig, create_pool_manager

# Create a pool manager explicitly
pool = create_pool_manager(
    backend="docker",
    config=PoolConfig(
        max_pool_size=10,          # Maximum containers
        min_pool_size=3,           # Keep at least 3 warm
        idle_timeout=300.0,        # Recycle idle containers after 5 min
        enable_prewarming=True,    # Create containers on startup
    ),
    lang="python",
)

# Use the pool in a session
with SandboxSession(
    lang="python",
    pool=pool,
) as session:
    result = session.run("print('Hello from pool!')")

# Container is automatically returned to pool when the session closes
# Clean up the pool when done
pool.close()
在多个会话之间共享池

为获得最高效率,可在多个会话之间共享同一个池:

from llm_sandbox import SandboxSession
from llm_sandbox.pool import create_pool_manager, PoolConfig

# Create a shared pool manager
pool = create_pool_manager(
    backend="docker",
    config=PoolConfig(
        max_pool_size=10,
        min_pool_size=3,
    ),
    lang="python",
    libraries=["numpy", "pandas"],  # Pre-install libraries in all containers
)

# Use the pool in multiple sessions
with SandboxSession(lang="python", pool=pool) as session1:
    result1 = session1.run("import pandas; print(pandas.__version__)")

with SandboxSession(lang="python", pool=pool) as session2:
    result2 = session2.run("import numpy; print(numpy.__version__)")

# Clean up when done
pool.close()
并发执行

容器池是线程安全的,能够高效处理并发请求:

from concurrent.futures import ThreadPoolExecutor
from llm_sandbox import SandboxSession
from llm_sandbox.pool import create_pool_manager, PoolConfig

# Create shared pool
pool = create_pool_manager(
    backend="docker",
    config=PoolConfig(max_pool_size=5),
    lang="python",
)

def run_code(task_id: int):
    with SandboxSession(lang="python", pool=pool) as session:
        return session.run(f'print("Task {task_id}")')

try:
    # Execute 20 tasks concurrently using only 5 containers
    with ThreadPoolExecutor(max_workers=10) as executor:
        results = list(executor.map(run_code, range(20)))
finally:
    pool.close()
池配置选项
from llm_sandbox.pool import PoolConfig, ExhaustionStrategy, create_pool_manager

config = PoolConfig(
    # Pool size limits
    max_pool_size=10,                      # Maximum containers in pool
    min_pool_size=2,                       # Minimum warm containers

    # Timeout configuration
    idle_timeout=300.0,                    # Recycle idle containers (seconds)
    acquisition_timeout=30.0,              # Wait time for available container

    # Health and lifecycle
    health_check_interval=60.0,            # Health check frequency
    max_container_lifetime=3600.0,         # Max container lifetime
    max_container_uses=100,                # Max uses before recycling

    # Pool exhaustion behavior
    exhaustion_strategy=ExhaustionStrategy.WAIT,  # WAIT, FAIL_FAST, or TEMPORARY

    # Pre-warming
    enable_prewarming=True,                # Pre-warm containers
)

pool = create_pool_manager(
    backend="docker",
    config=config,
    lang="python",
    libraries=["requests", "numpy"],       # Pre-install libraries
)
池耗尽策略

所有容器都处于忙碌状态时,池可以通过不同方式进行处理:

1. WAIT(默认)

等待容器可用:

config = PoolConfig(
    max_pool_size=5,
    exhaustion_strategy=ExhaustionStrategy.WAIT,
    acquisition_timeout=30.0,  # Wait up to 30 seconds
)
2. FAIL_FAST

立即引发错误:

config = PoolConfig(
    max_pool_size=5,
    exhaustion_strategy=ExhaustionStrategy.FAIL_FAST,
)
3. TEMPORARY

在池外创建临时容器:

config = PoolConfig(
    max_pool_size=5,
    exhaustion_strategy=ExhaustionStrategy.TEMPORARY,
)
监控池统计信息
from llm_sandbox.pool import create_pool_manager

pool = create_pool_manager(backend="docker", lang="python")

# Get pool statistics
stats = pool.get_stats()
print(f"Total containers: {stats['total_size']}")
print(f"Idle containers: {stats['state_counts']['idle']}")
print(f"Busy containers: {stats['state_counts']['busy']}")

pool.close()
使用池化功能提取产物

使用容器池化功能捕获绘图和可视化内容时,可以采用以下任一方式:

from llm_sandbox import ArtifactSandboxSession
from llm_sandbox.pool import create_pool_manager, PoolConfig
import base64
from pathlib import Path

# Create pool with pre-installed visualization libraries
pool = create_pool_manager(
    backend="docker",
    config=PoolConfig(max_pool_size=5, min_pool_size=2),
    lang="python",
    libraries=["matplotlib", "numpy"],
)

try:
    # Option 1: Use pool parameter (recommended for API consistency)
    with ArtifactSandboxSession(pool=pool, enable_plotting=True) 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.plot(x, y)
plt.title('Pooled Execution - Sine Wave')
plt.show()
        """)

        # Save generated plots
        for i, plot in enumerate(result.plots):
            Path(f"plot_{i}.{plot.format.value}").write_bytes(
                base64.b64decode(plot.content_base64)
            )

        print(f"Generated {len(result.plots)} plots using pooled container")

    # Option 2: Use ArtifactPooledSandboxSession (explicit class)
    # Both approaches work identically
    from llm_sandbox.pool import ArtifactPooledSandboxSession

    with ArtifactPooledSandboxSession(pool_manager=pool, enable_plotting=True) as session:
        result = session.run("print('Same functionality, different API')")

finally:
    pool.close()
示例

完整示例请参阅 examples/ 目录:

🤖 大模型框架集成

examples/agent_sdks/ 中提供了 11 个 Agent 框架的可运行示例,并固定了版本:

OpenAI Agents SDKClaude Agent SDKLangChain
DeepAgentsLlamaIndexGoogle ADK
CrewAIPydantic AIsmolagents
Strands AgentsAG2

每个文件都可独立运行,注明了经过验证的 SDK 版本,并实施了容器加固。这些示例都基于相同的核心——调用沙箱,并启用代码由模型编写后至关重要的控制措施:

from llm_sandbox import SandboxSession

SANDBOX_RUNTIME = {
    "network_mode": "none",                        # no egress
    "mem_limit": "512m",
    "pids_limit": 128,                             # bounds fork bombs
    "security_opt": ["no-new-privileges:true"],
}

def run_python(code: str) -> str:
    with SandboxSession(
        lang="python",
        keep_template=True,                        # else the image is re-pulled each call
        runtime_configs=SANDBOX_RUNTIME,
    ) as session:
        result = session.run(code, timeout=30)
    return result.stdout if result.exit_code == 0 else result.stderr

重要

安全策略仅供参考。 session.is_safe(code) 会返回判定结果—— 但它不会阻止执行,而且 run() 会执行被策略标记的代码。 调用 run() 之前,请自行检查。参阅 安全指南。

🔌 模型上下文协议(MCP)服务

LLM Sandbox 提供 模型上下文协议(MCP) 服务,让 Claude Desktop 等 AI 助手能够在沙箱环境中安全地执行代码。此集成支持大模型直接运行代码,并自动捕获可视化内容,同时支持多种语言。

功能
  • 安全执行代码:在隔离容器中使用你偏好的后端执行代码
  • 多语言支持:运行 Python、JavaScript、Java、C++、Go、R 和 Ruby 代码
  • 自动捕获可视化内容:自动捕获并返回绘图和可视化内容
  • 库管理:按需安装包和依赖项
  • 灵活支持后端:选择 Docker、Podman 或 Kubernetes 后端
安装

使用你偏好的后端安装支持 MCP 的 LLM Sandbox:

# For Docker backend
pip install 'llm-sandbox[mcp-docker]'

# For Podman backend
pip install 'llm-sandbox[mcp-podman]'

# For Kubernetes backend
pip install 'llm-sandbox[mcp-k8s]'
配置

将以下配置添加到 MCP 客户端(例如,Claude Desktop 的 claude_desktop_config.json):

{
  "mcpServers": {
    "llm-sandbox": {
      "command": "python3",
      "args": ["-m", "llm_sandbox.mcp_server.server"],
    }
  }
}
特定后端的配置

对于特定后端,你需要将 BACKEND 环境变量设为要使用的后端。根据所用后端,你可能还需要设置其他环境变量。例如,如果系统未自动设置 DOCKER_HOST,你可能需要将 DOCKER_HOST 环境变量设为要使用的主机。

Docker(默认):

{
  "mcpServers": {
    "llm-sandbox": {
      "command": "python3",
      "args": ["-m", "llm_sandbox.mcp_server.server"],
      "env": {
        "BACKEND": "docker",
        "DOCKER_HOST": "unix:///var/run/docker.sock" // change this to the actual host you are using
      }
    }
  }
}

Podman:

{
  "mcpServers": {
    "llm-sandbox": {
      "command": "python3",
      "args": ["-m", "llm_sandbox.mcp_server.server"],
      "env": {
        "BACKEND": "podman",
        "DOCKER_HOST": "unix:///var/run/podman/podman.sock" // change this to the actual host you are using
      }
    }
  }
}

对于 Kubernetes,你可能需要将 KUBECONFIG 环境变量设为 kubeconfig 文件的路径。

Kubernetes:

{
  "mcpServers": {
    "llm-sandbox": {
      "command": "python3",
      "args": ["-m", "llm_sandbox.mcp_server.server"],
      "env": {
        "BACKEND": "kubernetes",
        "KUBECONFIG": "/path/to/kubeconfig" // change this to the actual path to your kubeconfig file
      }
    }
  }
}
运行时配置环境变量

对于 Docker、Podman 和 Micromamba 后端,MCP 服务可以将 SANDBOX_* 环境变量转换为会话 runtime_configs。

{
  "mcpServers": {
    "llm-sandbox": {
      "command": "python3",
      "args": ["-m", "llm_sandbox.mcp_server.server"],
      "env": {
        "BACKEND": "podman",
        "DOCKER_HOST": "unix:///run/podman/podman.sock",
        "SANDBOX_NETWORK_MODE": "none",
        "SANDBOX_READ_ONLY": "true",
        "SANDBOX_CAP_DROP": "ALL",
        "SANDBOX_SECURITY_OPT": "no-new-privileges:true",
        "SANDBOX_MEMORY": "4g",
        "SANDBOX_CPU_COUNT": "1"
      }
    }
  }
}

支持的变量:SANDBOX_NETWORK_MODE、SANDBOX_READ_ONLY、SANDBOX_MEMORY、SANDBOX_MEM_LIMIT、 SANDBOX_CPUS、SANDBOX_CPU_COUNT、SANDBOX_CAP_DROP、SANDBOX_SECURITY_OPT 和 SANDBOX_PRIVILEGED。

SANDBOX_MEMORY 会规范化为后端安全的 mem_limit 运行时配置。SANDBOX_CPUS 和 SANDBOX_CPU_COUNT 会规范化为兼容 Linux 的 CPU 配额设置。

安全提示:对于强化型沙箱,建议使用 SANDBOX_NETWORK_MODE=none、SANDBOX_READ_ONLY=true、 SANDBOX_CAP_DROP=ALL 和限制性 SANDBOX_SECURITY_OPT 值。除非明确需要,否则请避免使用 SANDBOX_PRIVILEGED=true;请将 CPU 和内存限制设为尽可能低,并审查任何会重新启用特权的组合。 此 MCP 服务中的 SANDBOX_* 设置不适用于 Kubernetes 后端。 如果需要 Kubernetes 专用的资源或安全控制,请通过自定义 MCP 包装器提供自定义 pod_manifest,或直接使用 llm-sandbox Python API。

可用工具

MCP 服务提供以下工具:

  • execute_code:在安全沙箱中执行代码,并自动捕获可视化内容
  • get_supported_languages:获取支持的编程语言列表
  • get_language_details:获取特定语言的详细信息
使用示例

配置完成后,你可以让 AI 助手运行代码,它会自动使用 LLM Sandbox MCP 服务:

"Create a scatter plot showing the relationship between x and y data points using matplotlib"

助手会在安全沙箱中执行 Python 代码,并自动捕获生成的绘图或可视化内容。

🏗️ 架构

graph LR
    A[LLM Client] --> B[LLM Sandbox]
    B --> C[Container Backend]

    A1[OpenAI] --> A
    A2[Anthropic] --> A
    A3[Local LLMs] --> A
    A4[LangChain] --> A
    A5[LangGraph] --> A
    A6[LlamaIndex] --> A
    A7[MCP Clients] --> A

    C --> C1[Docker]
    C --> C2[Kubernetes]
    C --> C3[Podman]

    style A fill:#e1f5fe
    style B fill:#f3e5f5
    style C fill:#e8f5e8
    style A1 fill:#fff3e0
    style A2 fill:#fff3e0
    style A3 fill:#fff3e0
    style A4 fill:#fff3e0
    style A5 fill:#fff3e0
    style A6 fill:#fff3e0
    style A7 fill:#fff3e0
    style C1 fill:#e0f2f1
    style C2 fill:#e0f2f1
    style C3 fill:#e0f2f1

📚 文档

🤝 贡献

欢迎贡献!详情请参阅我们的贡献指南。

开发环境设置
# Clone the repository
git clone https://github.com/vndee/llm-sandbox.git
cd llm-sandbox

# Install in development mode
make install

# Run pre-commit hooks
uv run pre-commit run -a

# Run tests
make test

📖 引用

如果你在研究中使用 LLM Sandbox,请引用:

@software{huynh_llm_sandbox,
  author    = {Huynh, Duy V.},
  title     = {{LLM Sandbox: a portable runtime for securely executing LLM-generated code}},
  publisher = {Zenodo},
  doi       = {10.5281/zenodo.21760525},
  url       = {https://doi.org/10.5281/zenodo.21760525}
}

上述 DOI 指向最新版本。如需引用特定版本,请使用 Zenodo 记录中该版本自己的 DOI。

📄 许可证

本项目采用 MIT 许可证授权,详情请参阅 LICENSE 文件。

🌟 Star 历史

如果你觉得 LLM Sandbox 有用,请考虑在 GitHub 上为它点个 Star!

📞 支持与社区

贡献者

README 配图 ## Star History

Star History Chart

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。