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.
chat:write, channels:read, reactions:write, files:write, commandsSocket 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.
Add the Slack integration to your 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: 3Set the corresponding environment variables in your .env file:
SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_SIGNING_SECRET=your-signing-secret
SLACK_APP_TOKEN=xapp-your-app-tokenAccess the Slack integration programmatically through the @cognest/sdk and the @cognest/integrations/slack package:
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",
},
],
},
],
});| Method | Description | Returns |
|---|---|---|
| `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>` |
Subscribe to Slack events in your skill handlers or directly on the integration instance:
| Event | Trigger | Payload |
|---|---|---|
| `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 }` |
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:
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();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()`.