What Commands Are For
Commands are for real-time interaction while your model is generating. Think of them as the controls a user has while watching and interacting with the video stream:- Keyboard inputs (WASD for movement, spacebar for actions)
- Changing the prompt mid-generation
- Camera controls (pan, tilt, zoom)
- Adjusting parameters like speed or intensity
- Triggering actions (attack, jump, reset)
The @command Decorator
To accept user input, you decorate methods on your model with @command. Each decorated method
becomes an endpoint that users (or frontends) can call while your model is generating.
@command decorator takes two arguments:
name(required): The command name that clients use to call this methoddescription(optional): A human-readable description of what the command does
{"type": "set_prompt", "data": {"prompt": "a rainy night"}},
Reactor automatically routes it to your set_prompt method, and your next generated frames will
reflect the new prompt.
Typing Your Parameters
Reactor uses your function’s type annotations to automatically generate a schema for each command. This schema is used for validation and can be read by frontends to auto-generate UI controls. Supported types includestr, int, float, bool, and Literal for enumerated values.
Using Literal for Fixed Options
When a parameter should only accept specific values, use Literal:
direction must be one of those five strings. Frontends
can render this as a dropdown or button group.
Using Pydantic Field for Rich Metadata
For more control over validation and UI hints, use Pydantic’s Field:
Field lets you specify:
ge/le: Minimum and maximum values (great for sliders)description: What this parameter does...: Makes the parameter required (use a default value to make it optional)
Combining Everything
Here is a complete example with multiple parameter types:Automatic UI Generation
When you properly type your commands, Reactor can expose a schema that frontends read to automatically generate controls. This means you can test your model interactively without writing any frontend code. The schema includes command names, descriptions, parameter types, and constraints, so a generic controller can render appropriate inputs (text fields, sliders, dropdowns) for each command. As a bonus, the headless runtime (reactor run --runtime headless) also discovers your commands
from the @command decorators, letting you test them from the command line without any frontend.
Thread Safety: Commands Run in Parallel
Here is something important to understand: your command methods run in a different thread than yourstart_session loop.
When a user sends a command, Reactor calls your decorated method immediately, while your generation
loop continues running in its own thread. The safest pattern is to store user input in instance
variables, and have your pipeline read from those variables each frame:
threading.Lock.
If your pipeline is a separate class, consider giving it setters that your commands call directly,
rather than passing every user input through the
generate() signature. This keeps your code
cleaner as the number of inputs grows. See Writing a Pipeline
for architectural patterns.Now that you know how to accept user input, the next step is understanding how to structure your pipeline for continuous, real-time generation.
Writing a Pipeline
Learn how to structure your model for continuous real-time generation.
