Skip to main content

Dify Sandbox Python SDK

Python SDK for interacting with the Dify Sandbox API.

Installation

pip install -e sdk/

Or install dependencies directly:

pip install requests

Quick Start

from dify_sandbox import DifySandboxClient

# Initialize client
client = DifySandboxClient(
    base_url="http://localhost:8194",
    api_key="your-api-key"
)

# Run Python code
result = client.run_python("print('Hello from sandbox!')")
print(result.stdout)  # Output: Hello from sandbox!

# Run Node.js code
result = client.run_nodejs("console.log('Hello from Node.js!')")
print(result.stdout)  # Output: Hello from Node.js!

# Upload a Python script and run it from the sandbox upload directory
with open("hello.py", "rb") as f:
    uploaded = client.upload_file(f, filename="hello.py")

result = client.run_command(
    command="python3",
    args=[uploaded.filename],
    timeout=30,
)
print(result.stdout)

Features

  • Code Execution: Run Python and Node.js code in a secure sandbox
  • Command Execution: Launch sandbox-approved binaries (e.g. python3, node) against previously uploaded files via the deny-list enforced POST /v1/sandbox/run/command endpoint
  • File Operations: Upload and download files to/from the sandbox
  • Dependency Management: View and manage sandbox dependencies
  • Health Check: Monitor sandbox server status

API Reference

Client Initialization

client = DifySandboxClient(
    base_url="http://localhost:8194",  # Sandbox server URL
    api_key="your-api-key",             # API key for authentication
    timeout=30                          # Request timeout in seconds
)

Code Execution

Run Python Code

result = client.run_python(
    code="print('Hello, World!')",
    preload="",              # Optional: code to run before main code
    enable_network=False     # Optional: enable network access
)

print(result.stdout)    # Standard output
print(result.stderr)    # Standard error
print(result.exit_code) # Exit code (0 = success)

Run Node.js Code

result = client.run_nodejs(
    code="console.log('Hello, World!')",
    preload="",
    enable_network=False
)

print(result.stdout)
print(result.stderr)
print(result.exit_code)

Command Execution

Run a sandbox-approved binary against a file that was previously uploaded to the sandbox via upload_file. The endpoint enforces a deny-list of dangerous commands (shells, rm, sudo, package managers, …) and rejects any argument containing shell metacharacters so the request can never accidentally spawn a shell.

# 1. Upload the script you want to execute
with open("hello.py", "rb") as f:
    uploaded = client.upload_file(f, filename="hello.py")

# 2. Invoke python3 with the uploaded file as an argument
result = client.run_command(
    command="python3",            # Command basename (resolved via PATH)
    args=[uploaded.filename],     # Arguments; cannot contain shell metachars
    work_dir="",                  # "" or "." → sandbox upload_dir; or a relative subdir
    timeout=30,                   # 0 → use the sandbox worker timeout
    enable_network=False,         # Must respect global enable_network setting
)

print(result.stdout)
print(result.stderr)
print(result.exit_code)

work_dir rules

Input Result
"" or "." Resolved to the sandbox upload_dir itself
"scripts" Resolved to <upload_dir>/scripts
<upload_dir> (absolute) Resolved to upload_dir itself
/etc, ../etc, … Rejected with work_dir is invalid: ...

Deny-list

