These rules prevent common runtime failures. get_extension_schema is authoritative for exact config / input field names and types; this file explains what IDs mean and which node to pick.
Interaction Protocol Requirements ⚠️
CRITICAL: Certain Discord triggers impose strict timing requirements on how you respond. Violating these causes "The application did not respond" or "interaction failed" errors, even if your other actions succeed.
| Trigger Type | Required first action (within ~3s) | Timeout | What happens if violated |
|---|---|---|---|
discord_slash_command | See First response nodes below | ~3 seconds | Discord shows "The application did not respond" even if discord_send_message succeeds |
discord_button_click | Same | ~3 seconds | Same |
discord_select_menu | Same | ~3 seconds | Same |
discord_modal_submit | Same | ~3 seconds | Same |
discord_message_create | No requirement | N/A | Any action (discord_send_message, etc.) |
First response nodes (interaction triggers only)
These count as acknowledging the interaction (Interactions API). Pick one as the first action after the trigger:
| Node | When to use |
|---|---|
discord_interaction_response | Immediate text/embed reply (responseType: reply) |
discord_defer_interaction | Work may take longer than ~3s; shows "thinking" until you finish the deferred response |
discord_show_modal | Open a modal form (e.g. /warn → modal for reason); user continues on Modal Submit trigger |
discord_respond_to_interaction | Same as a direct reply; also edits the deferred "thinking" message when placed after defer |
discord_send_message, roles, bans, HTTP, AI, etc. do not acknowledge the interaction — use them after one of the nodes above (or after defer + a node that clears defer; see below).
Rule summary
If your trigger is an interaction type (slash command, button, select menu, or modal submit):
-
First action MUST be one of the first response nodes in the table above.
-
After defer (
discord_defer_interaction), you must complete the deferred response or Discord keeps "thinking" for up to ~15 minutes:discord_respond_to_interactionordiscord_edit_interaction_response— replaces the thinking message (preferred)discord_followup_message— first use after defer edits that placeholder; later uses are additional messages- If the graph only posts via
discord_send_message, the runtime removes the orphan thinking indicator when the automation finishes
-
After the interaction is acknowledged, you may use any other action (
discord_send_message, moderation, variables, HTTP, etc.). -
NEVER use
discord_send_messagealone as the first action after an interaction trigger.
Why This Matters
Discord's interaction model uses two separate APIs:
- Interactions API:
interaction.reply()/deferReply()— must be called within ~3 seconds - Messages API: posting to channels via
channelId
Your discord_send_message node uses the Messages API. It can post text to a channel successfully, but Discord still shows "interaction failed" because the interaction was never acknowledged.
Common Pattern
[Slash Command /hello] → [Interaction Response]
responseType: reply
content: "Hello! You ran /hello"
ephemeral: false
Do NOT do this:
[Slash Command /hello] → [Send message] ← WRONG! Interaction not acknowledged
channelId: {{outputs.trigger.channel.id}}
For slow operations (AI, database, etc.)
[Slash Command] → [Defer interaction] → ... your work ... → [Respond to interaction]
Use Respond to interaction (or Edit interaction response) after defer — not only Follow-up message on its own, unless it is the first message after defer (that node edits the thinking placeholder when deferred).
Always check get_extension_schema for handlerConfig.interactionProtocol metadata when using interaction-based triggers.
Messaging
| Goal | Node | Required IDs | Never do this |
|---|---|---|---|
| Post in a server channel, thread, or forum | discord_send_message | channelId = Discord channel snowflake (text, announcement, thread, etc.) | Pass a user id as channelId → Discord 404 Unknown Channel |
| Welcome / notify a user in private (DM) | discord_send_dm | userId = Discord user snowflake | Use discord_send_message with the member’s user id as channelId — wrong API surface |
| Reply in a channel using a known message | discord_reply_to_message | channelId, messageId, content | — |
| After a slash command / button / select / modal | discord_interaction_response or discord_followup_message | Needs discordInteraction in runtime context from that trigger | followup_message without an active interaction context will fail |
Rule of thumb: If the user says “DM”, “private message”, “welcome them personally”, or “not in the server chat”, plan discord_send_message for the public welcome channel and discord_send_dm for the direct message — not two discord_send_message nodes with mixed id types.
Moderation / guild (typical inputs)
discord_add_role/discord_remove_role:guildId,userId,roleIddiscord_ban_member: check schema fordeleteMessageDaysvs seconds in API; useget_extension_schemadiscord_timeout_member: schema usesduration(milliseconds), notdurationMs, unless the schema says otherwise — always confirm withget_extension_schema
Multiple TRIGGER nodes on one automation
The graph can include more than one TRIGGER node (e.g. Message Create + Message Reaction Remove). The Discord gateway dispatches each gateway event to every trigger whose definition matches that event; execution begins at that node’s id (triggerNodeId). The automation.trigger field is still the designated primary for defaults — it does not forbid extra trigger nodes.
Triggers vs actions
- Trigger nodes only need to match the gateway event; payload shape is in trigger outputs /
discordTriggerData. - Action nodes perform API calls; wrong id types produce 4xx errors that look generic in logs — cite
channelIdvsuserIdwhen explaining fixes.
Debugging “Unknown Channel” (10003)
- Confirm the node is
discord_send_messageandchannelIdis copied from a channel id (Developer Mode in Discord), not a user id, guild id, or role id. - If the intent was a DM, replace the node with
discord_send_dmand mapuserIdfrom the trigger’suser.id/member.id.
Extensions on the bot
install_extension/uninstall_extension— use the sameextensionNameas in the catalog (list_extensions). After swapping extensions, validate_automation again (graph must not reference an uninstalled extension). Preferget_extension_schemabefore changing nodes.
