Product

The facility is an API

Instrumented robot cells, a strict data contract, the embodiment matrix, and the sim-verify loop — behind one API.

POST /v1/runs → n, success_rate, ci95

the core primitive
import roborama  # reads ROBORAMA_API_KEY from the environment

run = roborama.run(
    robot="g1-edu-pro@fw2.3",            # embodiment @ pinned firmware
    environment="kitchen-std@v1.2",      # versioned catalogue scene
    policy=roborama.Policy.container(    # see policy packaging
        image="ghcr.io/acme/skill:v4",
        action_space="joint_delta_50hz",
        observation_contract="droid-3cam",
    ),
    task="load_dishwasher@v2",
    episodes="auto(ci=0.95, moe=0.03)",  # size n for ±3% at 95% — or an int
    perturbation={                       # the schedule IS the product spec
        "layout_jitter_mm": 25,
        "lighting": ["3000K", "5600K"],
        "distractors": "set-B",
        "seed": 42,
    },
    data={"retention": "30d", "train_on_failures": False},  # IP posture
    max_budget_usd=4_000,                # hard stop, metered live
)

print(run.result())
#  n=612  success_rate=0.874  ci95=(0.846, 0.898)
#  failure_clusters: [grasp_slip: 41, perception_miss: 22, collision: 9]
#  robot_hours=20.4  environment_hours=20.4  cost_usd=3_812
#  artifacts: mcap[], video[], ground_truth[], report_pdf
policies incontainercheckpoint (hf)endpoint
g1-edu-prohumanoid · 6 cellsg1-edu-plushumanoid · 2 cellsspot-armquadruped-manip · 2 cellsaloha2-probimanual · 2 cellsaloha-bimanualbimanual · 3 cellstiago-promobile-manipulator · 2 cellsstretch3mobile-manipulator · 4 cellsfr3-benchfixed-arm · 8 cellsnori-a3arm-pod · 24 cellsso-101arm-pod · 16 cells

calibrated cameras · force-torque · scripted resets

pipeline

One screen, the whole system

A customer’s task arrives as a draft Task Spec, gets piloted live, and freezes into an immutable, mutually signed revision that every report cites. Everything that comes back is an artifact, a statistic, or a hook — no dashboard-only state: anything you can see, an agent can curl.

hardware

Cells, not labs

A Roborama cell is a robot with a pinned firmware, a versioned scene, calibrated cameras and force-torque sensing, and a scripted reset. Your policy arrives as a container, a checkpoint, or an endpoint — its declared action_space and observation_contract are validated before any motor moves. Then the cell does the one thing labs are bad at: it runs the same experiment hundreds of times without a graduate student in the loop.

Everything is versioned — robots pin firmware (g1-edu-pro@fw2.3), environments and suites pin revisions. @latest is allowed, but the resolved pin is recorded: every result is reproducible and citable.

policies in, three ways
import roborama  # reads ROBORAMA_API_KEY from the environment

# 1. Container — runs in-facility, GPU-adjacent
container = roborama.Policy.container(
    image="ghcr.io/acme/skill:v4",
    action_space="joint_delta_50hz",
    observation_contract="droid-3cam",
)

# 2. Checkpoint — known runtimes: openpi, lerobot
checkpoint = roborama.Policy.checkpoint(
    hf="acme/skill-v4", runtime="openpi")

# 3. Endpoint — customer-hosted inference; measured RTT logged per step
endpoint = roborama.Policy.endpoint(
    url="https://inference.acme.ai/act",
    latency_budget_ms=80,
    fallback="halt",
)

# Declared contracts are validated before any motor moves.
run = roborama.run(
    robot="g1-edu-pro@fw2.3",
    environment="kitchen-std@v1.2",
    policy=container,
    task="pick_place@v1",
    episodes="auto(ci=0.95, moe=0.03)",
)
print(run.id)

pricing

Two meters, visible everywhere

Pricing is two numbers: robot-hours (occupancy of an embodiment) and environment-hours (occupancy of a scene). Both appear in every quote and every result — the canonical run here cost robot_hours=20.4, environment_hours=20.4, cost_usd=3,812.

No opaque credits. The rate card is a JSON file.

POST /v1/quotepriced before it runs
{
  "robot": "g1-edu-pro",
  "environment": "kitchen-std",
  "episodes": 600,
  "robot_hours": 20,
  "env_hours": 20,
  "usd": 3740,
  "queue_eta": "6h"
}
run.result()the same meters come back
n=612 success_rate=0.874 ci95=(0.846, 0.898)
failure_clusters: [grasp_slip: 41, perception_miss: 22, collision: 9]
robot_hours=20.4 environment_hours=20.4 cost_usd=3,812
artifacts: mcap[], video[], ground_truth[], report_pdf
n=612

the canonical run — episodes="auto(ci=0.95, moe=0.03)" sized the job for ±3 points at 95% confidence

7 of 8 min

of a real-world RL run went to resets and overhead in Physical Intelligence's published result — Roborama resets are scripted

caught

fw2.4 dropped −10.5 pts (0.787 vs 0.892, n=240 per cell) — flagged by the matrix before release

Sources and arithmetic on the research page.

