Secure WASM runtime to isolate and manage AI agent tasks
Project description
capsule-run
A secure, durable runtime for agentic workflows
Overview
Capsule is a runtime for coordinating AI agent tasks in isolated environments. It is designed to handle long-running workflows, large-scale processing, autonomous decision-making securely, or even multi-agent systems.
Each task runs inside its own WebAssembly sandbox, providing:
- Isolated execution: Each task runs isolated from your host system
- Resource limits: Set CPU, memory, and timeout limits per task
- Automatic retries: Handle failures without manual intervention
- Lifecycle tracking: Monitor which tasks are running, completed, or failed
Installation
pip install capsule-run
Getting started
Create hello.py:
from capsule import task
@task(name="main", compute="LOW", ram="64MB")
def main() -> str:
return "Hello from Capsule!"
Run it:
capsule run hello.py
Use
--verboseto display real-time task execution details.
Integrate Into an Existing Project
The run() function lets you execute tasks programmatically from your application code, no CLI needed.
from capsule import run
result = await run(
file="./capsule.py",
args=["code to execute"]
)
Create capsule.py:
from capsule import task
@task(name="main", compute="LOW", ram="64MB")
def main(code: str) -> str:
return exec(code)
How It Works
Simply annotate your Python functions with the @task decorator:
from capsule import task
@task(name="analyze_data", compute="MEDIUM", ram="512MB", timeout="30s", max_retries=1)
def analyze_data(dataset: list) -> dict:
"""Process data in an isolated, resource-controlled environment."""
return {"processed": len(dataset), "status": "complete"}
The runtime requires a task named
"main"as the entry point. Python can define the main task itself, but it's recommended to set it manually.
When you run capsule run main.py, your code is compiled into a WebAssembly module and executed in a dedicated sandbox.
Response Format
Every task returns a structured JSON envelope containing both the result and execution metadata:
{
"success": true,
"result": { "processed": 5, "status": "complete" },
"error": null,
"execution": {
"task_name": "data_processor",
"duration_ms": 1523,
"retries": 0,
"fuel_consumed": 45000
}
}
Response fields:
success— Boolean indicating whether the task completed successfullyresult— The actual return value from your task (json, string, null on failure etc..)error— Error details if the task failed ({ error_type: string, message: string })execution— Performance metrics:task_name— Name of the executed taskduration_ms— Execution time in millisecondsretries— Number of retry attempts that occurredfuel_consumed— CPU resources used (see Compute Levels)
Documentation
Task Configuration Options
| Parameter | Description | Type | Default | Example |
|---|---|---|---|---|
name |
Task identifier | str |
function name | "process_data" |
compute |
CPU level: "LOW", "MEDIUM", "HIGH" |
str |
"MEDIUM" |
"HIGH" |
ram |
Memory limit | str |
unlimited | "512MB", "2GB" |
timeout |
Maximum execution time | str |
unlimited | "30s", "5m" |
max_retries |
Retry attempts on failure | int |
0 |
3 |
allowed_files |
Folders accessible in the sandbox | list |
[] |
["./data", "./output"] |
allowed_hosts |
Domains accessible in the sandbox | list |
["*"] |
["api.openai.com", "*.anthropic.com"] |
env_variables |
Environment variables accessible in the sandbox | list |
[] |
["API_KEY"] |
Compute Levels
- LOW: Minimal allocation for lightweight tasks
- MEDIUM: Balanced resources for typical workloads
- HIGH: Maximum fuel for compute-intensive operations
- CUSTOM: Specify exact fuel value (e.g.,
compute="1000000")
Project Configuration (Optional)
Create a capsule.toml file in your project root to set default options:
[workflow]
name = "My AI Workflow"
version = "1.0.0"
entrypoint = "src/main.py" # Run `capsule run` without specifying a file
[tasks]
default_compute = "MEDIUM"
default_ram = "256MB"
default_timeout = "30s"
Task-level options always override these defaults.
HTTP Client
Standard requests library isn't compatible with WASM. Use Capsule's HTTP client:
from capsule import task
from capsule.http import get, post
@task(name="fetch", compute="MEDIUM", timeout="30s")
def main() -> dict:
response = get("https://api.example.com/data")
return {"status": response.status_code, "ok": response.ok()}
File Access
Tasks can read and write files within directories specified in allowed_files. Any attempt to access files outside these directories is not possible.
from capsule import task
@task(name="restricted_writer", allowed_files=["./output"])
def restricted_writer() -> None:
with open("./output/result.txt", "w") as f:
f.write("result")
@task(name="main")
def main() -> str:
restricted_writer()
Network Access
Tasks can make HTTP requests to domains specified in allowed_hosts. By default, all outbound requests are allowed (["*"]). Restrict access by providing a whitelist of domains.
Wildcards are supported:
*.example.commatches all subdomains ofexample.com.
from capsule import task
from capsule.http import get
@task(name="main", allowed_hosts=["api.openai.com", "*.anthropic.com"])
def main() -> dict:
response = get("https://api.openai.com/v1/models")
return response.json()
Environment Variables
Tasks can access environment variables to read configuration, API keys, or other runtime settings. Use Python's standard os.environ to access environment variables:
from capsule import task
import os
@task(name="main", env_variables=["API_KEY"])
def main() -> dict:
api_key = os.environ.get("API_KEY")
return {"api_key": api_key}
Compatibility
✅ Supported:
- Pure Python packages and standard library
json,math,re,datetime,collections, etc.
⚠️ Not yet supported:
- Packages with C extensions (e.g
numpy,pandas)
Links
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 Distributions
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 capsule_run-0.6.2.tar.gz.
File metadata
- Download URL: capsule_run-0.6.2.tar.gz
- Upload date:
- Size: 132.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6dff37415648367c969c541ad01951f003f5e7390265c423bcdc6041ce498ad8
|
|
| MD5 |
1a201104c4ee0cc9328f8f8ab0f99d9f
|
|
| BLAKE2b-256 |
075c9841f7f5ed219db1969142f7f6cc9c16cb9ced3617a4c0c710a4fbb5fe92
|
File details
Details for the file capsule_run-0.6.2-py3-none-win_amd64.whl.
File metadata
- Download URL: capsule_run-0.6.2-py3-none-win_amd64.whl
- Upload date:
- Size: 10.2 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70f91100bd9ff1b2ffe24e2261784bc7e80eee967bfbd31fc7482edd5d689819
|
|
| MD5 |
006eaa33f1511885e2b04e6d20f93d0a
|
|
| BLAKE2b-256 |
010c823b714242dd8a58105f9d1b9e0112452a8dd307a0533faf9da364e0162b
|
File details
Details for the file capsule_run-0.6.2-py3-none-manylinux_2_39_x86_64.whl.
File metadata
- Download URL: capsule_run-0.6.2-py3-none-manylinux_2_39_x86_64.whl
- Upload date:
- Size: 10.5 MB
- Tags: Python 3, manylinux: glibc 2.39+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6aec0c20e635379d595fa560a6787f6f0881cf4b9a7c25f35343a8ccadda13f2
|
|
| MD5 |
07ca5fd46381955f50e737d08f7f217d
|
|
| BLAKE2b-256 |
37459e4d5d9a7c2115a411830dd242b823507d7cc36d4b93cc05ba1617153501
|
File details
Details for the file capsule_run-0.6.2-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: capsule_run-0.6.2-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 9.5 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03de6420b4341fc8d2f72c9f89860ea976788f89892594775d30871909081236
|
|
| MD5 |
a3e72f50813f2bbe81d91d5e9fa55608
|
|
| BLAKE2b-256 |
ab462b755862dc51ad62f5f799412c7beb444bc0f8e79c682b1d200cab10094e
|