Auto Mode Providers

Use any of 100+ LLM providers with praisonai –auto via LiteLLM, with automatic OpenAI fallback

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

Diagram

Auto Mode Provider Selection

Yes

No

Success

Transient error

Retry

Exhausted

Terminal error

📝 Topic

🤖 AutoGenerator

LiteLLM\ninstalled?

⚡ LiteLLM\n100+ providers

🔑 OpenAI SDK

✅ agents.yaml

🔁 Retry\nup to 2×

⚠️ Fallback\nto OpenAI

Quick Start

  1. 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)
  2. Unlock 100+ Providers with LiteLLM

    Install LiteLLM to use Anthropic, Google, Azure, Bedrock, Ollama, and more:

    bash
    pip install litellm

    Switch 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"
  3. 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())
  4. 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 raising RuntimeError: 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.

Diagram
LLMToolResolverAutoGeneratorpraisonai –autoLLMToolResolverAutoGeneratorpraisonai –autogenerate(topic)list_available(){tool_name: source, …}prompt(topic, Available Tools=…)agents.yaml (with real tool names)agents.yaml

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.

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

Auto-Generator Safety

Shell-tool gating, prompt allow-list, and workspace containment for --auto.


How It Works

Diagram
OpenAILiteLLMAutoGeneratorCLIUserOpenAILiteLLMAutoGeneratorCLIUseropt[Transient error (429 / 5xx / timeout)]alt[OpenAI fallback succeeds][OpenAI fallback also fails]alt[LiteLLM succeeds][LiteLLM raises exception]praisonai –auto “topic”generate(topic)completion(model, response_format)structured JSONagents.yamlagents created & executedExceptionretry with backoff (up to 2×)Terminal error, or retries exhaustedlog warning + keep LiteLLM errorcore OpenAIClient.parse_structured_output(…)parsed Pydantic objectagents.yamlagents created & executedExceptionraise OpenAIError from LiteLLMError (both tracebacks shown)
StepWhat happens
1. LiteLLM attemptCalls litellm.completion(model=..., response_format=PydanticModel)
1a. Transient-error retryHTTP 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 fallbackIf LiteLLM still raises (terminal error, or retries exhausted), logs a warning and continues
3. OpenAI fallbackDelegates 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 failOpenAIError 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 providersRaises 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.

Diagram

Success

Error

No (auth, bad request, schema)

Yes

Yes

No

⚡ LiteLLM call

✅ agents.yaml

Transient?

⚠️ Fail fast → OpenAI fallback

Retries left?

⏱️ Wait 1s, then 2s\n(max 30s)

SettingValue
Retries2 (3 attempts in total)
Backoff1s, then 2s
Max delay30s
Transient errorsHTTP 408, 429, any 5xx; TimeoutError; ConnectionError; any exception whose class name contains Timeout or Connection
Terminal errorsAuthentication (401), bad request (400), schema / validation — fail on the first attempt
Retry-AfterHonoured 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:

text
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?

Diagram

Yes

No

Yes

Both

Which provider for –auto?

Do you only need\nOpenAI or Azure?

Install openai only\npip install openai

Anthropic, Gemini,\nBedrock, Ollama, etc.?

Install litellm\npip install litellm

Install both\npip install litellm openai\nLiteLLM preferred;\nOpenAI catches errors


Install Matrix

InstalledAuto mode behaviour
openai onlyOpenAI SDK used directly via beta.chat.completions.parse
litellm onlyLiteLLM used; transient errors retry 2× before raising (no fallback)
bothLiteLLM first; transient errors retry 2× before falling back to OpenAI with a warning; terminal errors fall back immediately
neitherImportError: Structured output requires either litellm or openai...

Configuration

Environment variableWhat it does
OPENAI_API_KEYAPI key used by both LiteLLM and OpenAI paths
OPENAI_MODEL_NAMEModel passed to whichever provider runs. For LiteLLM use prefixed names: anthropic/claude-sonnet-4, gemini/gemini-2.0-flash, ollama/llama3
OPENAI_API_BASEForwarded as base_url to the OpenAI client (overrides default endpoint)
ANTHROPIC_API_KEYRequired when OPENAI_MODEL_NAME=anthropic/...
GEMINI_API_KEYRequired when OPENAI_MODEL_NAME=gemini/...
OPENAI_MAX_RETRIESApplied automatically to the OpenAI fallback leg (via the core OpenAIClient). See OpenAI Client Retries for details.
OPENAI_TIMEOUTPer-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.
Auto Module SDK Reference

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 the model key 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 inherits default_llm (the workspace default) at execution time.

Anthropic / Bedrock / Ollama users get a runnable generated workflow with no manual model editing.

yaml
# Before — every agent step hard-coded OpenAI, unusable without an OpenAI key
steps:
  - name: Generate release notes
    agent:
      role: Writer
      model: gpt-4o-mini
yaml
# 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:

bash
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):

bash
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):

bash
pip install litellm
export OPENAI_MODEL_NAME=ollama/llama3
praisonai --auto "generate a release job workflow" --workflow

The 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):

bash
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:

python
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:

bash
pip install litellm openai

LiteLLM 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:

python
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