Skip to content

User Manual Providers

Andrei Andriiuk edited this page Oct 27, 2026 · 2 revisions

User Manual: Providers & Preflight

Screenshots below are from the live deployed instance at ace.strgm-ai.com, which has a configured local-oMLX provider (reached over the internet at omlx.strgm-ai.com, since the box running ace-service has no GPU of its own) and a configured Nebius provider. See Architecture for how routing actually works underneath this page.

LLM Providers

Open LLM Providers (route /providers) to see every configured provider.

The LLM Providers table — Local oMLX and Nebius, both configured

Each row shows the provider's name, its provider key (the stable routing prefix — e.g. nebius, so nebius/<model> always resolves to this row), base URL, default model (lets a bare provider key alone resolve to something runnable), and whether an API key is configured. Use Add provider or the row's edit icon to open the same form:

Field Notes
Name Display name only.
Provider key The stable prefix other config strings use — e.g. nebius.
Base URL The provider's OpenAI-wire-compatible endpoint, with its own trailing /v1.
API key A password field. When editing an existing provider with a key already set, it shows "configured — leave blank to keep it" — the real key is never round-tripped back to the browser, so a blank submission leaves it unchanged and an explicit empty string is the only way to clear it.
Default model Optional — lets nebius alone (with no model suffix) resolve to a real model.

Deleting a provider doesn't break any run that already used it — a finished run's provenance carries a frozen model string, independent of whether the provider row that resolved it still exists.

How a model string resolves

Every model-picking field in the UI (the main job model, reviewer model, trajectory reviewer model, judge model, and each experiment arm's model) is a cascading provider → model selector (ProviderModelPicker): choosing a provider loads its live model list from that provider's own API; for the local provider, that list is additionally merged with model ids seen in past runs, so a model that was used once stays pickable later even if it isn't advertised by a live /models call.

The one difference between the main model field and the reviewer/trajectory-reviewer/judge fields is whether leaving it blank is a legal choice: the main model is required (a run needs something to run against), while the reviewer/judge fields treat blank as "inherit the run's own model" — the picker never forces a selection there. Otherwise, typing is the same everywhere: pick a provider, then a model from that provider's own live list; there's no free-text entry for either field in the current UI.

Underneath the picker, the backend applies two different resolution rules to whatever model string actually arrives — not just from this UI, but from the REST API directly and from historical run data too. See Design Decisions for why they're deliberately different:

  • route(), the main coding-model convention: a bare string with no / is always treated as a local model id; a prefix/model string only routes to an external provider if prefix matches a registered provider key — anything else (an unrecognized prefix, or a local model id that just happens to contain a /) stays local. Never throws.
  • resolveModel(), the reviewer/trajectory-reviewer/judge convention: a blank value falls back to the local default; a bare, recognized provider key expands via that provider's own default model; a bare key for a provider with no default model configured, or an unrecognized bare key, is rejected outright with a clear error rather than silently falling back to something unintended.

Preflight

Open Preflight (route /preflight) for a one-click readiness check before trusting any run.

The Preflight page

Press Run preflight to run a real gradle test against the positive-control fixture in the server's own environment — this is the same JDK pin, the same Docker-outside-of-Docker wiring, and the same build tooling an actual benchmark run would use, verified before the clock on any real job starts (see Design Decisions, rule 14). Each check reports ok / degraded / fatal, and the page as a whole reports runnable or blocked.

On a remote-only deployment like this one, the generic model-server check reports unavailable — this is expected and harmless: Preflight checks a job's own --model, matched against whichever provider it's prefixed with (falling back to the local default only for a bare model name), so this generic view staying "unavailable" doesn't block anything targeting a configured external provider such as nebius/<model>. See DEPLOY.md's smoke-test section for the exact verification sequence an operator runs after first deploying.

Related pages

Clone this wiki locally