Slot as model
In a standard OpenAI request the model field names a specific model. hal0
extends this: the model field may instead name a slot (by its name/alias)
or a virtual role name. hal0 rewrites it to the backing model id and
ensures the right slot is loaded — all before the dispatcher routes the
request.
This lets a client pin a co-resident slot (e.g. always talk to the agent
slot) without knowing or hard-coding which model it currently serves. The alias
is stable across model swaps.
Addressing modes
Section titled “Addressing modes”model value | Resolution |
|---|---|
A chat-slot alias — any enabled type=llm slot, addressed by its own name (canonically agent, the default anchor, and utility, the helper role; legacy agent-hermes still redirects to agent) | Rewritten to the slot’s configured model id. |
A virtual hal0/* role name (hal0/agent, hal0/utility, hal0/npu, or the generalized hal0/<any-enabled-llm-slot>) | Live-resolved to whichever model the role currently maps to. Chat-completions only. |
| A raw registry model id | Used directly; routed to whichever upstream serves it. |
How the rewrite works
Section titled “How the rewrite works”Three steps run before dispatch, all in routes/v1.py:
1. Alias rewrite — _rewrite_chat_slot_alias
Section titled “1. Alias rewrite — _rewrite_chat_slot_alias”Runs for every /v1 request that reaches _dispatch_and_forward (chat,
completions, embeddings, rerankings, audio). The request’s model is checked
against the chat-slot alias map (slot name → configured model id, one entry
per enabled type=llm slot, plus the agent-hermes back-compat redirect). On
a match, hal0:
- replaces
body["model"]with the slot’s model id, and - rewrites the request’s cached body bytes, so any downstream consumer that re-reads the raw request forwards the rewritten model name — not the bare alias.
It is a no-op when the value isn’t a known alias, already equals its own model id, the slot manager is absent, or the config read fails (best-effort — it never blocks the request).
2. Virtual-name live-resolve — _normalize_chat_body (chat completions only)
Section titled “2. Virtual-name live-resolve — _normalize_chat_body (chat completions only)”POST /v1/chat/completions alone also resolves a hal0/* role name against
the currently-loaded slots (LiveSlotResolver), before the thinking-policy
injection. Each virtual name carries an ordered fallback chain — hal0/agent
tries the agent role; hal0/utility tries utility then falls back to
agent; hal0/npu tries npu, then utility, then agent — and hal0/<any enabled llm slot> resolves to (<slot>, agent). If nothing in the chain is
loaded yet, resolution falls back to the configured anchor slot so the caller
can still ensure-load it. This step doesn’t run for /v1/completions,
/v1/embeddings, or the other non-chat endpoints.
3. Backend-aware load — _ensure_backend_for_model
Section titled “3. Backend-aware load — _ensure_backend_for_model”After the alias rewrite, hal0 finds the chat slot that owns the resolved model
id and calls SlotManager.load(slot) before dispatch. This is idempotent
and blocks until the slot is ready, so the model is already loaded under the
slot’s declared device / profile whichever routing path dispatch then
takes. A model with no backing chat slot is left alone and dispatches as-is.
Slot name vs registry ref
Section titled “Slot name vs registry ref”- Slot name / alias — addresses the slot and follows whatever model the slot is configured to serve. Best for clients that want a stable handle.
- Registry model id — addresses the model. The dispatcher checks the registry binding, then warm upstream caches, then a cold-cache prefetch; a known id is routed straight to the upstream serving it.
Interaction with the GPU arbiter
Section titled “Interaction with the GPU arbiter”When the GPU is in exclusive image mode, the backend-aware load step refuses to
lazy-load an LLM back onto the GPU — it raises the structured gpu.image_mode
503 (with a Retry-After) rather than fighting the arbiter and resurrecting a
slot the arbiter just drained.
Related references
Section titled “Related references”- OpenAI-compatible API — the
/v1/*endpoints. - Slot lifecycle — what “loaded under its backend” means.
- hal0 CLI —
hal0 slotto create and configure slots.