Skip to content

HTTP API: models

The model catalogue the distribution declares — vendors, canonical model references, typed capabilities, context windows, lifecycle — and the explainable routing over it: what a stated need selects, what stands behind it, and why every excluded model fell out. Declared data; nothing here calls a model or reads a credential's value.

Rendered from docs/generated/openapi.json, which the executable generates from its capability registry and CI refuses stale. The raw document is at /openapi.json; a running server serves the same document at its own /openapi.json and Swagger UI at /swagger.

models

The model catalogue the distribution declares — vendors, canonical model references, typed capabilities, context windows, lifecycle — and the explainable routing over it: what a stated need selects, what stands behind it, and why every excluded model fell out. Declared data; nothing here calls a model or reads a credential's value.

GET /api/v1/models models.list

The model catalogue

Every declared vendor and model, optionally narrowed by vendor, capability word, or one id or alias. Vendors carry whether their named credential variable is set — presence only, never a value. The order is the declaration's, which is also routing's preference order; the catalogue's own findings (a duplicate alias, an undeclared vendor) ride along.

  • query
  • experimental
  • benchmark required
  • cache process (max_entries=4, ttl_seconds=5)
  • MCP tool majordomus_models
  • MCP resource {"name": "models", "uri": "majordomus://models"}
  • $ models list

Query parameters

nametyperequireddescriptionexamples
vendor string no Only this vendor. narrowed: "anthropic"
capability string no Only models declaring this capability word. narrowed: "text"
id string no One model, by canonical id or alias. narrowed: "claude-opus-5"

Try it

The port is whatever the server logged; 8741 is the one it asks for first. The values are the operation's first example.

curl -s "http://127.0.0.1:8741/api/v1/models?vendor=anthropic&capability=text&id=claude-opus-5"

Tested by apps/majordomus-cli/tests/http_serve.rs, which replays the route with these values against a server on a real socket.

Responses

statusbodymeaning
200 ModelsReport The model catalogue: the result.
400 ErrorBody invalid_input: The input does not fit the schema: a parameter of the wrong type, an unknown one, or a value the capability rejects.
404 ErrorBody not_found: The input names something the repository does not hold.
500 ErrorBody internal: The capability failed for a reason of its own; the message names it.
default ErrorBody Any other failure the transport reports: 405 method_not_allowed for another method on this path, 400 invalid_input for a body that is not a JSON object.
GET /api/v1/models/route models.route

Route a need to a model

Decide which declared model a stated need selects: the first in declaration order satisfying every requirement, the qualifying rest as the fallback chain, and every excluded model with the first check it failed. Pure over the catalogue and the input — the same question gets the same answer, and 'why' is in the answer itself.

  • query
  • experimental
  • benchmark required
  • cache disabled
  • MCP tool majordomus_models_route
  • $ models route

Query parameters

nametyperequireddescriptionexamples
require string no Capability words the model must declare, comma-separated: `vision,tools`. default: "text"
min_context integer (uint64) no The least context window, tokens.
vendor string no Only this vendor.
local_only boolean no Only local inference.
model string no A model named outright, by canonical id or alias — still checked against the other requirements.

Try it

The port is whatever the server logged; 8741 is the one it asks for first. The values are the operation's first example.

curl -s "http://127.0.0.1:8741/api/v1/models/route?require=text"

Tested by apps/majordomus-cli/tests/http_serve.rs, which replays the route with these values against a server on a real socket.

Responses

statusbodymeaning
200 RoutingDecision Route a need to a model: the result.
400 ErrorBody invalid_input: The input does not fit the schema: a parameter of the wrong type, an unknown one, or a value the capability rejects.
404 ErrorBody not_found: The input names something the repository does not hold.
500 ErrorBody internal: The capability failed for a reason of its own; the message names it.
default ErrorBody Any other failure the transport reports: 405 method_not_allowed for another method on this path, 400 invalid_input for a body that is not a JSON object.

Schemas

The components only this tag's operations use. Each row is the type's own field, its doc comment the description; a type another page owns links there.

ExcludedModel

object
One model that did not qualify, and exactly why.
propertytyperequireddescription
model string yes The canonical id.
reason string yes The first reason it fell out, in the order the checks run.

Used by RoutingDecision

Inference

"remote" | "local"
Where a vendor's inference runs.
  • remoteAn API over the network.
  • localA runtime on this machine.

Used by VendorView

ModelEntry

object
One model: the canonical reference this repository uses, the vendor's own name for it, and its typed capabilities. Capability words are data the catalogue declares — consumers compare against a requirement list, never against a hardcoded name.
propertytyperequireddescription
id string yes The canonical id, unique in the catalogue: what sessions, configuration and routing name. Stable even when a vendor renames.
vendor string yes The vendor that serves it.
native_id string yes The vendor's own identifier, verbatim.
aliases array of string no Other names that resolve to this model. Aliases live here and nowhere else.
capabilities array of string no Typed capability words: text, vision, tools, structured_output, reasoning, streaming, embeddings — the declared vocabulary, open for a catalogue to extend without a code change.
context_window integer | null no The context window, tokens.
status ModelStatus | null → ModelStatus no The lifecycle standing, when the catalogue declares one. Absent is undeclared: the catalogue admits only facts with provenance, and routing still considers the model, but nothing may say it is available on the catalogue's behalf.
note string | null no One line a person needs when choosing; never pricing — a price the tool cannot verify is a fact it must not state (nothing here fabricates cost data).

Used by ModelsReport

ModelStatus

"available" | "preview" | "deprecated" | "retired"
A model's lifecycle standing, as the catalogue declares it. There is no default: a catalogue entry that declares none has an undeclared standing, which is not the same fact as "available", and no reader may render it as one.
  • availableGenerally available.
  • previewUsable, expected to change.
  • deprecatedStill served, no longer chosen by routing unless named explicitly.
  • retiredGone; kept so an old record's reference still resolves to a row with a story.

Used by ModelEntry

ModelsReport

object
The answer of models.list.
propertytyperequireddescription
count integer (uint) yes How many models matched.
vendors array of VendorView → VendorView yes The vendors, declaration order.
models array of ModelEntry → ModelEntry yes The matching models, declaration order — which is routing's preference order.
diagnostics array of string no The catalogue's own findings: duplicate names, undeclared vendors. Empty is the ordinary case.

Used by models.list

RoutingDecision

object
The routing answer: what was selected, what stands behind it, who fell out and why. The whole decision is derived from the catalogue and the requirements — run it twice, get it twice; there is no state to consult and no health to guess.
propertytyperequireddescription
selected string | null no The selected model's canonical id; None when nothing qualifies.
reason string | null no Why the selected model was selected.
fallbacks array of string no The models that also qualify, in preference order: the fallback chain.
excluded array of ExcludedModel → ExcludedModel no Every model that did not qualify, with its reason.

Used by models.route

VendorView

object
One vendor with whether its credential is configured — presence of the named environment variable and nothing more. No value is read.
propertytyperequireddescription
id string yes The vendor id, unique in the catalogue.
title string yes The human name.
inference Inference → Inference no Where inference runs: remote (an API over the network) or local (a runtime on this machine). Typed here so routing's local_only is data, not a name test.
credential_env string | null no The environment variable whose presence means a credential is configured. Only the name lives here, and only presence is ever reported — no code in this crate reads the value, and the environment cache refuses to hold one.
credential_configured boolean | null no Whether the named credential variable is set in this process's environment. None when the vendor names no variable.

Used by ModelsReport

Searches the titles and descriptions of every page this site publishes.