Discord Action

Drives a Discord server from a flow. Seventeen operations grouped the way the panel groups them — messages, channels, threads, direct messages, and members & roles — so a flow can post a release note, open a thread for the discussion, and hand someone a role when they react.

Setup

Pick a Discord credential: a bot token (your own bot), an OAuth connection (HostWebhook's app, installed in one server with Add to Discord), or an incoming webhook. The kind you pick decides which operations are available. A webhook can post, and it can get, edit and delete the messages it posted itself — only those, and only in its own channel. It cannot react, pin, open threads, send DMs, quote-reply, answer a slash command or touch channels and roles, so the operation list narrows to match.


Mode — action or AI toolkit

The Mode selector decides who drives the node. In Action mode you pick one operation and fill its fields, and the node does that every time it runs. In AI toolkit mode the operations become tools an AI Node can call, and the model chooses which one and with what arguments.

ℹToolkit mode is opt-in per node, and it is what makes this node show up in an AI Node's tool picker. A node left in Action mode is invisible to agents.

What the agent has to say

  • The server is optional. No Discord tool requires guildId. When the model leaves it out, the tool uses the server HostWebhook's app was installed in (an OAuth connection). Your own bot can sit in several servers, so with a bot token the model still names the server when the operation needs one.
  • The channel comes from the trigger. When the run started from a Discord trigger, the event's channelId fills the tool's channelId if the model leaves it out. If the model picks a channel — "post it in #general" — its choice wins.
  • Templates never touch what the model writes. A {{…}} in the model's text reaches Discord as is. One thing is converted: models often write a line break as a literal \n, so in toolkit mode the \n, \r and \t the model wrote become real line breaks and tabs — the same in a message, a DM and an edit.

Operations

The Operation dropdown decides what the node does and which fields appear under it. These are the exact values the API validates against:

ValueIn the dropdownWhat it does
sendMessageSend messagePost text/embed to a channel or thread. Optional reply-to + threadId.
editMessageEdit messageEdit content/embeds of a message the bot (or the webhook) posted.
deleteMessageDelete messageDelete by id. Messages from other users need Manage Messages.
getMessageGet messageFetch a single message plus its reactions and attachments.
addReactionAdd reactionReact as the bot. Custom emoji format: name:id.
removeReactionRemove reactionRemove the reaction the bot itself added.
pinMessagePin messagePin a message in its channel. Needs Pin Messages (Discord split it from Manage Messages, which no longer pins).
createChannelCreate channelCreate text/voice/forum/announcement/category in a guild.
editChannelEdit channelRename, change topic, slowmode, parent category.
deleteChannelDelete channelPermanently deletes a channel — irreversible.
getChannelGet channelFetch the full config and permissions of a channel.
listChannelsList channelsIterate every channel in a guild — output is iterable.
createThreadCreate threadOff a message OR standalone (public/private/announcement).
sendDMSend DMDirect message a user by id. Fails with 403 if they don't accept DMs.
addRoleAdd role to memberThe role of the bot must be ABOVE the target role in the hierarchy.
removeRoleRemove role from memberSame hierarchy rule applies.
getMemberGet memberFetch the nick, roles, joined_at and user object of a member.

Replying to a slash command

When a Discord trigger fires on a slash command, HostWebhook answers Discord at once and the user sees Bot is thinking… while the flow runs. Send message with Reply inline to slash command on — the default — replaces that line with your message instead of posting a separate one.

  • Only the command that started this run. The reply goes to the interaction in this run's own trigger event — never to another run's command, another user's or another flow's. Two people typing /ask a second apart each get their own answer.
  • No command, normal post. A run that did not start from a slash command — a mention, a schedule, a webhook — posts in Channel ID as usual, whatever the switch says.
  • 15 minutes. Discord keeps a command open for a reply for 15 minutes. A run that reaches this node later — after a Delay or an approval, say — posts in Channel ID instead. The same happens when Discord no longer accepts the reply (it answers 401 or 404, as it does for the example event of a Test push). Keep Channel ID filled, e.g. {{payload.channelId}} from the trigger, so there is somewhere to post. A reply Discord refuses never marks your Discord credential as failing.
  • If a Discord Action fails in a run started by a slash command, the Bot is thinking… line of that run's command becomes ⚠️ Pipeline error and the reason, so the user is not left waiting. It only ever touches that run's own command.
  • Not with a webhook credential. Answering a command belongs to the application, so the switch is not offered there.

Text is sent as typed

Every field takes templates — {{payload.content}}, {{payload.options.question}} — and fills them in as text. What you typed is what Discord receives:

  • A message that starts with [ or { stays as you wrote it. Values put into it go in as they are — quotes and line breaks are not escaped as JSON.
  • A \n typed in a field stays as those two characters, so Windows paths (C:\new\temp) and code survive. For a line break, press Enter in the field. Only text an AI agent writes in toolkit mode has its \n turned into a line break (see What the agent has to say).
  • Embeds go through the API. The panel has a text field only; to send an embed, pass Discord's embeds array in the node's operationConfig. Templates inside it are filled in value by value, so an embed's title can be {{payload.username}}.

Permissions

Discord decides what the bot may do from its role in the server. Add to Discord asks for what the operations use: View Channels, Send Messages, Embed Links, Attach Files, Read Message History and Add Reactions to read and answer, plus the ones below. Discord's install screen lets you untick any of them; it never asks for Administrator, Kick or Ban. A server where the app was added before 3 October 2026 keeps the short list (read and answer only) until you run Add to Discord again for it. An operation whose permission the bot lacks fails until it has it:

  • Create, edit or delete a channel — Manage Channels.
  • Pin a message — Pin Messages. Discord split it from Manage Messages, which no longer pins.
  • Delete someone else's message — Manage Messages.
  • Create a thread — Create Public Threads (Create Private Threads for a private one). Posting into a thread needs Send Messages in Threads.
  • Add or remove a role — Manage Roles, with the bot's role above the target role.

Grant it in Discord: Server Settings → Roles → the bot's role (it carries the bot's name) → turn the permission on. Your own bot has the permissions you picked when you invited it: edit its role the same way, or invite it again with them.

When Discord refuses for a missing permission (403 Missing Permissions, or Missing Access when the bot cannot see the channel at all), the run fails with a 403 that names the permission the operation needs and says where to grant it. A 400 keeps Discord's own explanation — a message longer than 2,000 characters, for example.


Gotchas

  • Role hierarchy is enforced by Discord, not by us. The bot's own highest role has to sit above the role it is adding or removing. Same permissions, wrong order, and the call fails.
  • Deleting other people's messages needs Manage Messages. The bot can always delete its own (see Permissions).
  • A DM to someone who doesn't accept DMs fails. If the user turned off DMs from server members, or blocked the bot, Discord answers 403 (code 50007, Cannot send messages to this user) and the run fails at this node with a 403 that says so. If delivery matters, post in a channel instead.
  • Custom emoji use the name:id form in reactions, not the :name: you type in the client.
  • Deleting a channel is irreversible. There is no trash in Discord.
  • listChannels returns an iterable payload, so a Loop or Aggregator downstream fans out over the channels with no glue.