Metadata-Version: 2.4
Name: capsule-run
Version: 0.3.0
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Rust
Classifier: Topic :: Security
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Interpreters
Requires-Dist: componentize-py>=0.19.3
Summary: Secure WASM runtime to isolate and manage AI agent tasks
Keywords: webassembly,sandbox,agents,isolation,llm,ai
Author: Capsule Contributors
License: Apache-2.0
Requires-Python: >=3.8
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Homepage, https://github.com/mavdol/capsule
Project-URL: Repository, https://github.com/mavdol/capsule

# 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

```bash
pip install capsule-run
```

## Quick Start

Create `hello.py`:

```python
from capsule import task

@task(name="main", compute="LOW", ram="64MB")
def main() -> str:
    return "Hello from Capsule!"
```

Run it:

```bash
capsule run hello.py
```

## How It Works

Simply annotate your Python functions with the `@task` decorator:

```python
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"}
```

When you run `capsule run main.py`, your code is compiled into a WebAssembly module and executed in a dedicated sandbox.

## 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"]` |

### 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"`)

### HTTP Client

Standard `requests` library isn't compatible with WASM. Use Capsule's HTTP client:

```python
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

The **entry point task** (main) has access to the entire project directory. Sub-tasks have **no filesystem access by default** and must declare `allowed_files` to access specific paths.

Python's standard file operations work normally. Use `open()`, `os`, `pathlib`, or any file manipulation library:

```python
from capsule import task

@task(name="restricted_writer", allowed_files=["./output"])  # Sub-task with limited access
def restricted_writer() -> None:
    with open("./output/result.txt", "w") as f:
        f.write("result")

@task(name="main")  # Has access to entire project
def main() -> str:
    restricted_writer()
```

## 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

- [GitHub](https://github.com/mavdol/capsule)
- [Issues](https://github.com/mavdol/capsule/issues)

