Skip to content

Writing Actions

Actions are async JavaScript programs. Here are common patterns to help you write effective automations.

An action has access to event, trigger, and several utility functions. The script runs top-to-bottom.

// Read event data
const user = event.payload.user;
const message = event.payload.message;
// Do something
await module.request("twitch", "sendMessage", {
text: `Got your message: ${message}`
});

Your actions communicate with connected modules via RPC (Remote Procedure Call). Each module exposes methods described in its manifest (visible in the Modules page).

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);

Use module.notify() when you just want to send a command. Your action continues immediately.

await module.notify("obs", "switchScene", { scene: "Gaming" });
// Any module in the "twitch" group — Rawtoh picks one that's online
await module.request("twitch", "sendMessage", { text: "Hi" });
// A specific module by group/name
await module.request("twitch/bot1", "sendMessage", { text: "Hi from bot1" });

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.

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

Storage is a simple key-value store shared across all actions.

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!`
});
// Store an object
await storage.set("last_event", {
user: event.payload.user,
message: event.payload.message,
time: Date.now()
});
// Retrieve it later
const last = await storage.get("last_event");
if (last) {
log("Last event was from", last.user, "at", last.time);
}
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!" });

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);

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);
}

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.