KAL actions
Every Discord action KAL v2 can perform, with exact statement syntax, permission needs and result capture.
Actions are the statements that do something. Every action ends with ;, and every action accepts an optional INTO <var> clause that captures its outcome.
Messages#
| Statement | Notes |
|---|---|
REPLY <expr> [EPHEMERAL]; | Reply in the invocation context; EPHEMERAL only the caller sees |
SEND MESSAGE <expr> [TO <target>]; | Content message; target a channel or member |
SEND EMBED { β¦ } [TO <target>]; | Rich embed β see Components |
UPDATE MESSAGE <target> WITH { content = <expr>; }; | Edit a bot message's content |
DELETE MESSAGE <target>; | Remove a message (omit the target in message events to delete the triggering message) |
DEFER INTERACTION [EPHEMERAL]; | Acknowledge an interaction; buy 15 minutes for FOLLOWUP |
FOLLOWUP <expr> [EPHEMERAL]; | Send after a defer |
REACT <emoji> [TO <message>]; | Add a reaction |
REMOVE REACTION <emoji> FROM <message>; | Remove a reaction (from USER <user> for someone else's) |
PIN MESSAGE <m> [IN <ch>]; / UNPIN MESSAGE <m> [IN <ch>]; | Pin management |
CROSSPOST MESSAGE <m> [IN <ch>]; | Publish an announcement-channel message |
ATTACH <url> [AS <filename>] [TO <target>]; | Attach a file by URL (https) |
KAL VERSION 2.0;
AUTOMATION message_actions {
WHEN EVENT message_sent {
IF message.content == "ping" THEN {
REACT "β
" TO message;
REPLY "Pong!";
} END IF;
}
}
Members & roles#
| Statement | Notes |
|---|---|
ADD ROLE <role> TO <member>; | Role by id/name; hierarchy is enforced |
REMOVE ROLE <role> FROM <member>; | Same |
TIMEOUT <member> FOR <ms> [WITH <reason>]; | Duration in milliseconds; β€ 28 days |
REMOVE TIMEOUT FROM <member>; | Clear an active timeout |
| `BAN <member> [WITH <reason>] [DELETE <n> DAYS\ | HOURS\ |
UNBAN <user> [WITH <reason>]; | Lift a ban |
KICK <member> [WITH <reason>]; | Remove a member |
KAL VERSION 2.0;
AUTOMATION moderation_actions {
WHEN COMMAND banhammer [permission: "BanMembers"] {
BAN member WITH "Severe infraction" DELETE 7 DAYS;
REPLY "Done.";
}
}
The bot's own Discord permissions gate these actions (Ban Members for BAN/UNBAN, Kick Members for KICK, Moderate Members for timeouts, Manage Roles for roles). Protected members (the server owner, higher roles) are refused.
Channels & threads#
| Statement | Notes |
|---|---|
PURGE <n> [FROM <channel>]; | Bulk delete, 1β100 messages; needs Manage Messages |
CREATE CHANNEL <name> [TYPE <t>] [IN <category>] [TOPIC <topic>]; | Needs Manage Channels |
EDIT CHANNEL <ch> [NAME n] [TOPIC t] [SLOWMODE s] [NSFW b] [CATEGORY c]; | Or WITH { NAME β¦; } block form |
DELETE CHANNEL <ch> [WITH <reason>]; | Permanent |
SET PERMISSION ON <ch> FOR <target> [ALLOW <a>] [DENY <d>]; | Permission overwrites |
REMOVE PERMISSION ON <ch> FOR <target>; | Clear an overwrite |
| `CREATE THREAD <name> [FROM <msg> \ | IN <ch>] [TYPE <t>] [ARCHIVE <ms>];` |
CREATE FORUM_POST <name> IN <ch> WITH <content> [TAGS <expr>]; | Post into a forum channel |
ARCHIVE THREAD <t>; / LOCK THREAD <t>; | Thread moderation |
Flow-control actions#
| Statement | Notes |
|---|---|
LOG <expr>; | Structured log line for the run |
INSPECT <expr>; | Debug dump of a value |
ABORT [WITH <reason>]; | Stop the run immediately |
RATE <key> LIMIT <n> WITHIN <ms> { β¦ }; | Run the block only if under n per window |
LOCK <key> { β¦ } / UNLOCK <key>; | Cross-run mutual exclusion |
KAL VERSION 2.0;
AUTOMATION guarded_action {
WHEN COMMAND claim {
LOCK "claim_ticket" {
STATE INCREMENT "claims" BY 1;
}
UNLOCK "claim_ticket";
REPLY "Claimed.";
}
}
Capturing outcomes with INTO#
Every action can write its result into a variable. The result is a map with at least ok (boolean) and status ("SUCCEEDED" or "FAILED"):
KAL VERSION 2.0;
AUTOMATION capture_demo {
WHEN COMMAND clear {
PURGE 10 FROM channel INTO outcome;
IF outcome.ok THEN {
REPLY "Purge succeeded.";
} ELSE {
REPLY "Purge failed β check my permissions.";
} END IF;
}
}
Failed actions do not crash the run when captured β the failure lands in the variable and your script decides what to do. Un-captured failures surface as runtime errors with the action's line number.