Documentation menu

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

roborama.Policy
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)
PackagingRunsNotes
Policy.container(image, action_space, observation_contract)in-facility, GPU-adjacentany OCI image; lowest latency, no network in the loop
Policy.checkpoint(hf=..., runtime=..., inference=...)in-facility, managed runtimeknown runtimes: openpi, lerobot; the inference dict pins decoding
Policy.endpoint(url, latency_budget_ms, fallback)your infrastructuremeasured 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_failed and policy_endpoint_timeout in detail.