Skip to main content
Set llm="local" and the agent finds a running local model server, picks the best model on it, and configures itself — no URL, no model name, no key.
Discovery fires only when llm="local". Passing gpt-4o, ollama/llama3.2, or anthropic/… runs zero probes.

Quick Start

1

Discover whatever is running

Start any local server (Ollama, llama.cpp, LM Studio, vLLM), then run four lines.
No OPENAI_BASE_URL, no ollama/ prefix, no model name.
2

Pin an engine, let it pick the model

Name the engine and the resolver chooses the best model on it.
Swap ollama for llama_cpp, lm_studio, vllm, mlx_lm, or transformers_serve.
3

Pin engine and model

Name both for reproducibility.

How It Works

The agent calls the resolver, which probes loopback ports, identifies the engine, selects a model, and returns a target the normal LLM path uses unchanged. The resolver never infers identity from a port — a server matches only when its probe rules hold. This prevents silently talking to the wrong server.

Precedence ladder

The resolver checks sources in a fixed order. The first three are authoritative: if one names a server that does not answer, resolution raises instead of quietly probing another port.

Which option should I pick?

Pick the shortest spec that gives you the certainty you need.

Supported local engines

Identity is decided by probe rules, never by the port — several engines share :8080 and :8000.
llama_cpp and mlx_lm both default to :8080; vllm and transformers_serve both default to :8000. The “absent” rules (e.g. /props absent, /version absent) separate the co-tenants on each port.

Environment Variables

Every source is optional. The three authoritative sources raise when they name an unreachable server.

How model selection works

When you do not name a model, the resolver ranks the server’s models and picks the best one to chat with.
  • Tools-capable models rank first — an agent that can call tools is preferred.
  • Embedding-only models rank last — an embedder cannot hold a conversation, so it is never picked by accident.
  • Ties break by recency — among equally-capable models, the newest wins.
Worked example. On a machine serving qwen3:0.6b, all-minilm, nomic-embed-text, and mxbai-embed-large, the resolver picks qwen3:0.6b — even when the embedders are newer — because the three embed-only models are ranked last.
An explicitly named model must actually be served. llm="local:ollama/does-not-exist" raises ModelNotAvailableError and lists what is available, rather than sending a phantom model to the server.

Errors and gotchas

The resolver fails loudly and specifically instead of guessing.
No server responded on any probed port. Start one (ollama serve, then ollama pull qwen3:0.6b) or set PRAISONAI_LOCAL_BASE_URL to its address.
An authoritative source (the spec, PRAISONAI_LOCAL_BASE_URL, or OLLAMA_HOST) named a server that did not answer. Because it was named explicitly, the resolver does not fall through to another port — it raises so you fix the real target.
The server returned a bodyless HTTP 403. Ollama rejects any request whose Host header is not localhost or an IP address. Set OLLAMA_HOST on the server to allow the origin.
A specific model was requested but the engine does not have it. Pull it or name one from the list the error prints.
The llm="local:..." string was malformed. Expected forms: "local", "local:<engine>", "local:<engine>/<model>", a base URL, or "<url>#<model>".
Setting OLLAMA_HOST to a scheme with no port means port 80, not 11434. The resolver names this exact trap in the error:
Use OLLAMA_HOST=127.0.0.1:11434 (bare host defaults to 11434) instead.

Performance notes

Resolution is opt-in and cheap.
  • Discovery fires only for llm="local" — cloud models trigger zero probes.
  • Importing praisonaiagents does not import the resolver, so import time is unchanged.
  • A full resolve issues a handful of loopback HTTP requests and caches the result for 30 s (PRAISONAI_LOCAL_TTL).
  • The whole scan is budgeted (PRAISONAI_LOCAL_TIMEOUT, default 1.5 s; per-probe 0.4 s), so nothing stalls when no server is listening.

Explicit vs implicit local

llm="local" is the explicit request — you ask for a local model by name. The keyless local-first fallback is the implicit form — it only kicks in when no cloud key is set and you named no model at all.

Models

Provider auto-detection and the full model-selection precedence.

Keyless Local-First Run

The implicit local fallback when no cloud key is set.

Local Models

Point PraisonAI at Ollama or any OpenAI-compatible server.

Ollama

Use Ollama models with PraisonAI.