Providers
Jan Agent ships no inference engine, so a model always runs somewhere else. A provider is how it gets there.
Adding one
jan config set --provider anthropic --api-key sk-ant-...
Full form:
jan config set \ --provider openai \ --api-key sk-... \ --base-url https://api.openai.com/v1 \ --model gpt-4o \ --model gpt-4o-mini \ --api-type openai
| Flag | Description |
|---|---|
--provider | Provider id, e.g. openai, anthropic, groq. Required |
--api-key | API key |
--base-url | Endpoint base URL |
--model | Model to expose. Repeatable, and replaces any existing list |
--api-type | Wire protocol, openai or anthropic. Defaults to OpenAI-compatible |
Inspecting
jan config list # configured providers as JSON, keys redactedjan config path # where that file livesjan cli models list
jan config list can report no providers while jan cli models list returns plenty. That isn't a
bug - the second includes providers inherited from Jan Desktop, which aren't stored in
~/.jan/config.toml.
Inside the console, /config shows the same thing read-only, and /model switches model on the
spot.
From the console
/settings > providers manages the same ~/.jan/config.toml entries interactively:
- a opens an add form (
name,base url,api key, space-separatedmodels) - Enter edits the highlighted provider, prefilled - except the API key, which shows
(unchanged)and is kept as stored unless you type into the field. Typing replaces the key; blanking the field out clears it (for an endpoint that dropped auth) - d pressed twice deletes the highlighted provider
The name is read-only while editing, so an entry can never be orphaned. Inside a form, arrow keys
move between fields and k/j type as ordinary characters (API keys contain
them). The base URL must be https://, or http:// for a localhost endpoint, so a key is never
sent over a plaintext remote connection.
A provider saved with no models is queried for its GET /models the next time you open /model,
and the discovered ids are persisted - so a bare provider becomes selectable immediately.
Tokamak
Signing in avoids managing a key yourself:
jan login
Or /login from inside the console. The key is saved to ~/.jan/config.toml.
Where settings come from
Four sources, each beating the ones above it:
| Source | Notes | |
|---|---|---|
| 1 | ~/.jan/config.toml | The base, and the only file jan config set writes |
| 2 | Jan Desktop's settings.json | Inherit-only. Adds providers you haven't configured here, never overwrites one you have, and is never written back to |
| 3 | [provider] in a project's agent.toml | An explicit per-project choice, so it wins over both |
| 4 | --provider / --api-key, or JAN_API_KEY / <PROVIDER>_API_KEY | The most explicit and most ephemeral signal |
The useful consequence: Jan Desktop fills in providers for free without ever clobbering something you set deliberately, a project can pin its own provider without touching your global setup, and a single run can override everything.
Your own hardware
Any OpenAI-compatible endpoint works, which includes a model running locally. Jan Desktop's local API server is the easy path:
jan config set \ --provider local \ --base-url http://localhost:6767/v1 \ --model my-local-model
Nothing leaves your machine in that setup - Jan Desktop runs the model, Jan Agent drives it.
Per-project override
For a project that must use a specific provider, put it in agent.toml:
[provider]name = "openai"api_key = "sk-..."base_url = "https://api.openai.com/v1"models = ["gpt-4o"]
That file usually gets committed. Prefer leaving api_key out of it and keeping the key in
~/.jan/config.toml or the environment.
Removing one
jan config unset --provider openai