Using a Sandbox Directly (SandboxFactory)¶
SandboxFactory is the lightest entry point. It creates a sandbox instance and leaves lifecycle to the caller. Use it for:
- One-off scripts
- Unit tests (a clean environment per case)
- Quick experiments or fine-grained control over low-level APIs
Recommended: async with¶
import asyncio
from ms_enclave.sandbox.boxes import SandboxFactory
from ms_enclave.sandbox.model import DockerSandboxConfig, SandboxType
async def main():
config = DockerSandboxConfig(
image='python:3.11-slim',
tools_config={'python_executor': {}, 'file_operation': {}},
)
async with SandboxFactory.create_sandbox(SandboxType.DOCKER, config) as sandbox:
result = await sandbox.execute_tool('python_executor', {
'code': 'import sys; print(sys.version)'
})
print(result.output.strip())
asyncio.run(main())
Exiting the async with block automatically stops and removes the Docker container.
Key points¶
- Tools must be declared in
tools_config. Even registered tools won't load otherwise. execute_tool(tool_name, parameters)is the primary way to interact with a sandbox.tool_namemust match a key intools_config.- The return value is a
ToolResultwithstatus,output,errorfields.
Manual lifecycle¶
If your flow spans multiple async contexts (e.g., long-lived connections), control start/stop explicitly:
async def manual_lifecycle():
config = DockerSandboxConfig(tools_config={'shell_executor': {}})
sandbox = SandboxFactory.create_sandbox(SandboxType.DOCKER, config)
try:
await sandbox.start()
result = await sandbox.execute_tool('shell_executor', {'command': 'echo hi'})
print(result.output.strip())
finally:
await sandbox.stop() # always release in finally
Warning: forgetting
stop()leaks Docker containers. PreferLocalSandboxManagerin production — it ships with background cleanup.