> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reactor.inc/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> To build and serve your own model, start at /deploy/development/quickstart and /deploy/development/overview. Deploying is the default path: reactor init scaffolds a workspace, reactor auth login authenticates, and reactor model deploy registers the model, publishes the release with the weights/ folder, and activates it on Reactor's GPUs, in one command from that workspace. Docker must be running, because the publish step builds the image locally. Bump model.version in reactor.yaml before redeploying a change, because a release that already has an image is reactivated as it is. Deployment access is granted per account, so contact team@reactor.inc if a deploy is refused. Every key in reactor.yaml is documented at /deploy/platform/reactor-yaml. Model code imports reactor_runtime; Python client code imports reactor_sdk. The runtime overview explains the model interface. Running the model on your own machine with reactor run is optional and needs a GPU you attach with --gpus; /deploy/development/local-testing covers that loop and pairs a complete brightness model with a Python client test in a separate brightness-test workspace.
> Reactor hosts multiple models, each with its own connect slug (modelName) and command/event schema. The video model catalog — slug, typed SDK package, and links to its schema — is at /model-api-reference/overview. Robotics policy documentation starts at /robotics/overview; X-WAM observations, actions, and client integration are under /robotics/xwam/; Cosmos3 Nano Policy DROID is under /robotics/cosmos/nano-policy-droid/. Some models expose one slug per experience (e.g. HappyOyster); always take the slug from the model's own pages, never guess it.
> Fastest path to a working app: `npx create-reactor-app my-app --model=<slug>` scaffolds a complete app with secure auth wired up. Typed TypeScript SDKs are published as @reactor-models/<model>; Python uses the base reactor-sdk package.
> Auth: exchange an API key (rk_...) for a JWT via POST https://api.reactor.inc/tokens from your server. Never put the API key in client-side code.
> Append .md to any docs URL for clean Markdown. Search these docs via the MCP server at https://docs.reactor.inc/mcp.

# LingBot-VA LIBERO reference

> Camera tracks, controller units, seed rows, and executed-action flow control.

Connect to `reactor/lingbot-va` through the SDK and keep the session open while exchanging
observations and predictions. A **camera track** is a named stream of successive images from one
camera; publishing it attaches that stream to the session.

## API at a glance

| Direction | What crosses the connection |
| - | - |
| Your client → model | Two camera streams and a task instruction; this variant has no proprioception input. |
| Model → your client | `action_prediction` messages; `data.action` contains 16 × 7 LIBERO controller values. |

The first chunk arrives without execution feedback and includes four conditioning rows. Report the
rows you executed to receive subsequent predictions. Your application validates the output and
executes it through its own controller.

New to Reactor? [How the API works](/robotics/how-the-api-works) explains sessions, tracks,
commands, and the difference between an SDK message and the data returned by the example helper. For
a complete script, use [Get your first actions](/robotics/lingbot-va/libero/quickstart).

## Camera tracks

Publish in this order after `READY`, with RGB `uint8` arrays of shape `(128, 128, 3)`:

| Track | LIBERO observation key | View |
| - | - | - |
| `agentview` | `agentview_image` | External camera |
| `eye_in_hand` | `robot0_eye_in_hand_image` | Wrist camera |

The model resizes other resolutions internally. Preserve camera identity and field of view. The
reference wrapper vertically flips MuJoCo's bottom-up frames using `image[::-1]`; this is not a
180-degree rotation. Do not apply this transform to a camera that already supplies upright images.

Each view retains its newest frame. A later chunk commits the video observed during execution: 12
snapshots for the first commit, then 16. Longer windows retain the newest snapshots; shorter windows
are resampled. Video and executed-action messages have no shared observation identifier, so delivery
order approximates their pairing. A delay alone cannot guarantee synchronization.

## Commands

| Command | Payload | Constraint |
| - | - | - |
| `set_task_description` | `{"task_description": "put the bowl on the plate"}` | Nonempty task; at most 300 characters |
| `set_executed_action_json` | `{"executed_action_json": "<JSON row list>"}` | String, at most 8,000 characters; empty at episode start |
| `reset` | `{"sampling_seed": 42}` or `{}` | Seed integer `0..2147483647`; default `0` leaves sampling unseeded |

The echo is a JSON-encoded nested row list, without a `step` wrapper. Encode finite numbers with
`json.dumps(rows, allow_nan=False, separators=(",", ":"))`. Preserve precision and validate row
counts locally. Reset clears the policy memory, retained frames, and prediction counter, but leaves
the input state fields intact: **clear `executed_action_json` before resetting**.

A changed nonempty task also restarts policy memory and the counter. Use a fresh session when
changing tasks so a reset cannot seed from the previous task. For an uncertain timeout or stale
replies, close the connection and start a fresh session. Reset does not stop or reset your robot.

## Action reply

The `action_prediction` message's `data` contains `action`, a `(16, 7)` nested array, and `step`,
the zero-based prediction counter. Rows are:

```text theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
[dx, dy, dz, rotation_x, rotation_y, rotation_z, gripper]
```

These are **raw LIBERO controller inputs**, already unnormalized through the checkpoint's training
quantiles. Do not unnormalize them again or treat them as metres, joint targets, or absolute poses.
The rotation columns are axis-angle delta components, not Euler roll/pitch/yaw.

The reference
[robosuite 1.4.0 controller configuration](https://github.com/ARISE-Initiative/robosuite/blob/v1.4.0/robosuite/controllers/config/osc_pose.json)
clips arm inputs to `[-1, 1]`, then scales translation by `0.05` metres and rotation by `0.5`
radians. Its
[goal calculation](https://github.com/ARISE-Initiative/robosuite/blob/v1.4.0/robosuite/utils/control_utils.py)
adds translation in the world frame and left-multiplies the current orientation by the axis-angle
rotation. These are simulator controller semantics, not a calibrated physical-robot mapping.

The
[Panda gripper](https://github.com/ARISE-Initiative/robosuite/blob/v1.4.0/robosuite/models/grippers/panda_gripper.py)
uses the command sign: negative opens, positive closes, and zero preserves the internal target. The
scalar is not a jaw width. Raw model values are continuous and are not guaranteed to lie within
`[-1, 1]`; the controller applies its own handling.

## Advance the loop

1. In a fresh session, publish both views, clear the executed-action field, reset, and send the
   task. The first chunk needs no echo and returns `step: 0`.
2. Skip rows `0:4` of that first chunk and execute rows `4:16`. The skipped values are conditioning
   slots; normalized zero becomes nonzero motion after unnormalization.
3. Publish video while executing. Send the 12 executed rows in `executed_action_json` when done. The
   first commit uses the cached seed prediction for conditioning; the echo opens the gate.
4. For subsequent chunks, execute all 16 rows and echo exactly those 16 rows. Keep one chunk
   outstanding and check that the reply counter increments by one.

Progress requires a **different nonempty echo string**. An identical echo is not a retry and
produces no new chunk. The first echo must parse as a nonempty list; subsequent echoes must reshape
to `(16, 7)`. Invalid echoes can leave the client waiting without a reply. Do not change action
values just to force progress, or assume arbitrary partial execution is supported. If execution is
interrupted, stop the episode and reset with fresh observations.

The server cannot verify physical execution. The first-commit behavior also means modifying the seed
actions does not update that commit's cached action conditioning; validate this limitation before
adapting the policy to a controller that clips or modifies commands.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.