AgentFense SDK for Python
Python client library for the AgentFense service - a sandbox infrastructure for AI Agents with fine-grained file permission control.
Compatibility note: package/import names remain sandbox-rls / sandbox_rls for now.
Installation
pip install sandbox-rls
Or install from source:
cd sdk/python
pip install -e .
Quick Start (High-Level API)
The easiest way to use the SDK is with the high-level Sandbox class:
from sandbox_rls import Sandbox
# One-liner to create a sandbox from a local directory
with Sandbox.from_local("./my-project") as sandbox:
result = sandbox.run("python main.py")
print(result.stdout)
This automatically:
- Creates a codebase
- Uploads all files from the directory
- Creates a sandbox with the "agent-safe" preset
- Starts the sandbox
- Cleans up everything when done
Using Docker Runtime with Resource Limits
from sandbox_rls import Sandbox, RuntimeType, ResourceLimits
with Sandbox.from_local(
"./my-project",
preset="agent-safe",
runtime=RuntimeType.DOCKER,
image="python:3.11-slim",
resources=ResourceLimits(
memory_bytes=512 * 1024 * 1024, # 512 MB
pids_limit=100,
),
) as sandbox:
# Use a session for stateful commands
with sandbox.session() as session:
session.exec("cd /workspace")
session.exec("pip install -r requirements.txt")
result = session.exec("pytest")
print(result.stdout)
Permission Presets
The SDK includes several built-in permission presets:
| Preset | Description |
|---|---|
agent-safe |
Read all files, write to /output and /tmp, hide secrets (.env, *.key, etc.) |
read-only |
Read all files, no write access |
full-access |
Full read/write access to all files |
development |
Full access except secrets |
view-only |
Can see file names but not read content |
from sandbox_rls import list_presets, get_preset, extend_preset
# List all available presets
print(list_presets()) # ['agent-safe', 'development', 'full-access', 'read-only', 'view-only']
# Extend a preset with custom rules
rules = extend_preset(
"agent-safe",
additions=[{"pattern": "/custom/**", "permission": "write"}],
)
Error Handling
The SDK provides semantic exception classes:
from sandbox_rls import Sandbox, SandboxError, CommandTimeoutError, CommandExecutionError
try:
with Sandbox.from_local("./my-project") as sandbox:
result = sandbox.run("python main.py", timeout=30, raise_on_error=True)
except CommandTimeoutError as e:
print(f"Command timed out: {e}")
except CommandExecutionError as e:
print(f"Command failed with exit code {e.exit_code}: {e.stderr}")
except SandboxError as e:
print(f"Sandbox error: {e}")
Low-Level API
For fine-grained control, use the SandboxClient directly:
from sandbox_rls import SandboxClient, RuntimeType, ResourceLimits
# Connect to the sandbox server
client = SandboxClient(endpoint="localhost:9000")
# Create a codebase (file storage)
codebase = client.create_codebase(name="my-project", owner_id="user_123")
# Upload a file
client.upload_file(codebase.id, "hello.py", b'print("Hello, World!")')
# Create a sandbox with permissions and Docker runtime
sandbox = client.create_sandbox(
codebase_id=codebase.id,
permissions=[
{"pattern": "**/*.py", "permission": "read"},
{"pattern": "/docs/**", "permission": "write"},
],
runtime=RuntimeType.DOCKER,
image="python:3.11-slim",
resources=ResourceLimits(memory_bytes=256 * 1024 * 1024),
)
# Start the sandbox
client.start_sandbox(sandbox.id)
# Execute a command
result = client.exec(sandbox.id, command="python hello.py")
print(result.stdout) # Output: Hello, World!
# Clean up
client.destroy_sandbox(sandbox.id)
client.delete_codebase(codebase.id)
Features
Permission Levels
The SDK supports four permission levels:
| Level | Description |
|---|---|
none |
Completely invisible, not shown in ls |
view |
Visible in ls, but cannot read content |
read |
Can read file content |
write |
Can modify file |
Permission Patterns
You can use glob patterns, directory paths, or file paths:
from sandbox_rls import PermissionRule, Permission, PatternType
permissions = [
# Glob pattern - matches all .py files
PermissionRule(pattern="**/*.py", permission=Permission.READ),
# Directory - applies to entire directory
PermissionRule(pattern="/docs/", permission=Permission.WRITE, type=PatternType.DIRECTORY),
# Specific file
PermissionRule(pattern="/config.yaml", permission=Permission.VIEW, type=PatternType.FILE),
]
sandbox = client.create_sandbox(codebase_id=codebase.id, permissions=permissions)
Stateful Sessions
Sessions maintain a persistent shell process that preserves working directory and environment variables:
with client.session(sandbox.id) as session:
session.exec("cd /workspace/src") # Change directory
session.exec("export DEBUG=1") # Set environment variable
session.exec("source venv/bin/activate") # Activate virtualenv
result = session.exec("python main.py") # All above state is preserved
Command Execution
Execute commands with optional stdin, environment variables, and timeout:
from datetime import timedelta
result = client.exec(
sandbox_id=sandbox.id,
command="python script.py",
stdin="input data",
env={"DEBUG": "1"},
workdir="/workspace/src",
timeout=timedelta(seconds=30),
)
print(f"Exit code: {result.exit_code}")
print(f"stdout: {result.stdout}")
print(f"stderr: {result.stderr}")
print(f"Duration: {result.duration}")
Streaming Output
For long-running commands, use streaming:
for chunk in client.exec_stream(sandbox.id, command="long-running-task"):
print(chunk.decode(), end="")
File Operations
# List files
files = client.list_files(codebase.id, path="/src", recursive=True)
for f in files:
print(f"{f.path} - {f.size} bytes")
# Download a file
content = client.download_file(codebase.id, "config.yaml")
print(content.decode())
# Upload a file
result = client.upload_file(codebase.id, "new_file.txt", b"file content")
print(f"Uploaded {result.size} bytes, checksum: {result.checksum}")
Context Manager
Both the high-level Sandbox and low-level SandboxClient support context managers:
# High-level (recommended)
with Sandbox.from_local("./project") as sandbox:
sandbox.run("make test")
# Automatically cleans up sandbox and codebase
# Low-level
with SandboxClient(endpoint="localhost:9000") as client:
sandbox = client.create_sandbox(codebase_id="cb_123")
# ... use the sandbox ...
# Connection is automatically closed
API Reference
High-Level API
Sandbox Class
Sandbox.from_local(path, preset, permissions, runtime, image, resources, ...)- Create sandbox from local directorySandbox.from_codebase(codebase_id, preset, ...)- Create sandbox from existing codebaseSandbox.connect(sandbox_id)- Connect to existing sandboxsandbox.run(command, timeout, env, workdir, raise_on_error)- Execute command (simplified)sandbox.exec(command, stdin, env, workdir, timeout)- Execute command (full API)sandbox.session(shell, env)- Create stateful sessionsandbox.read_file(path)- Read file as stringsandbox.write_file(path, content)- Write filesandbox.list_files(path, recursive)- List filessandbox.start()/sandbox.stop()- Lifecycle controlsandbox.destroy(delete_codebase)- Clean up
Presets
get_preset(name)- Get preset as PermissionRule listget_preset_dicts(name)- Get preset as dict listextend_preset(base, additions, overrides)- Extend presetlist_presets()- List available presetsregister_preset(name, rules)- Register custom preset
Low-Level API
SandboxClient
create_sandbox(codebase_id, permissions, runtime, image, resources, labels, expires_in)- Create sandboxget_sandbox(sandbox_id)- Get sandbox infolist_sandboxes(codebase_id)- List sandboxesstart_sandbox(sandbox_id)- Start sandboxstop_sandbox(sandbox_id)- Stop sandboxdestroy_sandbox(sandbox_id)- Destroy sandboxexec(sandbox_id, command, stdin, env, workdir, timeout)- Execute commandexec_stream(sandbox_id, command, ...)- Execute with streamingcreate_session(sandbox_id, shell, env)- Create sessionsession_exec(session_id, command, timeout)- Execute in sessioncreate_codebase(name, owner_id)- Create codebaseget_codebase(codebase_id)- Get codebase infolist_codebases(owner_id)- List codebasesdelete_codebase(codebase_id)- Delete codebaseupload_file(codebase_id, file_path, content)- Upload filedownload_file(codebase_id, file_path)- Download filelist_files(codebase_id, path, recursive)- List files
Types
RuntimeType- BWRAP, DOCKERResourceLimits- memory_bytes, cpu_quota, cpu_shares, pids_limitPermission- NONE, VIEW, READ, WRITEPatternType- GLOB, DIRECTORY, FILESandboxStatus- PENDING, RUNNING, STOPPED, ERRORSessionStatus- UNKNOWN, ACTIVE, CLOSED
Exceptions
SandboxError- Base exceptionSandboxNotFoundError- Sandbox not foundSandboxNotRunningError- Sandbox not runningCodebaseError- Codebase operation errorCodebaseNotFoundError- Codebase not foundCommandTimeoutError- Command timed outCommandExecutionError- Command failed (non-zero exit)PermissionDeniedError- Permission deniedSessionError- Session operation errorConnectionError- Connection to service failed
Development
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Format code
black sandbox_rls tests
ruff check --fix sandbox_rls tests
# Type check
mypy sandbox_rls
License
MIT
Metadata
Release files for sandbox-rls 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sandbox_rls-0.2.0.tar.gz | 54.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sandbox_rls-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 107.0 kB
Release files / sandbox_rls-0.2.0.tar.gz
| Download URL | sandbox_rls-0.2.0.tar.gz |
|---|---|
| Size | 54.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
516dad1be3cb129dc7eb908f4651f5010fe7caa0a3a42632d55bbba961147d20
|
|
BLAKE2b-256 checksum How to use checksums |
b3a4e43ab12aa1a32f229b29fee29029efd9551d776f76215691a42950c74b2c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Release files / sandbox_rls-0.2.0-py3-none-any.whl
| Download URL | sandbox_rls-0.2.0-py3-none-any.whl |
|---|---|
| Size | 53.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
10aa3c43a53e9f1ef8136ba344b4153a2403be25b23bdbdea6183a5c37802e74
|
|
BLAKE2b-256 checksum How to use checksums |
8355cf6de0454bd45f5142f6304698b3db2aca60d7d92dbc075aa17ae05a8d89
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|