Connect a client
Any client that speaks the OpenAI Chat Completions API (or the Responses API) can use ignis. Three settings are all it needs: a base URL, an API key if you set one, and a model id.
The base URL
Section titled “The base URL”| Where the client runs | Base URL |
|---|---|
| On the same machine | http://127.0.0.1:8000/v1 |
In a container started with -p 8000:8000 |
the same, on the host’s address |
The server listens on 127.0.0.1:8000 by default (--server-bind,
IGNIS_SERVER_BIND), so another machine reaches it only if you bind a wider
address; the container image binds 0.0.0.0:8000
(Model and server). The routes are
listed in The API; /v1/docs/ on the running server is the
generated reference.
The API key
Section titled “The API key”With no key set, /v1 needs none, and any value a client insists on sending is
accepted. To require one:
ignis-server --server-api-key sk-... # or IGNIS_SERVER_API_KEY=sk-...ignis-server --server-api-key auto # generate one and print itClients then send Authorization: Bearer sk-...; a request without it is
refused 401 and loads nothing. The Playground’s static pages and /v1/docs/
stay open. /ui/metrics is behind the key like /v1
(Access).
The model id
Section titled “The model id”The id a request names is the served id: qwen3.8-27b unless you started
another model. GET /v1/models shows it first (data[0], active: true).
A request that names no model is served by the loaded one, which is what the
Playground does. A request that names another model the server lists switches
the server to it; see the caution below.
curl http://127.0.0.1:8000/v1/chat/completions \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $IGNIS_SERVER_API_KEY" \ -d '{"model":"qwen3.8-27b","messages":[{"role":"user","content":"Hello"}],"max_tokens":256}'Drop the Authorization header when no key is set. Streaming, the agent lane
and the Responses API are in the examples.
The OpenAI Python SDK
Section titled “The OpenAI Python SDK”from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8000/v1", api_key="sk-...")
reply = client.chat.completions.create( model="qwen3.8-27b", messages=[{"role": "user", "content": "Hello"}], max_tokens=256,)print(reply.choices[0].message.content)The OpenAI JavaScript SDK
Section titled “The OpenAI JavaScript SDK”import OpenAI from "openai";
const client = new OpenAI({ baseURL: "http://127.0.0.1:8000/v1", apiKey: "sk-..." });
const reply = await client.chat.completions.create({ model: "qwen3.8-27b", messages: [{ role: "user", content: "Hello" }], max_tokens: 256,});console.log(reply.choices[0].message.content);With no key set on the server, api_key / apiKey still has to be a
non-empty string for the SDK; ignis ignores it.
Both SDKs honour Retry-After on a 503. That is how a client rides out
engine_full (every lane busy) and model_switching: the header is 1 to 60
seconds, 60 being the most the OpenAI SDK waits (The API).
The Responses API works through responses.create, and its WebSocket mode
through responses.connect (Responses).
A request field ignis cannot honour is a 400 naming it in param, not a
silent drop; if an SDK sends one, that error says which
(Chat completions).
Coding agents: opencode and others
Section titled “Coding agents: opencode and others”Point the agent’s OpenAI-compatible provider at the base URL above, give it the
key if you set one, and name the served id as its model. For opencode, a
provider in opencode.json:
{ "$schema": "https://opencode.ai/config.json", "provider": { "ignis": { "npm": "@ai-sdk/openai-compatible", "name": "ignis (local)", "options": { "baseURL": "http://127.0.0.1:8000/v1" }, "models": { "qwen3.8-27b": { "name": "Qwen3.8-27B", "tool_call": true } } } }, "model": "ignis/qwen3.8-27b", "small_model": "ignis/qwen3.8-27b"}With a key, add "apiKey": "{env:IGNIS_SERVER_API_KEY}" to options. Both
model and small_model name the same id, for the reason below.
Two things matter for agents:
- Subagents. A request can state its lane as
class: "agent"or as an@agentsuffix on the model name (qwen3.8-27b@agent). Anagentrequest never displaces aninteractiveone when the KV pool is full (KV pool). - Long reasoning. Absent
max_tokens, a request generates at most--model-default-max-tokens(38,912) tokens, reasoning included, and ends withfinish_reason: "length"at that point (Chat completions).
Two model ids make the server switch
Section titled “Two model ids make the server switch”The same holds for any front end that picks ids from GET /v1/models, which
lists every servable model.
Open WebUI and other front ends
Section titled “Open WebUI and other front ends”Add ignis as an OpenAI-compatible connection with the base URL above (and the
key). The front end then lists the models from GET /v1/models: the loaded one
first, then every model a request naming it would switch to.
The Playground never causes this: its chat and Decide requests name no model, and it switches only when you ask it to (Load on the Server view, the image tools, the model picker under the prompt box) (Get a model, Switching models).
- Switching models for explicit and implicit switches and what a request sees during one.
- Deadlines for how long a request may run and what it is answered when it runs over.
- Troubleshooting.
