Stealth previewdocs are early and rough. Please don't share publicly.
New Theory
DocsAPIModels
ReferenceModels

Models

Per-model wire contracts — the shapes the NT inference API enforces for each base model.

View as Markdown

Draft — pending review.

This page hasn't been reviewed yet. Content may change before it's considered ready.

The NT inference API supports multiple base models. Each base has a different input shape — different state dimensions, different camera names, different image resolution. These per-model shapes are the contract.

When you call Robot(model="so101").run(...), the API resolves the model, reads its contract, and validates your first observation frame against it. If the shapes don't match, the connection closes with code 4422 before any inference runs.

What a contract is

A contract declares five things about a model's wire interface:

FieldTypeWhat it means
state_shapelist of intExpected dimensions of the joint-state vector your read_state() callback returns
state_dtypestrExpected dtype ("float32")
camerasobject{required: [...], expected: [...]}required camera keys must be present in your images dict (missing one closes 4422); an expected camera key missing at the first frame zero-fills, and dropping it after that closes 4422
image_shapelist of intExpected shape of each camera array, CHW ([C, H, W])
action_shapelist of intShape of each action chunk the server returns ([horizon, action_dim])

The first four fields are checked on your first observation frame. action_shape is informational — the server outputs it, not you.

How to read the contract for your model

curl -H "Authorization: Bearer $NT_API_KEY" \
  https://nt-registry-production.up.railway.app/v1/models/ft_6341c5_d13da9

The response includes the full contract block. Fine-tune entries return the resolved contract inherited from their base. The registry is an always-on service — the curl returns in about a second without waking the GPU container.

Coercion within a contract

The API coerces missing data within a contract, but not for every camera, and only at the first frame. If your images dict is missing a camera listed in cameras.expected (and not in cameras.required) on that first frame, the server fills that slot with zeros and the connection stays alive. A camera missing from cameras.required at the first frame closes 4422contract_mismatch.camera_missing — instead. Once a camera has sent a frame, dropping it later closes 4422contract_mismatch.camera_dropped — even if it was only ever listed in cameras.expected.

Coercion does not apply across contracts. An [8]-dimensional state vector sent to a model expecting [14] closes 4422, not coerced.

Choosing a model

Pick the model whose embodiment matches your hardware.

  • MA2-SO-101 — SO-101 single-arm, 6D state, 2 cameras

On this page