Built a Slack CV assistant – 3 lessons that apply to any interactive Slack workflow in n8n

:waving_hand: Hey n8n Community,

I shared a two-part CV screening assistant last week, built for my friend’s recruiter (drop a CV in Slack, get an instant structured summary + a button to save it). A few people asked about the build decisions, so here are the 3 things that’ll actually transfer to any interactive Slack workflow you build in n8n.

1. Let the button carry the data, skip the database between workflows

Interactive Slack workflows have to be split in two: one workflow posts the message with buttons, a second one catches the clicks (Slack interactivity needs its own webhook). The obvious-but-wrong instinct is to write your data to a database in workflow 1 and read it back in workflow 2.

You don’t need to. Slack buttons have a value field that travels with the click. I stuffed the entire extracted candidate JSON into the Save button’s value, so when the click comes in, workflow 2 already has everything, no database, no state, no re-running the extraction. The only limit is 2000 characters per value, which is plenty for structured data.

Takeaway: if the data fits in 2000 chars, the button is your state store.

2. Respond to Slack in under 3 seconds, or the user sees an error

Slack expects a 200 response within 3 seconds of a button click. If your workflow does real work first (writes to a Sheet, calls an API), you’ll blow past that and the user gets a red error banner, even if the work eventually succeeds.

Fix: acknowledge immediately, work after. In n8n, branch the webhook so the “Respond 200” node fires in parallel with the rest of the workflow, not after it. The user gets instant confirmation, and the Sheet append happens a beat later in the background.

Takeaway: ack first, work second, always parallel, never chained.

3. Slack file events lie about timing, use the message event instead

Slack’s file_shared event fires before Slack has finished processing the upload, so the file metadata is sometimes missing when your workflow runs. It works half the time, which is the worst kind of bug.

The message event is delivered only after processing is complete, so the file data is always there. Switch your trigger to listen for messages, filter to ones that actually have a file attached, then download the file explicitly. Reliable every time instead of a coin flip.

Takeaway: for file uploads, trigger on message, not file_shared.

Bonus gotcha that cost me an hour: the n8n Slack node currently has a bug where Block Kit button payloads sometimes just don’t render, you get the fallback text and no buttons. Posting the card via a direct HTTP call to Slack’s chat.postMessage API instead of the Slack node fixes it.

Templates and full setup (sticky notes cover all of the above) are in the repo: n8n-workflows/easybits-cv-slack-assistant at a8138f54ec6b225b7e90e2a66b4491c746767214 · felix-sattler-easybits/n8n-workflows · GitHub

What’s the trickiest interactive Slack workflow you’ve built in n8n? Curious whether anyone’s found a cleaner way around the 3-second rule than the parallel-ack trick.

Best,
Felix