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

# Runtime Selection

> Choose which runtime executes each model — per model, per provider, or per agent

Runtime selection lets you pick which execution backend (Claude Code, Codex CLI, the built-in PraisonAI runtime) runs each model — declared on the model map, not the agent.

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

agent = Agent(
    name="Coder",
    instructions="Write Python code",
    runtime="claude-code",
)
agent.start("Build a CLI tool that lists open PRs")
```

The user chooses a runtime backend for the agent; PraisonAI resolves CLI versus native execution for each model.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Runtime Resolution Order"
        A[Per-model runtime] --> B[Per-provider default]
        B --> C[Auto-selection]
        C --> D[Built-in praisonai]
    end

    classDef model fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef provider fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef auto fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef default fill:#10B981,stroke:#7C90A0,color:#fff

    class A model
    class B provider
    class C auto
    class D default
```

## Quick Start

<Steps>
  <Step title="Simple Usage">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    agent = Agent(
        name="Coder",
        instructions="Write Python code",
        runtime="claude-code"
    )

    agent.start("Build a CLI tool that lists open PRs")
    ```
  </Step>

  <Step title="With Configuration">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent
    from praisonaiagents.runtime import AgentRuntimeConfig

    agent = Agent(
        name="Coder",
        instructions="Write Python code",
        runtime=AgentRuntimeConfig(
            runtime="claude-code",
            config_overrides={"timeout": 120}
        )
    )
    ```
  </Step>
</Steps>

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant Resolver as RuntimeResolver
    participant Registry as RuntimeRegistry
    participant Runtime

    User->>Agent: agent.start("...")
    Agent->>Resolver: resolve(model, provider)
    Resolver->>Resolver: check per-model runtime
    Resolver->>Resolver: fall back to per-provider default
    Resolver->>Resolver: fall back to built-in praisonai
    Resolver->>Registry: resolve(runtime_id)
    Registry-->>Resolver: Runtime instance
    Resolver-->>Agent: RuntimeResolutionResult
    Agent->>Runtime: execute turn
    Runtime-->>User: response
```

**Resolution order** (from `RuntimeResolver`):

1. **Per-model runtime** — `model_runtime_configs[model_name]`
2. **Per-provider default** — `provider_runtime_configs[provider_name]`
3. **Auto-selection** — `resolve_runtime()` picks the highest-priority runtime whose `supports(model_ref)` returns true; see [Agent Runtime Protocol](/docs/features/agent-runtime-protocol)
4. **Built-in default** — `"praisonai"`
5. **Legacy `cli_backend`** — emits `DeprecationWarning`

Provider is inferred from the model name by `resolve_provider()` (core SDK): an explicit `provider/model` prefix wins, then entry-point-registered matchers, then the built-ins below. Since [PraisonAI PR #4651](https://github.com/MervinPraison/PraisonAI/pull/4651) **every** built-in provider resolves through `providers.<name>.runtime_default`, not just anthropic/openai/google.

| Provider id  | Matches model names like                                                             |
| ------------ | ------------------------------------------------------------------------------------ |
| `anthropic`  | any name containing `claude` (`claude-sonnet-4-6`, `us.anthropic.claude-3-5-sonnet`) |
| `openai`     | `gpt-…`, `o1-…`, `o3-…`, `o4-…`, `chatgpt-…`                                         |
| `google`     | `gemini-…`, `gemma-…`                                                                |
| `groq`       | `llama-…` / `mixtral-…` / `gemma2-…` **and** containing `groq`                       |
| `cohere`     | `command-…`, `c4ai-…`                                                                |
| `mistral`    | `mistral-…`, `codestral-…`, `open-mistral-…`, `open-mixtral-…`                       |
| `ollama`     | `ollama/…`                                                                           |
| `deepseek`   | `deepseek-…`                                                                         |
| `xai`        | `grok-…`                                                                             |
| `perplexity` | `pplx-…`, `sonar-…`                                                                  |

<Warning>
  **Before [PraisonAI PR #4651](https://github.com/MervinPraison/PraisonAI/pull/4651), only anthropic / openai / google resolved.** A `providers.groq.runtime_default` (or any provider outside those three) was silently ignored — model-name → provider inference recognised just three vendors. Since #4651 all built-ins resolve, and third parties can register their own vendor via the `praisonaiagents.model_providers` entry-point group — see [Model Provider Plugins](/docs/features/model-provider-plugins).
</Warning>

## Configuration

### Agent parameter forms

| Form                 | Example                                                         | When to use                                 |
| -------------------- | --------------------------------------------------------------- | ------------------------------------------- |
| `str` (runtime ID)   | `runtime="claude-code"`                                         | Most cases                                  |
| `dict`               | `runtime={"runtime": "claude-code", "config_overrides": {...}}` | Inline overrides                            |
| `AgentRuntimeConfig` | `runtime=AgentRuntimeConfig(runtime="claude-code", ...)`        | Full programmatic control                   |
| `None` (default)     | omit                                                            | Use model-map / provider-default / built-in |

Invalid types raise:

```
Invalid runtime type: <type>. Expected bool, str, dict, RuntimeConfig, or AgentRuntimeConfig instance.
```

### YAML — choose your level

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TD
    Start[Need runtime control?] -->|One backend for all models| Prov[Set providers.*.runtime_default]
    Start -->|Different backend per model| Model[Set models.*.runtime]
    Start -->|One agent is special| Agent[Set agent runtime override]
    Prov --> Run[framework: praisonai required]
    Model --> Run
    Agent --> Run

    classDef decide fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef config fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef gate fill:#8B0000,stroke:#7C90A0,color:#fff

    class Start decide
    class Prov,Model,Agent config
    class Run gate
```

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
framework: praisonai   # required — runtime features only work here

providers:
  anthropic:
    runtime_default: claude-code
  openai:
    runtime_default: codex-cli
  groq:
    runtime_default: praisonai        # resolves since PR #4651 (was ignored before)
  deepseek:
    runtime_default: praisonai
  # google, cohere, mistral, ollama, xai, perplexity resolve the same way

models:
  claude-3-sonnet:
    runtime: claude-code
  gpt-4o:
    runtime: praisonai

agents:
  coder:
    role: Developer
    llm: claude-3-sonnet
    # resolves to claude-code from models.claude-3-sonnet.runtime
  reviewer:
    role: Reviewer
    llm: gpt-4o
    runtime: claude-code   # agent-level override beats model/provider
```

### `AgentRuntimeConfig` options

| Option                  | Type             | Default | Description                                                                                   |
| ----------------------- | ---------------- | ------- | --------------------------------------------------------------------------------------------- |
| `runtime`               | `Optional[str]`  | `None`  | Runtime ID (e.g. `"claude-code"`, `"codex-cli"`, `"grok-cli"`, `"gemini-cli"`, `"praisonai"`) |
| `config_overrides`      | `Dict[str, Any]` | `{}`    | Runtime-specific config passed to the runtime factory                                         |
| `provider_default`      | `Optional[str]`  | `None`  | Provider default (YAML `providers.<name>.runtime_default`)                                    |
| `enable_auto_selection` | `bool`           | `True`  | Allow auto-selection step in resolution order                                                 |
| `metadata`              | `Dict[str, Any]` | `{}`    | Free-form metadata                                                                            |

Helper methods: `from_runtime_id(id, **kwargs)`, `from_dict(d)`, `to_dict()`, `merge_overrides(overrides)`, `with_runtime(id)`, `is_explicit()`.

### Built-in runtime IDs

Reference IDs: `"claude-code"`, `"codex-cli"`, `"grok-cli"`, `"gemini-cli"`, `"praisonai"`. Built-in default is `"praisonai"`.

<Note>
  **Subscription-backed runtimes.** Use `runtime="codex-cli"`, `"grok-cli"`, `"gemini-cli"`, or `"claude-code"` when you want to route turns through a CLI that owns its own subscription/OAuth session — no API key needed. See the [CLI Backend Protocol](/docs/docs/features/cli-backend-protocol#built-in-backends).
</Note>

### Framework gate

Runtime features require an adapter whose `SUPPORTS_RUNTIME_FEATURES = True` (the built-in `praisonai` adapter has it). Frameworks without that flag raise:

```
ValueError: Runtime features (runtime, models.*.runtime, providers.*.runtime_default) are not supported for framework='<x>'. Use a framework whose adapter sets SUPPORTS_RUNTIME_FEATURES = True (e.g. framework='praisonai').
```

Third-party adapters opt in by setting `SUPPORTS_RUNTIME_FEATURES = True` on their subclass — see [Capability Flags](/docs/docs/features/framework-adapter-plugins#capability-flags).

### Fail-closed behaviour

Unknown runtime IDs raise — they do **not** silently fall back:

```
Unknown runtime ID: <id>. Available runtimes: [...]. Original error: ...
```

Top-level `RuntimeError` from Agent:

```
Runtime resolution failed for agent='<name>', model='<model>': <err>. Fix the runtime ID/configuration or remove the runtime override.
```

<Warning>
  If you typo a runtime ID, the agent fails at start. This is intentional — silent fallbacks should not ship to production.
</Warning>

## Common Patterns

1. **One provider, one runtime everywhere** — set `providers.<name>.runtime_default` for any built-in vendor (`anthropic`, `openai`, `google`, `groq`, `cohere`, `mistral`, `ollama`, `deepseek`, `xai`, `perplexity`), e.g. `providers.groq.runtime_default: praisonai`.
2. **Mix runtimes per model** — `models.claude-3-sonnet.runtime: claude-code` plus `models.gpt-4o.runtime: praisonai`.
3. **Per-agent override** — agent-level `runtime` beats model/provider config when one role needs different behaviour.

## Migration from `cli_backend`

`cli_backend` still works but emits `DeprecationWarning` (slated for removal in 2.0.0).

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Before (deprecated)
agent = Agent(name="X", cli_backend="claude-code")

# After
agent = Agent(name="X", runtime="claude-code")
```

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Before
agents:
  coder:
    cli_backend: claude-code

# After (preferred — declare at the model)
models:
  claude-3-sonnet:
    runtime: claude-code
agents:
  coder:
    llm: claude-3-sonnet
```

For automatic YAML migration, run `praisonai doctor fix --execute` (or `praisonai doctor runtime --fix --execute`) — see [Runtime Config Migration](/docs/features/doctor-runtime-migration).

Agent-level YAML warning:

```
Agent-level 'cli_backend' in YAML is deprecated. Use 'runtime' parameter or model-scoped runtime configuration instead.
```

<Note>
  **YAML `cli_backend:` fail-closed rules (PR #4111).** The wrapper adapter resolves `cli_backend:` into the `cli_backend` kwarg core `Agent` expects. Two paths now fail loudly instead of silently misrouting:

  * **`process: workflow`** rejects `cli_backend:` — the workflow engine runs agents natively:

    ```
    cli_backend (declared by: <role>) is not supported for 'process: workflow' YAMLs; the workflow engine runs agents natively. Remove cli_backend or convert to a sequential/hierarchical process.
    ```

  * **Unresolvable backend ids** fail closed during resolution:

    ```
    Agent '<role>' requests cli_backend=<cfg> but it could not be resolved. Install praisonai-code and use an id from 'praisonai backends', or remove the cli_backend field.
    ```
</Note>

## Best Practices

<AccordionGroup>
  <Accordion title="Prefer model-map config over agent-level">
    Keep runtime choice with the model, not the role. Use `models.<name>.runtime` unless one agent truly needs an override.
  </Accordion>

  <Accordion title="Always set a provider_default">
    `providers.<name>.runtime_default` makes adding new models painless — new models inherit the provider backend automatically.
  </Accordion>

  <Accordion title="Don't catch the fail-closed error">
    Typo'd runtime IDs should fail at startup, not silently fall back to the built-in runtime.
  </Accordion>

  <Accordion title="Migrate cli_backend to runtime">
    Use the migration table above or `praisonai doctor fix` (the shorter equivalent of `praisonai doctor runtime --fix`) before 2.0.0 removes `cli_backend`.
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Agent Runtime Protocol" icon="plug" href="/docs/features/agent-runtime-protocol">
    Plugin harness registry, register\_runtime, and praisonai.runtimes entry points
  </Card>

  <Card title="Runtime Preflight" icon="shield-check" href="/docs/features/runtime-preflight">
    Validate team YAML before AgentTeam.start()
  </Card>

  <Card title="Model Provider Plugins" icon="plug" href="/docs/features/model-provider-plugins">
    Register custom model-name → provider matchers via entry points
  </Card>
</CardGroup>
