Skip to main content

Management API — Endpoint Index

A single-page index of every /api endpoint. Each area has a dedicated page with request/response examples — follow the section links.

All endpoints return the management envelope: {success, data, error}.

Models (/api/models) — full reference​

EndpointMethodDescription
/api/modelsGETList all models
/api/modelsPOSTDownload a model (HF or local path)
/api/models/previewPOSTPreview model metadata & memory estimates
/api/models/{id}GETGet model details
/api/models/{id}DELETEDelete model from disk
/api/models/{id}/loadPOSTLoad model to GPU
/api/models/{id}/unloadPOSTUnload model from GPU
/api/models/{id}/lockPOSTLock model (prevent unload)
/api/models/{id}/unlockPOSTUnlock model
/api/models/{id}/cancelPOSTCancel in-progress download
/api/models/{id}/leasePOSTLease the resident model (returns lease_id once)
/api/models/{id}/leaseGETLive lease and last ended lease (never the ID)
/api/models/{id}/lease/renewPOSTRenew (header X-miLLM-Lease)
/api/models/{id}/leaseDELETERelease (header X-miLLM-Lease)

POST …/load and …/unload read X-miLLM-Lease; see Model lease.

SAEs (/api/saes) — full reference​

EndpointMethodDescription
/api/saesGETList SAEs + attachment status
/api/saes/downloadPOSTDownload SAE from HuggingFace
/api/saes/previewPOSTPreview SAE repository files
/api/saes/attachmentGETSingle-SAE attachment status (incl. steering_apply_count)
/api/saes/attachmentsGETMulti-SAE attachment status — every attached (sae_id, layer) entry, total VRAM and the vram_envelope_mb warning (Feature 12 cross-layer circuit serving)
/api/saes/attach-setPOSTAttach a set of SAEs at once for cross-layer circuit serving — loads only the referenced SAEs (fp16), installs one hook per (sae_id, layer), idempotent per key
/api/saes/{id}GET / DELETEGet / delete an SAE
/api/saes/{id}/compatibilityGETDry-run compatibility check
/api/saes/{id}/attachPOSTAttach to loaded model
/api/saes/{id}/detachPOSTDetach
/api/saes/{id}/cancelPOSTCancel in-progress download
/api/saes/monitoringPOSTConfigure monitoring (alias of /api/monitoring/configure)

Steering (/api/saes/steering) — full reference​

EndpointMethodDescription
/api/saes/steeringGETGet steering status and values
/api/saes/steeringPOSTSet single feature value
/api/saes/steering/batchPOSTSet multiple feature values
/api/saes/steering/enablePOSTEnable steering
/api/saes/steering/disablePOSTDisable steering (keep values)
/api/saes/steering/{idx}DELETERemove single feature
/api/saes/steeringDELETEClear all values & disable

Monitoring (/api/monitoring) — full reference​

EndpointMethodDescription
/api/monitoringGETGet monitoring state
/api/monitoring/configurePOSTConfigure (features, history size, top-k)
/api/monitoring/enablePOSTToggle without reconfiguring
/api/monitoring/historyGET / DELETEActivation history / clear
/api/monitoring/statisticsGET / DELETEFeature statistics / reset
/api/monitoring/statistics/topPOSTTop features by metric

Profiles (/api/profiles) — full reference​

EndpointMethodDescription
/api/profilesGET / POSTList / create
/api/profiles/save-currentPOSTSave live steering as a profile
/api/profiles/activeGETGet active profile
/api/profiles/{id}GET / PATCH / DELETEGet / update (partial) / delete
/api/profiles/{id}/activatePOSTActivate (replaces current steering)
/api/profiles/{id}/deactivatePOSTDeactivate
/api/profiles/{id}/exportGETExport as JSON
/api/profiles/importPOSTImport from JSON

Clusters (/api/clusters) — imported cluster definitions (concepts)​

Clusters are cluster-typed steering documents imported from miStudio (or a Hugging Face pack). One cluster serves at a time, behind a global intensity dial.

