Upload a local checkpoint
There is no upload API — publish the checkpoint directory to a Hub repo you control, or bake it into an image, then evaluate like any other policy.
Local uploadHugging FaceDocker
There is no direct artifact upload today — no upload call, no signed
upload URLs, and no size limits to document, because nothing is
uploaded to Roborama directly. A checkpoint sitting on your machine
still gets onto hardware through two supported routes: publish the
directory to a Hugging Face repo you control and
import it, or copy it into a
container image and run that. Both
end at the same place — a field on the Policy object — and everything
downstream is identical.
Prerequisites
- The complete checkpoint directory — weights plus config plus normalization and processor files. A weights file alone does not identify the policy.
- Route 1: a Hugging Face account,
huggingface-cli, and a policy that speaks a managed runtime —openpiorlerobot. - Route 2: Docker and a registry Roborama can pull from — works for any runtime, including fully custom serving code.
Connect
Route 1 — publish to the Hub (recommended for supported runtimes)
Create a repo per version — the convention is version-in-repo-id, since
no revision field exists — and upload the directory:
huggingface-cli upload acme/skill-v4 ./pretrained_model
For lerobot, the uploaded directory must contain exactly what the
runtime expects to load:
config.json
model.safetensors
train_config.json
policy_preprocessor.json
policy_postprocessor.json
(PreTrainedPolicy.push_model_to_hub publishes the same layout from
code.) The repo must be readable without authentication — the hf:
field carries no token. From here the path is exactly
Import from Hugging Face:
point Policy.checkpoint(hf="acme/skill-v4", runtime="lerobot") at
the new repo.
Route 2 — bake into a container image
When the runtime isn't managed, or the weights shouldn't be public, copy the directory into an image next to your serving code:
FROM pytorch/pytorch:2.4.0-cuda12.4-cudnn9-runtime
WORKDIR /policy
COPY pretrained_model/ /policy/checkpoint/
COPY serve.py /policy/serve.py
CMD ["python", "serve.py", "--checkpoint", "checkpoint"]
Build, push, and continue as
Run your container:
Policy.container(image=...) with your declared contracts.
On either route, 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. Privating or deleting the source repo later does not delete
an already-fetched copy; purge does
(data contract).
Validate
The three layers are the same on both routes. Mock mode
(ROBORAMA_MOCK=1, or mock=True on the client) dry-runs the loop
with no API key and no hardware — worth doing before you publish
anything. Admission then checks the declared action_space and
observation_contract against the pinned robot and scene; a mismatch
is rejected with contract_validation_failed, free. Cell startup is
where the checkpoint fetch or container start is actually exercised.
The layers are laid out in
Bring your policy.
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
Quote before you run: both meters, the dollars, and the queue ETA, free, valid seven days. Nothing bills until a motor moves — Billing & budgets covers the meters and the hard stops.
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
Submit with run() — Policy.checkpoint on
route 1, Policy.container on route 2 — and follow episodes live with
run.watch() or the SSE stream.
Inspect results
run.result() returns n, the success rate, and a Wilson ci95; each
episode carries video, MCAP telemetry, and a replay spec; and
run.report(format="pdf") renders the citable record. Retention and
export formats: data contract.
Compare versions
Publish acme/skill-v5 — or push a :v5 image — keep every pin the
same, and compare() reports the paired
delta between the two: same declared test, different artifact.
Troubleshoot
| Code | Symptom | Fix |
|---|---|---|
contract_validation_failed | submission rejected — the declared contracts don't match the pinned robot and scene | declare what the checkpoint was trained for; pin hardware that provides it |
firmware_pin_unavailable | the requested model@firmware isn't installed on any cell | list installed firmwares with robots.list() and pin one of them |
task_unknown | task id or version typo in the submission | check the task catalogue and pin an existing version |
budget_exceeded | run halted at max_budget_usd; partial result kept | read the partial n and interval; resubmit with a higher cap if needed |
retention_expired | artifacts fetched after the retention window, or after a purge | the data is gone by design — re-run for fresh episodes |
Where next
- Import from Hugging Face — route 1 continues here.
- Run your container — route 2 continues here.
- Import from private storage — the same bake, but CI does the copying from a bucket.
- Bring your policy — all six paths side by side.