> ## Documentation Index
> Fetch the complete documentation index at: https://starforge.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Register and promote a model

> A named version line across runs — which model is in production, and which run produced it

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf model register alice/support-agent --run run-4f2a91 --notes "kl 0.01, 500 steps"
sf model promote alice/support-agent@3
sf model ls
```

A run id is a fact about an experiment. A model version is a decision — *this* is the one we are
willing to serve. Registering turns the first into the second.

Without it, "which model is in production right now?" and "which run produced the previous version,
and who promoted it when?" are answerable only by somebody who remembers a run id. The registry
turns "I ran 300 jobs" into "we have 5 models in use".

## Three kinds of version, three jobs

A platform ends up with three things called "version". They do not overlap:

| Concept                       | Attached to     | Answers                                            |
| ----------------------------- | --------------- | -------------------------------------------------- |
| Artifact                      | One run         | What this training run produced                    |
| **Model version** (this page) | One named model | Which models we have, and which version each is on |
| Deployment revision           | One deployment  | What configuration this live service is running    |

Canary and rollback live at the **deployment revision** layer; the registry does not duplicate them —
two places able to express "which one is running" would fork immediately.

## Using it

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
# train → export → register as a new version (numbers auto-increment; no naming step)
sf export <RUN_ID>
sf model register qa-assistant --run <RUN_ID> --notes "new data mix"

# look at the version line
sf model ls                    # every model, and which version each runs
sf model ls alice/qa-assistant # the full version line for one model

# promote / retire
sf model promote alice/qa-assistant 3
sf model archive alice/qa-assistant 2
```

Base models and externally supplied weights belong on the line too, otherwise the first entry is missing:

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf model register qa-assistant --path /shared/models/qwen-base --notes "base model"
```

## Deployments follow the registry

Pick "model registry" as a deployment's source and **leave the version empty to follow production**:

```json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
{ "kind": "model", "model": "alice/qa-assistant" }
```

Swapping models then only takes `sf model promote` — the deployment never needs to know which training
run is behind it. Pin a specific one with `"version": 3`.

## Relationship to the evaluation gate

Registering a version requires that the training run **passed its evaluation gate** (when one was
declared). The registry is an asset catalogue; entering a run that explicitly fell short makes the
gate's verdict pointless. Admins can override (audited).

Every version on the line carries the verdict from its training run — a number on a version line
without an evaluation behind it is just a path.

<Note>
  **Versions are immutable**: a version pins a run id and a weight path. To change weights, register a
  new version. If a version already referenced by a deployment could change content, "which version is
  live" would stop being an answerable question.

  **Exactly one production version at a time**: promoting a new one archives the previous. With two
  marked production, the reason this table exists is gone.
</Note>
