Import from private storage
CI downloads your checkpoint with a scoped read credential and bakes it into an image — Roborama pulls the image, never the bucket.
Amazon S3Google CloudMicrosoft Azure
The API does not accept s3://, gs://, or azure:// checkpoint
sources, and there are no storage-credential fields anywhere. The
supported workflow keeps credentials entirely on your side: CI
downloads the checkpoint with a scoped read credential and bakes it
into a container image at build time. Roborama pulls the image, never
the bucket — your cloud credentials never leave your CI.
Prerequisites
- The full checkpoint under one prefix — weights, config, and
normalization stats. A weights file alone does not identify
preprocessing or inference settings; if
norm_stats.jsonor the processor files aren't baked in alongside the weights, the policy runs confidently wrong. - A manifest, checked in CI. Commit the expected file list with
checksums next to the Dockerfile and verify with
sha256sum -c. An incomplete download or a checksum mismatch fails your build, not the run — that is the point: fail before you buy episodes. - A scoped read credential in CI — the per-provider minimum is in the table below. The credential only needs to live for the build, so prefer short-lived OIDC role assumption over stored keys.
- A registry Roborama can pull from. Today the image must be pullable without registry credentials. If that posture doesn't fit your weights, Connect your endpoint keeps them off our side entirely.
Connect
The worked example bakes s3://acme-checkpoints/skill-v4/ into
ghcr.io/acme/skill:v4.
- Commit the Dockerfile and a checksum manifest
FROM pytorch/pytorch:2.4.0-cuda12.4-cudnn9-runtime WORKDIR /policy COPY checkpoint/ /policy/checkpoint/ COPY serve.py /policy/serve.py CMD ["python", "serve.py", "--checkpoint", "checkpoint"]Generate the manifest once, on the machine that trained the policy, and commit it next to the Dockerfile:
sha256sum $(find checkpoint -type f) > checkpoint.manifest - Download with a scoped role and verify
In GitHub Actions, assume a read-only role via OIDC — the job gets a credential that lives minutes and is never stored:
permissions: id-token: write steps: - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/ckpt-read aws-region: us-east-1Then download the prefix and check it against the manifest:
aws s3 cp --recursive \ s3://acme-checkpoints/skill-v4/ ./checkpoint/ sha256sum -c checkpoint.manifestA missing file or a mismatched hash stops the build here — before an image exists, long before an episode is bought.
- Build, push, and hand the image to a run
docker build -t ghcr.io/acme/skill:v4 . docker push ghcr.io/acme/skill:v4From here the path is exactly Run your container:
Policy.container(image="ghcr.io/acme/skill:v4")with your declared contracts. The canonical container run,run_8842, is this image ong1-edu-pro@fw2.3inkitchen-std@v1.2.
The same download on GCS and Azure
Only the download step changes; the manifest check, build, and push are identical.
| Provider | Download | Minimum permission |
|---|---|---|
| Amazon S3 | aws s3 cp --recursive s3://acme-checkpoints/skill-v4/ ./checkpoint/ | s3:GetObject on the prefix |
| Google Cloud Storage | gcloud storage cp -r gs://acme-checkpoints/skill-v4 ./checkpoint | roles/storage.objectViewer on the bucket |
| Microsoft Azure | az storage blob download per blob (download-batch for a prefix) | Storage Blob Data Reader on the container |
Prefix, individual objects, or a tarball unpacked during the build — whatever your CI downloads, Roborama only ever sees the finished image.
Weights baked into an image travel with it: the copy 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. Emptying your bucket later
does not delete an already-fetched copy; purge does
(data contract).
Validate
Mock mode (ROBORAMA_MOCK=1, or mock=True on the client) dry-runs
quote → submit → result with no API key and no hardware. At submission,
admission 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 then pulls and starts
the image — a broken entrypoint surfaces there, after admission and
before episodes (Bring your policy
lays out the three layers).
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
Quotes are free and resolve both meters before you commit: 600
episodes of g1-edu-pro in kitchen-std — the worked example's setup
— prices at $3,740, queue ETA about 6 hours. Meters and hard stops:
Billing & budgets.
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(), passing the
Policy.container built above; follow live with run.watch().
Inspect results
run.result() returns n, the success rate, and a Wilson ci95 — the
canonical run for this image, run_8842, reports n=612, rate=0.874,
ci95=(0.846, 0.898) at $3,812. Episodes carry video, MCAP telemetry,
and replay specs; run.report(format="pdf") is the citable record.
Field detail: data contract.
Compare versions
Bake skill-v5 from its own prefix into its own image, keep every pin
and declaration the same, and compare()
reports the paired delta — same declared test, different weights.
Troubleshoot
Download and checksum failures happen inside your CI — deliberately, no Roborama error code exists for them. The codes below are the run path's.
| Code | Symptom | Fix |
|---|---|---|
contract_validation_failed | submission rejected — the baked policy declares contracts the pinned robot and scene don't provide | 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
- Run your container — the direct integration this workflow lands on.
- Walkthrough: GitHub + S3 — this workflow end to end, code and weights in different places.
- Package your policy — the same CI bake, starting from a code repo.
- Bring your policy — all six paths side by side.