1. Actions
  2. Post Message

Publish Slack messages to a public or private channel in your Slack Workspace as the Trigger.dev Slack bot. If you need to publish messages to your customer’s Slack channels, consider using Incoming Webhooks and our fetch function.

Params

keyRequired
string

A unique string. Please see the Keys and Resumability doc for more info.

messageRequired
object
channelName
string

The name of the channel, can optionally include the #. E.g. #team. Alternatively you can use the channelId param.

channelId
string

The slack ID of the channel, e.g. C04GWUTDC4W. Can be used instead of channelName. Use channelId if the slack channel name could change.

textRequired
string

The formatted text of the message to be published, formatted as mrkdwn.

blocks
object

You can use blocks to create a rich message with images, buttons, and more.

You can either pass in a JavaScript object or use JSX Slack to create blocks. We highly recommend using JSX Slack as it’s much easier to read and write. See the block example to see it in action.

For full details on Slack blocks, see the Slack API docs.

thread_ts
string

The “timestamp ID” of the message to reply to. If not specified, the message will be published as a new thread.

metadata
object

A JSON object that will be attached to the message. This can be used to store custom data about the message, but will not be displayed to users. Useful for passing data to a blockActionInteraction trigger.

username
string

The name of the bot that will publish the message. If not specified, the message will be published as the Trigger.dev Slack bot.

icon_emoji
string

The emoji to use as the icon for the bot that will publish the message. If not specified, the message will be published as the Trigger.dev Slack bot.

icon_url
string

The URL of an image to use as the icon for the bot that will publish the message. If not specified, the message will be published as the Trigger.dev Slack bot.

Response

okDefault: true
boolean

Always true; non-ok responses will halt the workflow run and throw an error.

channel
string

The channel ID of the channel the message was published to.

ts
string

The “timestamp ID” of the message, which can be used to update or delete the message.

message
object

Example Workflows

Notify Slack on New GitHub Star

import * as github from "@trigger.dev/github";
import * as slack from "@trigger.dev/slack";

new Trigger({
  id: "new-star",
  name: "On New Star",
  on: github.events.newStarEvent({
    repo: "triggerdotdev/trigger.dev",
  }),
  run: async (event, ctx) => {
    await slack.postMessage("⭐️ New Star", {
      channelName: "github-stars",
      text: `Repo ${event.repository.full_name} got a star from ${event.sender.login}, for a total of ${event.repository.stargazers_count} stars!`,
    });
  },
}).listen();

Blocks with interactivity

You can add interaction and richer visual elements using Blocks. The easiest way to add them is using jsx-slack (which is a separate npm package that you can install).

This example messages your team every minute (!) and asks them how they’re doing. There are two buttons and a dropdown menu.

In this examples there are two workflows:

  1. Messages your team every minute (!) and asks them how they’re doing.
  2. Receives the interaction from users. It adds reactions when the buttons are pressed and posts a message when a user selects from the dropdown menu.

Please note, that to use jsx-slack you will need to add the jsxImportSource pragma to the top of your file. This is because jsx-slack is not a React library, but it uses the same syntax as React. Also, you might need to add "jsx": "react-jsx" to your compilerOption in tsconfig.json. The workflow file needs to be a .jsx or .tsx file (like when you use React).

/** @jsxImportSource jsx-slack */
import * as slack from "@trigger.dev/slack";
import JSXSlack, {
  Actions,
  Blocks,
  Button,
  Section,
  Select,
  Option,
} from "jsx-slack";
import { z } from "zod";

const BLOCK_ID = "issue.action.block";

//1. every minute see how your employees are doing, we don't recommend this frequency 😉
new Trigger({
  id: "slack-interactivity",
  name: "Testing Slack Interactivity",
  on: scheduleEvent({
    rateOf: {
      minutes: 1,
    },
  }),
  run: async (event, ctx) => {
    await slack.postMessage("jsx-test", {
      channelName: "test-integrations",
      //text appears in Slack notifications on mobile/desktop
      text: "How is your progress today?",
      //import and use JSXSlack to make creating rich messages much easier
      blocks: JSXSlack(
        <Blocks>
          <Section>How is your progress today?</Section>
          <Actions blockId={BLOCK_ID}>
            <Button value="blocked" actionId="status-blocked">
              I'm blocked
            </Button>
            <Button
              value="help"
              actionId="status-help"
              url="https://xkcd.com/1349/"
            >
              Get help
            </Button>
            <Select actionId="rating" placeholder="Rate it!">
              <Option value="5">5 {":star:".repeat(5)}</Option>
              <Option value="4">4 {":star:".repeat(4)}</Option>
              <Option value="3">3 {":star:".repeat(3)}</Option>
              <Option value="2">2 {":star:".repeat(2)}</Option>
              <Option value="1">1 {":star:".repeat(1)}</Option>
            </Select>
          </Actions>
        </Blocks>
      ),
    });
  },
}).listen();

//2. this workflow listens for Slack interactions filtered by the block id and actions we used above
new Trigger({
  id: "slack-block-interaction",
  name: "Slack Block Interaction",
  on: slack.events.blockActionInteraction({
    blockId: BLOCK_ID,
    actionId: ["status-blocked", "status-help", "rating"],
  }),
  run: async (event, ctx) => {
    //create promises from all the actions
    const promises = event.actions.map((action) => {
      switch (action.action_id) {
        case "status-blocked": {
          //the user is blocked so add a 😢 emoji as a reaction
          if (event.message) {
            return slack.addReaction("React to message", {
              name: "cry",
              timestamp: event.message.ts,
              channelId: event.channel.id,
            });
          }
          break;
        }
        case "status-help": {
          //the user needs help so add an 🆘 emoji as a reaction
          if (event.message) {
            return slack.addReaction("React to message", {
              name: "sos",
              timestamp: event.message.ts,
              channelId: event.channel.id,
            });
          }
          break;
        }
        case "rating": {
          if (action.type != "static_select") {
            throw new Error("This action should be a select");
          }

          //post the rating as a message that appears below the original,
          //only the user pressing the button will see this message
          return slack.postMessageResponse(
            "Added a comment to the issue",
            event.response_url,
            {
              text: `You rated your day ${action.selected_option?.value} stars`,
              replace_original: false,
            }
          );
        }
        default:
          return Promise.resolve();
      }
    });

    await Promise.all(promises);
  },
}).listen();