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.
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.
Quick Start
- 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") - 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
Resolution order (from RuntimeResolver):
- Per-model runtime —
model_runtime_configs[model_name] - Per-provider default —
provider_runtime_configs[provider_name] - Auto-selection —
resolve_runtime()picks the highest-priority runtime whosesupports(model_ref)returns true; see Agent Runtime Protocol - Built-in default —
"praisonai" - Legacy
cli_backend— emitsDeprecationWarning
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 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-… |
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
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/providerAgentRuntimeConfig 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".
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 requiredthe runtime produced no content; the model returned an empty response or the call failed upstreamThe 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
- One provider, one runtime everywhere — set
providers.<name>.runtime_defaultfor any built-in vendor (anthropic,openai,google,groq,cohere,mistral,ollama,deepseek,xai,perplexity), e.g.providers.groq.runtime_default: praisonai. - Mix runtimes per model —
models.claude-3-sonnet.runtime: claude-codeplusmodels.gpt-4o.runtime: praisonai. - Per-agent override — agent-level
runtimebeats 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).
# Before (deprecated)
agent = Agent(name="X", cli_backend="claude-code")
# After
agent = Agent(name="X", runtime="claude-code")# 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-sonnetFor 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.