Skip to content

Slack

Overview#

The Slack integration lets your Cognest assistant operate as a fully interactive Slack bot. It can send and receive messages in channels and DMs, respond to slash commands, react to messages, upload files, and listen for workspace events. The integration supports both HTTP webhook mode and Socket Mode for firewall-restricted environments.

Prerequisites#

  1. A Slack workspace where you have permission to install apps
  2. A Slack App created at api.slack.com/apps
  3. Bot token scopes: chat:write, channels:read, reactions:write, files:write, commands
  4. Event subscriptions enabled with the request URL pointing to your Cognest webhook endpoint

Socket Mode

If your assistant runs behind a firewall or you don't want to expose a public webhook URL, enable Socket Mode in your Slack app settings and provide the SLACK_APP_TOKEN. Cognest will automatically use WebSocket connections instead of HTTP webhooks.

Configuration#

Add the Slack integration to your cognest.config.yaml:

cognest.config.yaml
integrations:
  slack:
    enabled: true
    credentials:
      bot_token: ${SLACK_BOT_TOKEN}
      signing_secret: ${SLACK_SIGNING_SECRET}
      app_token: ${SLACK_APP_TOKEN}      # Optional — required for Socket Mode
    settings:
      socket_mode: false                  # Set to true for Socket Mode
      default_channel: "general"          # Fallback channel for outbound messages
      parse_mentions: true                # Resolve @user mentions to display names
      unfurl_links: false                 # Disable link previews in bot messages
      retry_on_rate_limit: true           # Automatically retry when rate-limited
      max_retries: 3

Set the corresponding environment variables in your .env file:

.env
SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_SIGNING_SECRET=your-signing-secret
SLACK_APP_TOKEN=xapp-your-app-token

SDK Usage#

Access the Slack integration programmatically through the @cognest/sdk and the @cognest/integrations/slack package:

skills/deploy-notify.ts
import { Cognest } from "@cognest/sdk";
import { SlackIntegration } from "@cognest/integrations/slack";

const cognest = new Cognest();
const slack = cognest.integration<SlackIntegration>("slack");

// Send a simple text message
await slack.send({
  channel: "#engineering",
  text: "Deployment to production completed successfully.",
});

// Send a message with Block Kit layout
await slack.sendBlocks({
  channel: "#engineering",
  blocks: [
    {
      type: "section",
      text: {
        type: "mrkdwn",
        text: "*Deployment Report*\nAll 42 services deployed to production.",
      },
    },
    {
      type: "actions",
      elements: [
        {
          type: "button",
          text: { type: "plain_text", text: "View Logs" },
          url: "https://logs.example.com/deploy/latest",
        },
      ],
    },
  ],
});

Available Methods#

MethodDescriptionReturns
`send(options)`Send a plain text message to a channel or DM`Promise<SlackMessage>`
`sendBlocks(options)`Send a message with Block Kit layout blocks`Promise<SlackMessage>`
`reply(options)`Reply in a thread (requires `thread_ts`)`Promise<SlackMessage>`
`updateMessage(options)`Edit an existing message by timestamp`Promise<SlackMessage>`
`deleteMessage(options)`Delete a message by channel and timestamp`Promise<void>`
`uploadFile(options)`Upload a file to a channel or thread`Promise<SlackFile>`
`addReaction(options)`Add an emoji reaction to a message`Promise<void>`

Events#

Subscribe to Slack events in your skill handlers or directly on the integration instance:

EventTriggerPayload
`message`A message is posted in a channel the bot is in`{ channel, user, text, ts, thread_ts? }`
`command`A slash command registered to the app is invoked`{ command, text, user, channel, trigger_id }`
`reaction_added`A reaction emoji is added to a message`{ reaction, user, item: { channel, ts } }`
`app_mention`The bot is @mentioned in a channel`{ channel, user, text, ts }`
`file_shared`A file is shared in a channel the bot can see`{ file_id, user, channel }`

Example#

The following example builds a support triage skill that listens for messages in a support channel, categorizes them with the Think Engine, and responds with a threaded reply:

skills/support-triage.ts
import { Cognest, Skill, IncomingEvent } from "@cognest/sdk";
import { SlackIntegration, SlackMessageEvent } from "@cognest/integrations/slack";

const cognest = new Cognest();
const slack = cognest.integration<SlackIntegration>("slack");

const supportTriage = new Skill({
  name: "support-triage",
  description: "Categorize and respond to support requests in #support",
});

supportTriage.on("slack:message", async (event: IncomingEvent<SlackMessageEvent>) => {
  const { channel, text, ts, user } = event.payload;

  // Only handle messages in the support channel
  if (channel !== "C04SUPPORT") return;

  // Add a eyes reaction to acknowledge receipt
  await slack.addReaction({
    channel,
    timestamp: ts,
    name: "eyes",
  });

  // Use the Think Engine to categorize the request
  const classification = await cognest.think({
    prompt: `Classify this support request into one of: billing, technical, account, other.

Request: "${text}"

Respond with JSON: { "category": "...", "priority": "low" | "medium" | "high", "summary": "..." }`,
    responseFormat: "json",
  });

  const { category, priority, summary } = classification.parsed;

  // Reply in a thread with the triage result
  await slack.reply({
    channel,
    thread_ts: ts,
    text: [
      `*Support Triage* — <@${user}>\n`,
      `> *Category:* ${category}`,
      `> *Priority:* ${priority}`,
      `> *Summary:* ${summary}\n`,
      priority === "high"
        ? "<!channel> This has been flagged as high priority."
        : "A team member will follow up shortly.",
    ].join("\n"),
  });

  // Send a summary to the internal triage channel
  await slack.sendBlocks({
    channel: "#support-triage",
    blocks: [
      {
        type: "section",
        text: {
          type: "mrkdwn",
          text: `*New ${priority} priority ticket*\nCategory: ${category}\nFrom: <@${user}>\n> ${summary}`,
        },
      },
      {
        type: "context",
        elements: [
          {
            type: "mrkdwn",
            text: `<https://your-workspace.slack.com/archives/${channel}/p${ts.replace(".", "")}|View original message>`,
          },
        ],
      },
    ],
  });
});

cognest.register(supportTriage);
cognest.start();

Troubleshooting#

Common Issues

**Bot not responding to messages** — Ensure Event Subscriptions are enabled in your Slack app config and the request URL is verified. Check that the bot has been invited to the target channel with `/invite @your-bot`. **"not_authed" error** — Your `SLACK_BOT_TOKEN` is missing or invalid. Bot tokens start with `xoxb-`. Regenerate the token in the OAuth & Permissions section of your Slack app. **Socket Mode disconnects** — Verify your `SLACK_APP_TOKEN` starts with `xapp-` and that Socket Mode is toggled on in the app settings. Check your network allows outbound WebSocket connections. **Rate limiting** — Slack enforces rate limits per method. Enable `retry_on_rate_limit: true` in your config to handle this automatically. For burst workloads, consider queuing messages with `cognest.queue()`.