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.
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.")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.
How It Works
Resolution Order
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
modeis notchat(e.g. OpenAI Responses-API-only ids likegpt-5-proare filtered out — the Chat Completions path can’t call them). Entries with nomodeare kept, so older cached catalogues still work. - De-prioritises unstable preview / experimental /
-autoids. - De-prioritises dated snapshot ids matching
-YYYY-MM-DDor-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-turboclass 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’sgoogle-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).
Quick Start
- Auto-pick model from credentials
Set your API key and run any command — no
--modelneeded: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).
- 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.
- Pin the model for the project
Add a
.praison.jsonto your project root:json { "model": "anthropic/claude-3-5-sonnet-20241022" }Every
praisonaicommand in this directory now uses this model. - Check with praisonai doctor
bash praisonai doctorShows which credentials are present and which model would be selected on the next zero-config run.
Resolution Order
| Priority | Source | Persisted as MRU? |
|---|---|---|
| 1 (highest) | --model flag / config / YAML | ✅ Yes |
| 2 | Most-recently-used (~/.praisonai/state/model.json) | — |
| 3 | MODEL_NAME or OPENAI_MODEL_NAME env var | ✅ Yes |
| 4 | Provider 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.jsonThis honours PRAISONAI_HOME ($PRAISONAI_HOME/state/model.json when set). The legacy ~/.praison/state/model.json is still read as a fallback.
Content:
{"model": "claude-sonnet-4-5"}To reset it (force credential-based re-inference):
rm ~/.praisonai/state/model.jsonOr 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.
- name: Run agent task
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
MODEL_NAME: "anthropic/claude-3-5-sonnet-20241022"
run: praisonai run task.yamlWatch 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
modefilter. Ids the catalogue marksmode: "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-07andclaude-3-5-haiku-20241022style ids rank below their stable aliases.
To force a specific id anyway, use Agent(llm="…"), --model, or MODEL_NAME / OPENAI_MODEL_NAME.