Skip to content

Repository files navigation



中文 | English

PyPI versionPyPI - 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.

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
config=DockerSandboxConfig(
image='python:3.11-slim',
memory_limit='512m',
tools_config={
'python_executor': {},
'file_operation': {},
'shell_executor': {}
}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, config) assandbox:
# 1) Write fileawaitsandbox.execute_tool('file_operation', {
'operation': 'write', 'file_path': '/sandbox/hello.txt', 'content': 'hi from enclave'
})
# 2) Execute Python coderesult=awaitsandbox.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.

importasyncio, os, jsonfromopenaiimportOpenAIfromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefdemo():
client=OpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
asyncwithSandboxManagerFactory.create_manager() asm:
cfg=DockerSandboxConfig(image="python:3.11-slim", tools_config={"python_executor": {}, "shell_executor": {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
tools=list((awaitm.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].messagemessages.append(msg.model_dump())
ifgetattr(msg, "tool_calls", None):
fortcinmsg.tool_calls:
name=tc.function.nameargs=json.loads(tc.function.argumentsor"{}")
result=awaitm.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.contentor"")
else:
print(msg.contentor"")
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

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryasyncdefmain():
asyncwithSandboxManagerFactory.create_manager(base_url='http://127.0.0.1:8000') asm:
# Use exactly like HttpSandboxManager# e.g., create a DOCKER sandbox and execute a tool# ... your code ...passasyncio.run(main())

Example: explicit selection + custom config

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportSandboxManagerConfig, SandboxManagerTypeasyncdefmain():
cfg=SandboxManagerConfig(cleanup_interval=600)
asyncwithSandboxManagerFactory.create_manager(
manager_type=SandboxManagerType.LOCAL, config=cfg
) asm:
# Use exactly like LocalSandboxManager# ... your code ...passasyncio.run(main())

Discover registered manager types:

fromms_enclave.sandbox.managerimportSandboxManagerFactoryprint(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):

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
cfg=DockerSandboxConfig(
tools_config={'python_executor': {}}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, cfg) assb:
r=awaitsb.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asmanager:
cfg=DockerSandboxConfig(tools_config={'shell_executor': {}})
sandbox_id=awaitmanager.create_sandbox(SandboxType.DOCKER, cfg)
# Execute commandres=awaitmanager.execute_tool(sandbox_id, 'shell_executor', {'command': 'echo hello'})
print(res.output.strip()) # hello# View listinfos=awaitmanager.list_sandboxes()
print([i.idforiininfos])
# Stop and deleteawaitmanager.stop_sandbox(sandbox_id)
awaitmanager.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:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(tools_config={'python_executor': {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
r=awaitm.execute_tool(sid, 'python_executor', {'code': 'print("Hello remote")'})
print(r.output)
awaitm.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asm:
cfg=DockerSandboxConfig(
image='python:3.11-slim',
tools_config={'python_executor': {}}
)
# Create a pool of 2 pre-warmed sandboxesawaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
# Execute multiple tasks; sandboxes are reused and queued FIFO when busytasks= [
m.execute_tool_in_pool('python_executor', {'code': f'print("task {i}")', 'timeout': 30})
foriinrange(5)
]
results=awaitasyncio.gather(*tasks)
print([r.output.strip() forrinresults])
# Pool statsstats=awaitm.get_stats()
print('pool_size =', stats['pool_size'])
asyncio.run(main())

HTTP pool example:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(image='python:3.11-slim', tools_config={'python_executor': {}})
awaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
r=awaitm.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_types, 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

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

Example of Reading/Writing Host Files in Sandbox

asyncwithLocalSandboxManager() asmanager:
# Create sandboxconfig=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=awaitmanager.create_sandbox(SandboxType.DOCKER, config)
# Write fileresult=awaitmanager.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=awaitsandbox.execute_tool('python_executor', {'code': 'print(1/0)'})
ifresult.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.

Resources

Security policy

Stars

56 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - modelscope/ms-enclave: A modular and stable agent sandbox runtime environment. · GitHub
Skip to content

Repository files navigation



中文 | English

PyPI versionPyPI - 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.

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
config=DockerSandboxConfig(
image='python:3.11-slim',
memory_limit='512m',
tools_config={
'python_executor': {},
'file_operation': {},
'shell_executor': {}
}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, config) assandbox:
# 1) Write fileawaitsandbox.execute_tool('file_operation', {
'operation': 'write', 'file_path': '/sandbox/hello.txt', 'content': 'hi from enclave'
})
# 2) Execute Python coderesult=awaitsandbox.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.

importasyncio, os, jsonfromopenaiimportOpenAIfromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefdemo():
client=OpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
asyncwithSandboxManagerFactory.create_manager() asm:
cfg=DockerSandboxConfig(image="python:3.11-slim", tools_config={"python_executor": {}, "shell_executor": {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
tools=list((awaitm.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].messagemessages.append(msg.model_dump())
ifgetattr(msg, "tool_calls", None):
fortcinmsg.tool_calls:
name=tc.function.nameargs=json.loads(tc.function.argumentsor"{}")
result=awaitm.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.contentor"")
else:
print(msg.contentor"")
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

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryasyncdefmain():
asyncwithSandboxManagerFactory.create_manager(base_url='http://127.0.0.1:8000') asm:
# Use exactly like HttpSandboxManager# e.g., create a DOCKER sandbox and execute a tool# ... your code ...passasyncio.run(main())

Example: explicit selection + custom config

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportSandboxManagerConfig, SandboxManagerTypeasyncdefmain():
cfg=SandboxManagerConfig(cleanup_interval=600)
asyncwithSandboxManagerFactory.create_manager(
manager_type=SandboxManagerType.LOCAL, config=cfg
) asm:
# Use exactly like LocalSandboxManager# ... your code ...passasyncio.run(main())

Discover registered manager types:

fromms_enclave.sandbox.managerimportSandboxManagerFactoryprint(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):

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
cfg=DockerSandboxConfig(
tools_config={'python_executor': {}}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, cfg) assb:
r=awaitsb.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asmanager:
cfg=DockerSandboxConfig(tools_config={'shell_executor': {}})
sandbox_id=awaitmanager.create_sandbox(SandboxType.DOCKER, cfg)
# Execute commandres=awaitmanager.execute_tool(sandbox_id, 'shell_executor', {'command': 'echo hello'})
print(res.output.strip()) # hello# View listinfos=awaitmanager.list_sandboxes()
print([i.idforiininfos])
# Stop and deleteawaitmanager.stop_sandbox(sandbox_id)
awaitmanager.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:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(tools_config={'python_executor': {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
r=awaitm.execute_tool(sid, 'python_executor', {'code': 'print("Hello remote")'})
print(r.output)
awaitm.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asm:
cfg=DockerSandboxConfig(
image='python:3.11-slim',
tools_config={'python_executor': {}}
)
# Create a pool of 2 pre-warmed sandboxesawaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
# Execute multiple tasks; sandboxes are reused and queued FIFO when busytasks= [
m.execute_tool_in_pool('python_executor', {'code': f'print("task {i}")', 'timeout': 30})
foriinrange(5)
]
results=awaitasyncio.gather(*tasks)
print([r.output.strip() forrinresults])
# Pool statsstats=awaitm.get_stats()
print('pool_size =', stats['pool_size'])
asyncio.run(main())

HTTP pool example:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(image='python:3.11-slim', tools_config={'python_executor': {}})
awaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
r=awaitm.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_types, 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

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

Example of Reading/Writing Host Files in Sandbox

asyncwithLocalSandboxManager() asmanager:
# Create sandboxconfig=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=awaitmanager.create_sandbox(SandboxType.DOCKER, config)
# Write fileresult=awaitmanager.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=awaitsandbox.execute_tool('python_executor', {'code': 'print(1/0)'})
ifresult.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.

Resources

Security policy

Stars

56 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - modelscope/ms-enclave: A modular and stable agent sandbox runtime environment. · GitHub
Skip to content

Repository files navigation



中文 | English

PyPI versionPyPI - 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.

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
config=DockerSandboxConfig(
image='python:3.11-slim',
memory_limit='512m',
tools_config={
'python_executor': {},
'file_operation': {},
'shell_executor': {}
}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, config) assandbox:
# 1) Write fileawaitsandbox.execute_tool('file_operation', {
'operation': 'write', 'file_path': '/sandbox/hello.txt', 'content': 'hi from enclave'
})
# 2) Execute Python coderesult=awaitsandbox.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.

importasyncio, os, jsonfromopenaiimportOpenAIfromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefdemo():
client=OpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
asyncwithSandboxManagerFactory.create_manager() asm:
cfg=DockerSandboxConfig(image="python:3.11-slim", tools_config={"python_executor": {}, "shell_executor": {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
tools=list((awaitm.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].messagemessages.append(msg.model_dump())
ifgetattr(msg, "tool_calls", None):
fortcinmsg.tool_calls:
name=tc.function.nameargs=json.loads(tc.function.argumentsor"{}")
result=awaitm.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.contentor"")
else:
print(msg.contentor"")
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

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryasyncdefmain():
asyncwithSandboxManagerFactory.create_manager(base_url='http://127.0.0.1:8000') asm:
# Use exactly like HttpSandboxManager# e.g., create a DOCKER sandbox and execute a tool# ... your code ...passasyncio.run(main())

Example: explicit selection + custom config

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportSandboxManagerConfig, SandboxManagerTypeasyncdefmain():
cfg=SandboxManagerConfig(cleanup_interval=600)
asyncwithSandboxManagerFactory.create_manager(
manager_type=SandboxManagerType.LOCAL, config=cfg
) asm:
# Use exactly like LocalSandboxManager# ... your code ...passasyncio.run(main())

Discover registered manager types:

fromms_enclave.sandbox.managerimportSandboxManagerFactoryprint(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):

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
cfg=DockerSandboxConfig(
tools_config={'python_executor': {}}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, cfg) assb:
r=awaitsb.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asmanager:
cfg=DockerSandboxConfig(tools_config={'shell_executor': {}})
sandbox_id=awaitmanager.create_sandbox(SandboxType.DOCKER, cfg)
# Execute commandres=awaitmanager.execute_tool(sandbox_id, 'shell_executor', {'command': 'echo hello'})
print(res.output.strip()) # hello# View listinfos=awaitmanager.list_sandboxes()
print([i.idforiininfos])
# Stop and deleteawaitmanager.stop_sandbox(sandbox_id)
awaitmanager.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:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(tools_config={'python_executor': {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
r=awaitm.execute_tool(sid, 'python_executor', {'code': 'print("Hello remote")'})
print(r.output)
awaitm.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asm:
cfg=DockerSandboxConfig(
image='python:3.11-slim',
tools_config={'python_executor': {}}
)
# Create a pool of 2 pre-warmed sandboxesawaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
# Execute multiple tasks; sandboxes are reused and queued FIFO when busytasks= [
m.execute_tool_in_pool('python_executor', {'code': f'print("task {i}")', 'timeout': 30})
foriinrange(5)
]
results=awaitasyncio.gather(*tasks)
print([r.output.strip() forrinresults])
# Pool statsstats=awaitm.get_stats()
print('pool_size =', stats['pool_size'])
asyncio.run(main())

HTTP pool example:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(image='python:3.11-slim', tools_config={'python_executor': {}})
awaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
r=awaitm.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_types, 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

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

Example of Reading/Writing Host Files in Sandbox

asyncwithLocalSandboxManager() asmanager:
# Create sandboxconfig=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=awaitmanager.create_sandbox(SandboxType.DOCKER, config)
# Write fileresult=awaitmanager.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=awaitsandbox.execute_tool('python_executor', {'code': 'print(1/0)'})
ifresult.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.

Resources

Security policy

Stars

56 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - modelscope/ms-enclave: A modular and stable agent sandbox runtime environment. · GitHub
Skip to content

Repository files navigation



中文 | English

PyPI versionPyPI - 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.

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
config=DockerSandboxConfig(
image='python:3.11-slim',
memory_limit='512m',
tools_config={
'python_executor': {},
'file_operation': {},
'shell_executor': {}
}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, config) assandbox:
# 1) Write fileawaitsandbox.execute_tool('file_operation', {
'operation': 'write', 'file_path': '/sandbox/hello.txt', 'content': 'hi from enclave'
})
# 2) Execute Python coderesult=awaitsandbox.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.

importasyncio, os, jsonfromopenaiimportOpenAIfromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefdemo():
client=OpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
asyncwithSandboxManagerFactory.create_manager() asm:
cfg=DockerSandboxConfig(image="python:3.11-slim", tools_config={"python_executor": {}, "shell_executor": {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
tools=list((awaitm.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].messagemessages.append(msg.model_dump())
ifgetattr(msg, "tool_calls", None):
fortcinmsg.tool_calls:
name=tc.function.nameargs=json.loads(tc.function.argumentsor"{}")
result=awaitm.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.contentor"")
else:
print(msg.contentor"")
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

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryasyncdefmain():
asyncwithSandboxManagerFactory.create_manager(base_url='http://127.0.0.1:8000') asm:
# Use exactly like HttpSandboxManager# e.g., create a DOCKER sandbox and execute a tool# ... your code ...passasyncio.run(main())

Example: explicit selection + custom config

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportSandboxManagerConfig, SandboxManagerTypeasyncdefmain():
cfg=SandboxManagerConfig(cleanup_interval=600)
asyncwithSandboxManagerFactory.create_manager(
manager_type=SandboxManagerType.LOCAL, config=cfg
) asm:
# Use exactly like LocalSandboxManager# ... your code ...passasyncio.run(main())

Discover registered manager types:

fromms_enclave.sandbox.managerimportSandboxManagerFactoryprint(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):

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
cfg=DockerSandboxConfig(
tools_config={'python_executor': {}}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, cfg) assb:
r=awaitsb.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asmanager:
cfg=DockerSandboxConfig(tools_config={'shell_executor': {}})
sandbox_id=awaitmanager.create_sandbox(SandboxType.DOCKER, cfg)
# Execute commandres=awaitmanager.execute_tool(sandbox_id, 'shell_executor', {'command': 'echo hello'})
print(res.output.strip()) # hello# View listinfos=awaitmanager.list_sandboxes()
print([i.idforiininfos])
# Stop and deleteawaitmanager.stop_sandbox(sandbox_id)
awaitmanager.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:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(tools_config={'python_executor': {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
r=awaitm.execute_tool(sid, 'python_executor', {'code': 'print("Hello remote")'})
print(r.output)
awaitm.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asm:
cfg=DockerSandboxConfig(
image='python:3.11-slim',
tools_config={'python_executor': {}}
)
# Create a pool of 2 pre-warmed sandboxesawaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
# Execute multiple tasks; sandboxes are reused and queued FIFO when busytasks= [
m.execute_tool_in_pool('python_executor', {'code': f'print("task {i}")', 'timeout': 30})
foriinrange(5)
]
results=awaitasyncio.gather(*tasks)
print([r.output.strip() forrinresults])
# Pool statsstats=awaitm.get_stats()
print('pool_size =', stats['pool_size'])
asyncio.run(main())

HTTP pool example:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(image='python:3.11-slim', tools_config={'python_executor': {}})
awaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
r=awaitm.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_types, 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

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

Example of Reading/Writing Host Files in Sandbox

asyncwithLocalSandboxManager() asmanager:
# Create sandboxconfig=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=awaitmanager.create_sandbox(SandboxType.DOCKER, config)
# Write fileresult=awaitmanager.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=awaitsandbox.execute_tool('python_executor', {'code': 'print(1/0)'})
ifresult.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.

Resources

Security policy

Stars

56 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - modelscope/ms-enclave: A modular and stable agent sandbox runtime environment. · GitHub
Skip to content

Repository files navigation



中文 | English

PyPI versionPyPI - 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.

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
config=DockerSandboxConfig(
image='python:3.11-slim',
memory_limit='512m',
tools_config={
'python_executor': {},
'file_operation': {},
'shell_executor': {}
}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, config) assandbox:
# 1) Write fileawaitsandbox.execute_tool('file_operation', {
'operation': 'write', 'file_path': '/sandbox/hello.txt', 'content': 'hi from enclave'
})
# 2) Execute Python coderesult=awaitsandbox.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.

importasyncio, os, jsonfromopenaiimportOpenAIfromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefdemo():
client=OpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
asyncwithSandboxManagerFactory.create_manager() asm:
cfg=DockerSandboxConfig(image="python:3.11-slim", tools_config={"python_executor": {}, "shell_executor": {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
tools=list((awaitm.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].messagemessages.append(msg.model_dump())
ifgetattr(msg, "tool_calls", None):
fortcinmsg.tool_calls:
name=tc.function.nameargs=json.loads(tc.function.argumentsor"{}")
result=awaitm.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.contentor"")
else:
print(msg.contentor"")
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

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryasyncdefmain():
asyncwithSandboxManagerFactory.create_manager(base_url='http://127.0.0.1:8000') asm:
# Use exactly like HttpSandboxManager# e.g., create a DOCKER sandbox and execute a tool# ... your code ...passasyncio.run(main())

Example: explicit selection + custom config

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportSandboxManagerConfig, SandboxManagerTypeasyncdefmain():
cfg=SandboxManagerConfig(cleanup_interval=600)
asyncwithSandboxManagerFactory.create_manager(
manager_type=SandboxManagerType.LOCAL, config=cfg
) asm:
# Use exactly like LocalSandboxManager# ... your code ...passasyncio.run(main())

Discover registered manager types:

fromms_enclave.sandbox.managerimportSandboxManagerFactoryprint(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):

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
cfg=DockerSandboxConfig(
tools_config={'python_executor': {}}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, cfg) assb:
r=awaitsb.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asmanager:
cfg=DockerSandboxConfig(tools_config={'shell_executor': {}})
sandbox_id=awaitmanager.create_sandbox(SandboxType.DOCKER, cfg)
# Execute commandres=awaitmanager.execute_tool(sandbox_id, 'shell_executor', {'command': 'echo hello'})
print(res.output.strip()) # hello# View listinfos=awaitmanager.list_sandboxes()
print([i.idforiininfos])
# Stop and deleteawaitmanager.stop_sandbox(sandbox_id)
awaitmanager.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:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(tools_config={'python_executor': {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
r=awaitm.execute_tool(sid, 'python_executor', {'code': 'print("Hello remote")'})
print(r.output)
awaitm.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asm:
cfg=DockerSandboxConfig(
image='python:3.11-slim',
tools_config={'python_executor': {}}
)
# Create a pool of 2 pre-warmed sandboxesawaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
# Execute multiple tasks; sandboxes are reused and queued FIFO when busytasks= [
m.execute_tool_in_pool('python_executor', {'code': f'print("task {i}")', 'timeout': 30})
foriinrange(5)
]
results=awaitasyncio.gather(*tasks)
print([r.output.strip() forrinresults])
# Pool statsstats=awaitm.get_stats()
print('pool_size =', stats['pool_size'])
asyncio.run(main())

HTTP pool example:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(image='python:3.11-slim', tools_config={'python_executor': {}})
awaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
r=awaitm.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_types, 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

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

Example of Reading/Writing Host Files in Sandbox

asyncwithLocalSandboxManager() asmanager:
# Create sandboxconfig=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=awaitmanager.create_sandbox(SandboxType.DOCKER, config)
# Write fileresult=awaitmanager.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=awaitsandbox.execute_tool('python_executor', {'code': 'print(1/0)'})
ifresult.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.

Resources

Security policy

Stars

56 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - modelscope/ms-enclave: A modular and stable agent sandbox runtime environment. · GitHub
Skip to content

Repository files navigation



中文 | English

PyPI versionPyPI - 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.

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
config=DockerSandboxConfig(
image='python:3.11-slim',
memory_limit='512m',
tools_config={
'python_executor': {},
'file_operation': {},
'shell_executor': {}
}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, config) assandbox:
# 1) Write fileawaitsandbox.execute_tool('file_operation', {
'operation': 'write', 'file_path': '/sandbox/hello.txt', 'content': 'hi from enclave'
})
# 2) Execute Python coderesult=awaitsandbox.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.

importasyncio, os, jsonfromopenaiimportOpenAIfromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefdemo():
client=OpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
asyncwithSandboxManagerFactory.create_manager() asm:
cfg=DockerSandboxConfig(image="python:3.11-slim", tools_config={"python_executor": {}, "shell_executor": {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
tools=list((awaitm.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].messagemessages.append(msg.model_dump())
ifgetattr(msg, "tool_calls", None):
fortcinmsg.tool_calls:
name=tc.function.nameargs=json.loads(tc.function.argumentsor"{}")
result=awaitm.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.contentor"")
else:
print(msg.contentor"")
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

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryasyncdefmain():
asyncwithSandboxManagerFactory.create_manager(base_url='http://127.0.0.1:8000') asm:
# Use exactly like HttpSandboxManager# e.g., create a DOCKER sandbox and execute a tool# ... your code ...passasyncio.run(main())

Example: explicit selection + custom config

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportSandboxManagerConfig, SandboxManagerTypeasyncdefmain():
cfg=SandboxManagerConfig(cleanup_interval=600)
asyncwithSandboxManagerFactory.create_manager(
manager_type=SandboxManagerType.LOCAL, config=cfg
) asm:
# Use exactly like LocalSandboxManager# ... your code ...passasyncio.run(main())

Discover registered manager types:

fromms_enclave.sandbox.managerimportSandboxManagerFactoryprint(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):

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
cfg=DockerSandboxConfig(
tools_config={'python_executor': {}}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, cfg) assb:
r=awaitsb.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asmanager:
cfg=DockerSandboxConfig(tools_config={'shell_executor': {}})
sandbox_id=awaitmanager.create_sandbox(SandboxType.DOCKER, cfg)
# Execute commandres=awaitmanager.execute_tool(sandbox_id, 'shell_executor', {'command': 'echo hello'})
print(res.output.strip()) # hello# View listinfos=awaitmanager.list_sandboxes()
print([i.idforiininfos])
# Stop and deleteawaitmanager.stop_sandbox(sandbox_id)
awaitmanager.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:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(tools_config={'python_executor': {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
r=awaitm.execute_tool(sid, 'python_executor', {'code': 'print("Hello remote")'})
print(r.output)
awaitm.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asm:
cfg=DockerSandboxConfig(
image='python:3.11-slim',
tools_config={'python_executor': {}}
)
# Create a pool of 2 pre-warmed sandboxesawaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
# Execute multiple tasks; sandboxes are reused and queued FIFO when busytasks= [
m.execute_tool_in_pool('python_executor', {'code': f'print("task {i}")', 'timeout': 30})
foriinrange(5)
]
results=awaitasyncio.gather(*tasks)
print([r.output.strip() forrinresults])
# Pool statsstats=awaitm.get_stats()
print('pool_size =', stats['pool_size'])
asyncio.run(main())

HTTP pool example:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(image='python:3.11-slim', tools_config={'python_executor': {}})
awaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
r=awaitm.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_types, 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

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

Example of Reading/Writing Host Files in Sandbox

asyncwithLocalSandboxManager() asmanager:
# Create sandboxconfig=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=awaitmanager.create_sandbox(SandboxType.DOCKER, config)
# Write fileresult=awaitmanager.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=awaitsandbox.execute_tool('python_executor', {'code': 'print(1/0)'})
ifresult.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.

Resources

Security policy

Stars

56 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - modelscope/ms-enclave: A modular and stable agent sandbox runtime environment. · GitHub
Skip to content

Repository files navigation



中文 | English

PyPI versionPyPI - 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.

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
config=DockerSandboxConfig(
image='python:3.11-slim',
memory_limit='512m',
tools_config={
'python_executor': {},
'file_operation': {},
'shell_executor': {}
}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, config) assandbox:
# 1) Write fileawaitsandbox.execute_tool('file_operation', {
'operation': 'write', 'file_path': '/sandbox/hello.txt', 'content': 'hi from enclave'
})
# 2) Execute Python coderesult=awaitsandbox.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.

importasyncio, os, jsonfromopenaiimportOpenAIfromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefdemo():
client=OpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
asyncwithSandboxManagerFactory.create_manager() asm:
cfg=DockerSandboxConfig(image="python:3.11-slim", tools_config={"python_executor": {}, "shell_executor": {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
tools=list((awaitm.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].messagemessages.append(msg.model_dump())
ifgetattr(msg, "tool_calls", None):
fortcinmsg.tool_calls:
name=tc.function.nameargs=json.loads(tc.function.argumentsor"{}")
result=awaitm.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.contentor"")
else:
print(msg.contentor"")
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

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryasyncdefmain():
asyncwithSandboxManagerFactory.create_manager(base_url='http://127.0.0.1:8000') asm:
# Use exactly like HttpSandboxManager# e.g., create a DOCKER sandbox and execute a tool# ... your code ...passasyncio.run(main())

Example: explicit selection + custom config

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportSandboxManagerConfig, SandboxManagerTypeasyncdefmain():
cfg=SandboxManagerConfig(cleanup_interval=600)
asyncwithSandboxManagerFactory.create_manager(
manager_type=SandboxManagerType.LOCAL, config=cfg
) asm:
# Use exactly like LocalSandboxManager# ... your code ...passasyncio.run(main())

Discover registered manager types:

fromms_enclave.sandbox.managerimportSandboxManagerFactoryprint(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):

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
cfg=DockerSandboxConfig(
tools_config={'python_executor': {}}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, cfg) assb:
r=awaitsb.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asmanager:
cfg=DockerSandboxConfig(tools_config={'shell_executor': {}})
sandbox_id=awaitmanager.create_sandbox(SandboxType.DOCKER, cfg)
# Execute commandres=awaitmanager.execute_tool(sandbox_id, 'shell_executor', {'command': 'echo hello'})
print(res.output.strip()) # hello# View listinfos=awaitmanager.list_sandboxes()
print([i.idforiininfos])
# Stop and deleteawaitmanager.stop_sandbox(sandbox_id)
awaitmanager.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:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(tools_config={'python_executor': {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
r=awaitm.execute_tool(sid, 'python_executor', {'code': 'print("Hello remote")'})
print(r.output)
awaitm.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asm:
cfg=DockerSandboxConfig(
image='python:3.11-slim',
tools_config={'python_executor': {}}
)
# Create a pool of 2 pre-warmed sandboxesawaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
# Execute multiple tasks; sandboxes are reused and queued FIFO when busytasks= [
m.execute_tool_in_pool('python_executor', {'code': f'print("task {i}")', 'timeout': 30})
foriinrange(5)
]
results=awaitasyncio.gather(*tasks)
print([r.output.strip() forrinresults])
# Pool statsstats=awaitm.get_stats()
print('pool_size =', stats['pool_size'])
asyncio.run(main())

HTTP pool example:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(image='python:3.11-slim', tools_config={'python_executor': {}})
awaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
r=awaitm.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_types, 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

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

Example of Reading/Writing Host Files in Sandbox

asyncwithLocalSandboxManager() asmanager:
# Create sandboxconfig=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=awaitmanager.create_sandbox(SandboxType.DOCKER, config)
# Write fileresult=awaitmanager.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=awaitsandbox.execute_tool('python_executor', {'code': 'print(1/0)'})
ifresult.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.

Resources

Security policy

Stars

56 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - modelscope/ms-enclave: A modular and stable agent sandbox runtime environment. · GitHub
Skip to content

Repository files navigation



中文 | English

PyPI versionPyPI - 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.

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
config=DockerSandboxConfig(
image='python:3.11-slim',
memory_limit='512m',
tools_config={
'python_executor': {},
'file_operation': {},
'shell_executor': {}
}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, config) assandbox:
# 1) Write fileawaitsandbox.execute_tool('file_operation', {
'operation': 'write', 'file_path': '/sandbox/hello.txt', 'content': 'hi from enclave'
})
# 2) Execute Python coderesult=awaitsandbox.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.

importasyncio, os, jsonfromopenaiimportOpenAIfromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefdemo():
client=OpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
asyncwithSandboxManagerFactory.create_manager() asm:
cfg=DockerSandboxConfig(image="python:3.11-slim", tools_config={"python_executor": {}, "shell_executor": {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
tools=list((awaitm.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].messagemessages.append(msg.model_dump())
ifgetattr(msg, "tool_calls", None):
fortcinmsg.tool_calls:
name=tc.function.nameargs=json.loads(tc.function.argumentsor"{}")
result=awaitm.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.contentor"")
else:
print(msg.contentor"")
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

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryasyncdefmain():
asyncwithSandboxManagerFactory.create_manager(base_url='http://127.0.0.1:8000') asm:
# Use exactly like HttpSandboxManager# e.g., create a DOCKER sandbox and execute a tool# ... your code ...passasyncio.run(main())

Example: explicit selection + custom config

importasynciofromms_enclave.sandbox.managerimportSandboxManagerFactoryfromms_enclave.sandbox.modelimportSandboxManagerConfig, SandboxManagerTypeasyncdefmain():
cfg=SandboxManagerConfig(cleanup_interval=600)
asyncwithSandboxManagerFactory.create_manager(
manager_type=SandboxManagerType.LOCAL, config=cfg
) asm:
# Use exactly like LocalSandboxManager# ... your code ...passasyncio.run(main())

Discover registered manager types:

fromms_enclave.sandbox.managerimportSandboxManagerFactoryprint(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):

importasynciofromms_enclave.sandbox.boxesimportSandboxFactoryfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
cfg=DockerSandboxConfig(
tools_config={'python_executor': {}}
)
asyncwithSandboxFactory.create_sandbox(SandboxType.DOCKER, cfg) assb:
r=awaitsb.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asmanager:
cfg=DockerSandboxConfig(tools_config={'shell_executor': {}})
sandbox_id=awaitmanager.create_sandbox(SandboxType.DOCKER, cfg)
# Execute commandres=awaitmanager.execute_tool(sandbox_id, 'shell_executor', {'command': 'echo hello'})
print(res.output.strip()) # hello# View listinfos=awaitmanager.list_sandboxes()
print([i.idforiininfos])
# Stop and deleteawaitmanager.stop_sandbox(sandbox_id)
awaitmanager.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:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(tools_config={'python_executor': {}})
sid=awaitm.create_sandbox(SandboxType.DOCKER, cfg)
r=awaitm.execute_tool(sid, 'python_executor', {'code': 'print("Hello remote")'})
print(r.output)
awaitm.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:

importasynciofromms_enclave.sandbox.managerimportLocalSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithLocalSandboxManager() asm:
cfg=DockerSandboxConfig(
image='python:3.11-slim',
tools_config={'python_executor': {}}
)
# Create a pool of 2 pre-warmed sandboxesawaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
# Execute multiple tasks; sandboxes are reused and queued FIFO when busytasks= [
m.execute_tool_in_pool('python_executor', {'code': f'print("task {i}")', 'timeout': 30})
foriinrange(5)
]
results=awaitasyncio.gather(*tasks)
print([r.output.strip() forrinresults])
# Pool statsstats=awaitm.get_stats()
print('pool_size =', stats['pool_size'])
asyncio.run(main())

HTTP pool example:

importasynciofromms_enclave.sandbox.managerimportHttpSandboxManagerfromms_enclave.sandbox.modelimportDockerSandboxConfig, SandboxTypeasyncdefmain():
asyncwithHttpSandboxManager(base_url='http://127.0.0.1:8000') asm:
cfg=DockerSandboxConfig(image='python:3.11-slim', tools_config={'python_executor': {}})
awaitm.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)
r=awaitm.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_types, 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

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

Example of Reading/Writing Host Files in Sandbox

asyncwithLocalSandboxManager() asmanager:
# Create sandboxconfig=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=awaitmanager.create_sandbox(SandboxType.DOCKER, config)
# Write fileresult=awaitmanager.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=awaitsandbox.execute_tool('python_executor', {'code': 'print(1/0)'})
ifresult.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.

Resources

Security policy

Stars

56 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages