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

Diagram

Runtime Resolution Order

Per-model runtime

Per-provider default

Auto-selection

Built-in praisonai

Quick Start

  1. Simple Usage
    python
    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")
  2. With Configuration
    python
    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}
        )
    )

How It Works

Diagram
RuntimeRuntimeRegistryRuntimeResolverAgentUserRuntimeRuntimeRegistryRuntimeResolverAgentUseragent.start(“…”)resolve(model, provider)check per-model runtimefall back to per-provider defaultfall back to built-in praisonairesolve(runtime_id)Runtime instanceRuntimeResolutionResultexecute turnresponse

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
  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 every built-in provider resolves through providers.<name>.runtime_default, not just anthropic/openai/google.

Provider idMatches model names like
anthropicany name containing claude (claude-sonnet-4-6, us.anthropic.claude-3-5-sonnet)
openaigpt-…, o1-…, o3-…, o4-…, chatgpt-…
googlegemini-…, gemma-…
groqllama-… / mixtral-… / gemma2-… and containing groq
coherecommand-…, c4ai-…
mistralmistral-…, codestral-…, open-mistral-…, open-mixtral-…
ollamaollama/…
deepseekdeepseek-…
xaigrok-…
perplexitypplx-…, sonar-…

Configuration

Agent parameter forms

FormExampleWhen to use
str (runtime ID)runtime="claude-code"Most cases
dictruntime={"runtime": "claude-code", "config_overrides": {...}}Inline overrides
AgentRuntimeConfigruntime=AgentRuntimeConfig(runtime="claude-code", ...)Full programmatic control
None (default)omitUse 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

Diagram

One backend for all models

Different backend per model

One agent is special

Need runtime control?

Set providers.*.runtime_default

Set models.*.runtime

Set agent runtime override

framework: praisonai required

yaml
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

OptionTypeDefaultDescription
runtimeOptional[str]NoneRuntime ID (e.g. "claude-code", "codex-cli", "grok-cli", "gemini-cli", "praisonai")
config_overridesDict[str, Any]{}Runtime-specific config passed to the runtime factory
provider_defaultOptional[str]NoneProvider default (YAML providers.<name>.runtime_default)
enable_auto_selectionboolTrueAllow auto-selection step in resolution order
metadataDict[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".

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.

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.

Empty responses

An empty turn from the built-in runtime always carries an error on the RuntimeResult, so content="" with error=None never happens. The message depends on whether the API key was reachable:

OPENAI_API_KEY environment variable is required
the runtime produced no content; the model returned an empty response or the call failed upstream

The first fires when OPENAI_API_KEY is unset. The second is new: it fires when the key is set but the model returned nothing — a model the key cannot access, exhausted quota, or a provider error swallowed upstream. Check result.error to tell “the model answered nothing” apart from “the call never happened”.

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
# Before (deprecated)
agent = Agent(name="X", cli_backend="claude-code")

# After
agent = Agent(name="X", runtime="claude-code")
yaml
# 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.

Agent-level YAML warning:

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

Best Practices

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.

Always set a provider_default

providers.<name>.runtime_default makes adding new models painless — new models inherit the provider backend automatically.

Don't catch the fail-closed error

Typo’d runtime IDs should fail at startup, not silently fall back to the built-in runtime.

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.


Related