Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md



中文   |   English  

PyPI version PyPI - Downloads

📖 中文文档   |   📖 English Documentation

⭐ If you like this project, please click the "Star" button in the upper right corner to support us. Your support is our motivation to move forward!

Introduction

ms-enclave is a modular and stable sandbox runtime environment that provides a secure isolated execution environment for applications. It implements strong isolation through Docker containers, equipped with local/HTTP managers and an extensible tool system, helping you execute code safely and efficiently in a controlled environment.

  • 🔒 Secure Isolation: Complete isolation and resource limits based on Docker
  • 🧩 Modular: Both sandboxes and tools are extensible (registered factory)
  • ⚡ Stable Performance: Clean implementation, fast startup, with lifecycle management
  • 🌐 Remote Management: Built-in FastAPI service, supports HTTP management
  • 🔧 Tool System: Standardized tools enabled by sandbox type (OpenAI-style schema)

System Requirements

  • Python >= 3.10
  • Operating System: Linux, macOS, or Windows with Docker support
  • Docker daemon available on local machine (Notebook sandbox requires port 8888 open)

Installation

Install from PyPI

pip install ms-enclave # If Docker support is needed, install extra dependencies pip install 'ms-enclave[docker]'

Install from Source

git clone https://github.com/modelscope/ms-enclave.git cd ms-enclave pip install -e . # If Docker support is needed, install extra dependencies pip install -e '.[docker]'

Quick Start: Minimal Viable Example (SandboxFactory)

Tools need to be explicitly enabled in the configured tools_config, otherwise they won't be registered.

import asyncio from ms_enclave.sandbox.boxes import SandboxFactory from ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType async def main(): config = DockerSandboxConfig( image='python:3.11-slim', memory_limit='512m', tools_config={ 'python_executor': {}, 'file_operation': {}, 'shell_executor': {} } ) async with SandboxFactory.create_sandbox(SandboxType.DOCKER, config) as sandbox: # 1) Write file await sandbox.execute_tool('file_operation', { 'operation': 'write', 'file_path': '/sandbox/hello.txt', 'content': 'hi from enclave' }) # 2) Execute Python code result = await sandbox.execute_tool('python_executor', { 'code': "print('Hello from sandbox!')\nprint(open('/sandbox/hello.txt').read())" }) print(result.output) asyncio.run(main())

Agent Model Tool Calling (OpenAI Tools)

Expose sandbox tools to the Agent in OpenAI Tools format, allowing the model to trigger tools and execute them securely in the sandbox.

import asyncio, os, json from openai import OpenAI from ms_enclave.sandbox.manager import SandboxManagerFactory from ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType async def demo(): client = OpenAI( base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key=os.getenv("DASHSCOPE_API_KEY") ) async with SandboxManagerFactory.create_manager() as m: cfg = DockerSandboxConfig(image="python:3.11-slim", tools_config={"python_executor": {}, "shell_executor": {}}) sid = await m.create_sandbox(SandboxType.DOCKER, cfg) tools = list((await m.get_sandbox_tools(sid)).values()) messages = [{"role": "user", "content": "Print 'hello' in Python, then list /sandbox via shell."}] rsp = client.chat.completions.create(model="qwen-plus", messages=messages, tools=tools, tool_choice="auto") msg = rsp.choices[0].message messages.append(msg.model_dump()) if getattr(msg, "tool_calls", None): for tc in msg.tool_calls: name = tc.function.name args = json.loads(tc.function.arguments or "{}") result = await m.execute_tool(sid, name, args) messages.append({"role": "tool", "content": result.model_dump_json(), "tool_call_id": tc.id, "name": name}) final = client.chat.completions.create(model="qwen-plus", messages=messages) print(final.choices[0].message.content or "") else: print(msg.content or "") asyncio.run(demo())

Notes:

  • Use get_sandbox_tools(sandbox_id) to retrieve tool schemas (OpenAI-compatible)
  • Pass tools=... to the model, handle returned tool_calls and execute them in the sandbox
  • Call the model again to generate the final answer

Typical Usage Patterns & Examples

  • Direct use of SandboxFactory: Create/destroy sandboxes within a single process, most lightweight; suitable for scripts or one-time tasks
  • Using LocalSandboxManager: Uniformly orchestrate lifecycle/cleanup of multiple sandboxes on local machine; suitable for service-oriented, multi-task parallel scenarios
  • Using HttpSandboxManager: Manage sandboxes uniformly through remote HTTP service; suitable for cross-machine/distributed or stronger isolation deployments

0) Manager Factory: SandboxManagerFactory (Automatic Local/HTTP selection)

When to use:

  • You want a single entry point that chooses Local or HTTP manager automatically.
  • You prefer central registration and discovery of available manager types.

Key points:

  • If manager_type is provided, it is used directly.
  • If base_url is provided (in config or kwargs), HTTP manager is created.
  • Otherwise, Local manager is created by default.

Example: implicit selection by base_url

