Policies
Three ways to hand us a policy — container, checkpoint, endpoint — each behind the same declared contracts, validated before any motor moves.
A policy enters the facility in one of three packagings. All three sit behind
the same two declarations — an action_space and an observation_contract —
and both are validated against the robot and scene before any motor moves.
A policy that expects three cameras and gets two fails at submission with
contract_validation_failed, not at episode 40 with a mystery cluster.
The three packagings
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)| Packaging | Runs | Notes |
|---|---|---|
Policy.container(image, action_space, observation_contract) | in-facility, GPU-adjacent | any OCI image; lowest latency, no network in the loop |
Policy.checkpoint(hf=..., runtime=..., inference=...) | in-facility, managed runtime | known runtimes: openpi, lerobot; the inference dict pins decoding |
Policy.endpoint(url, latency_budget_ms, fallback) | your infrastructure | measured round-trip time logged per step; weights never leave your side |
Container is the default for anything custom: ship an OCI image, we run it GPU-adjacent to the cell. Checkpoint is the low-friction path when your policy already speaks a known runtime — point at a Hugging Face repo and name the runtime. Endpoint inverts the trust: inference stays on your infrastructure and the facility streams observations to your URL. That choice is also an IP posture — see the data contract.
Checkpoints also pin how they're decoded. The inference dict —
{"action_horizon": 50, "chunk_size": 50, "temp": 0.0} — is recorded with
the run, because reproducibility includes decoding, not just weights: the
same checkpoint at a different action horizon is a different policy as far
as your statistics are concerned, the same way a firmware bump is a
different robot.
Declared contracts
action_space names the command interface and rate the policy emits:
joint_delta_50hz, joint_abs_20hz, ee_pose_10hz, and the rest of the
catalogued spaces. observation_contract names the camera set and
proprioception schema it expects — droid-3cam is three RGB views plus the
joint-state schema. Validation checks both against the pinned robot and
scene: the declared space must be one the firmware accepts, and every feed
the contract names must exist in the cell.
The contracts are not paperwork; they are what makes a result attributable. When a policy fails, you want to know it failed on physics, not on a silently resampled action rate or a missing camera.
Endpoint latency and the fallback
An endpoint policy puts your network in the control loop, so the latency
budget is explicit: latency_budget_ms=80 means any step whose round trip
exceeds 80 ms triggers the declared fallback — "halt" freezes the arm and
ends the episode, which then lands in its own cluster rather than polluting
the physics statistics. Measured RTT is logged per step to /events, so you
can tell a policy problem from a network problem after the fact. Persistent
unreachability fails the run with policy_endpoint_timeout.
Where next
- run() — the call every packaging plugs into.
- Data contract — retention,
train_on_failures, and who sees your weights. - Error codes —
contract_validation_failedandpolicy_endpoint_timeoutin detail.