Documentation menu

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.json or 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.

  1. 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
  2. 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-1

    Then download the prefix and check it against the manifest:

    aws s3 cp --recursive \
      s3://acme-checkpoints/skill-v4/ ./checkpoint/
    sha256sum -c checkpoint.manifest

    A missing file or a mismatched hash stops the build here — before an image exists, long before an episode is bought.

  3. Build, push, and hand the image to a run
    docker build -t ghcr.io/acme/skill:v4 .
    docker push ghcr.io/acme/skill:v4

    From 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 on g1-edu-pro@fw2.3 in kitchen-std@v1.2.

The same download on GCS and Azure

Only the download step changes; the manifest check, build, and push are identical.

ProviderDownloadMinimum permission
Amazon S3aws s3 cp --recursive s3://acme-checkpoints/skill-v4/ ./checkpoint/s3:GetObject on the prefix
Google Cloud Storagegcloud storage cp -r gs://acme-checkpoints/skill-v4 ./checkpointroles/storage.objectViewer on the bucket
Microsoft Azureaz 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).

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

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.

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

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.

CodeSymptomFix
contract_validation_failedsubmission rejected — the baked policy declares contracts the pinned robot and scene don't providedeclare what the checkpoint was trained for; pin hardware that provides it
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 in the submissioncheck the task catalogue and pin an existing version
budget_exceededrun halted at max_budget_usd; partial result keptread the partial n and interval; resubmit with a higher cap if needed
retention_expiredartifacts fetched after the retention window, or after a purgethe data is gone by design — re-run for fresh episodes

Where next