import asyncio from ms_enclave.sandbox.manager import SandboxManagerFactory async def main(): async with SandboxManagerFactory.create_manager(base_url='http://127.0.0.1:8000') as m: # Use exactly like HttpSandboxManager # e.g., create a DOCKER sandbox and execute a tool # ... your code ... pass asyncio.run(main())

Example: explicit selection + custom config

import asyncio from ms_enclave.sandbox.manager import SandboxManagerFactory from ms_enclave.sandbox.model import SandboxManagerConfig, SandboxManagerType async def main(): cfg = SandboxManagerConfig(cleanup_interval=600) async with SandboxManagerFactory.create_manager( manager_type=SandboxManagerType.LOCAL, config=cfg ) as m: # Use exactly like LocalSandboxManager # ... your code ... pass asyncio.run(main())

Discover registered manager types:

from ms_enclave.sandbox.manager import SandboxManagerFactory print(SandboxManagerFactory.get_registered_types())

1) Direct Sandbox Creation: SandboxFactory (Lightweight, Temporary)

Use Cases:

  • Temporarily run a piece of code in scripts or microservices
  • Fine-grained control over sandbox lifecycle (cleanup on context exit)

Example (Docker sandbox + Python execution):

import asyncio from ms_enclave.sandbox.boxes import SandboxFactory from ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType async def main(): cfg = DockerSandboxConfig( tools_config={'python_executor': {}} ) async with SandboxFactory.create_sandbox(SandboxType.DOCKER, cfg) as sb: r = await sb.execute_tool('python_executor', { 'code': 'import platform; print(platform.python_version())' }) print(r.output) asyncio.run(main())

2) Local Unified Orchestration: LocalSandboxManager (Multiple Sandboxes, Lifecycle Management)

Use Cases:

  • Need to create/manage multiple sandboxes within the same process (create, query, stop, periodic cleanup)
  • Want unified status view, statistics, and health checks

Example:

import asyncio from ms_enclave.sandbox.manager import LocalSandboxManager from ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType async def main(): async with LocalSandboxManager() as manager: cfg = DockerSandboxConfig(tools_config={'shell_executor': {}}) sandbox_id = await manager.create_sandbox(SandboxType.DOCKER, cfg) # Execute command res = await manager.execute_tool(sandbox_id, 'shell_executor', {'command': 'echo hello'}) print(res.output.strip()) # hello # View list infos = await manager.list_sandboxes() print([i.id for i in infos]) # Stop and delete await manager.stop_sandbox(sandbox_id) await manager.delete_sandbox(sandbox_id) asyncio.run(main())

3) Remote Unified Management: HttpSandboxManager (Cross-machine/Isolated Deployment)

Use Cases:

  • Run sandbox service on a separate host/container, invoke remotely via HTTP
  • Multiple applications share a secure controlled sandbox cluster

Start the service first (choose one):

# Method A: Command line ms-enclave server --host 0.0.0.0 --port 8000 # Method B: Python startup python -c "from ms_enclave.sandbox import create_server; create_server().run(host='0.0.0.0', port=8000)"

Client example:

import asyncio from ms_enclave.sandbox.manager import HttpSandboxManager from ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType async def main(): async with HttpSandboxManager(base_url='http://127.0.0.1:8000') as m: cfg = DockerSandboxConfig(tools_config={'python_executor': {}}) sid = await m.create_sandbox(SandboxType.DOCKER, cfg) r = await m.execute_tool(sid, 'python_executor', {'code': 'print("Hello remote")'}) print(r.output) await m.delete_sandbox(sid) asyncio.run(main())

4) Pooled Sandboxes: Pre-warmed workers (Sandbox Pool)

Why:

  • Amortize container startup by keeping a fixed-size pool of ready sandboxes.
  • Each execution borrows a sandbox and returns it; requests queue FIFO when all are busy.

Local pool example:

import asyncio from ms_enclave.sandbox.manager import LocalSandboxManager from ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType async def main(): async with LocalSandboxManager() as m: cfg = DockerSandboxConfig( image='python:3.11-slim', tools_config={'python_executor': {}} ) # Create a pool of 2 pre-warmed sandboxes await m.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg) # Execute multiple tasks; sandboxes are reused and queued FIFO when busy tasks = [ m.execute_tool_in_pool('python_executor', {'code': f'print("task {i}")', 'timeout': 30}) for i in range(5) ] results = await asyncio.gather(*tasks) print([r.output.strip() for r in results]) # Pool stats stats = await m.get_stats() print('pool_size =', stats['pool_size']) asyncio.run(main())

HTTP pool example:

import asyncio from ms_enclave.sandbox.manager import HttpSandboxManager from ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType async def main(): async with HttpSandboxManager(base_url='http://127.0.0.1:8000') as m: cfg = DockerSandboxConfig(image='python:3.11-slim', tools_config={'python_executor': {}}) await m.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg) r = await m.execute_tool_in_pool('python_executor', {'code': 'print("hello from pool")', 'timeout': 30}) print(r.output) asyncio.run(main())

