> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Compute Provider Plugins

> Ship your own compute backend as a separate package

Ship a compute backend in its own package and register it under the `praisonai.compute` entry-point group — `run_on=`, `compute=`, and `tools_run_on=` pick it up with no change to the main repo.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Compute Provider Plugin"
        A[📦 Your package] --> B[🔌 praisonai.compute entry point]
        B --> C[🤖 Agent tools_run_on='runpod']
    end

    classDef pkg fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef entry fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff

    class A pkg
    class B entry
    class C agent
```

## Quick Start

**1. Declare the entry point**

Point the `praisonai.compute` group at a class in your package.

```toml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# pyproject.toml — in your plugin package
[project.entry-points."praisonai.compute"]
runpod = "praisonai_compute_runpod:RunpodCompute"
```

**2. Implement the protocol**

Satisfy `ComputeProviderProtocol`. Set an optional `display_name` for a friendly phrase.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# praisonai_compute_runpod/__init__.py

class RunpodCompute:
    display_name = "a Runpod cloud sandbox"  # optional, used in explanations

    async def provision(self, config):
        ...  # start an instance, return an InstanceInfo

    async def execute(self, instance_id, command, timeout=300):
        ...  # run a command, return {"stdout", "stderr", "exit_code"}

    async def shutdown(self, instance_id):
        ...  # tear the instance down

    @property
    def is_available(self):
        return True  # credentials present, SDK importable, etc.
```

**3. Use it like a built-in**

After `pip install`, the name resolves anywhere a compute place is accepted.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(name="runner", instructions="Run code", tools_run_on="runpod")
agent.start("Print the Python version")
```

***

## How It Works

Providers are discovered from the entry-point group and loaded on demand — only when a caller names one.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant Agent
    participant Registry as Compute registry
    participant Plugin as Your provider

    Agent->>Registry: tools_run_on="runpod"
    Registry->>Registry: entry_points(group="praisonai.compute")
    Registry->>Plugin: load RunpodCompute (on demand)
    Plugin-->>Registry: provider instance
    Registry-->>Agent: resolved place
```

| Behaviour | What happens |
| - | - |
| Discovery | Names come from `importlib.metadata.entry_points(group="praisonai.compute")` — no file in the main repo changes. |
| Friendly phrase | A `display_name` class attribute is used in `where_does_it_run()` and `repr(agent)`; without it, the bare name is shown. |
| Failure isolation | Providers load lazily, so a broken plugin fails only for the caller that names it — everyone else is unaffected. |
| `managed ps` | Derives its list from the registry, so a contributed place is listed and stopped automatically — no extra wiring. |

> [!NOTE]
>
> **Built-in names are protected.** The sandbox and managed-backend registries subclass the base `PluginRegistry`, so since [PraisonAI PR #4176](https://github.com/MervinPraison/PraisonAI/pull/4176) an entry point whose name (case-insensitive) matches a built-in provider (`docker`, `local`, `e2b`, …) is skipped and the built-in is kept (a `DEBUG` line notes the collision). This matters most here because these loaders decide **where user code executes** — a pip-installed package cannot silently take over `docker` — the same guard now applies whether the sandbox registry comes from `praisonai-code` (via [PR #4176](https://github.com/MervinPraison/PraisonAI/pull/4176)) or from a standalone `praisonai-sandbox` install (via [PR #4184](https://github.com/MervinPraison/PraisonAI/pull/4184)). Use runtime `register(...)` for a deliberate override. See [Plugin Precedence](https://praison.ai/docs/features/plugin-precedence.md).

***

## Protocol Reference

Implement these on your provider class. `display_name` is optional; the rest are required.

| Member | Kind | Purpose |
| - | - | - |
| `provision(config)` | `async` | Start one instance and return its `InstanceInfo`. |
| `execute(instance_id, command, timeout=300)` | `async` | Run a command; return `{"stdout", "stderr", "exit_code"}`. |
| `shutdown(instance_id)` | `async` | Tear the instance down. |
| `is_available` | property | `True` when the backend can run (credentials, SDK, daemon). |
| `display_name` | class attr | Optional phrase used in explanations instead of the bare name. |

> [!NOTE]
>
> `run_on=` hosts the **whole loop** on a compute place, while `tools_run_on=` moves only the tools. A contributed provider works with both, plus per-agent `compute=`. See [Placement](https://praison.ai/docs/features/placement.md#where-run-on-and-compute-can-point).

> [!NOTE]
>
> The seven built-in providers (`local`, `docker`, `e2b`, `modal`, `daytona`, `flyio`, `tenki`) ship in the [`praisonai-sandbox`](https://praison.ai/docs/features/praisonai-sandbox-package#compute-providers-live-here-too) package as reference implementations behind the same `praisonai.compute` entry-point group your plugin registers under ([PR #4092](https://github.com/MervinPraison/PraisonAI/pull/4092)). See the sandbox-package page for their canonical import locations.

***

## Best Practices

> [accordion] Set display\_name for readable explanations
>
> A bare provider name reads awkwardly in `where_does_it_run()`. Set `display_name = "a Runpod cloud sandbox"` on the class so the phrase reads naturally everywhere the place is described.

> [accordion] Make is\_available cheap and honest
>
> `is_available` is checked before your provider runs. Return `False` when a required key or SDK is missing rather than raising — the caller gets a clear "unavailable" instead of a stack trace.

> [accordion] Keep imports lazy
>
> Import heavy SDK dependencies inside your methods, not at module top level. Providers load on demand, so a missing optional dependency should fail only when the provider is actually used.

> [accordion] Ship the extra alongside the entry point
>
> Declare an optional install extra for your provider's SDK so users can `pip install your-package[runpod]`. This keeps the base install light and the failure mode obvious.

***

## Related

> [card] [Placement](https://praison.ai/docs/features/placement.md)
>
> Where the whole agent, its tools, and its code calls run.

> [card] [Sandbox Backends](https://praison.ai/docs/features/sandbox-backends.md)
>
> The sibling `praisonai.sandbox` entry-point group for `Agent(sandbox=…)`.

> [card] [Managed Backend Plugins](https://praison.ai/docs/features/managed-backend-plugins.md)
>
> Register a hosted agent runtime under `praisonai.managed_backends`.

> [card] [Reclaim Stray Sandboxes](https://praison.ai/docs/features/reclaim-stray-sandboxes.md)
>
> `managed ps` lists contributed places automatically.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.