Default Model Selection

The CLI auto-selects the best available model from your credentials — no more hardcoded gpt-4o-mini

When you don’t specify a model, the CLI ranks every model your credential unlocks by capability and picks the best one. A one-line notice tells you what was chosen and why. The same resolver drives the SDK Agent(llm=None) path — construct an Agent with no llm= and it picks from your credentials too.

python
import os
from praisonaiagents import Agent

os.environ["OPENAI_API_KEY"] = "sk-..."

# No llm= and only OPENAI_API_KEY set — picks the best stable, chat-callable
# OpenAI model in the catalogue (not gpt-5-pro, not gpt-5-2025-08-07).
agent = Agent(instructions="Summarise the latest release notes.")
agent.start("Give me the top three changes in the last PR.")
Diagram

Default Model Selection

📋 User Request

⚙️ Default Model Selection

✅ Result

Diagram
Default Model SelectionAgentUserDefault Model SelectionAgentUserRequestProcess requestResultResponse
python
from praisonaiagents import Agent

agent = Agent(
    name="Assistant",
    instructions="Help with tasks",
)

agent.start("Summarise the key points from this week")

The user omits --model; the CLI picks the best credential-backed model and prints what it chose.

Diagram

Default Model Selection

📝 Command no –model

🔍 Scan Credentials

⚙️ Pick Best Model

🤖 Agent

✅ Response + Notice

How It Works

Diagram
AgentResolverCLIUserAgentResolverCLIUserpraisonai “task” (no –model)Resolve default modelBest credential-backed modelBuild with chosen modelResponse + “using <model>” notice

Resolution Order

Diagram

Default Model Resolution Order

wins immediately

Not set

Found

Not found

Set

Not set

First present credential

Nothing found

Best id, prefix preserved

Ranking yields nothing

1️⃣ Explicit –model flag\nor config / YAML

✅ Use this model

2️⃣ Most-recently-used\n~/.praisonai/state/model.json

3️⃣ MODEL_NAME or\nOPENAI_MODEL_NAME env var

4️⃣ Credential scan

🏅 Rank that provider’s\nmodels by capability

gpt-4o-mini (fallback)

Degrade to fixed\nrepresentative\n(gpt-4o-mini for OpenAI)

How the ranking works

When only a credential is set, the CLI ranks every model that credential unlocks by capability (tool-use, context, reasoning, vision) and uses the best-available one — not a fixed cheap default.

  • Prefers tool-use (essential for agentic work).
  • Excludes models whose LiteLLM mode is not chat (e.g. OpenAI Responses-API-only ids like gpt-5-pro are filtered out — the Chat Completions path can’t call them). Entries with no mode are kept, so older cached catalogues still work.
  • De-prioritises unstable preview / experimental / -auto ids.
  • De-prioritises dated snapshot ids matching -YYYY-MM-DD or -YYYYMMDD (e.g. gpt-5-2025-08-07, claude-3-5-haiku-20241022) so the stable alias wins.
  • De-prioritises -mini / nano / small / lite / haiku / flash / 3.5-turbo class ids.
  • Then larger max_context, then reasoning, then vision.
  • Non-chat ids by name (embeddings, rerankers, speech, image, moderation, vision-encoder, clip) are also excluded from the chat default.
  • Google/Gemini aliasing: a GEMINI_API_KEY-only run still ranks litellm’s google-labelled Gemini models (and vice-versa).

The ranking returns a bare id, but the provider prefix is preserved — anthropic/<id>, gemini/<id>, cohere/<id>, openrouter/openai/<id>, etc. keep their prefix so runtime routing is unchanged. If ranking yields nothing — including when every candidate was filtered out by the mode or name gates — best_available() returns None and selection degrades to the historical fixed representative (gpt-4o-mini for OpenAI).

Diagram

Capability Ranking

🚫 Non-chat mode\nexcluded

🚫 Non-chat names\nexcluded

🔧 Tool-use

🧱 Stable + non-dated\nnon-preview

📈 Non-mini class

📐 Larger context

🧠 Reasoning

👁️ Vision

✅ Best id

Quick Start

  1. Auto-pick model from credentials

    Set your API key and run any command — no --model needed:

    bash
    export ANTHROPIC_API_KEY=sk-ant-...
    praisonai chat "Tell me a joke"
    No model set; using claude-sonnet-4-5 because ANTHROPIC_API_KEY is present.

    The one-line notice only appears when a provider-inferred default is used (not when using the MRU or an explicit override).

  2. Override for a single run
    bash
    praisonai chat --model gpt-4o "Explain quantum entanglement"

    This model is saved as the most-recently-used and will be the default for the next run.

  3. Pin the model for the project

    Add a .praison.json to your project root:

    json
    {
      "model": "anthropic/claude-3-5-sonnet-20241022"
    }

    Every praisonai command in this directory now uses this model.

  4. Check with praisonai doctor
    bash
    praisonai doctor

    Shows which credentials are present and which model would be selected on the next zero-config run.


Resolution Order

PrioritySourcePersisted as MRU?
1 (highest)--model flag / config / YAML✅ Yes
2Most-recently-used (~/.praisonai/state/model.json)—
3MODEL_NAME or OPENAI_MODEL_NAME env var✅ Yes
4Provider credential probe — capability-ranked best-available for the first present credential (prefix preserved)❌ No
5 (lowest)gpt-4o-mini hard fallback❌ No

Provider-inferred defaults (priority 4) and the gpt-4o-mini fallback (priority 5) are intentionally not persisted as MRU. Persisting them would let a stale default win over fresh credential-based inference on a later run when your available providers have changed.


MRU State

The most-recently-used model is stored at:

~/.praisonai/state/model.json

This honours PRAISONAI_HOME ($PRAISONAI_HOME/state/model.json when set). The legacy ~/.praison/state/model.json is still read as a fallback.

Content:

json
{"model": "claude-sonnet-4-5"}

To reset it (force credential-based re-inference):

bash
rm ~/.praisonai/state/model.json

Or simply run with an explicit --model — that overwrites the MRU automatically.


Best Practices

Pin the model in CI

Don’t rely on auto-selection in automated pipelines. CI environments often have credentials for multiple providers, and the selected model can change if you add or remove a key.

yaml
- name: Run agent task
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
    MODEL_NAME: "anthropic/claude-3-5-sonnet-20241022"
  run: praisonai run task.yaml
Watch the transparency notice in development

The transparency notice (No model set; using X because Y is present.) only fires for provider-inferred defaults. If you see it unexpectedly in a staging environment, your .praison.json or MODEL_NAME env var may not be set.

OPENAI_MODEL_NAME is still honoured

For backward compatibility, the OPENAI_MODEL_NAME environment variable still overrides credential-based inference. If you have a legacy .env with this variable, it takes priority over the credential probe.

Why your zero-config default isn't the newest flagship

Two safety filters keep the default stable and callable:

  • LiteLLM mode filter. Ids the catalogue marks mode: "responses" (Responses API only) are excluded, e.g. gpt-5-pro / gpt-5-pro-2025-10-06. PR #5750.
  • Dated snapshot filter. gpt-5-2025-08-07 and claude-3-5-haiku-20241022 style ids rank below their stable aliases.

To force a specific id anyway, use Agent(llm="…"), --model, or MODEL_NAME / OPENAI_MODEL_NAME.


Related