Writing Actions
Actions are async JavaScript programs. Here are common patterns to help you write effective automations.
Basic structure
Section titled “Basic structure”An action has access to event, trigger, and several utility functions. The script runs top-to-bottom.
// Read event dataconst user = event.payload.user;const message = event.payload.message;
// Do somethingawait module.request("twitch", "sendMessage", { text: `Got your message: ${message}`});Calling modules (RPC)
Section titled “Calling modules (RPC)”Your actions communicate with connected modules via RPC (Remote Procedure Call). Each module exposes methods described in its manifest (visible in the Modules page).
Request (with response)
Section titled “Request (with response)”Use module.request() when you need a result. Your action pauses until the module responds.
const result = await module.request("twitch", "getUser", { username: "viewer42"});log("User info:", result);Notify (fire-and-forget)
Section titled “Notify (fire-and-forget)”Use module.notify() when you just want to send a command. Your action continues immediately.
await module.notify("obs", "switchScene", { scene: "Gaming" });Targeting
Section titled “Targeting”// Any module in the "twitch" group — Rawtoh picks one that's onlineawait module.request("twitch", "sendMessage", { text: "Hi" });
// A specific module by group/nameawait module.request("twitch/bot1", "sendMessage", { text: "Hi from bot1" });What methods are available?
Section titled “What methods are available?”The available methods depend on the module. Check the manifest of the module group in the Modules page to see:
- Method names and descriptions
- Parameters (name, type, required or not)
- Expected return values
- Example calls
You can also use the Test RPC button in the dashboard to try methods interactively before writing your action.
Module logs
Section titled “Module logs”Every RPC call made during an action execution is logged automatically. In the process details, you can see:
- Which method was called and on which module
- The parameters sent
- Whether it was a request or a notify
- How long it took
- Any errors that occurred
Using storage
Section titled “Using storage”Storage is a simple key-value store shared across all actions.
Counter example
Section titled “Counter example”const key = `command_count_${event.payload.user}`;const count = (await storage.get(key)) || 0;await storage.set(key, count + 1);
await module.request("twitch", "sendMessage", { text: `You've used this command ${count + 1} times!`});Storing complex data
Section titled “Storing complex data”// Store an objectawait storage.set("last_event", { user: event.payload.user, message: event.payload.message, time: Date.now()});
// Retrieve it laterconst last = await storage.get("last_event");if (last) { log("Last event was from", last.user, "at", last.time);}Timing and delays
Section titled “Timing and delays”await module.request("twitch", "sendMessage", { text: "Starting countdown..." });await sleep(1000);await module.request("twitch", "sendMessage", { text: "3..." });await sleep(1000);await module.request("twitch", "sendMessage", { text: "2..." });await sleep(1000);await module.request("twitch", "sendMessage", { text: "1... Go!" });Logging
Section titled “Logging”Use log() to debug your actions. Logs appear in the process details in the dashboard.
log("Event received:", event.name);log("Payload:", event.payload);log("User:", event.payload.user, "Message:", event.payload.message);Error handling
Section titled “Error handling”If a module call fails, it throws an error. Use try/catch to handle it:
try { await module.request("twitch", "sendMessage", { text: "Hello!" });} catch (error) { log("Failed to send message:", error);}Limits
Section titled “Limits”Keep in mind:
- Actions timeout after 30 seconds
- Memory is limited to 8 MB
- Logs are capped at 1000 entries per execution
If your action needs to do a lot of work, break it into smaller automations.