> ## 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 catalog of every model — slug, typed SDK package, and links to its schema — is at /model-api-reference/overview. 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.

# Test your deployment

> Run the RLDX-1 cookbook client against your deployed model.

This guide runs the
[RLDX-1 cookbook client](https://github.com/reactor-team/reactor-cookbook/tree/main/models/rldx-1/client)
against [RLDX-1 deployed in your account](/deploy/development/robotics/rldx-1). The client sends
synthetic camera frames and synthetic state.

<Warning>
  Do not send the returned actions to a robot. The synthetic inputs do not represent real
  observations. The client simulates action execution and does not implement a robot controller.
</Warning>

## Requirements

The client uses Python 3.12 and `reactor-sdk >= 1.6.0, < 2`.

On macOS, install [uv](https://docs.astral.sh/uv/) with [Homebrew](https://brew.sh/):

```bash theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
brew install uv
```

For other platforms, follow the
[uv installation guide](https://docs.astral.sh/uv/getting-started/installation/).

From the cookbook repository root, install the client:

```bash theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
cd models/rldx-1/client
uv sync --python 3.12 --upgrade-package reactor-sdk
source .venv/bin/activate
```

## Run the client

[Create an API key](/authentication#get-your-api-key) for the same Reactor account as the
deployment. CLI sign-in does not set `REACTOR_API_KEY` for the Python client.

Replace `<account-slug>` below with the account slug that the CLI printed when you published the
model. Wait for the model to become ready before you run the client.

```bash theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
export REACTOR_API_KEY=rk_your_key_here
python main.py --model <account-slug>/rldx-1 --duration 60
```

In a new terminal, return to `models/rldx-1/client` and activate `.venv` again. The client allows
300 seconds to connect by default. Startup can include image and checkpoint loading, especially
after a deployment scales to zero. Use `--connect-timeout` to change that wait. Check
[model status](/deploy/cli-reference/reactor_model_status) and [logs](/deploy/platform/logs) if the
connection times out.

## Example output

This abbreviated example shows the output format. Angle-bracket placeholders stand for results from
your run, not measured performance claims.

```text theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
[schema] views=['left_view', 'right_view', 'wrist_view'] resolution=256x256 control_hz=20 ...
[carrier] frame_metadata
[first chunk]
  source_seq=0 source_capture_us=<client timestamp>
  echo matches the tick we sent: True
  age of source snapshot on our clock: <measured> ms
  view_skew_us=<measured>

===== RLDX-1 sync summary =====
ticks published: <count> ; action chunks received: <count>
WebRTC RTT ms: avg=<measured> (from <count> samples)
RTC: requests=<count> actions_executed=<count> resets=<count>
RTC request-to-response ms: p50=<measured> p99=<measured>
inter-arrival ms: p50=<measured> p99=<measured>
observation-to-action E2E ms: p50=<measured> p99=<measured>
echo correlation: <matched>/<count> chunks
view_skew_us: p50=<measured> p99=<measured> max=<measured>
command_errors: <none or count>
```

| Metric                      | Meaning                                                                                                                       |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `WebRTC RTT`                | Network round-trip estimate from the SDK. This is separate from RTC latency.                                                  |
| `RTC request-to-response`   | Time from the client sending a request until its matching action chunk arrives, measured on the client clock.                 |
| `observation-to-action E2E` | Time from the shared capture time of the source observation until its action arrives, measured on the client clock.           |
| `inter-arrival`             | Time between action chunks. This measures cadence, not per-chunk latency.                                                     |
| `view_skew_us`              | Capture-time spread across the views used for a chunk. Expect zero when the model uses views from the same observation tick.  |
| `echo correlation`          | Whether returned source stamps match ticks that the client sent.                                                              |
| `resets`                    | RTC recovery events, such as missed deadlines or an invalid plan chain. If this count rises, inspect the client error output. |
| `actions_executed`          | Simulated execution steps. These are not commands sent to robot hardware.                                                     |
| `command_errors`            | Errors from the model, including invalid requests or state fallback.                                                          |

For latency metrics, p50 is the median and p99 is the 99th percentile.

In streaming mode, cadence follows the server execution horizon. In RTC mode, requests follow the
client execution horizon. A late response does not shift the control timeline.

The client prints RTT every 10 seconds and its average in the final summary. `N/A` means no valid
RTT measurement is available. Use `--stats-interval 5` for five-second reports or
`--stats-interval 0` to disable them.

If the deployment does not return source echo fields, E2E and echo correlation are unavailable. View
skew can still be available because frames retain their shared capture time.

## What the handshake selects

The client reads the `model_schema` handshake. It does not hardcode the views, state layout, or
control rate. The handshake selects:

* The views (`left_view`, `right_view`, and `wrist_view`), resolution, and control rate.
* The state vectors and their lengths.
* The state carrier, either frame metadata or `set_state_json`.

The client reads one clock value with `time_micros()` at each observation tick. It sends that value
as `capture_time_us` on all three frames. Use this monotonic clock instead of `time.time()`. It
serializes one state snapshot and attaches the same bytes to each frame when the carrier is
`frame_metadata`.

When the handshake announces `capture_us` and `seq` in `state_tag_keys`, the client includes them in
the state JSON. RLDX-1 echoes them as `source_capture_us` and `source_seq` on the action chunk. The
client uses the echo to identify the observation that produced the action.

The correlation fields `source_capture_us`, `source_seq`, and `view_skew_us` can be `null`. Null
means the measurement is unavailable, not zero.

## Guided RTC

This cookbook configures guided Real-Time Chunking (RTC) in `config.yml`. The client controls
inference timing when the handshake announces `inference_trigger: client_request`.

The model uses a 20 Hz control rate and an action horizon of 16. It uses an RTC execution horizon of
8 and an RTC delay of 5 control steps. Each returned chunk contains 16 actions, but the client
requests a replacement every 8 steps.

The scheduler starts in a hold state and requests the first plan without a prefix. For later
requests, it includes the next 5 actions from the active plan as a prefix. It continues simulated
execution of that plan while inference runs. At `install_step`, it discards the returned prefix and
installs the remaining actions.

Each request and response carries the active plan ID and install metadata. A late response or an
invalid plan chain triggers `reset` and returns the scheduler to its hold state. If a deployment
announces `inference_trigger: streaming`, the server controls inference timing automatically.

When state is missing or invalid, the model applies its configured fallback. The default `hold_last`
value reuses the last valid state and skips inference until the first valid state arrives. The
client reports a `command_error` with `command="state"` when this fallback engages. Other
configurations can fill missing state with zeros or skip inference. Inspect these errors even when
actions continue to arrive.

For the full client, metrics, and transport pattern, read the
[complete RLDX-1 cookbook guide](https://github.com/reactor-team/reactor-cookbook/tree/main/models/rldx-1/client).
