Python SDK for AgentFense - A sandbox infrastructure service for AI Agents with fine-grained file permission control
Project description
AgentFense SDK for Python
Python client library for the AgentFense service - a sandbox infrastructure for AI Agents with fine-grained file permission control.
Installation
pip install agentfense
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 agentfense 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 agentfense 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 agentfense 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 agentfense 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 agentfense 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 agentfense 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 agentfense tests
ruff check --fix agentfense tests
# Type check
mypy agentfense
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentfense-0.2.1.tar.gz.
File metadata
- Download URL: agentfense-0.2.1.tar.gz
- Upload date:
- Size: 53.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
291d4b80f6639d218acb5800de4709d8dd48f927a4558c5a56704005994e96a0
|
|
| MD5 |
8a8a9797ca317cb52e93121f468d3c89
|
|
| BLAKE2b-256 |
2d37e9323d1a5c9af1c4571d69c698a0d343b65ca3063ba2791ff927ea76fef3
|
File details
Details for the file agentfense-0.2.1-py3-none-any.whl.
File metadata
- Download URL: agentfense-0.2.1-py3-none-any.whl
- Upload date:
- Size: 52.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
308916d170741ffa0ed0e520331dced86014de2188f1a4b5bba9e9d57daac99e
|
|
| MD5 |
284596e768ef2f3899e79d9a8ad130e7
|
|
| BLAKE2b-256 |
c10cd1b1ff30e194c0cb8e87d74b118a04e8d0ef5e24ae25e2b6ce3b4205f80d
|