EndpointMethodDescription
/api/clustersGETList imported clusters with bound state, warnings and intensity
/api/clusters/importPOSTImport a cluster definition or bundle
/api/clusters/hub/searchGETSearch public cluster packs on Hugging Face
/api/clusters/hub/{repo_id}/definitionsGETList a Hub repo's cluster definitions
/api/clusters/hub/importPOSTImport one definition from a Hub repo
/api/clusters/{cluster_id}/activatePOSTActivate a cluster (hard compatibility gate)
/api/clusters/{cluster_id}/deactivatePOSTDeactivate a cluster
/api/clusters/{cluster_id}DELETEDelete a cluster profile
/api/clusters/active/intensityPUTSet the active cluster's intensity (global λ dial)
/api/clusters/{cluster_id}/intensityPUTSet a specific cluster's intensity (λ)
/api/clusters/{cluster_id}/exportGETRe-export the lossless original definition

Circuits (/api/circuits) — imported multi-layer circuits (concepts)​

Circuits are multi-layer interventions spanning several SAEs, each carrying an evidence rung (0–3). A circuit below rung 2 is refused unless activation passes acknowledge_unvalidated. Serving requires an SAE attached on every member layer (Feature 12 multi-SAE).

EndpointMethodDescription
/api/circuitsGETList imported circuits with evidence rung, layers and serveability (?min_rung=, ?serveable=, ?limit=, ?offset=)
/api/circuits/activeGETThe currently serving circuit(s) and their steering state
/api/circuits/claimsGETWhich circuit holds which layer
/api/circuits/claims/releasePOSTRelease a stuck layer claim
/api/circuits/importPOSTImport a circuit definition
/api/circuits/{circuit_id}/activatePOSTActivate (serve) a circuit — refused UNVALIDATED_CIRCUIT below rung 2 unless acknowledged; CIRCUIT_LAYER_CONTENTION when another circuit already holds a layer
/api/circuits/{circuit_id}/deactivatePOSTStop serving a circuit
/api/circuits/active/intensityPUTSet the active circuit's global intensity (λ) — NO_ACTIVE_CIRCUIT / AMBIGUOUS_ACTIVE_CIRCUIT when zero or several circuits serve
/api/circuits/{circuit_id}DELETEDelete an imported circuit
/api/circuits/{circuit_id}/exportGETExport the raw circuit definition

Circuit sensing (/api/circuit-sensing) — observed edge firings (WebSocket event)​

Records when a served circuit's edges co-activate during generation. This is an observation of firing, not a causal claim — an edge earns a causal reading only from rung-2 edge validation upstream in miStudio, never from a sensing event. Instrument, not gate — context text is never sent over WebSocket; fetch event detail for the ±K window.

EndpointMethodDescription
/api/circuit-sensing/statusGETEdge-sensing status: sensable/unsensable edges, per-request overhead, enabled_circuits
/api/circuit-sensing/eventsGETList observed edge firings newest-first (?limit=, ?since=, scoping params)
/api/circuit-sensing/events/{event_id}GETOne observed edge firing incl. the ±K context window (404 CIRCUIT_SENSING_EVENT_NOT_FOUND when pruned/cleared)
/api/circuit-sensing/eventsDELETEClear observed edge firings
/api/circuit-sensing/{circuit_id}/enablePOSTEnable edge sensing for a circuit
/api/circuit-sensing/{circuit_id}/disablePOSTDisable edge sensing for a circuit

Sensing (/api/sensing) — cluster co-activation events (concepts)​

EndpointMethodDescription
/api/sensing/statusGETArmed state, threshold mode, per-request overhead, retention limits, and enabled_clusters (persistent intent, distinct from armed)
/api/sensing/eventsGETEvents newest-first (?profile_id=, ?limit=, ?since=); age-expired rows are pruned on read
/api/sensing/events/{id}GETEvent detail incl. the ±K context window (404 when pruned/cleared)
/api/sensing/eventsDELETEClear events (?profile_id= scopes to one cluster)
/api/sensing/{profile_id}/enablePOSTEnable sensing for a cluster (arms live when that cluster is active with an SAE attached)
/api/sensing/{profile_id}/disablePOSTDisable sensing (disarms live)
/api/sensing/{profile_id}/configPUTRuntime overrides: {"min_k": n} sets the quorum (validated against the sensable-member ceiling), {"min_k": null} restores the default (all sensable members). Stored miLLM-locally — exports stay lossless. Re-arms live

