Python
The canonical SDK — module-level primitives, resource namespaces, and results that carry n and ci95 by construction.
The Python SDK is the canonical surface: these docs are written in it first,
and the other SDKs mirror it. It reads ROBORAMA_API_KEY (keys carry the
rbr_live_ prefix) from the environment, so authentication is an export, not
an argument.
pip install roborama-sdk
import roborama # reads ROBORAMA_API_KEY from the environment
run = roborama.run(
robot="g1-edu-pro@fw2.3",
environment="kitchen-std@v1.2",
task="pick_place@v1",
episodes="auto(ci=0.95, moe=0.03)",
)
print(run.result()) # n=612 rate=0.874 ci95=(0.846, 0.898)Primitives
The seven primitives are module-level functions — roborama.run(),
roborama.eval(), roborama.verify(), roborama.matrix(),
roborama.threshold(), roborama.compare(), and roborama.transfer() — one
call per physical question. Each is documented field by field on its own
page, starting with run().
Resources
Nouns live in resource namespaces: roborama.runs, roborama.robots,
roborama.environments, roborama.suites, roborama.streams,
roborama.keys, roborama.budgets, and roborama.data, with the
list()/get() shapes you would expect — roborama.runs.get("run_8842"),
roborama.robots.list(), roborama.environments.list(cls="kitchen").
roborama.quote() and roborama.usage() sit at module level, like the
primitives.
Policies
Three constructors, each with a declared contract:
roborama.Policy.container(image, action_space, observation_contract) for
images we run GPU-adjacent in the facility;
roborama.Policy.checkpoint(hf="acme/skill-v4", runtime="openpi") for known
runtimes (openpi, lerobot); and roborama.Policy.endpoint(url, latency_budget_ms=80, fallback="halt") for inference you host, with measured
round-trip time logged per step. Contracts are validated before any motor
moves — see policies. Everything the run
primitive offers, in one call:
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_pdfResults
| Accessor | What it returns |
|---|---|
run.result() | n, success_rate, ci95, failure_clusters, robot_hours, environment_hours, cost_usd |
run.episodes[i] | one episode: video_url, mcap_url, replay_spec |
run.watch() | live iterator — episode ticker plus WebRTC stream URLs |
run.export(format="lerobot") | dataset export; also "rlds" and "mcap-bundle" |
run.report(format="pdf") | the verification report, citable |
result() blocks until the run completes; watch() is how you avoid
blocking. There is no accessor that returns a success rate without n and
ci95 attached, and that is a feature.
Errors
roborama.RoboramaError is the base class. Every code in
the error reference maps to a subclass — budget_exceeded
raises roborama.BudgetExceeded — and every instance carries the code as
err.code, so you can catch narrowly and log exactly:
import roborama
try:
run = roborama.run(
robot="g1-edu-pro@fw2.3",
environment="kitchen-std@v1.2",
task="pick_place@v1",
episodes=600,
max_budget_usd=500,
)
print(run.result())
except roborama.BudgetExceeded as err:
print(err.code, err.run_id) # budget_exceeded run_8907
partial = err.partial_result # kept: n, success_rate, ci95 for what ran
print(partial.n, partial.success_rate, partial.ci95)
Versioning
SDK releases ship with the control plane, so the client and the API never drift. The surface documented on this page is the contract; anything the SDK does beyond it is convenience, not behavior to build against.