ComfyUI-Slack
Connect ComfyUI and Slack
Nodes (5)
ComfyUI-Slack
<p align="center"> <img src="images/comfy_slack_connection.png" alt="ComfyUI → Slack" width="600"> </p>Send generated images, videos, text, and audio directly to a Slack channel from within a ComfyUI workflow. Drop a Send to Slack node at the end of any workflow and the result lands in your Slack channel — or a direct message — the moment it finishes rendering. No manual downloading, no copy-paste, no leaving your chat.
It also works the other way around: @mention the bot in Slack with a prompt (and optionally an image or video) and it runs the matching ComfyUI workflow, posting the result back in the same thread. See Trigger Workflows from Slack.
What it looks like
🖼️ Send Image
Wire an IMAGE output into Send Image to Slack — pick the channel (or a user for a DM),
format, and quality, and it's uploaded the instant the workflow finishes.
🎬 Send Video
Send Video to Slack encodes a frame batch (with optional audio) via the bundled FFmpeg into H.264/H.265/VP9/GIF and uploads the clip — no separate FFmpeg install required.
<table> <tr> <td width="58%"><img src="images/send_video.png" alt="Send Video to Slack node"></td> <td width="42%"><img src="images/slack_video.png" alt="Video delivered in Slack"></td> </tr> <tr> <td align="center"><em>The node in ComfyUI</em></td> <td align="center"><em>…plays back in Slack</em></td> </tr> </table>💬 Send Text
Send Text to Slack posts a Markdown message — perfect for piping an LLM caption, a prompt, or a status line straight into the channel. Standard Markdown is translated to Slack's formatting automatically.
<p align="center"> <img src="images/send_text.png" alt="Send Text to Slack node" width="820"> </p>🔊 Send Audio
Send Audio to Slack encodes an AUDIO input (MP3/M4A/Opus/FLAC/WAV) and uploads it as a
playable audio file.
Installation
ComfyUI Manager (recommended)
In ComfyUI Manager, open Custom Nodes Manager, search for ComfyUI-Slack, and click Install. Restart ComfyUI when prompted. Dependencies are installed automatically.
Manual
- Clone this repository into your ComfyUI
custom_nodesdirectory:cd ComfyUI/custom_nodes git clone https://github.com/claussteinmassl/ComfyUI-Slack - Install dependencies into the ComfyUI Python environment:
pip install -r requirements.txt - Restart ComfyUI.
Slack App Setup
ComfyUI-Slack requires a Slack Bot Token (xoxb-...) from a dedicated Slack App.
Why create your own app instead of installing one from the Slack Marketplace? ComfyUI-Slack has no hosted service behind it — it runs entirely on your machine and talks to Slack directly using a token you control. A Marketplace app would route your images and messages through someone else's servers; here nothing leaves your machine except the calls to Slack's own API. Slack tokens are also tied to a single workspace, so the app must be created and installed inside your workspace to get a token that works there. Creating the app is a one-time, few-minute setup — the manifest below makes it nearly copy-paste.
You can create the app two ways: paste a ready-made manifest (fast), or click through the settings by hand (so you understand what each one does). Both produce the same app — pick one.
Quick start: create the app from a manifest (recommended)
Slack can build an app from a manifest that pre-fills the name, scopes, and — for the listener — Socket Mode, interactivity, and event subscriptions in a single step.
- Go to https://api.slack.com/apps → Create New App → From a manifest.
- Select your workspace, then click Next.
- Switch the format toggle to JSON, paste the manifest below, click Next, then Create.
{
"display_information": {
"name": "ComfyUI",
"description": "Send ComfyUI images and videos to Slack, and trigger workflows from Slack."
},
"features": {
"bot_user": {
"display_name": "ComfyUI",
"always_online": true
}
},
"oauth_config": {
"scopes": {
"bot": [
"files:write",
"chat:write",
"channels:read",
"groups:read",
"users:read",
"im:write",
"app_mentions:read",
"files:read"
]
}
},
"settings": {
"event_subscriptions": {
"bot_events": [
"app_mention"
]
},
"interactivity": {
"is_enabled": true
},
"socket_mode_enabled": true,
"org_deploy_enabled": false,
"token_rotation_enabled": false
}
}
Slack's Create from a manifest screen defaults to YAML and its YAML parser is currently flaky (even the sample manifest can fail to validate). Use the JSON toggle instead.
This manifest configures both the send nodes and the Slack listener. The scopes
files:write, chat:write, channels:read, groups:read, and im:write cover the send nodes
(channels:read/groups:read let you type a channel name instead of an ID — public and
private respectively; im:write lets you send directly to a user as a DM); the listener
additionally needs users:read (resolve usernames in the allow-list), app_mentions:read, and
files:read, plus the entire "settings" block (Socket Mode, interactivity, and the app_mention
event). If you only want the send nodes you can drop users:read, app_mentions:read,
files:read, and the "settings" block — or just leave them; the extras are harmless.
A manifest cannot create tokens or install the app, so a few steps remain manual:
- Install the app to your workspace and copy the Bot User OAuth Token (
xoxb-...) — see steps 3–5 below. - Invite the bot to your channel:
/invite @ComfyUI. - (Listener only) create an App-Level Token with the
connections:writescope (xapp-...). App-level tokens can't be set via manifest — see Trigger Workflows from Slack.
Manual setup (what the manifest configures)
Prefer to configure the app by hand, or want to understand each setting the manifest applies? Follow these steps instead — they produce exactly the same app.
1. Create a Slack App
Go to https://api.slack.com/apps and click Create New App → From scratch.
- App name:
ComfyUI(or any name you prefer) - Workspace: select your workspace
2. Add Bot Token Scopes
In the left sidebar go to OAuth & Permissions, scroll to Bot Token Scopes, and add:
| Scope | Purpose |
|-------|---------|
| files:write | Upload images and videos |
| chat:write | Post messages to channels |
| channels:read | Resolve public channel names to IDs |
| groups:read | Resolve private channel names to IDs |
| im:write | Send directly to a user as a DM |
3. Install the App to Your Workspace
Still on OAuth & Permissions, click Install to Workspace and click Allow.
4. Copy the Bot Token
After installation you'll see a Bot User OAuth Token that starts with xoxb-. Copy it — you'll need it in the next step.
5. Set the Environment Variable
The token is never entered in the node UI. Set it in the environment before launching ComfyUI.
Windows (PowerShell, current session only):
$env:SLACK_BOT_TOKEN = "xoxb-your-token-here"
Windows (persistent, via System Properties):
Open Start → Edit the system environment variables → Environment Variables, add a new User variable named SLACK_BOT_TOKEN with your token as the value. Restart ComfyUI after saving.
macOS / Linux:
export SLACK_BOT_TOKEN="xoxb-your-token-here"
Add that line to your shell profile (~/.zshrc, ~/.bashrc, etc.) to make it permanent.
6. Choose a Destination
The nodes' channel field accepts a channel or a user:
| You enter | Goes to |
|-----------|---------|
| #general, general, or C0B6SUZMHC6 | that channel |
| @alice, or a user ID U… | a direct message to that user (needs im:write) |
Names resolve to IDs automatically. A bare name with no #/@ is treated as a channel first, then
a user — prefix with # or @ to be explicit. For a private channel the bot must be a member,
so invite it first:
/invite @ComfyUI
Prefer the raw ID? Right-click the channel → View channel details → scroll to the bottom; it looks like
C0B6SUZMHC6.
Trigger Workflows from Slack (Socket Mode)
The package can also work the other way around: a user @mentions the bot in Slack with a prompt (and optionally an attached image or video), the bot picks the matching ComfyUI workflow, runs it, and posts the result back in the same thread.
This runs as a background listener inside ComfyUI using Slack Socket Mode — an outbound WebSocket, so no public URL or ngrok is needed. It is opt-in and off by default; if you only use the send nodes you can ignore this section entirely.
<p align="center"> <img src="images/poster_mockup_workflow_example.png" alt="Poster-mockup workflow triggered from Slack" width="820"> </p>Example: an image attached to a Slack @mention enters the workflow at SLACK_INPUT_IMAGE, gets
composited into a framed poster mockup, and the SLACK_OUTPUT node sends the finished render back
to the same Slack thread.
How it works
- You save one or more workflows in API format and register them in a
manifest.json. - You @mention the bot:
@ComfyUI a cat astronaut(optionally attach an image/video). - The listener picks a workflow deterministically (no AI):
- by input type — no file → a
textworkflow, image → animageworkflow, video → avideoworkflow; - an explicit
[name]prefix always wins, e.g.@ComfyUI [poster-mockup] make a poster; - if several workflows still match, the bot posts buttons to choose.
- by input type — no file → a
- The listener injects your prompt / file / channel / thread into the workflow and queues it.
- The workflow ends in a Send to Slack node, which posts the result back in your thread.
In Slack, end to end
1. @mention the bot and attach an image. Here mockup matches more than one workflow, so the
keyword alone doesn't decide it.
2. The bot asks which workflow to run. When several workflows match, it posts buttons instead of guessing.
<p align="center"> <img src="images/slack_buttons.png" alt="ComfyUI asks which workflow to run" width="420"> </p>3. Pick one, and the result comes back in the thread. The bot confirms the queued run, @-mentions you, and posts the finished render — here the image composited into a framed poster mockup.
<p align="center"> <img src="images/slack_receive_result.png" alt="Finished poster mockup posted back in Slack" width="420"> </p>1. Extra Slack App configuration
If you created the app from the manifest above, Socket Mode, Interactivity, the
app_mentionevent subscription, and the extra bot scopes are already set — you only need to create the App-Level Token (third bullet) and reinstall/invite the bot.
In addition to the bot token setup above, do the following in your Slack App:
-
Socket Mode (left sidebar → Socket Mode): toggle Enable Socket Mode on.
-
Interactivity (Interactivity & Shortcuts): toggle on. With Socket Mode you do not need a Request URL. (Required for the disambiguation buttons.)
-
App-Level Token (Basic Information → App-Level Tokens): create one with the
connections:writescope. It starts withxapp-— this is theSLACK_APP_TOKEN. -
Event Subscriptions (Event Subscriptions → Subscribe to bot events): add
app_mention. -
Additional Bot Token Scopes (OAuth & Permissions), on top of the send scopes:
| Scope | Purpose | |-------|---------| |
app_mentions:read| Receive @mentions | |files:read| Download attached images/videos | |chat:write| Post status, errors, and choice buttons | |users:read| Resolve usernames inSLACK_ALLOWED_USERSto IDs | -
Reinstall the app to your workspace to apply the new scopes, and invite the bot to the channel (
/invite @ComfyUI).
2. Build a workflow registry
-
In ComfyUI, enable dev mode (Settings → Enable Dev Mode Options) so the Save (API Format) button appears.
-
Build a workflow that ends in a
Send Image to Slack/Send Video to Slacknode. The final send node is the only one the listener requires; rename it (right-click → Title) toSLACK_OUTPUT. Rename any of the optional input nodes too if your workflow uses them:| Rename this node to | Role | |---------------------|------| |
SLACK_OUTPUT| The finalSend … to Slacknode — receives the channel, thread, and the triggering user to @-mention. Required. | |SLACK_PROMPT(optional) | The text prompt node (e.g. the positiveCLIPTextEncode) — receives the message text. Omit it for fixed-prompt or input-only workflows; the message text is then ignored. | |SLACK_INPUT_IMAGE(optional) | ALoadImagenode — receives an attached image (slot 1) | |SLACK_INPUT_IMAGE_2,SLACK_INPUT_IMAGE_3, … (optional) | ExtraLoadImagenodes for workflows that take several distinct input images. Slot numbers must be contiguous (SLACK_INPUT_IMAGE, then_2,_3, …); the n-th attached image fills slot n | |SLACK_INPUT_VIDEO(optional) | A video-load node (e.g. VideoHelperSuiteVHS_LoadVideo) — receives an attached video | -
Click Save (API Format) and put the file in a folder alongside a
manifest.json. See the bundledworkflows/folder for working examples (manifest.json,txt2img.api.json,img2img.api.json).
manifest.json lists your workflows:
{
"workflows": [
{
"name": "txt2img",
"label": "Generate image",
"description": "Generate an image from a text prompt",
"modality": "text",
"keywords": ["image", "picture", "photo"],
"template": "txt2img.api.json"
}
]
}
| Field | Meaning |
|-------|---------|
| name | Used by the [name] override and help listing |
| label | Text shown on the Slack choice button |
| description | Shown in the @ComfyUI help listing |
| modality | text, image, video, or any — what input the workflow consumes |
| keywords | Optional words that, if present in the message, auto-pick this workflow |
| template | The API-format JSON file, relative to the manifest |
Video input needs a video-load node in your template (e.g. VideoHelperSuite). It is not a dependency of this package — install the relevant node pack separately.
Multiple input images. A workflow accepts N images, where N is the number of
SLACK_INPUT_IMAGEslot markers in its template. When you attach M images: M = N runs the workflow once (image n → slot n); M a larger multiple of N (e.g. 3 images into a 1-slot workflow, or 4 into a 2-slot one) prompts you with Continue / Cancel and, on Continue, runs the workflowM / Ntimes in batches of N; anything else (too few, or not a clean multiple) is rejected with an explanation. Fan-out is capped bySLACK_MAX_FANOUT(default 25).
3. Set the listener environment variables
| Variable | Required | Default | Purpose |
|----------|----------|---------|---------|
| SLACK_LISTENER_ENABLED | yes (to turn it on) | off | Master switch — set to 1/true |
| SLACK_APP_TOKEN | yes | — | App-level token (xapp-...) |
| SLACK_BOT_TOKEN | yes | — | Bot token (xoxb-...), reused from the send setup |
| SLACK_WORKFLOW_DIR | yes | — | Folder containing manifest.json + templates |
| SLACK_ALLOWED_USERS | one of these | empty | CSV of allowed users — names or IDs (@alice, a display name, or U…) |
| SLACK_ALLOWED_CHANNELS | one of these | empty | CSV of allowed channels — names or IDs (#general or C…) |
| SLACK_COMFY_URL | no | auto | Override the local ComfyUI URL (e.g. http://127.0.0.1:8188) |
| SLACK_MAX_INPUT_MB | no | 20 | Max size of an attachment to download |
| SLACK_MAX_FANOUT | no | 25 | Max number of runs one message may fan out into (see below) |
| SLACK_NOTIFY_USER | no | true | @-mention the triggering user in result & error replies; set to false to disable |
| SLACK_COMFY_API_KEY | only for API-node workflows | — | comfy.org API key (comfyui-...); see below |
comfy.org API nodes (OpenAI, etc.) need a key. When you queue a workflow in the browser, the ComfyUI frontend silently attaches your login token so partner/API nodes can authenticate — having credits is not enough on its own. A workflow triggered by the listener has no browser session, so any API node fails with
Unauthorized: Please login first to use this node. Generate an API key at platform.comfy.org and set it asSLACK_COMFY_API_KEY; the listener forwards it with each queued prompt. Workflows using only local nodes don't need it.
Authorization is default-deny. Until you set
SLACK_ALLOWED_USERSand/orSLACK_ALLOWED_CHANNELS, every trigger is refused. Each trigger queues a GPU job on your machine, so list only the users/channels you trust.
Names or IDs in the allow-lists. Entries may be names (
@alice,#general) or raw IDs (U…,C…); names are resolved automatically. A name that can't be resolved — a typo, an ambiguous display name, or a missingusers:read/groups:readscope — is skipped with a warning in the ComfyUI log rather than failing; ID entries always work. So a scope mistake degrades to "ID-only", it never locks everyone out.
Running the listener on several machines. You can point multiple machines at the same Slack app to share the load. Slack delivers each event to exactly one connection (at random, up to 10 connections per app), so a request runs on whichever machine happens to receive it — there are no duplicate runs. Buttons (workflow choice and fan-out confirmation) are stateless: a click can be handled by any machine, which re-downloads the needed input files on demand. For this to behave consistently, give every machine an identical
SLACK_WORKFLOW_DIR(samemanifest.json, templates, and models) and the same allow-lists; otherwise the same request can succeed or fail depending on which machine catches it. If you'd rather route all Slack traffic to one box, simply leaveSLACK_LISTENER_ENABLEDunset on the others — they can still use the send nodes.
Windows (PowerShell, current session):
$env:SLACK_LISTENER_ENABLED = "1"
$env:SLACK_APP_TOKEN = "xapp-your-token-here"
$env:SLACK_WORKFLOW_DIR = "C:\path\to\your\workflows"
$env:SLACK_ALLOWED_USERS = "@alice,U0456DEF" # names or IDs
On startup you should see [ComfyUI-Slack] Socket Mode listener started. and a line listing
the loaded workflows in the ComfyUI terminal.
4. Use it
| In Slack | Result |
|----------|--------|
| @ComfyUI mockup + image | Matches both mockup workflows → shows the choice buttons |
| @ComfyUI [poster-mockup] make a poster + image | Forces the poster-mockup workflow |
| @ComfyUI try this on a shirt + image | Auto-picks tshirt-mockup via its shirt keyword |
| @ComfyUI help | Lists the available workflows |
@ComfyUI help replies with every registered workflow, its required input, and a one-line
description pulled from your manifest.json:
Nodes
SlackSendImage
Sends one or more images from a batch to a Slack channel.
| Input | Type | Description |
|-------|------|-------------|
| images | IMAGE | Image tensor batch |
| channel | STRING | Channel or user — #general, @alice, or a raw ID. A user is sent a DM. |
| filename_prefix | STRING | Base name for the uploaded file |
| save_output | BOOLEAN | Also write the image to disk (see Saving a local copy) |
| save_location | COMBO | ComfyUI output folder or Absolute path |
| output_folder | STRING | Base folder for the saved copy; used only in Absolute path mode |
| format | COMBO | PNG, JPEG, or WEBP |
| quality | INT 1–100 | JPEG/WEBP quality; ignored for PNG |
| title (optional) | STRING | File title shown in Slack |
| message (optional) | STRING | Message posted alongside the file |
| thread_ts (optional) | STRING | Thread to reply under — connect a SlackThreadStart node to group outputs in one thread; also auto-filled by the Slack listener |
Each image in the batch is uploaded as a separate file named {filename_prefix}_{index:05d}.{ext}. The optional message is attached to the first file only.
Supported formats:
| Format | Extension | Quality |
|--------|-----------|---------|
| PNG | .png | Lossless (quality ignored) |
| JPEG | .jpg | 1–100 |
| WEBP | .webp | 1–100 |
SlackSendVideo
Encodes a frame batch into a video via FFmpeg and uploads it to a Slack channel.
| Input | Type | Description |
|-------|------|-------------|
| images | IMAGE | Frame batch (B, H, W, C) |
| channel | STRING | Channel or user — #general, @alice, or a raw ID. A user is sent a DM. |
| filename_prefix | STRING | Base name for the uploaded file |
| save_output | BOOLEAN | Also write the video to disk (see Saving a local copy) |
| save_location | COMBO | ComfyUI output folder or Absolute path |
| output_folder | STRING | Base folder for the saved copy; used only in Absolute path mode |
| frame_rate | FLOAT | Playback frame rate (1–120 fps) |
| format | COMBO | h264-mp4, h265-mp4, vp9-webm, or gif |
| quality | INT 0–100 | 100 = best quality, 0 = smallest file |
| audio (optional) | AUDIO | Audio to mux into the video (not supported for GIF) |
| title (optional) | STRING | File title shown in Slack |
| message (optional) | STRING | Message posted alongside the file |
| thread_ts (optional) | STRING | Thread to reply under — connect a SlackThreadStart node to group outputs in one thread; also auto-filled by the Slack listener |
Supported formats:
| Format | Codec | Container | Quality → CRF |
|--------|-------|-----------|---------------|
| h264-mp4 | libx264 | MP4 | (100-q)*51/100 |
| h265-mp4 | libx265 | MP4 | (100-q)*51/100 |
| vp9-webm | libvpx-vp9 | WebM | (100-q)*63/100 |
| gif | GIF palette | GIF | N/A |
Frames are padded to even dimensions automatically (required by most codecs). FFmpeg is bundled via imageio-ffmpeg — no separate installation needed.
SlackSendText
Posts a text message to a Slack channel (or as a DM). The message field accepts standard Markdown, which is translated to Slack's formatting before sending.
| Input | Type | Description |
|-------|------|-------------|
| text | STRING (multiline) | Message body; Markdown is translated to Slack formatting |
| channel | STRING | Channel or user — #general, @alice, or a raw ID. A user is sent a DM. |
| filename_prefix | STRING | Base name for the saved .md copy (only used when save_output is on) |
| save_output | BOOLEAN | Also write the message to disk as a .md file (see Saving a local copy) |
| save_location | COMBO | ComfyUI output folder or Absolute path |
| output_folder | STRING | Base folder for the saved copy; used only in Absolute path mode |
| thread_ts (optional) | STRING | Thread to reply under — connect a SlackThreadStart node to group outputs in one thread; also auto-filled by the Slack listener |
| user_id (optional) | STRING | User to @-mention at the start of the message; auto-filled by the Slack listener |
Markdown translation: standard Markdown is rewritten to Slack mrkdwn:
| Markdown | Slack |
|----------|-------|
| **bold** / __bold__ | *bold* |
| *italic* / _italic_ | _italic_ |
| ~~strike~~ | ~strike~ |
| [text](url) | <url\|text> |
| # Heading | *Heading* (mrkdwn has no headings) |
| - item | • item |
| `code` / ```block``` | left as-is (already valid in Slack) |
The local copy (when save_output is on) stores the original Markdown source, not the translated text.
SlackSendAudio
Encodes an AUDIO input via FFmpeg and uploads it to a Slack channel as a standalone audio file.
| Input | Type | Description |
|-------|------|-------------|
| audio | AUDIO | Audio to send |
| channel | STRING | Channel or user — #general, @alice, or a raw ID. A user is sent a DM. |
| filename_prefix | STRING | Base name for the uploaded file |
| save_output | BOOLEAN | Also write the audio to disk (see Saving a local copy) |
| save_location | COMBO | ComfyUI output folder or Absolute path |
| output_folder | STRING | Base folder for the saved copy; used only in Absolute path mode |
| format | COMBO | mp3, m4a, opus, flac, or wav |
| quality | INT 1–100 | Bitrate for lossy formats; ignored for flac/wav |
| title (optional) | STRING | File title shown in Slack |
| message (optional) | STRING | Message posted alongside the file |
| thread_ts (optional) | STRING | Thread to reply under — connect a SlackThreadStart node to group outputs in one thread; also auto-filled by the Slack listener |
Supported formats:
| Format | Codec | Extension | Quality |
|--------|-------|-----------|---------|
| mp3 | libmp3lame | .mp3 | 1–100 → 32–320 kbps |
| m4a | aac | .m4a | 1–100 → 32–320 kbps |
| opus | libopus | .opus | 1–100 → 32–320 kbps |
| flac | flac | .flac | Lossless (quality ignored) |
| wav | pcm_s16le | .wav | Lossless (quality ignored) |
Audio is encoded by piping the waveform to the bundled FFmpeg — no separate installation needed.
SlackThreadStart
Posts a root message to Slack and outputs its thread_ts. Wire that output into
the thread_ts input of any send node (Image / Video / Text / Audio) to make all
of them post into the same Slack thread — ideal when one workflow produces
several outputs that belong together. The connection also makes the send nodes
run after the thread has been opened.
| Input | Type | Description |
|-------|------|-------------|
| channel | STRING | Channel or user — #general, @alice, or a raw ID. A user starts the thread in a DM. |
| mode | COMBO | New thread each run or Reuse existing thread (see below) |
| header (optional) | STRING (multiline) | Text of the root message that opens the thread; Markdown is translated to Slack formatting |
| Output | Type | Description |
|--------|------|-------------|
| thread_ts | STRING | Timestamp of the root message — feed it into the send nodes' thread_ts inputs |
Modes:
- New thread each run — every workflow execution posts a fresh root and starts a new thread.
- Reuse existing thread — re-running the workflow keeps appending to the same thread (new results land in the existing thread). The reused thread is remembered for the current ComfyUI session; restarting ComfyUI (or changing the channel/header) starts a new thread.
A send node whose thread_ts is left unconnected posts to the channel root as
usual, so adding this node is fully optional.
Saving a local copy
All four send nodes can keep a local copy of what they send. Saving is additive — the content is always sent to Slack, and turning save_output on simply also writes it to disk (before sending, so the local copy survives even if Slack errors). The text node saves a .md file; the others save the uploaded media file.
ComfyUI output folder— writes into ComfyUI's standardoutput/directory using the same naming as the built-in Save nodes:{filename_prefix}_{counter:05}_.{ext}.filename_prefixmay include a subfolder (e.g.renders/Clip), and the counter auto-increments so existing files are never overwritten.Absolute path— writes into theoutput_folderyou specify (created if missing) as{filename_prefix}_{index:05d}.{ext}. Leavingoutput_folderempty in this mode raises an error.
In the node UI, save_location and output_folder are greyed out while save_output is off, and output_folder stays greyed out unless Absolute path is selected.
Troubleshooting
SLACK_BOT_TOKEN environment variable is not set — set the variable in the shell that launches ComfyUI and restart.
Slack upload failed: not_in_channel — the bot hasn't been invited to the channel. Run /invite @ComfyUI in Slack.
Slack channel "…" not found — the channel name in the node couldn't be resolved. Check the
spelling; for a private channel, invite the bot first (/invite @ComfyUI) — private channels
resolve only when the bot is a member, and need the groups:read scope. You can always fall back
to the raw channel ID (e.g. C0B6SUZMHC6).
Allow-list names are ignored — a name in SLACK_ALLOWED_USERS/SLACK_ALLOWED_CHANNELS is
skipped (with a warning in the ComfyUI log) when it can't be resolved: a typo, an ambiguous
display name, or a missing users:read/groups:read scope. Add the scope and reinstall the
app, fix the spelling, or use the raw ID (U…/C…).
FFmpeg encoding failed — check that the frame batch is not empty and that the selected codec is compatible with your FFmpeg build.
Listener doesn't start — confirm SLACK_LISTENER_ENABLED is 1/true and that
SLACK_APP_TOKEN, SLACK_BOT_TOKEN, and SLACK_WORKFLOW_DIR are all set. The terminal logs
the exact missing piece on startup.
Bot replies "You're not authorized" — set SLACK_ALLOWED_USERS and/or
SLACK_ALLOWED_CHANNELS. Authorization is default-deny, so an empty allowlist blocks everyone.
Unauthorized: Please login first to use this node — the workflow uses a comfy.org
API/partner node (e.g. an OpenAI node). The browser login that authenticates these nodes in the
GUI isn't present for a listener-triggered run, and credits alone don't authenticate the request.
Generate an API key at platform.comfy.org and set
SLACK_COMFY_API_KEY before launching ComfyUI.
template missing required node title marker(s) — rename the final Slack send node to
SLACK_OUTPUT in your workflow (the only required marker), then re-export it with
Save (API Format). A SLACK_PROMPT node is optional.
Mention does nothing — make sure the bot is invited to the channel, app_mention is
subscribed under Event Subscriptions, and Socket Mode is enabled. Re-install the app after
changing scopes.
License
MIT — see LICENSE. © 2026 Claus Steinmassl.