Use this file to discover all available pages before exploring further.
The Reactor SDKs are how your app opens a session, sends commands, and receives video and events from any model. There are two:
JavaScript ships both a React API (provider, components, hooks) and an imperative API (the Reactor class). Use React for browser apps, imperative for vanilla JS or fine-grained control. The browser obtains a short-lived JWT token from your server.
Python is an async library for scripts, servers, and computer-vision pipelines. It receives frames as NumPy arrays and authenticates with your API key directly, server-side.
Every code example below offers all three. Pick a tab and it stays selected down the page.
Never ship your API key to the browser. Browser apps exchange it for a JWT on your server; Python
runs server-side and uses the key directly. See Authentication.
The base Reactor class is the generic, model-agnostic entry point. It speaks raw JSON over the wire: you call sendCommand(name, payload) and listen for generic message events. It works against any model. This page teaches the base layer, so the examples work no matter which model you connect to.
Typed SDKs (for example, HeliosModel) extend the base class and expose strongly-named methods (setPrompt(), sendImage(), …) that mirror a model’s schema. They add ergonomics, not capabilities, and every method is still a sendCommand() under the hood.
Reach for the base Reactor class when you’re experimenting with a model that has no typed SDK yet, developing locally against an in-progress model, writing a one-off script, or want a single SDK that can talk to several models. For everything else the typed SDK is the recommended path. See Typed model SDKs for the full story and the name-to-name mapping.For the commands and events a specific model accepts, see the Model API Reference.
from reactor_sdk import Reactorasync with Reactor(model_name="your-model-name", api_key=os.environ["REACTOR_API_KEY"]) as reactor: # disconnects automatically on exit pass
See Authentication for how to obtain a token or API key.
The browser SDK delivers the model’s video as a media track you render in a <video> element. Python delivers decoded frames as NumPy arrays for processing.
JavaScript
React
Python
Listen for the trackReceived event and attach the stream to a video element.
Track listener
const video = document.getElementById("video") as HTMLVideoElement;reactor.on("trackReceived", (name, track, stream) => { video.srcObject = stream;});
ReactorView displays the model’s video output automatically.
ReactorView
import { ReactorView } from "@reactor-team/js-sdk";<ReactorView className="w-full aspect-video" videoObjectFit="cover"/>
Frames are delivered as NumPy arrays with shape (H, W, 3), dtype uint8, in RGB color order. They start arriving once the connection reaches READY and continue until you disconnect.
Frame handler
@reactor.on_framedef on_frame(frame): print(f"Frame: {frame.shape}") # e.g. (768, 1280, 3)
Common uses:
Common uses
# Save with PILfrom PIL import ImageImage.fromarray(frame).save("frame.png")# Process with OpenCV (convert RGB to BGR first)import cv2cv2.imwrite("frame.png", cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))# Run inferenceresult = my_model(frame)
Commands control what the model does. The available commands depend on the model. See the Model API Reference. Wait for the connection to reach ready before sending commands; the model is not available until the connection is fully established.
JavaScript
React
Python
Send command
reactor.on("statusChanged", async (status) => { if (status === "ready") { await reactor.sendCommand("set_prompt", { prompt: "a forest at dawn" }); }});
Send command
import { useReactor } from "@reactor-team/js-sdk";function Controls() { const { sendCommand, status } = useReactor((s) => s); return ( <button disabled={status !== "ready"} onClick={() => sendCommand("set_prompt", { prompt: "a forest at dawn" })} > Set prompt </button> );}
Send command
from reactor_sdk import ReactorStatus@reactor.on_status(ReactorStatus.READY)async def on_ready(status): await reactor.send_command("set_prompt", {"prompt": "a forest at dawn"})
# From a path (name and MIME type are inferred)ref = await reactor.upload_file("photo.jpg")# From bytesref = await reactor.upload_file(image_bytes, name="photo.jpg")# From a file objectwith open("photo.jpg", "rb") as f: ref = await reactor.upload_file(f)
uploadFile() returns a FileRef (JavaScript ·
Python) containing the upload ID, filename, MIME type, and
size. Pass multiple FileRef values in a single command and mix them with scalar arguments like
transition.
The track name ("webcam") must match the attribute name declared on the model. The model declares which tracks it accepts in its capabilities, which are fetched automatically during connection.
from reactor_sdk import ReactorError@reactor.on_errordef on_error(error: ReactorError): print(f"[{error.component}:{error.code}] {error.message}") if error.recoverable: print(f"Retrying in {error.retry_after or 3}s")
See ReactorError (JavaScript ·
Python) for all error codes and fields.
If a connection drops unexpectedly, the session stays alive on the GPU for 30 seconds. Reconnect
within that window to resume without losing server-side state. For more information, see
Sessions.
JavaScript
React
Python
Reconnect
// Terminate the sessionawait reactor.disconnect();// Disconnect but keep the session alive on the serverawait reactor.disconnect(true);await reactor.reconnect();
Reconnect
import { useReactor } from "@reactor-team/js-sdk";const { disconnect, reconnect } = useReactor((s) => s);// Terminate the sessionawait disconnect();// Disconnect but keep the session alive on the serverawait disconnect(true);await reconnect();
Reconnect
# Terminate the sessionawait reactor.disconnect()# Disconnect but keep the session alive on the serverawait reactor.disconnect(recoverable=True)await reactor.reconnect()
To reconnect automatically when the error is recoverable:
import { useReactor } from "@reactor-team/js-sdk";const { reconnect, lastError } = useReactor((s) => ({ reconnect: s.reconnect, lastError: s.lastError,}));// Watch the store's lastError and reconnect when a recoverable error lands.useEffect(() => { if (lastError?.recoverable) { const timer = setTimeout(() => reconnect(), (lastError.retryAfter ?? 3) * 1000); return () => clearTimeout(timer); }}, [lastError, reconnect]);
Auto-reconnect
from reactor_sdk import ReactorError@reactor.on_errorasync def on_error(error: ReactorError): if error.recoverable: await asyncio.sleep(error.retry_after or 3) await reactor.reconnect()