-
Notifications
You must be signed in to change notification settings - Fork 6
Document Internal Slack channels #1601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,120 +1,128 @@ | ||||||
| --- | ||||||
| title: Sending a message to an internal Slack workspace | ||||||
| description: How to send a message to an internal Slack workspace using Knock. | ||||||
| title: Sending messages to your team's Slack workspace | ||||||
| description: Use an Internal Slack channel to send Knock workflow messages to channels and people in your team's Slack workspace. | ||||||
| tags: ["slack", "chat"] | ||||||
| section: Integrations > Slack | ||||||
| layout: integrations | ||||||
| --- | ||||||
|
|
||||||
| In this documentation we'll cover how to send a message to an internal Slack workspace using Knock. It assumes that you have already created a Slack app and created a Slack channel in Knock as outlined in the [Slack integration](/integrations/chat/slack/overview) documentation. | ||||||
|
|
||||||
| ## Slack channels are connections on Objects | ||||||
|
|
||||||
| In Knock, we model channels in a Slack workspace as connections on Objects. [Objects](/concepts/objects) allow you to model any resource in your system within Knock, and while their primary purpose is to act as non-user recipients, they are very flexible abstractions. | ||||||
| Knock's Internal Slack channel gives your team a managed way to send workflow messages to your own Slack workspace. Connect the Knock Slack extension once, then choose a Slack channel or person as the destination for each workflow step. | ||||||
|
|
||||||
| You don't need to create a Slack app, manage bot tokens, or store Slack `channel_data` on your workflow recipients. | ||||||
|
|
||||||
| <Callout | ||||||
| type="info" | ||||||
| title="Knock channels and Slack destinations are different." | ||||||
| text={ | ||||||
| <> | ||||||
| The <strong>Internal Slack channel</strong> is a managed Knock channel | ||||||
| backed by the Knock Slack extension. A <strong>Slack destination</strong> | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| is the channel or person in your workspace that you select on a workflow step. | ||||||
| One Internal Slack channel can be used by many workflow steps, each with its | ||||||
| own destination. | ||||||
| </> | ||||||
| } | ||||||
| /> | ||||||
|
|
||||||
| ### An overview of Objects | ||||||
| ## Before you begin | ||||||
|
|
||||||
| Individual Objects exist within [a collection](/concepts/objects#collection-naming) and always have [a unique ID](/concepts/objects#the-object-identifier) or key within that collection. The Object itself can store any number and type of properties as key-value pairs. You can see some examples of possible Object structures in [the official documentation on setting Object data](/concepts/objects#sending-object-data-to-knock). | ||||||
| To create an Internal Slack channel, you need a Knock role with permission to manage both channels and extensions. After it is created, team members with permission to edit workflows can use it in workflow steps. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| Let’s say you are building a devtool product like GitHub and want to set up Slack notifications whenever someone comments on an issue within a repository. First, you’ll want to create an Object to model your repository as part of the `repositories` collection: | ||||||
| The Knock Slack app can send to: | ||||||
|
|
||||||
| ```javascript | ||||||
| import Knock from "@knocklabs/node"; | ||||||
| const knockClient = new Knock({ apiKey: process.env.KNOCK_API_KEY }); | ||||||
| - Public channels in your workspace. | ||||||
| - Private channels where the Knock Slack app is a member. Invite `@Knock` to a private channel before selecting it. | ||||||
| - Active people in your workspace via direct message. | ||||||
|
|
||||||
| await knockClient.objects.set("repositories", "repo-1", { | ||||||
| name: "My repo", | ||||||
| }); | ||||||
| ``` | ||||||
| ## Create an Internal Slack channel | ||||||
|
|
||||||
| Once you have a repository object created, you can add the channel data for Slack as a connection on the object. | ||||||
| <Steps titleSize="h3"> | ||||||
| <Step title="Choose Internal Slack"> | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| In the Knock dashboard, open **Settings > Channels and sources** and click | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Now that we can link straight to the dashboard, nice to add |
||||||
| **Create channel**. Select **Chat**, then choose **Slack** with the | ||||||
| **Internal** badge. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(if we like my suggestion about lowercase in other places and indicating the badge with code syntax; not necessary)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whatever we decide on the above suggestion, I think we should also say "Click next." |
||||||
| </Step> | ||||||
|
|
||||||
| ## Objects as workflow recipients | ||||||
| <Step title="Connect your Slack workspace"> | ||||||
| If your project is already connected to Slack through the [Knock Slack | ||||||
| extension](/integrations/extensions/slack) with the required permissions, | ||||||
| Knock uses that connection to create the Internal Slack channel. | ||||||
|
|
||||||
| To add channel data, we’ll set up an <a href="https://api.slack.com/messaging/webhooks" target="_blank">incoming webhook in Slack</a>. To get this URL from Slack, you can go to “Incoming Webhooks” within your dashboard and toggle the "Activate Incoming Webhooks" feature. If you’ve already installed your app into a workspace, you will be asked to reinstall it and select a channel the app will post messages to. | ||||||
| If Slack is not connected, or if the existing connection needs additional | ||||||
| permissions, Knock opens the Slack authorization flow. Choose your workspace | ||||||
| and approve the requested permissions. After you return to Knock, the | ||||||
| Internal Slack channel is created automatically. | ||||||
|
|
||||||
| <Image | ||||||
| src="/images/integrations/chat/slack/activate-incoming-webhooks.png" | ||||||
| className="rounded-md mx-auto border border-gray-200" | ||||||
| alt="activating incoming webhooks in Slack" | ||||||
| width={2000} | ||||||
| height={1130} | ||||||
| /> | ||||||
| To generate a new webhook, scroll to the bottom of the page where you see the “Add | ||||||
| New Webhook to Workspace” button. If you connected an initial channel, you can copy | ||||||
| your webhook, or you can connect another channel and then copy the webhook URL: | ||||||
|
|
||||||
| <Image | ||||||
| src="/images/integrations/chat/slack/copy-webhook.png" | ||||||
| className="rounded-md mx-auto border border-gray-200" | ||||||
| alt="creating a Slack channel in Knock dashboard" | ||||||
| width={2000} | ||||||
| height={1734} | ||||||
| /> | ||||||
| </Step> | ||||||
|
|
||||||
| ### Set the webhook as channel data | ||||||
| <Step title="Confirm the connection"> | ||||||
| The channel configuration shows the Slack workspace managed by the Knock | ||||||
| Slack extension. Its credentials apply across your Knock environments and | ||||||
| cannot be edited from the channel configuration. | ||||||
|
|
||||||
| Now that you have the webhook URL, we’ll store that webhook as a special property on the repository Object called channel data. [Channel data is both channel and recipient-specific data](https://docs.knock.app/managing-recipients/setting-channel-data) stored for use with particular channels, like a token used for push notifications or webhooks stored for chat apps like Slack, Teams, and Discord. Both Users and Objects can store channel data. | ||||||
| You can create one Internal Slack channel per Knock project. The same | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| channel can be reused across any number of workflows. | ||||||
|
|
||||||
| In the code example below, we’ll use the `knockClient.objects.setChannelData` method to update the channel data for our repository Object. | ||||||
| </Step> | ||||||
| </Steps> | ||||||
|
|
||||||
| ```javascript | ||||||
| import Knock from "@knocklabs/node"; | ||||||
| const knockClient = new Knock({ apiKey: process.env.KNOCK_API_KEY }); | ||||||
|
|
||||||
| await knockClient.objects.setChannelData( | ||||||
| "repositories", | ||||||
| repository.id, | ||||||
| process.env.KNOCK_SLACK_CHANNEL_ID, | ||||||
| { | ||||||
| data: { | ||||||
| connections: [ | ||||||
| { | ||||||
| incoming_webhook: { url: "url-from-slack" }, | ||||||
| }, | ||||||
| ], | ||||||
| }, | ||||||
| }, | ||||||
| ); | ||||||
| ``` | ||||||
| ## Add Internal Slack to a workflow | ||||||
|
|
||||||
| Here, you’ll also need your `KNOCK_SLACK_CHANNEL_ID` as the third parameter, which is the channel ID of your Slack integration within Knock, so that Knock can reference that channel when it processes workflows that use it. The last parameter is an object of a specific format that varies based on [the type of message provider](/managing-recipients/setting-channel-data#provider-data-requirements). In this case, it is a `SlackConnection` object with an `incoming_webhook` property that contains the URL you copied from Slack. | ||||||
| <Steps titleSize="h3"> | ||||||
| <Step title="Add a channel step"> | ||||||
| Open a workflow and add a channel step using your Internal Slack channel. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(note: also updated capitalization on Internal while I was here) |
||||||
| </Step> | ||||||
|
|
||||||
| ### Trigger a workflow with an object recipient | ||||||
| <Step title="Choose where to send the message"> | ||||||
| Use the **Send to** field to search the connected workspace. Choose a | ||||||
| destination from either the **Channels** or **People** tab. | ||||||
|
|
||||||
| With the channel data in place, you can add Slack as a workflow step in any workflow. For this example, we’ll create a `new-issue` workflow that pings users in our connected Slack channel whenever someone adds a new issue. | ||||||
| The destination is stored on this workflow step. Other steps using the same | ||||||
| Internal Slack channel can send somewhere else. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(ditto on the internal capitalization note) |
||||||
|
|
||||||
| <Image | ||||||
| src="/images/integrations/chat/slack/workflow-with-slack-step-new.png" | ||||||
| className="rounded-md mx-auto border border-gray-200" | ||||||
| alt="workflow with a Slack step" | ||||||
| width={2202} | ||||||
| height={1922} | ||||||
| /> | ||||||
| </Step> | ||||||
|
|
||||||
| As you create your message template, remember that in this case the repository Object is the recipient of your workflow. That means any properties you reference on your Liquid template tags need to exist as properties of the Object as well: | ||||||
| <Step title="Design and commit the message"> | ||||||
| Write the Slack message using Knock's markdown or Block Kit editor, then | ||||||
| commit the workflow. You do not need to configure a recipient connection in | ||||||
| the template settings; Knock supplies the Slack destination and credentials | ||||||
| for you. | ||||||
| </Step> | ||||||
| </Steps> | ||||||
|
|
||||||
| ```markdown | ||||||
| There was an issue opened on the following repo: **{{ recipient.name }}** | ||||||
| ``` | ||||||
| ## Trigger the workflow | ||||||
|
|
||||||
| Finally, we’ll add the workflow trigger to our code with the repository Object as a recipient. | ||||||
| Trigger a workflow that uses Internal Slack the same way you trigger any other Knock workflow. A recipient is still required for the workflow run, but that recipient does not need Slack channel data. | ||||||
|
|
||||||
| ```javascript | ||||||
| ```javascript title="Trigger a workflow that sends to Internal Slack" | ||||||
| import Knock from "@knocklabs/node"; | ||||||
|
|
||||||
| const knock = new Knock({ apiKey: process.env.KNOCK_API_KEY }); | ||||||
|
|
||||||
| await knock.workflows.trigger("new-issue", { | ||||||
| recipients: [{ collection: "repositories", id: "repo-1" }], | ||||||
| await knock.workflows.trigger("support-alert", { | ||||||
| recipients: ["user-1"], | ||||||
| data: { | ||||||
| summary: "A customer needs help with a failed import.", | ||||||
| }, | ||||||
| }); | ||||||
| ``` | ||||||
|
|
||||||
| With that, you should see a message in your selected Slack channel: | ||||||
| The workflow recipient still provides the `recipient` variables used in Liquid templates, step conditions, and the rest of the workflow. The destination selected in **Send to** only changes where that Internal Slack step is delivered. | ||||||
|
|
||||||
| <Image | ||||||
| src="/images/integrations/chat/slack/slack-message.png" | ||||||
| className="rounded-md mx-auto border border-gray-200" | ||||||
| alt="A Slack message" | ||||||
| width={2000} | ||||||
| height={552} | ||||||
| /> | ||||||
| ## How recipient preferences work | ||||||
|
|
||||||
| Internal Slack sends bypass the workflow recipient's notification preferences because the message is going to a team destination, not to a Slack connection owned by that recipient. Channel and step conditions still evaluate normally against the workflow recipient. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| Each Internal Slack step sends exactly one message to its selected destination. In workflow runs and message details, **Delivered to** shows the Slack channel or person that received the message while the message's recipient remains the workflow recipient. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| ## Manage or reconnect Slack | ||||||
|
|
||||||
| The Knock Slack extension owns the workspace connection and credentials used by the Internal Slack channel. Manage the connection from **Settings > Extensions**, not from the channel's provider settings. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| If the extension is disconnected or needs to be authorized again, Knock preserves the Internal Slack channel and its workflow references but skips affected Slack steps until the workspace is reconnected. The workflow run log identifies the disconnected Slack connection as the reason. Open **Settings > Extensions** and reconnect Slack to resume delivery. | ||||||
|
|
||||||
| ## When to use a different Slack setup | ||||||
|
|
||||||
| Use an Internal Slack channel when you want Knock to message your own team's workspace through the Knock Slack app. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think this is clearer, I found it confusing that the heading said when to use a different setup and then the paragraph started with use an internal one |
||||||
|
|
||||||
| If you are building a customer-facing Slack integration, use [your own Slack app and SlackKit](/integrations/chat/slack/sending-a-message-to-channels). If you need to supply a custom bot token, incoming webhook, or Liquid-based destination, use a customer-configured Slack channel with a [recipient connection override](/integrations/chat/slack/overriding-recipient-connections). | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think we should consider cutting this. It's enough of an edge case that someone on this page might not have any context for what "custom bot tokens, incoming webhooks, or Liquid-based destination" even means and I think calling it out explicitly here might confuse more people than it helps. |
||||||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per the comment in standup this morning, just want to be sure that "Internal Slack" is how we want to refer to this? I think this was the update from (Internal) but just wanted to be sure that this is the phrasing we landed on
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the changelog is using "internal Slack" (i.e. not a proper noun Internal), so maybe we can use that across the board and reference the
Internalbadge in particular with code syntax?