The deny-list is the union of a built-in default (shells, rm, sudo, apt, pip3, npm, …) and the operator-configured blocked_commands list. User configuration can only add entries — never remove them. Commands that match the deny-list, or arguments containing shell metacharacters (|, &, ;, <, >, `, $, *, ?, {, }, ~, !, #, quotes, …) are rejected with a 400 before any process is spawned.

File Operations

Upload File

# Upload from file path
result = client.upload_file("/path/to/file.txt")
print(result.filename)  # Uploaded filename in sandbox
print(result.size)      # File size in bytes

# Upload from file object
with open("local_file.txt", "rb") as f:
    result = client.upload_file(f, filename="custom_name.txt")

Download File

# Download to memory
content = client.download_file("sandbox_file.txt")

# Download to local file
client.download_file("sandbox_file.txt", save_path="local_copy.txt")

Dependency Management

Get Dependencies

deps = client.get_dependencies(language="python3")
print(deps.dependencies)  # List of installed packages

Update Dependencies

response = client.update_dependencies(language="python3")
print(response.message)

Install Dependencies

Install pip packages on demand. Each entry in packages is a standard pip requirement specifier ("requests", "numpy==1.21.0", "pandas>=2.0", ...). The server sanitises the list (deduplicates, rejects unsafe characters and oversized inputs), runs pip install, and rebuilds the read-only sandbox view so the new packages become visible to subsequent /v1/sandbox/run calls without an extra round-trip.

from dify_sandbox import DifySandboxClient

client = DifySandboxClient(base_url="http://localhost:8194", api_key="dify-sandbox")

result = client.install_dependencies(
    packages=["requests", "numpy==1.21.0", "pandas>=2.0"],
)
print(result.packages)  # Cleaned list of packages forwarded to pip

Refresh Dependencies

response = client.refresh_dependencies(language="python3")
print(response.message)

Reset Sandbox

Bring the sandbox back to its post-startup state. The server wipes every entry inside the upload directory, drops the dynamic preload dependency map (so anything added via install_dependencies is forgotten), reinstalls python-requirements.txt and rebuilds the read-only sandbox view. There is no dry-run mode — the request is executed immediately, so any uploaded files and any dynamically installed packages are removed.

from dify_sandbox import DifySandboxClient

client = DifySandboxClient(base_url="http://localhost:8194", api_key="dify-sandbox")

result = client.reset_sandbox()
print(result.files_removed)         # how many files were wiped
print(result.uploads_cleared)       # absolute path of the directory
print(result.dependencies_after)    # dependencies that survive

Health Check

if client.health_check():
    print("Sandbox is healthy")
else:
    print("Sandbox is not responding")

Data Models

RunCodeResponse

@dataclass
class RunCodeResponse:
    stdout: str      # Standard output from code execution
    stderr: str      # Standard error from code execution
    exit_code: int   # Exit code (0 = success)
    error: str       # Sandbox-side error message (empty on success)

RunCommandResponse

@dataclass
class RunCommandResponse:
    stdout: str      # Standard output from the executed command
    stderr: str      # Standard error from the executed command
    exit_code: int   # Exit code (0 = success)
    error: str       # Sandbox-side error message (empty on success)

UploadFileResponse

@dataclass
class UploadFileResponse:
    filename: str  # Filename in sandbox
    size: int      # File size in bytes

DependencyInfo

@dataclass
class DependencyInfo:
    language: str       # Language (python3/nodejs)
    dependencies: list  # List of dependencies

InstallDependenciesResponse

@dataclass
class InstallDependenciesResponse:
    packages: list  # Cleaned list of pip requirement specifiers forwarded to pip

ResetSandboxResponse

@dataclass
class ResetSandboxResponse:
    files_removed: int       # Number of entries removed from upload_dir
    uploads_cleared: str     # Absolute path of the wiped upload directory
    dependencies_after: list # Dependencies that survived the reset (i.e. python-requirements.txt)

### DifySandboxResponse

```python
@dataclass
class DifySandboxResponse:
    code: int       # Response code (0 = success)
    message: str    # Response message
    data: Any       # Response data

End-to-end Example: Upload a Script, Then Run It

from dify_sandbox import DifySandboxClient

client = DifySandboxClient(base_url="http://localhost:8194", api_key="dify-sandbox")

# Local script we want to run inside the sandbox
script = b"""
import sys
print("hello from the sandbox!")
print("args:", sys.argv[1:])
"""

# 1. Upload the script — the server stores it in upload_dir and returns the
#    filename it used (a UUID is appended to avoid collisions).
with open("hello.py", "wb") as f:
    f.write(script)

uploaded = client.upload_file("hello.py")
print("uploaded as:", uploaded.filename)

# 2. Run python3 with the uploaded file as its argument.
result = client.run_command(
    command="python3",
    args=[uploaded.filename],
    timeout=10,
)

assert result.exit_code == 0, result.stderr
print(result.stdout)

Examples

See the examples/ directory for complete usage examples:

  • basic_usage.py - Basic code execution examples
  • file_operations.py - File upload and download examples
  • dependency_management.py - Dependency management examples
  • command_execution.py - Upload a script and run it through the deny-list-enforced run_command endpoint

Error Handling

The SDK raises exceptions for API errors:

try:
    result = client.run_python("invalid code")
except Exception as e:
    print(f"Error: {e}")

run_command raises the same kind of exception when the deny-list rejects the command, when an argument contains shell metacharacters, or when the work directory is invalid — the exception message is the human-readable reason returned by the sandbox.

License

MIT License

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dify_sandbox-1.1.0.tar.gz (11.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dify_sandbox-1.1.0-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file dify_sandbox-1.1.0.tar.gz.

File metadata

  • Download URL: dify_sandbox-1.1.0.tar.gz
  • Upload date:
  • Size: 11.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15

File hashes

Hashes for dify_sandbox-1.1.0.tar.gz
Algorithm Hash digest
SHA256 f846fbca07ca3bf5d3f3d009200663cbfaeae8dcea0fae0316b007870360474b
MD5 0c05cddfbd27e6f04e17a9c63ddb06ea
BLAKE2b-256 d691937b6cb08a829e9a84d6f1638ce40c08ecfc6d2ff893d99ec9bbf6646e8b

See more details on using hashes here.

File details

Details for the file dify_sandbox-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: dify_sandbox-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15

File hashes

Hashes for dify_sandbox-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2310a20241c75d063647901e744a2ca1b84ce3e12407c93383f7e56cd00c976b
MD5 9a108171c2b6f7562eb1b3eec4d0fcda
BLAKE2b-256 944004e66d986cb7e1fbe728e06bc084a93bb743377e442253a3a8cab5e58636

See more details on using hashes here.

Release history Release notifications | RSS feed

1.1.3

2 files

1.1.2

2 files

1.1.1

2 files

This release

1.1.0 This release

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page