Programatic message threading with your Slack Bot

Thread related messages & avoid being an automated spammer.

Sean Rennie
3 min readMay 24, 2021


Photo by SUNBEAM PHOTOGRAPHY on Unsplash

In part one I wrote about why and how we built a Slack bot. We use our bot as middleware to send notifications from a browser app. The bot exposes endpoints mapped to methods like chat.postMessage in Slack’s web-api. We POST to the endpoint with a block-kit-builder formatted message. Each message to Slack returns a message ID (ts) which we use to thread related messages. It’s a great way to avoid spamming our channels.

Drone pilots use our app to upload imagery to our services. We want to notify a channel when:

  • an upload is started
  • every 25% progress is reached
  • the pilot pauses, resumes or cancels the upload
  • a file fails upload

In this post I’ll walk though how we implemented this notification flow.

Setting up

To send messages to Slack I’ll need:

  • Channel ID
  • Url to the GCP function hosting the bot
  • A way to cache message IDs so they survive page refreshes

You can get a channel Id by right licking the name of your channel, “then copy link”. Paste it anywhere, the ID is the characters on the end. Something like this: C21S4MN6C4(👈🏻 Not an actual ID). Make sure you’ve added your bot to that channel too.

To find the url for the Cloud function go to the GCP console and look under the TRIGGER tab. It’ll look something like: https://europe-west1-[project-name] The name on the end is the same as the name we used when deploying the bot in part 1.

To cache the ts key I’m using local storage. Nothing fancy here. Usually there are one or two keys live at anyone point. I use an upload Id to scope keys in the cache.

Sending the first message

I’ve structured my notifications as a series of async functions. I use a primary notifySlack function which makes the request. Other notification specific functions with names like notifySlackUploadInit, and notifySlackUploadComplete call into it. The notifySlack uses fetch for POSTing to the bot with the channel ID and message body. It returns a ts key which I’ll use later to thread messages.

These two functions will send a message to Slack that looks like this:

Block Kit Builder is a great tool for designing messages. Copy the JSON and use it directly in the request function.

My storeUploadNotificationTs function adds the ts key to local storage. It uses the upload ID to scope it in case a user triggers other uploads from a different tab.

Threading messages

To send a message as a thread of another message we’ll add the ts key to the request. This function sends an “Upload Completed” message:

I retrieve the ts key from local storage and add it to the request’s thread_ts property. Because it’s the end of the line, I clean up local storage. The resulting threaded message now looks like this:

That’s it. The hard part is getting a Slack bot setup and working. Then with this endpoint I can send messages to any channel in our workspace from any client app.



Sean Rennie

Software engineer with a love of maps and anything geospatial. I enjoy techno, the outdoors, tequila & coffee. Currently working at Sensat Ltd