Auto Mode Providers
Use any of 100+ LLM providers with praisonai –auto via LiteLLM, with automatic OpenAI fallback
from praisonaiagents import Agent
agent = Agent(name="generator", instructions="Auto-generate content using configured providers.")
agent.start("Generate a product description for a smart speaker.")Auto mode picks a provider for you: LiteLLM first (100+ providers), OpenAI as a safety net. The user describes a task in auto mode; the generator picks LiteLLM or falls back to OpenAI and writes the resulting agents YAML.
Quick Start
- Default (OpenAI only)
Install PraisonAI and set your OpenAI key:
bash pip install "praisonai-frameworks[crewai]"bash export OPENAI_API_KEY=sk-...Run auto mode:
bash praisonai --auto "research AI trends"Or programmatically:
python from praisonai import AutoGenerator generator = AutoGenerator(topic="research AI trends") result = generator.generate() print(result) - Unlock 100+ Providers with LiteLLM
Install LiteLLM to use Anthropic, Google, Azure, Bedrock, Ollama, and more:
bash pip install litellmSwitch to Anthropic Claude:
bash export ANTHROPIC_API_KEY=sk-ant-... export OPENAI_MODEL_NAME=anthropic/claude-sonnet-4 praisonai --auto "research AI trends"Switch to Google Gemini:
bash export GEMINI_API_KEY=... export OPENAI_MODEL_NAME=gemini/gemini-2.0-flash praisonai --auto "research AI trends"Switch to a local Ollama model:
bash export OPENAI_MODEL_NAME=ollama/llama3 praisonai --auto "research AI trends" - Programmatic Use (Sync & Async)
Both sync and async paths honour the LiteLLM → OpenAI fallback:
python from praisonai import AutoGenerator generator = AutoGenerator(topic="summarise recent AI papers") agents_yaml = generator.generate() print(agents_yaml)Async version:
python import asyncio from praisonai import AutoGenerator async def main(): generator = AutoGenerator(topic="summarise recent AI papers") agents_yaml = await generator.agenerate() print(agents_yaml) asyncio.run(main()) - Calling from an existing event loop (FastAPI, Jupyter)
AutoGenerator.generate()can now be called from inside a running event loop — it offloads to a worker thread automatically instead of raisingRuntimeError: This event loop is already running.python from fastapi import FastAPI from praisonai import AutoGenerator app = FastAPI() @app.get("/generate") async def generate(topic: str): generator = AutoGenerator(topic=topic) # Safe to call .generate() here — no RuntimeError agents_yaml = generator.generate() return {"yaml": agents_yaml}Prefer
await generator.agenerate()when you are already in an async context — it avoids the thread-offload overhead. The sync.generate()form is provided as a safe fallback.
Tool inventory in --auto
praisonai --auto shows the planner a live list of installed tools, sourced from the canonical ToolResolver. What the planner sees always matches what your agents can actually call at run time — no drift.
If the resolver is unavailable (e.g. praisonai_tools and praisonaiagents.tools both fail to import), the planner falls back to a frozen list so --auto still produces a working plan.
One warm resolver cache per run. The AutoGenerator planning step and the downstream AgentsGenerator execution step share the same context-local resolver — installed-tool discovery only runs once per --auto invocation.
Safe by Default
praisonai --auto treats your topic as untrusted input, so shell tools stay opt-in and the generation prompt is fenced against injection.
# No shell tool is added — the topic never asks for code execution
praisonai --auto "research AI trends"execute_command is attached only when the topic matches a code_execution keyword (execute, run code, python, script, command, shell), and a server-side gate strips it from any role whose task did not trigger that intent.
Shell-tool gating, prompt allow-list, and workspace containment for --auto.
How It Works
| Step | What happens |
|---|---|
| 1. LiteLLM attempt | Calls litellm.completion(model=..., response_format=PydanticModel) |
| 1a. Transient-error retry | HTTP 408/429/5xx, timeouts, and connection errors on the LiteLLM leg are retried up to 2× with 1s → 2s exponential backoff, capped at 30s. Retry-After is honoured. Terminal errors (auth, bad request, schema) fail fast. |
| 2. Runtime fallback | If LiteLLM still raises (terminal error, or retries exhausted), logs a warning and continues |
| 3. OpenAI fallback | Delegates to the core-owned OpenAIClient.parse_structured_output(...), which calls beta.chat.completions.parse under the hood. Inherits OPENAI_MAX_RETRIES and OPENAI_TIMEOUT automatically. |
| 3a. Both providers fail | OpenAIError is raised with __cause__ = LiteLLMError. The traceback shows both provider failures via Python’s raise ... from chaining, so users can debug the LiteLLM cause without inspecting log files. |
| 4. No providers | Raises ImportError with install instructions |
Automatic Retries on LiteLLM
A transient rate limit or server error no longer breaks praisonai --auto — the LiteLLM leg retries before anything else happens.
| Setting | Value |
|---|---|
| Retries | 2 (3 attempts in total) |
| Backoff | 1s, then 2s |
| Max delay | 30s |
| Transient errors | HTTP 408, 429, any 5xx; TimeoutError; ConnectionError; any exception whose class name contains Timeout or Connection |
| Terminal errors | Authentication (401), bad request (400), schema / validation — fail on the first attempt |
Retry-After | Honoured when the provider sends it, as delta-seconds ("5") or an HTTP-date ("Wed, 15 Oct 2026 09:00:00 GMT") |
Each retry logs a warning:
Transient LLM error (<exc>); retrying in <delay>s (attempt N/2).When retries run out, the existing OpenAI fallback runs and the LiteLLM error is chained as the cause.
Which Provider Should I Use?
Install Matrix
| Installed | Auto mode behaviour |
|---|---|
openai only | OpenAI SDK used directly via beta.chat.completions.parse |
litellm only | LiteLLM used; transient errors retry 2× before raising (no fallback) |
| both | LiteLLM first; transient errors retry 2× before falling back to OpenAI with a warning; terminal errors fall back immediately |
| neither | ImportError: Structured output requires either litellm or openai... |
Configuration
| Environment variable | What it does |
|---|---|
OPENAI_API_KEY | API key used by both LiteLLM and OpenAI paths |
OPENAI_MODEL_NAME | Model passed to whichever provider runs. For LiteLLM use prefixed names: anthropic/claude-sonnet-4, gemini/gemini-2.0-flash, ollama/llama3 |
OPENAI_API_BASE | Forwarded as base_url to the OpenAI client (overrides default endpoint) |
ANTHROPIC_API_KEY | Required when OPENAI_MODEL_NAME=anthropic/... |
GEMINI_API_KEY | Required when OPENAI_MODEL_NAME=gemini/... |
OPENAI_MAX_RETRIES | Applied automatically to the OpenAI fallback leg (via the core OpenAIClient). See OpenAI Client Retries for details. |
OPENAI_TIMEOUT | Per-request timeout (float seconds) applied automatically to the OpenAI fallback leg (via the core OpenAIClient). Unset keeps the SDK default of 600s. See OpenAI Client Timeout. |
Full API reference for AutoGenerator, WorkflowAutoGenerator, and BaseAutoGenerator
Job-workflow generation honours your configured model
The praisonai --auto ... --workflow job-workflow generator now emits YAML that matches your configured model instead of hard-coding gpt-4o-mini:
- The generation prompt advertises the workspace’s configured model (
config_list[0]["model"]) to the LLM, and instructs it: “Do NOT invent model names. If unsure, omit themodelkey entirely and it will inherit the workspace default.” - The YAML writer only pins
model:on an agent step when the generator supplied a real value. When the model is omitted, the step inheritsdefault_llm(the workspace default) at execution time.
Anthropic / Bedrock / Ollama users get a runnable generated workflow with no manual model editing.
# Before — every agent step hard-coded OpenAI, unusable without an OpenAI key
steps:
- name: Generate release notes
agent:
role: Writer
model: gpt-4o-mini# After — model is omitted (inherits your workspace default), or names your configured model
steps:
- name: Generate release notes
agent:
role: Writer
# no model: → inherits default_llm (e.g. ollama/llama3)Common Patterns
Switch from OpenAI to Anthropic:
pip install litellm
export ANTHROPIC_API_KEY=sk-ant-...
export OPENAI_MODEL_NAME=anthropic/claude-sonnet-4
praisonai --auto "write a market analysis report"Run against a local Ollama model (no cloud keys needed):
pip install litellm
# Ollama must be running locally on port 11434
export OPENAI_MODEL_NAME=ollama/llama3
praisonai --auto "summarise today's news"Generate a job workflow on Ollama (emitted YAML matches your model):
pip install litellm
export OPENAI_MODEL_NAME=ollama/llama3
praisonai --auto "generate a release job workflow" --workflowThe generated workflow YAML either omits model: (steps inherit ollama/llama3 from the workspace) or names ollama/llama3 directly — it runs without an OpenAI key, where previously every step said model: gpt-4o-mini and failed at execution.
Belt-and-braces production setup (LiteLLM + OpenAI fallback):
pip install litellm openai
export ANTHROPIC_API_KEY=sk-ant-...
export OPENAI_API_KEY=sk-...
export OPENAI_MODEL_NAME=anthropic/claude-sonnet-4
# LiteLLM runs first; transient errors retry on LiteLLM, and only after retries are exhausted does the call fall back to OpenAI
praisonai --auto "generate a weekly status report"Async programmatic use:
import asyncio
from praisonai import AutoGenerator
async def run():
async with AutoGenerator(topic="competitor analysis") as gen:
yaml_config = await gen.agenerate()
print(yaml_config)
asyncio.run(run())Best Practices
Install both litellm and openai in production
Install both packages so transient LiteLLM failures (rate limits, network blips, provider outages) don’t break agent generation:
pip install litellm openaiLiteLLM retries transient errors first; OpenAI catches whatever is still failing.
Watch logs for the fallback warning
The warning LiteLLM structured completion failed (...); falling back to OpenAI SDK. means LiteLLM silently degraded. Check: – Is your provider API key set correctly? – Does the model support response_format (structured output)? – Is the provider having an outage?
Retries log a separate, earlier warning on every attempt: Transient LLM error (...); retrying in Ns (attempt N/2). The fallback warning fires once — when retries are exhausted, or immediately on a terminal error.
Investigate before relying on the fallback long-term.
If BOTH providers fail, you no longer need to read the log — the raised exception’s __cause__ now holds the original LiteLLM traceback.
Pin model names in config_list for concurrent generators
If your code runs multiple AutoGenerator instances in parallel, set model names in config_list rather than OPENAI_MODEL_NAME to avoid environment variable races:
from praisonai import AutoGenerator
gen = AutoGenerator(
topic="topic",
config_list=[{
"model": "anthropic/claude-sonnet-4",
"api_key": "sk-ant-...",
}]
)Do not import litellm at module scope
Lazy loading is on by default — litellm is never imported at module load time. Do not add import litellm at the top of your files. Let AutoGenerator pull it in on demand. This keeps startup fast and avoids import-time side effects.
Related
Command-line reference for praisonai --auto
Automatically create and run agents from a prompt
Auto-Generator SafetyShell-tool gating, prompt allow-list, and workspace containment
Structured OutputControl agent output format with Pydantic models
YAML WorkflowsThe agents.yaml format generated by auto mode
OpenAI Client RetriesTurn on SDK-level retries for the OpenAI fallback path