{"id":31033063,"url":"https://github.com/modelscope/ms-enclave","last_synced_at":"2026-01-20T16:53:30.596Z","repository":{"id":314625547,"uuid":"1054752888","full_name":"modelscope/ms-enclave","owner":"modelscope","description":null,"archived":false,"fork":false,"pushed_at":"2025-09-11T11:01:28.000Z","size":51,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-13T18:08:34.885Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/modelscope.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-11T09:30:18.000Z","updated_at":"2025-09-11T11:01:32.000Z","dependencies_parsed_at":"2025-09-13T18:22:21.252Z","dependency_job_id":null,"html_url":"https://github.com/modelscope/ms-enclave","commit_stats":null,"previous_names":["modelscope/ms-enclave"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/modelscope/ms-enclave","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modelscope%2Fms-enclave","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modelscope%2Fms-enclave/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modelscope%2Fms-enclave/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modelscope%2Fms-enclave/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/modelscope","download_url":"https://codeload.github.com/modelscope/ms-enclave/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modelscope%2Fms-enclave/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275706287,"owners_count":25513176,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-18T02:00:09.552Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-14T01:12:35.581Z","updated_at":"2026-01-20T16:53:30.582Z","avatar_url":"https://github.com/modelscope.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cbr\u003e\n    \u003cimg src=\"docs/asset/image/logo.png\"/\u003e\n    \u003cbr\u003e\n\u003cp\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"README_zh.md\"\u003e中文\u003c/a\u003e \u0026nbsp ｜ \u0026nbsp English \u0026nbsp\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/python-%E2%89%A53.10-5be.svg\"\u003e\n\u003ca href=\"https://badge.fury.io/py/ms-enclave\"\u003e\u003cimg src=\"https://badge.fury.io/py/ms-enclave.svg\" alt=\"PyPI version\" height=\"18\"\u003e\u003c/a\u003e\n\u003ca href=\"https://pypi.org/project/ms-enclave\"\u003e\u003cimg alt=\"PyPI - Downloads\" src=\"https://static.pepy.tech/badge/ms-enclave\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/modelscope/ms-enclave/pulls\"\u003e\u003cimg src=\"https://img.shields.io/badge/PR-welcome-55EB99.svg\"\u003e\u003c/a\u003e\n\u003cp\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://ms-enclave.readthedocs.io/zh-cn/latest\"\u003e 📖  中文文档\u003c/a\u003e \u0026nbsp ｜ \u0026nbsp \u003ca href=\"https://ms-enclave.readthedocs.io/en/latest\"\u003e 📖  English Documentation\u003c/a\u003e\n\u003cp\u003e\n\n\n\u003e ⭐ 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!\n\n## Introduction\n\nms-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.\n\n- 🔒 Secure Isolation: Complete isolation and resource limits based on Docker\n- 🧩 Modular: Both sandboxes and tools are extensible (registered factory)\n- ⚡ Stable Performance: Clean implementation, fast startup, with lifecycle management\n- 🌐 Remote Management: Built-in FastAPI service, supports HTTP management\n- 🔧 Tool System: Standardized tools enabled by sandbox type (OpenAI-style schema)\n\n## System Requirements\n\n- Python \u003e= 3.10\n- Operating System: Linux, macOS, or Windows with Docker support\n- Docker daemon available on local machine (Notebook sandbox requires port 8888 open)\n\n## Installation\n\n### Install from PyPI\n\n```bash\npip install ms-enclave\n# If Docker support is needed, install extra dependencies\npip install 'ms-enclave[docker]'\n```\n\n### Install from Source\n\n```bash\ngit clone https://github.com/modelscope/ms-enclave.git\ncd ms-enclave\npip install -e .\n# If Docker support is needed, install extra dependencies\npip install -e '.[docker]'\n```\n\n## Quick Start: Minimal Viable Example (SandboxFactory)\n\n\u003e Tools need to be explicitly enabled in the configured tools_config, otherwise they won't be registered.\n\n```python\nimport asyncio\nfrom ms_enclave.sandbox.boxes import SandboxFactory\nfrom ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType\n\nasync def main():\n    config = DockerSandboxConfig(\n        image='python:3.11-slim',\n        memory_limit='512m',\n        tools_config={\n            'python_executor': {},\n            'file_operation': {},\n            'shell_executor': {}\n        }\n    )\n\n    async with SandboxFactory.create_sandbox(SandboxType.DOCKER, config) as sandbox:\n        # 1) Write file\n        await sandbox.execute_tool('file_operation', {\n            'operation': 'write', 'file_path': '/sandbox/hello.txt', 'content': 'hi from enclave'\n        })\n        # 2) Execute Python code\n        result = await sandbox.execute_tool('python_executor', {\n            'code': \"print('Hello from sandbox!')\\nprint(open('/sandbox/hello.txt').read())\"\n        })\n        print(result.output)\n\nasyncio.run(main())\n```\n---\n\n## Agent Model Tool Calling (OpenAI Tools)\n\nExpose sandbox tools to the Agent in OpenAI Tools format, allowing the model to trigger tools and execute them securely in the sandbox.\n\n````python\nimport asyncio, os, json\nfrom openai import OpenAI\nfrom ms_enclave.sandbox.manager import SandboxManagerFactory\nfrom ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType\n\nasync def demo():\n    client = OpenAI(\n        base_url=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n        api_key=os.getenv(\"DASHSCOPE_API_KEY\")\n    )\n    async with SandboxManagerFactory.create_manager() as m:\n        cfg = DockerSandboxConfig(image=\"python:3.11-slim\", tools_config={\"python_executor\": {}, \"shell_executor\": {}})\n        sid = await m.create_sandbox(SandboxType.DOCKER, cfg)\n\n        tools = list((await m.get_sandbox_tools(sid)).values())\n        messages = [{\"role\": \"user\", \"content\": \"Print 'hello' in Python, then list /sandbox via shell.\"}]\n\n        rsp = client.chat.completions.create(model=\"qwen-plus\", messages=messages, tools=tools, tool_choice=\"auto\")\n        msg = rsp.choices[0].message\n        messages.append(msg.model_dump())\n\n        if getattr(msg, \"tool_calls\", None):\n            for tc in msg.tool_calls:\n                name = tc.function.name\n                args = json.loads(tc.function.arguments or \"{}\")\n                result = await m.execute_tool(sid, name, args)\n                messages.append({\"role\": \"tool\", \"content\": result.model_dump_json(), \"tool_call_id\": tc.id, \"name\": name})\n            final = client.chat.completions.create(model=\"qwen-plus\", messages=messages)\n            print(final.choices[0].message.content or \"\")\n        else:\n            print(msg.content or \"\")\n\nasyncio.run(demo())\n````\n\n**Notes:**\n- Use `get_sandbox_tools(sandbox_id)` to retrieve tool schemas (OpenAI-compatible)\n- Pass `tools=...` to the model, handle returned `tool_calls` and execute them in the sandbox\n- Call the model again to generate the final answer\n---\n\n## Typical Usage Patterns \u0026 Examples\n\n- Direct use of SandboxFactory: Create/destroy sandboxes within a single process, most lightweight; suitable for scripts or one-time tasks\n- Using LocalSandboxManager: Uniformly orchestrate lifecycle/cleanup of multiple sandboxes on local machine; suitable for service-oriented, multi-task parallel scenarios\n- Using HttpSandboxManager: Manage sandboxes uniformly through remote HTTP service; suitable for cross-machine/distributed or stronger isolation deployments\n\n### 0) Manager Factory: SandboxManagerFactory (Automatic Local/HTTP selection)\n\nWhen to use:\n- You want a single entry point that chooses Local or HTTP manager automatically.\n- You prefer central registration and discovery of available manager types.\n\nKey points:\n- If manager_type is provided, it is used directly.\n- If base_url is provided (in config or kwargs), HTTP manager is created.\n- Otherwise, Local manager is created by default.\n\nExample: implicit selection by base_url\n```python\nimport asyncio\nfrom ms_enclave.sandbox.manager import SandboxManagerFactory\n\nasync def main():\n    async with SandboxManagerFactory.create_manager(base_url='http://127.0.0.1:8000') as m:\n        # Use exactly like HttpSandboxManager\n        # e.g., create a DOCKER sandbox and execute a tool\n        # ... your code ...\n        pass\n\nasyncio.run(main())\n```\n\nExample: explicit selection + custom config\n```python\nimport asyncio\nfrom ms_enclave.sandbox.manager import SandboxManagerFactory\nfrom ms_enclave.sandbox.model import SandboxManagerConfig, SandboxManagerType\n\nasync def main():\n    cfg = SandboxManagerConfig(cleanup_interval=600)\n    async with SandboxManagerFactory.create_manager(\n        manager_type=SandboxManagerType.LOCAL, config=cfg\n    ) as m:\n        # Use exactly like LocalSandboxManager\n        # ... your code ...\n        pass\n\nasyncio.run(main())\n```\n\nDiscover registered manager types:\n```python\nfrom ms_enclave.sandbox.manager import SandboxManagerFactory\nprint(SandboxManagerFactory.get_registered_types())\n```\n\n### 1) Direct Sandbox Creation: SandboxFactory (Lightweight, Temporary)\n\nUse Cases:\n\n- Temporarily run a piece of code in scripts or microservices\n- Fine-grained control over sandbox lifecycle (cleanup on context exit)\n\nExample (Docker sandbox + Python execution):\n\n```python\nimport asyncio\nfrom ms_enclave.sandbox.boxes import SandboxFactory\nfrom ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType\n\nasync def main():\n    cfg = DockerSandboxConfig(\n        tools_config={'python_executor': {}}\n    )\n    async with SandboxFactory.create_sandbox(SandboxType.DOCKER, cfg) as sb:\n        r = await sb.execute_tool('python_executor', {\n            'code': 'import platform; print(platform.python_version())'\n        })\n        print(r.output)\n\nasyncio.run(main())\n```\n\n### 2) Local Unified Orchestration: LocalSandboxManager (Multiple Sandboxes, Lifecycle Management)\n\nUse Cases:\n\n- Need to create/manage multiple sandboxes within the same process (create, query, stop, periodic cleanup)\n- Want unified status view, statistics, and health checks\n\nExample:\n\n```python\nimport asyncio\nfrom ms_enclave.sandbox.manager import LocalSandboxManager\nfrom ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType\n\nasync def main():\n    async with LocalSandboxManager() as manager:\n        cfg = DockerSandboxConfig(tools_config={'shell_executor': {}})\n        sandbox_id = await manager.create_sandbox(SandboxType.DOCKER, cfg)\n\n        # Execute command\n        res = await manager.execute_tool(sandbox_id, 'shell_executor', {'command': 'echo hello'})\n        print(res.output.strip())  # hello\n\n        # View list\n        infos = await manager.list_sandboxes()\n        print([i.id for i in infos])\n\n        # Stop and delete\n        await manager.stop_sandbox(sandbox_id)\n        await manager.delete_sandbox(sandbox_id)\n\nasyncio.run(main())\n```\n\n### 3) Remote Unified Management: HttpSandboxManager (Cross-machine/Isolated Deployment)\n\nUse Cases:\n\n- Run sandbox service on a separate host/container, invoke remotely via HTTP\n- Multiple applications share a secure controlled sandbox cluster\n\nStart the service first (choose one):\n\n```bash\n# Method A: Command line\nms-enclave server --host 0.0.0.0 --port 8000\n\n# Method B: Python startup\npython -c \"from ms_enclave.sandbox import create_server; create_server().run(host='0.0.0.0', port=8000)\"\n```\n\nClient example:\n\n```python\nimport asyncio\nfrom ms_enclave.sandbox.manager import HttpSandboxManager\nfrom ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType\n\nasync def main():\n    async with HttpSandboxManager(base_url='http://127.0.0.1:8000') as m:\n        cfg = DockerSandboxConfig(tools_config={'python_executor': {}})\n        sid = await m.create_sandbox(SandboxType.DOCKER, cfg)\n        r = await m.execute_tool(sid, 'python_executor', {'code': 'print(\"Hello remote\")'})\n        print(r.output)\n        await m.delete_sandbox(sid)\n\nasyncio.run(main())\n```\n\n### 4) Pooled Sandboxes: Pre-warmed workers (Sandbox Pool)\n\nWhy:\n- Amortize container startup by keeping a fixed-size pool of ready sandboxes.\n- Each execution borrows a sandbox and returns it; requests queue FIFO when all are busy.\n\nLocal pool example:\n\n```python\nimport asyncio\nfrom ms_enclave.sandbox.manager import LocalSandboxManager\nfrom ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType\n\nasync def main():\n    async with LocalSandboxManager() as m:\n        cfg = DockerSandboxConfig(\n            image='python:3.11-slim',\n            tools_config={'python_executor': {}}\n        )\n        # Create a pool of 2 pre-warmed sandboxes\n        await m.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)\n\n        # Execute multiple tasks; sandboxes are reused and queued FIFO when busy\n        tasks = [\n            m.execute_tool_in_pool('python_executor', {'code': f'print(\"task {i}\")', 'timeout': 30})\n            for i in range(5)\n        ]\n        results = await asyncio.gather(*tasks)\n        print([r.output.strip() for r in results])\n\n        # Pool stats\n        stats = await m.get_stats()\n        print('pool_size =', stats['pool_size'])\n\nasyncio.run(main())\n```\n\nHTTP pool example:\n\n```python\nimport asyncio\nfrom ms_enclave.sandbox.manager import HttpSandboxManager\nfrom ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType\n\nasync def main():\n    async with HttpSandboxManager(base_url='http://127.0.0.1:8000') as m:\n        cfg = DockerSandboxConfig(image='python:3.11-slim', tools_config={'python_executor': {}})\n        await m.initialize_pool(pool_size=2, sandbox_type=SandboxType.DOCKER, config=cfg)\n\n        r = await m.execute_tool_in_pool('python_executor', {'code': 'print(\"hello from pool\")', 'timeout': 30})\n        print(r.output)\n\nasyncio.run(main())\n```\n\nNotes:\n- Waiting timeout: `await m.execute_tool_in_pool(..., timeout=1.0)` raises `TimeoutError` if no sandbox is available in time.\n- FIFO behavior: pool borrows/returns in FIFO order under load.\n- Errors: even if a tool execution fails, the sandbox is returned to the pool.\n\n---\n\n## Sandbox Types \u0026 Tool Support\n\nCurrent built-in sandbox types:\n\n- DOCKER (General container execution)\n  - Supported tools:\n    - python_executor (Execute Python code)\n    - shell_executor (Execute Shell commands)\n    - file_operation (Read/write/delete/list files)\n    - 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`\n  - Features: Configurable memory/CPU limits, volume mounts, network toggle, privileged mode, port mapping\n\n- DOCKER_NOTEBOOK (Jupyter Kernel Gateway environment)\n  - Supported tools:\n    - notebook_executor (Execute code through Jupyter kernel, supports saving code context)\n  - Note: This type only loads notebook_executor; other DOCKER-specific tools won't be enabled in this sandbox\n  - Dependencies: Requires port 8888 exposed, network enabled\n\nTool loading rules:\n\n- Tools are only initialized and available when explicitly declared in `tools_config`\n- Tools validate `required_sandbox_type`, automatically ignored if mismatched\n\nExample:\n\n```python\nDockerSandboxConfig(tools_config={'python_executor': {}, 'shell_executor': {}, 'file_operation': {}})\nDockerNotebookConfig(tools_config={'notebook_executor': {}})\n```\n\n---\n\n## Common Configuration Options\n\n- `image`: Docker image name (e.g., `python:3.11-slim` or `jupyter-kernel-gateway`)\n- `memory_limit`: Memory limit (e.g., `512m`/`1g`)\n- `cpu_limit`: CPU limit (float, \u003e0)\n- `volumes`: Volume mounts, formatted as `{host_path: {\"bind\": \"/container/path\", \"mode\": \"rw\"}}`\n- `ports`: Port mapping, formatted as `{ \"8888/tcp\": (\"127.0.0.1\", 8888) }`\n- `network_enabled`: Whether to enable network (Notebook sandbox requires True)\n- `remove_on_exit`: Whether to delete container on exit (default True)\n\nManager Config (SandboxManagerConfig):\n- `base_url`: If set, HttpSandboxManager is selected automatically\n- `cleanup_interval`: Background cleanup interval in seconds (local manager)\n\n**Example of Installing Additional Dependencies in Sandbox**\n```python\nasync with SandboxFactory.create_sandbox(SandboxType.DOCKER, config) as sandbox:\n    # 1) Write a file\n    requirements_file = '/sandbox/requirements.txt'\n    await sandbox.execute_tool('file_operation', {\n        'operation': 'write', 'file_path': f'{requirements_file}', 'content': 'numpy\\npandas\\nmodelscope\\n'\n    })\n    # 2) Execute Python code\n    result = await sandbox.execute_tool('python_executor', {\n        'code': f\"print('Hello from sandbox!')\\nprint(open(f'{requirements_file}').read())\"\n    })\n    print(result.output)\n\n    # 3) Execute CLI\n    result_cli = await sandbox.execute_command(f'pip install -r {requirements_file}')\n    print(result_cli.stdout, flush=True)\n```\n\n**Example of Reading/Writing Host Files in Sandbox**\n```python\nasync with LocalSandboxManager() as manager:\n    # Create sandbox\n    config = DockerSandboxConfig(\n        # image='python-sandbox',\n        image='python:3.11-slim',\n        tools_config={'python_executor': {}, 'file_operation': {}},\n        volumes={'~/Code/ms-enclave/output': {'bind': '/sandbox/data', 'mode': 'rw'}}\n    )\n    sandbox_id = await manager.create_sandbox(SandboxType.DOCKER, config)\n\n    # Write file\n    result = await manager.execute_tool(\n        sandbox_id, 'file_operation', {'operation': 'write', 'file_path': '/sandbox/data/hello.txt', 'content': 'Hello, Sandbox!'}\n    )\n    print(result.model_dump())\n```\n\n---\n\n## Error Handling \u0026 Debugging\n\n```python\nresult = await sandbox.execute_tool('python_executor', {'code': 'print(1/0)'})\nif result.error:\n    print('Error message:', result.error)\nelse:\n    print('Output:', result.output)\n```\n\n---\n\n## Development \u0026 Testing\n\n```bash\n# Clone repository\ngit clone https://github.com/modelscope/ms-enclave.git\ncd ms-enclave\n\n# Create virtual environment\nconda create -n ms-enclave python=3.10 -y\nconda activate ms-enclave\n\n# Install dependencies\npip install -e \".[dev]\"\n\n# Run tests\npytest\n\n# Run examples (provided in repository)\npython examples/sandbox_usage_examples.py\npython examples/local_manager_example.py\npython examples/server_manager_example.py\n```\n\n---\n\n## Contributing\n\nWe welcome contributions! Please check [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n### Contribution Steps\n\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feature/amazing-feature`\n3. Develop and add tests\n4. Run tests locally: `pytest`\n5. Commit changes: `git commit -m 'Add amazing feature'`\n6. Push branch: `git push origin feature/amazing-feature`\n7. Submit Pull Request\n\n## License\n\nThis project is licensed under the Apache 2.0 License. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmodelscope%2Fms-enclave","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmodelscope%2Fms-enclave","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmodelscope%2Fms-enclave/lists"}