evaluation

The matrix

One policy against ten embodiments and three environments, every cell sized by episodes_per_cell="auto(ci=0.95, moe=0.05)". Pass and fail are declared gates — here, a Wilson 95% lower bound of at least 0.80 — not vibes.

pass = Wilson 95% lower bound 0.80

cell-a
kitchen-std
warehouse-std
g1-edu-pro @ fw2.3
0.937(0.893, 0.964)n=190
0.892(0.846, 0.925)n=240
0.862(0.809, 0.902)n=210
g1-edu-pro @ fw2.4
0.921(0.874, 0.952)n=190
0.787(0.731, 0.835)n=240
0.838(0.782, 0.882)n=210
g1-edu-plus @ fw2.3
0.953(0.912, 0.975)n=190
0.921(0.880, 0.949)n=240
0.890(0.841, 0.926)n=210
aloha2-pro @ fw1.1
0.937(0.893, 0.964)n=190
0.871(0.823, 0.908)n=240
0.843(0.788, 0.886)n=210
spot-arm @ fw4.1
0.884(0.831, 0.922)n=190
0.746(0.687, 0.797)n=240
0.790(0.730, 0.840)n=210
tiago-pro @ fw2.0
0.905(0.855, 0.939)n=190
0.808(0.753, 0.853)n=240
0.724(0.660, 0.780)n=210
fr3-bench @ fw5.2
0.947(0.905, 0.971)n=190
0.821(0.768, 0.864)n=240
0.790(0.730, 0.840)n=210
stretch3 @ fw1.9
0.879(0.825, 0.918)n=190
0.729(0.670, 0.781)n=240
0.629(0.561, 0.691)n=210
nori-a3 @ fw1.0
0.800(0.737, 0.851)n=190
0.537(0.474, 0.599)n=240
0.467(0.400, 0.534)n=210
so-101 @ fw1.2
0.742(0.675, 0.799)n=190
0.463(0.401, 0.526)n=240
0.410(0.346, 0.478)n=210

This grid caught a real regression: g1-edu-pro@fw2.4 dropped 10.5 points in the kitchen replica against fw2.3 after a wrist-controller change opened a grasp_slip cluster.

simulation

The verify loop

Simulation is a first-class input. verify() consumes the initial conditions your simulator flagged as uncertain — PolaRiS, Isaac, and world-model formats, or Roborama layout-replay specs — runs them on physical hardware, and returns ground truth formatted to recalibrate your simulator: mocap 6-DoF object poses and commanded-vs-executed trajectories. Disagreement episodes are the payload; an audit_sample of random episodes guards against the sim’s blind spots.

Simulator vendors can license the same ground truth as calibration exports under sim-calibration-v1 (validation use, no policy training).

the sim interlock
import roborama  # reads ROBORAMA_API_KEY from the environment

policy = roborama.Policy.checkpoint(hf="acme/skill-v4", runtime="openpi")

# Initial conditions your simulator marked uncertain: sampled states from
# PolaRiS / Isaac / world-model exports, or Roborama layout-replay specs.
scenarios = roborama.scenarios.from_file("sim_flagged_p1.json")

report = roborama.verify(
    policy=policy,
    scenarios=scenarios,
    robots=["g1-edu-pro@fw2.3", "g1-edu-plus@fw2.3"],
    audit_sample=0.10,          # random episodes vs. the sim's blind spots
    return_ground_truth=True,   # mocap 6-DoF poses + commanded-vs-executed,
                                # formatted to recalibrate your simulator
)

print(report.sim_agreement)  # where reality matched sim predictions
print(report.disagreements)  # scenario ids where reality diverged

data

The data contract

Every episode ships MCAP with a fixed channel set, plus video and a re-runnable replay spec. /meta carries what reproducibility actually requires: firmware, calibration age, actuator cycle counts, thermal state, seed, and the realized — not just requested — perturbations.

Retention is explicit per run, and data.train_on_failures defaults to False — your failures are your IP. Details in the data contract.

episode.mcapfixed channel set
/joint_states_measured/joint_targets_commanded/camera/*/ft_wrist/gt/object_poses/events/meta

/meta firmware · calibration age · actuator cycle counts · thermal state · seed · realized (not just requested) perturbations

exportslerobotrldsmcap-bundle

observability

Watch it run

Every run exposes a live episode ticker and WebRTC streams for its cell, and five webhook events — run.completed, episode.failed, threshold.crossed, regression.detected, estop.triggered — so your CI, your training loop, or your agent can react without polling.

Wire it into release sign-off with CI gates.

● LIVErun_9101 · espresso@v1g1-edu-pro@fw2.3 · n=412

cell-g1-04 — episode 341/412 · scripted reset between episodes

result.stage_rates — Wilson 95%

grasp_cup0.966 (0.944, 0.980)
cup_placed0.932 (0.904, 0.953)
extraction0.893 (0.860, 0.919)
served0.850 (0.812, 0.881)
run.completedepisode.failedthreshold.crossedregression.detectedestop.triggered

cell-g1-04 · wss://streams.roborama.com/cells/cell-g1-04/webrtc

Built for engineers. Legible to agents.

Get started