Notes:

  • Waiting timeout: await m.execute_tool_in_pool(..., timeout=1.0) raises TimeoutError if no sandbox is available in time.
  • FIFO behavior: pool borrows/returns in FIFO order under load.
  • Errors: even if a tool execution fails, the sandbox is returned to the pool.

Sandbox Types & Tool Support

Current built-in sandbox types:

  • DOCKER (General container execution)

    • Supported tools:
      • python_executor (Execute Python code)
      • shell_executor (Execute Shell commands)
      • file_operation (Read/write/delete/list files)
      • multi_code_executor (Multi-language code execution, supports python, cpp, csharp, go, java, nodejs, ts, rust, php, bash, pytest, jest, go_test, lua, r, perl, d_ut, ruby, scala, julia, kotlin_script, verilog, lean, swift, racket) Requires specifying image volcengine/sandbox-fusion:server-20250609
    • Features: Configurable memory/CPU limits, volume mounts, network toggle, privileged mode, port mapping
  • DOCKER_NOTEBOOK (Jupyter Kernel Gateway environment)

    • Supported tools:
      • notebook_executor (Execute code through Jupyter kernel, supports saving code context)
    • Note: This type only loads notebook_executor; other DOCKER-specific tools won't be enabled in this sandbox
    • Dependencies: Requires port 8888 exposed, network enabled

Tool loading rules:

  • Tools are only initialized and available when explicitly declared in tools_config
  • Tools validate required_sandbox_type, automatically ignored if mismatched

Example:

DockerSandboxConfig(tools_config={'python_executor': {}, 'shell_executor': {}, 'file_operation': {}}) DockerNotebookConfig(tools_config={'notebook_executor': {}})

Common Configuration Options

  • image: Docker image name (e.g., python:3.11-slim or jupyter-kernel-gateway)
  • memory_limit: Memory limit (e.g., 512m/1g)
  • cpu_limit: CPU limit (float, >0)
  • volumes: Volume mounts, formatted as {host_path: {"bind": "/container/path", "mode": "rw"}}
  • ports: Port mapping, formatted as { "8888/tcp": ("127.0.0.1", 8888) }
  • network_enabled: Whether to enable network (Notebook sandbox requires True)
  • remove_on_exit: Whether to delete container on exit (default True)

Manager Config (SandboxManagerConfig):

  • base_url: If set, HttpSandboxManager is selected automatically
  • cleanup_interval: Background cleanup interval in seconds (local manager)

Example of Installing Additional Dependencies in Sandbox

async with SandboxFactory.create_sandbox(SandboxType.DOCKER, config) as sandbox: # 1) Write a file requirements_file = '/sandbox/requirements.txt' await sandbox.execute_tool('file_operation', { 'operation': 'write', 'file_path': f'{requirements_file}', 'content': 'numpy\npandas\nmodelscope\n' }) # 2) Execute Python code result = await sandbox.execute_tool('python_executor', { 'code': f"print('Hello from sandbox!')\nprint(open(f'{requirements_file}').read())" }) print(result.output) # 3) Execute CLI result_cli = await sandbox.execute_command(f'pip install -r {requirements_file}') print(result_cli.stdout, flush=True)

Example of Reading/Writing Host Files in Sandbox

async with LocalSandboxManager() as manager: # Create sandbox config = DockerSandboxConfig( # image='python-sandbox', image='python:3.11-slim', tools_config={'python_executor': {}, 'file_operation': {}}, volumes={'~/Code/ms-enclave/output': {'bind': '/sandbox/data', 'mode': 'rw'}} ) sandbox_id = await manager.create_sandbox(SandboxType.DOCKER, config) # Write file result = await manager.execute_tool( sandbox_id, 'file_operation', {'operation': 'write', 'file_path': '/sandbox/data/hello.txt', 'content': 'Hello, Sandbox!'} ) print(result.model_dump())

Error Handling & Debugging

result = await sandbox.execute_tool('python_executor', {'code': 'print(1/0)'}) if result.error: print('Error message:', result.error) else: print('Output:', result.output)

Development & Testing

# Clone repository git clone https://github.com/modelscope/ms-enclave.git cd ms-enclave # Create virtual environment conda create -n ms-enclave python=3.10 -y conda activate ms-enclave # Install dependencies pip install -e ".[dev]" # Run tests pytest # Run examples (provided in repository) python examples/sandbox_usage_examples.py python examples/local_manager_example.py python examples/server_manager_example.py

Contributing

We welcome contributions! Please check CONTRIBUTING.md for details.

Contribution Steps

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Develop and add tests
  4. Run tests locally: pytest
  5. Commit changes: git commit -m 'Add amazing feature'
  6. Push branch: git push origin feature/amazing-feature
  7. Submit Pull Request

License

This project is licensed under the Apache 2.0 License. See LICENSE for details.

关于 About

A modular and stable agent sandbox runtime environment.

语言 Languages

Python98.2%
Shell1.6%
Makefile0.2%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
69
Total Commits
峰值: 21次/周
Less
More

核心贡献者 Contributors