Skip to content

Discord

Overview#

The Discord integration allows your Cognest assistant to join Discord servers as a bot, send rich embed messages, handle slash commands, manage threads, and react to server events. It uses the Discord Gateway (WebSocket) for real-time event delivery and the REST API for outbound actions. The integration handles connection lifecycle, heartbeats, and reconnection automatically.

Prerequisites#

  1. A Discord Application created at the Discord Developer Portal
  2. A Bot user added to the application with the MESSAGE CONTENT privileged intent enabled
  3. Bot invited to your server with scopes: bot and applications.commands
  4. Bot permissions: Send Messages, Embed Links, Add Reactions, Manage Threads, Read Message History

Privileged Intents

The MESSAGE CONTENT intent is required for your bot to read message text. Without it, message events will have empty content fields. Enable this under your application's Bot settings in the Developer Portal.

Configuration#

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

cognest.config.yaml
integrations:
  discord:
    enabled: true
    credentials:
      bot_token: ${DISCORD_BOT_TOKEN}
      application_id: ${DISCORD_APPLICATION_ID}
    settings:
      intents:
        - GUILDS
        - GUILD_MESSAGES
        - GUILD_MESSAGE_REACTIONS
        - GUILD_MEMBERS
        - GUILD_VOICE_STATES
        - MESSAGE_CONTENT
      command_prefix: "!"                 # Prefix for text-based commands (optional)
      register_commands_on_start: true    # Auto-register slash commands on boot
      presence:
        status: online                   # online | idle | dnd | invisible
        activity:
          type: watching                 # playing | streaming | listening | watching
          name: "for /help"

Set the corresponding environment variables in your .env file:

.env
DISCORD_BOT_TOKEN=your-bot-token
DISCORD_APPLICATION_ID=your-application-id

SDK Usage#

Access the Discord integration through the @cognest/sdk and @cognest/integrations/discord:

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

const cognest = new Cognest();
const discord = cognest.integration<DiscordIntegration>("discord");

// Send a text message
await discord.send({
  channelId: "1234567890",
  content: "Build completed with zero errors.",
});

// Send a rich embed
await discord.sendEmbed({
  channelId: "1234567890",
  embed: {
    title: "Deployment Report",
    description: "All services deployed to **production** successfully.",
    color: 0x00e5cc,
    fields: [
      { name: "Services", value: "42", inline: true },
      { name: "Duration", value: "3m 12s", inline: true },
      { name: "Region", value: "us-east-1", inline: true },
    ],
    timestamp: new Date().toISOString(),
    footer: { text: "Cognest" },
  },
});

// Create a thread from a message
const thread = await discord.createThread({
  channelId: "1234567890",
  messageId: "9876543210",
  name: "Discussion: Q4 Planning",
  autoArchiveDuration: 1440, // 24 hours
});

Available Methods#

MethodDescriptionReturns
`send(options)`Send a text message to a channel`Promise<DiscordMessage>`
`sendEmbed(options)`Send a rich embed message to a channel`Promise<DiscordMessage>`
`reply(options)`Reply to a specific message (with reference)`Promise<DiscordMessage>`
`editMessage(options)`Edit an existing message by ID`Promise<DiscordMessage>`
`deleteMessage(options)`Delete a message by channel and message ID`Promise<void>`
`addReaction(options)`Add an emoji reaction to a message`Promise<void>`
`createThread(options)`Create a new thread from a message or channel`Promise<DiscordThread>`

Events#

Subscribe to Discord Gateway events in your skills:

EventTriggerPayload
`message`A message is sent in a visible channel`{ channelId, author, content, guildId, messageId }`
`command`A registered slash command is invoked`{ name, options, user, channelId, guildId, interactionId }`
`reaction`A reaction is added or removed`{ emoji, userId, channelId, messageId, action }`
`member_join`A new member joins the server`{ user, guildId, joinedAt }`
`member_leave`A member leaves or is removed from the server`{ userId, guildId }`
`voice_state`A member joins, leaves, or moves voice channels`{ userId, channelId, guildId, selfMute, selfDeaf }`

