Documentation menu

Import from Hugging Face

Point the checkpoint field at a public model repo, name the runtime, and evaluate — no export step, no container build.

Hugging Face

If your policy already speaks a known runtime, this is the shortest path onto hardware: Policy.checkpoint(hf=..., runtime=...) names a Hugging Face model repo and one of the managed runtimes — openpi or lerobot — and Roborama fetches the checkpoint and serves it GPU-adjacent to the cell. No export, no Dockerfile, no server of yours in the loop.

Prerequisites

A model repository, not a dataset repository. The Hub hosts both kinds under the same naming scheme: a model repo holds weights and config, a dataset repo holds training episodes. The hf: field must point at the model kind.

Readable without authentication. The hf: field carries a repo id and nothing else — there is no token parameter anywhere in the API. On the Hub side, private repos and gated models are real mechanisms (per-user access approval, fine-grained read tokens scoped to a repo), but Roborama has nowhere to accept a token, so private and gated models cannot be imported directly today. Route those weights through Import from private storage instead: your CI downloads with its own credentials and bakes the checkpoint into a container image.

The runtime's expected files, all present.

RuntimeRequired files
lerobotconfig.json, model.safetensors, train_config.json, plus the processor files (policy_preprocessor.json, policy_postprocessor.json)
openpia training-config name (e.g. pi05_droid) plus the checkpoint directory, with assets/<asset_id>/norm_stats.json present alongside the weights

Compatible hardware. Declare the action_space and observation_contract the checkpoint was trained for, and pin a robot and scene that provide them — aloha2-pro@fw1.1 in cell-a@v1.0 in the example below. Admission checks the declarations against the pins, so a policy that expects droid-3cam needs a cell that has three cameras.

Pin a version in the repo id

There is no revision field — you cannot pin a commit or a tag. The supported convention is version-in-repo-id: publish an immutable release repo per version (acme/skill-v4; the canonical openpi run uses pi/espresso-v7) and never push to it again. Mutating a repo in place makes results unattributable — two runs against the same repo id can be two different policies, and nothing in the record will say so.

Connect

One call packages the checkpoint, one call runs it. The runtime names how the checkpoint is served; the declared contracts say what it needs from the cell.

import and evaluate a Hub checkpoint
import roborama  # reads ROBORAMA_API_KEY from the environment

policy = roborama.Policy.checkpoint(
    hf="acme/act-so101-pick-v2",
    runtime="lerobot",
    inference={"action_horizon": 100, "chunk_size": 100, "temp": 0.0},
    action_space="joint_delta_50hz",
    observation_contract="droid-3cam",
)

run = roborama.run(
    robot="aloha2-pro@fw1.1",
    environment="cell-a@v1.0",
    policy=policy,
    task="pick_place@v1",
    episodes=300,
    max_budget_usd=1000,
)
print(run.result())
# n=300  rate=0.843  ci95=(0.797, 0.881)

The inference dict — action_horizon, chunk_size, temp — is recorded with the run, because reproducibility includes decoding: the same checkpoint at a different action horizon is a different policy as far as your statistics are concerned.

The fetched copy

A checkpoint fetched for a run is cached to schedule and execute that run, and is deleted when the run's data.retention window closes — or immediately on roborama.data.purge(run_id), receipted. Making the source repo private after import does not delete an already-fetched copy; purge does. Retention and the rest of the IP posture live in the data contract.

Validate

Three layers, in the order they can fail:

  1. Local (mock). ROBORAMA_MOCK=1 or mock=True runs the full quote → submit → result loop against packaged fixtures — no API key, no hardware. Catch a malformed call at your desk.
  2. Admission (free). At submission, the declared action_space and observation_contract are checked against the pinned robot and scene. A mismatch returns contract_validation_failed (422), and a rejected submission costs nothing.
  3. Cell startup. The cell fetches the repo and loads the checkpoint under the named runtime. A repo that went private, or a checkpoint missing its files, surfaces here — after admission, before episodes.
the local dry-run
import roborama

# Mock mode: no API key, no hardware. The whole loop runs
# offline against packaged fixtures — or set ROBORAMA_MOCK=1.
client = roborama.Client(mock=True)

quote = client.quote(
    robot="aloha2-pro",
    environment="cell-a",
    episodes=300,
)
print(quote)
# {robot_hours: 10.0, env_hours: 10.0, usd: 860, queue_eta: "2h"}

run = client.run(
    robot="aloha2-pro@fw1.1",
    environment="cell-a@v1.0",
    policy=roborama.Policy.checkpoint(
        hf="acme/act-so101-pick-v2",
        runtime="lerobot",
    ),
    task="pick_place@v1",
    episodes=300,
    max_budget_usd=1000,
)
print(run.result())
# n=300  rate=0.843  ci95=(0.797, 0.881)

Quote

A quote resolves both meters and the dollars before you commit anything: quotes are free, rejected submissions are free, and nothing bills until a motor moves. max_budget_usd is the mid-run hard stop. Meters, tiers, and account-level controls are covered in Billing & budgets.

quote before you run
import roborama  # reads ROBORAMA_API_KEY from the environment

quote = roborama.quote(
    robot="g1-edu-pro",
    environment="kitchen-std",
    episodes=600,
)
print(quote)
# {robot_hours: 20.0, env_hours: 20.0, usd: 3740, queue_eta: "6h"}

Evaluate

Submission is the same run() every packaging plugs into — the Connect example above already passes the policy in. Episodes tick as the cell works through them; follow live with run.watch() or the SSE stream.

watch it live
import roborama  # reads ROBORAMA_API_KEY from the environment

run = roborama.runs.get("run_8842")

for event in run.watch():   # live: episode ticker + WebRTC stream URLs
    print(event.episode, event.status)

stream = roborama.streams.get("cell-g1-04")
print(stream)
# {webrtc: "wss://streams.roborama.com/cells/cell-g1-04/webrtc",
#  mjpeg: "https://streams.roborama.com/cells/cell-g1-04/mjpeg",
#  viewer_token: "vt_7Kq2mHentXw4"}

Inspect results

run.result() carries n, the success rate, and a Wilson 95% interval — the canonical openpi import, run_9101 (pi/espresso-v7 on espresso@v1), reports n=412, rate=0.85. Per-episode artifacts (video, MCAP telemetry, replay spec) hang off run.episodes, and run.report(format="pdf") renders the citable verification report. Field-by-field detail: data contract.

Compare versions

Version-in-repo-id makes comparison mechanical: keep the declared test configuration — robot, scene, task, contracts, inference — identical and change only the repo id, acme/act-so101-pick-v1 against acme/act-so101-pick-v2. compare() reports the paired delta; change anything else and you are comparing test setups, not policies.

Troubleshoot

CodeSymptomFix
contract_validation_failedsubmission rejected — the checkpoint's processor expects a camera set the pinned robot lacks, or an action space its firmware doesn't acceptdeclare the contracts the checkpoint was trained for, and pin a robot and scene that provide them
firmware_pin_unavailablethe requested model@firmware isn't installed on any celllist installed firmwares with robots.list() and pin one of them
task_unknowntask id or version typo — pick_place@v2 when the catalogue has pick_place@v1check the task catalogue and pin an existing version
budget_exceededrun halted mid-flight at max_budget_usd; partial result kept, with honest n and intervalread the partial result; resubmit with a higher cap if the interval is too wide
retention_expiredartifacts fetched after the run's data.retention window closed, or after a purgethe data is gone by design — re-run if you need fresh episodes

Where next