Modules
Modules are the bridge between Rawtoh and the outside world — learn how they work.
Modules are the bridge between Rawtoh and the outside world. They connect to external services and let your automations interact with them.
Module (definition)
A module (also called a module definition or module group) describes an integration. It defines:
- A slug — a unique identifier like
twitch,obs, orspotify - A name — a human-readable label
- A manifest — an OpenRPC document describing what the module can do
Private vs public modules
Module definitions can be either:
- Public — visible to all organizations. These are shared integrations (e.g. Twitch, OBS).
- Private — scoped to a single organization. Only members of that organization can use them.
The manifest
The manifest is the module's API contract, written as an OpenRPC document. It lists:
- Events the module can emit — e.g.
chat.message,eventsub.stream_online. These are the events your triggers can watch for. - Methods the module exposes — e.g.
chat.say,scene.set_current. These are functions your actions can call.
The manifest comes from the module's author and is set on the module definition. It powers the autocomplete in the script editor and lets you see what's available. All names use dot notation — e.g. chat.message, chat.say.
Module Instance
A module instance is an actual, running connection. While a module is a definition, an instance is a deployment.
Example:
- Module definition:
twitch - Instances:
main-bot— your primary Twitch botalerts-bot— a secondary bot for alerts
Each instance is authenticated by its own Ed25519 key pair, which the module generates itself — Rawtoh only ever stores the public half. The pair is bound to the instance once, by redeeming an enrollment token. After that there is no secret to copy, rotate, or leak: on every connection the module proves it holds the private key by signing a challenge from the server.
Enrollment token
The token (rth_e_…) is the only thing a human ever copies. It is:
- Shown once — when the instance is created, or from Re-enroll later on
- Single use — redeeming it spends it; a failed enrollment needs a fresh token, not a retry
- Short-lived — it expires after 15 minutes
- Opaque — it carries no hub address or organization; the module is configured with the hub it talks to
Until a token is redeemed, the instance shows as Not enrolled and cannot connect. Redeeming a token for an instance that is already enrolled replaces its key: that is how you recover a lost private key or move a module to another machine, and any process still connected with the old key is disconnected. Deleting the instance revokes the key and closes the connection at once.
Why instances?
You might need multiple connections to the same service. For example, two Twitch bots, or multiple OBS instances on different machines. Each instance operates independently and can emit its own events.
How modules connect
Modules connect to Rawtoh via a WebSocket connection. Once connected, a module can:
- Register itself — sign a server-issued challenge with its private key
- Emit events — send data to Rawtoh that triggers can react to
- Receive method calls — Rawtoh sends requests to the module when an action calls one of its methods
Rawtoh automatically manages subscriptions — when you create, update, or delete triggers, connected modules are kept in sync without any manual action.
Calling modules from scripts
In your action code, use the module() function to call methods on connected modules:
import { module } from "rawtoh"
// By group only (picks the most recently connected instance)
await module("twitch").request("chat.say", { message: "Hello!" })
// By group and instance name (targets a specific instance)
await module("twitch", "main-bot").request("chat.say", { message: "Hello!" })
// Fire-and-forget (doesn't wait for the module's response)
await module("obs").notify("scene.set_current", { sceneName: "BRB" })Communication modes
| Mode | Description |
|---|---|
.request(method, params) | Waits for the module's response before continuing |
.notify(method, params) | Fire-and-forget — continues immediately without waiting |
Setting up a module
Hosted modules: Install with Rawtoh
The first-party modules (Twitch, OBS, Discord, Cron, Board) run as web apps on Rawtoh's domain. Sign in there with your Rawtoh account and click Install with Rawtoh: the module creates the instance in your organization, enrolls its key pair, and connects — no token to copy. You need the owner role in the organization. Each module also accepts a pasted enrollment token under Enrollment token (advanced) if you'd rather create the instance yourself.
Any other module: enrollment token
- Go to Module → Definitions and make sure the module definition exists (or create one)
- Go to Module → Instances, click Add instance, pick the definition and give the instance a name
- Copy the enrollment token — it's shown only once and expires in 15 minutes
- Paste it into your module (for headless modules, typically the
RAWTOH_ENROLL_TOKENvariable or an--enrollflag on first run). The module generates its key pair and redeems the token - The instance switches from Not enrolled to online once the module establishes its WebSocket connection
Lost the private key, or reinstalling on another machine? Pick Re-enroll on the instance to get a fresh token. The running module keeps working until the new token is actually redeemed.