Example#

This example creates a moderation skill that uses the Think Engine to analyze new messages and flag potentially harmful content:

skills/community-moderator.ts
import { Cognest, Skill, IncomingEvent } from "@cognest/sdk";
import {
  DiscordIntegration,
  DiscordMessageEvent,
  DiscordCommandEvent,
} from "@cognest/integrations/discord";

const cognest = new Cognest();
const discord = cognest.integration<DiscordIntegration>("discord");

const moderation = new Skill({
  name: "community-moderator",
  description: "AI-powered content moderation for Discord servers",
  commands: [
    {
      name: "modstats",
      description: "Show moderation statistics for the current channel",
    },
  ],
});

// Analyze incoming messages
moderation.on("discord:message", async (event: IncomingEvent<DiscordMessageEvent>) => {
  const { channelId, content, author, messageId, guildId } = event.payload;

  // Skip bot messages
  if (author.bot) return;

  const analysis = await cognest.think({
    prompt: `Analyze this Discord message for policy violations.

Message: "${content}"

Respond with JSON: {
  "safe": boolean,
  "reason": string | null,
  "severity": "none" | "low" | "medium" | "high"
}`,
    responseFormat: "json",
  });

  const { safe, reason, severity } = analysis.parsed;

  if (!safe && (severity === "medium" || severity === "high")) {
    // Flag the message with a warning reaction
    await discord.addReaction({
      channelId,
      messageId,
      emoji: "warning",
    });

    // Send a moderation notice to the mod log channel
    await discord.sendEmbed({
      channelId: process.env.MOD_LOG_CHANNEL!,
      embed: {
        title: "Content Flag",
        color: severity === "high" ? 0xff4d4d : 0xffaa00,
        fields: [
          { name: "Author", value: `<@${author.id}>`, inline: true },
          { name: "Severity", value: severity, inline: true },
          { name: "Channel", value: `<#${channelId}>`, inline: true },
          { name: "Reason", value: reason ?? "No reason provided" },
          { name: "Content", value: `> ${content.slice(0, 200)}` },
        ],
        timestamp: new Date().toISOString(),
      },
    });
  }
});

// Handle /modstats slash command
moderation.on("discord:command", async (event: IncomingEvent<DiscordCommandEvent>) => {
  if (event.payload.name !== "modstats") return;

  const stats = await cognest.store.get(`modstats:${event.payload.channelId}`);

  await discord.sendEmbed({
    channelId: event.payload.channelId,
    embed: {
      title: "Moderation Stats (Last 24h)",
      color: 0x00e5cc,
      fields: [
        { name: "Messages Scanned", value: String(stats?.scanned ?? 0), inline: true },
        { name: "Flags Raised", value: String(stats?.flagged ?? 0), inline: true },
        { name: "Auto-Removed", value: String(stats?.removed ?? 0), inline: true },
      ],
    },
  });
});

cognest.register(moderation);
cognest.start();

Troubleshooting#

Common Issues

**Empty message content** — The MESSAGE_CONTENT privileged intent must be enabled in the Discord Developer Portal under your application's Bot settings. Without it, `content` will be an empty string for guild messages. **Slash commands not appearing** — Set `register_commands_on_start: true` in your config or run `cognest integration sync discord`. Global commands can take up to one hour to propagate; guild commands appear instantly. **Bot goes offline intermittently** — This is usually a heartbeat acknowledgement issue. Ensure your host has a stable network connection. Cognest handles reconnection automatically, but frequent disconnects may indicate resource constraints. **"Missing Permissions" errors** — Verify the bot role has the required permissions in the target channel. Channel-level permission overrides can restrict the bot even if server-level permissions are correct. Check Server Settings > Roles and the channel's permission overwrites.