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.
The first two are checkpoint-transfer paths: an artifact (weights or an image) moves to the facility. A hosted endpoint is a different thing — an execution mode where nothing moves and the facility calls out. Weights in private storage or on your laptop reach the facility through a packaging workflow that ends in one of the two transfer paths; the bring-your-policy guide maps what you already have to the right route.
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.
What identifies a policy
A weights hash alone does not identify a policy — it says nothing about the
preprocessing that feeds the network, the runtime code that decodes it, or
the inference settings it decodes with. The complete identity is the
artifact plus its execution configuration: for a checkpoint, the repo id
(version it in the id — pi/espresso-v7), the runtime, and the inference
dict; for a container, the image digest, which seals code, weights, and
preprocessing into one immutable reference; for an endpoint, the URL you
declared — which is why deployment versions belong in it. All of it is
recorded with the run.
Repeatability follows from that record: rerunning a result means rerunning its recorded configuration under the recorded protocol — same policy identity, robot pin, environment revision, and perturbation seed — subject to the run's retention window and the pinned hardware still being on the floor (firmware availability).
The cell interface
However packaged, every policy faces the same interface. The cell runtime
feeds your server the observations named by the declared
observation_contract and expects actions in the declared action_space,
at its declared rate. For checkpoint packagings, action chunking is
declared in inference (action_horizon, chunk_size) and recorded with
the run; a container or endpoint policy owns its own decoding. Between
episodes the runtime signals an episode boundary, and your policy clears
its per-episode state — physical scene reset is the cell's job (scripted or
teleop-assisted, per the environment),
never your policy's.
The inference interface is also deliberately separate from the robot's local control and safety loops: your policy commands the declared action space; joint-limit enforcement, self-collision checks, and the e-stop path run on the robot side regardless of what the policy sends. A formal wire-level specification of the interface (routes and schemas) is not yet published; the declaration is validated at admission and the server is exercised at cell startup.
Fetch, cache, retention
A checkpoint 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. Making the source
repo private after import does not delete an already-fetched copy; purge
does. Endpoint-packaged policies create no cached copy of weights at all —
that is the point of the mode.
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
- Bring your policy — from wherever your code and weights live today to an admitted policy.
- 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.