Event detail responses include context_parts {before, span, after} — the window split at the fired span so clients can highlight it (older events predate the field and carry null).

Health & operations (/api/health) — full reference​

EndpointMethodDescription
/api/healthGETLiveness
/api/health/readyGETReadiness
/api/health/detailedGETComponent breakdown, queue state (inference) and the live lease
/api/health/gpusGETPer-card memory, including what miLLM holds
/api/health/inferenceGETActive backend & capabilities
/api/health/metricsGETApp metrics
/api/health/metrics/prometheusGETPrometheus format
/api/health/circuitsGETCircuit breakers
/api/health/circuits/{name}/resetPOSTReset a breaker
/api/health/versionGETVersion

Queue state: the inference block of /api/health/detailed​

A stable, typed contract (Feature 29). The block is always present; when it cannot be read it carries error and the other fields are null. Unmeasured is null, never 0.

FieldTypeMeaning
backend"queue" | "cbm"The serial queue, or continuous batching while it runs
cbm_enabled, cbm_runningboolContinuous batching configured / serving now
queue_pendingintInteractive requests waiting plus holding a slot (it is incremented before the slot is taken — not "waiting" alone)
queue_max_concurrent, queue_max_pendingintMAX_CONCURRENT_REQUESTS, MAX_PENDING_REQUESTS
in_flightint | nullSlots held now. The idle cache release holds a slot too and counts, because a request arriving then waits for it. Batch chunks count once the batch API ships. null while continuous batching runs
queue_waitingint | nullInteractive requests waiting: queue_pending − holding. null while continuous batching runs
batch_backlog_rowsint | nullRows not yet run across in-progress batches; null until a batch API exists (not 0)
estimated_wait_secondsfloat | nullAn estimate of how long a request arriving now waits for a slot
errorstring | nullWhy the block could not be read

The estimate is

estimated_wait_seconds = median(last 50 slot-holding durations) × (queue_waiting + in_flight) / queue_max_concurrent

null with fewer than 3 measured durations, and while continuous batching runs (its requests hold no queue slot). The batch backlog is not added: interactive requests go first at every batch chunk boundary. It is an estimate, not a promise.

/api/health/detailed also carries lease: the live lease on the resident model (model_id, model_name, holder, reason, acquired_at, renewed_at, expires_at, ttl_seconds, seconds_remaining) or null. Never the lease ID. No nvidia-smi runs on this endpoint.

Per-card memory: GET /api/health/gpus​

{"read_at": "2026-10-06T12:00:00Z", "reason": null, "cards": [
{"smi_index": 0, "uuid": "GPU-247a…", "name": "NVIDIA GeForce RTX 3090",
"total_mb": 24576, "used_mb": 17396, "free_mb": 7180,
"torch_index": 0, "torch_measured": true, "millm_allocated_mb": 0, "millm_reserved_mb": 16820,
"engine_memory": null, "processes": [{"pid": 4242, "used_mb": 17100}], "processes_reason": null}]}
  • Total, used and free come from nvidia-smi. torch_index is torch's index, matched by UUID; a card torch cannot see is listed with torch_index: null, not dropped.
  • millm_allocated_mb / millm_reserved_mb are torch's allocator on that card. They are read only on cards miLLM has placed a transformers model on (torch_measured: true); on any other card they are null. Reading a card never creates a CUDA context on it. torch's reserved figure excludes the CUDA context itself, which nvidia-smi counts per process.
  • A resident GGUF model's memory is llama.cpp's, not torch's: its cards say engine_memory: "not_measured_by_torch", and processes (nvidia-smi's per-process list, where the container can read it) is the only measurement of it.
  • Without nvidia-smi the answer is 200 with cards: [] and reason — never zeros.
  • The read runs in a worker thread and takes no request-queue slot, so it is safe to poll during a generation.