This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @chat-adapter/discord@4.34.0 ### Minor Changes -0fdb902: Add opt-in Discord Components v2 rendering for Chat SDK cards via `contentFormat: DiscordContentFormat.ComponentsV2`. -5341f90: Ignore `@everyone`/`@here` pings by default in gateway mode. Previously the legacy gateway listener treated global pings as bot mentions, so the bot responded to announcements. A new `respondToGlobalMentions` config option (default `false`) restores the old behavior when enabled, and also lets forwarded gateway messages opt in via the `mention_everyone` field. -6c2a391: Add support for renaming native Discord thread channels. ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/slack@4.34.0 ### Minor Changes -1721fa0: Add support for Slack's Agent messaging experience (`agent_view`). - New core event `onAppContextChanged` with a normalized `AppContextEntity[]` describing the user's active view (channel / canvas / list / message / unknown). - `AppHomeOpenedEvent` now carries the folded active-view context as `entities` and the opened `tab` (Slack: `"home"` / `"messages"`), so handlers can tell a Home-tab open from the DM-open signal under `agent_view`. - Slack adapter: new `agentView` config flag (under `agent_view`, `app_home_opened` is the DM-open signal regardless of tab and folded context is surfaced), routing for the `app_context_changed` event, and a `getAppContext(message)` helper to read the folded context on DM messages. - `setSuggestedPrompts` now accepts an optional thread reference (agent_view lets prompts sit at the top of the agent conversation). - Under `agentView`, DM (Messages-tab) messages are threaded per new Slack's model — each user message is a thread root (`thread_ts ?? ts`). Conversation-scoped threads returned by `openDM()` keep working: when that thread is subscribed, incoming top-level DM messages route to it. - `createSlackAdapter` env auth fallback (`SLACK_BOT_TOKEN` / `SLACK_CLIENT_ID` / `SLACK_CLIENT_SECRET`) is now disabled only when an auth or verification field (`botToken`, `clientId`, `clientSecret`, `installationProvider`, `signingSecret`, `webhookVerifier`) is passed explicitly, instead of by any config object — so `createSlackAdapter({ agentView: true })` still picks up env credentials, while explicit-secret configs stay immune to ambient env vars. - Bumped `@slack/web-api` to `^7.18.0` (adds the optional `thread_ts` typing for `setSuggestedPrompts`). -4717a38: Add chart support and richer table rendering, with native Slack data table and data visualization blocks. - New core `ChartElement` and `Chart()` builder (JSX supported) with pie, bar, area, and line charts, mirroring Slack's data visualization model: pie charts take `segments`, series charts take named `series` plotted against shared `categories` with optional `xLabel`/`yLabel`. - `TableElement` / `Table()` gain optional `caption` (accessible table description) and `pageSize` (rows per page) fields. - Charts degrade gracefully on platforms without native chart support: the underlying data renders as a text table via the shared card fallback (new `chartElementToFallbackText` helper). - Slack adapter: card tables now render as [data table blocks](https://docs.slack.dev/reference/block-kit/blocks/data-table-block) by default — paginated and sortable — instead of plain table blocks. Header-only tables keep the plain table block; tables exceeding Slack limits (100 data rows, 20 columns, 10,000 characters) fall back to ASCII as before. - Slack adapter: card charts render as [data visualization blocks](https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block). Charts violating Slack constraints (50-character title, 12 segments/series, 20 categories, 20-character labels, one data point per category, max 2 charts per message) fall back to a text rendering instead of being rejected by the API. - The `@chat-adapter/slack/blocks` subpath gets the same treatment: `SlackChartElement` types, `chart` card children, data table rendering, and matching limits. - `postMessage` now surfaces Slack's per-block validation details when the API rejects blocks (`invalid_blocks`), instead of the bare "An API error occurred" message. -0f743c9: Add declarative agent-experience config and harden native streaming: - `suggestedPrompts` — a static payload or per-thread resolver, applied automatically when an assistant/agent thread opens (`assistant_thread_started` in legacy `assistant_view`, or a Messages-tab `app_home_opened` under `agentView`, where prompts pin at the top of the agent conversation without a `thread_ts`). The resolver receives the thread context (`channelId`, `userId`, legacy `threadTs`/`teamId`/`enterpriseId`, and active-view `entities` under `agentView`); returning `null`/`undefined` skips the thread. Prompts beyond Slack's 4-prompt limit are dropped with a warning, and resolver/API failures are logged without failing the webhook. - `loadingMessages` — default rotating status strings for the assistant thinking indicator, used by `startTyping` and `setAssistantStatus` when no explicit status/messages are passed. - `nativeStreaming` config (default `true`). Set `false` on Slack flavours without the `chat.startStream` family (e.g. GovSlack) to always stream via post-and-edit. - If the workspace rejects the first native streaming call, `stream()` now falls back to throttled post-and-edit mid-stream instead of failing the reply; already-consumed text is preserved. Permanent platform errors (`unknown_method`, `method_deprecated`, `feature_not_enabled`) latch native streaming off for subsequent streams on the adapter instance. Structured chunks (`task_update` / `plan_update`) are skipped in fallback mode. - `feedbackButtons` — append Slack's native thumbs up/down (`context_actions` + `feedback_buttons` block) to every streamed reply. Pass `true` for defaults or an options object (`actionId`, labels, values); clicks dispatch through `bot.onAction` with a positive/negative value. A `buildFeedbackButtonsBlock(options?)` helper is exported for attaching the block to non-streamed messages. New exported types: `SlackFeedbackButtonsOptions`, `SlackSuggestedPrompt`, `SlackSuggestedPrompts`, `SlackSuggestedPromptsContext`, `SlackSuggestedPromptsOptions`. ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/telegram@4.34.0 ### Minor Changes -8d7ccdb: Add Telegram media group uploads for multiple files and attachments. ### Patch Changes -2531a42: Fix `detectMention` (and the Telegram adapter's `isBotMentioned`) falsely matching `@bot` when `@bot-dev` is mentioned. `\b` (word boundary) matches between a word character and a hyphen, so `/@bot\b/` incorrectly matches `@bot-dev`. Replaced with `(?![\w-])` to exclude hyphens. - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/web@4.34.0 ### Minor Changes -6714efc: Support AI SDK v7 as a peer dependency. - `chat` now accepts `ai@^6.0.182 || ^7.0.0` (`chat/ai` tools work with both majors). - `@chat-adapter/web` now accepts `ai@^6 || ^7`, `@ai-sdk/react@^3 || ^4`, `@ai-sdk/svelte@^4 || ^5`, and `@ai-sdk/vue@^3 || ^4`. - The `chat/ai` tool factories now declare explicit `Tool<Input, Output>` return types instead of relying on inference, so the published declarations no longer depend on `ai` internals that changed in v7. The public type surface is unchanged. ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/whatsapp@4.34.0 ### Minor Changes -2338a66: Add `sendTemplate()` for sending pre-approved template messages, enabling business-initiated conversations outside the 24-hour customer service window -8bd8a57: Implement outbound file and attachment sending for the WhatsApp adapter. Supports binary `FileUpload` uploads, typed `Attachment` payloads (binary or HTTPS link passthrough), multi-file sequential sends, smart MIME-to-message-type mapping, caption placement with audio/long-text fallbacks, and card+file sequencing. ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/x@4.34.0 ### Minor Changes -4bca64f: add image upload support to X posts and DMs via the chunked media upload endpoints ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## chat@4.34.0 ### Minor Changes -1721fa0: Add support for Slack's Agent messaging experience (`agent_view`). - New core event `onAppContextChanged` with a normalized `AppContextEntity[]` describing the user's active view (channel / canvas / list / message / unknown). - `AppHomeOpenedEvent` now carries the folded active-view context as `entities` and the opened `tab` (Slack: `"home"` / `"messages"`), so handlers can tell a Home-tab open from the DM-open signal under `agent_view`. - Slack adapter: new `agentView` config flag (under `agent_view`, `app_home_opened` is the DM-open signal regardless of tab and folded context is surfaced), routing for the `app_context_changed` event, and a `getAppContext(message)` helper to read the folded context on DM messages. - `setSuggestedPrompts` now accepts an optional thread reference (agent_view lets prompts sit at the top of the agent conversation). - Under `agentView`, DM (Messages-tab) messages are threaded per new Slack's model — each user message is a thread root (`thread_ts ?? ts`). Conversation-scoped threads returned by `openDM()` keep working: when that thread is subscribed, incoming top-level DM messages route to it. - `createSlackAdapter` env auth fallback (`SLACK_BOT_TOKEN` / `SLACK_CLIENT_ID` / `SLACK_CLIENT_SECRET`) is now disabled only when an auth or verification field (`botToken`, `clientId`, `clientSecret`, `installationProvider`, `signingSecret`, `webhookVerifier`) is passed explicitly, instead of by any config object — so `createSlackAdapter({ agentView: true })` still picks up env credentials, while explicit-secret configs stay immune to ambient env vars. - Bumped `@slack/web-api` to `^7.18.0` (adds the optional `thread_ts` typing for `setSuggestedPrompts`). -4717a38: Add chart support and richer table rendering, with native Slack data table and data visualization blocks. - New core `ChartElement` and `Chart()` builder (JSX supported) with pie, bar, area, and line charts, mirroring Slack's data visualization model: pie charts take `segments`, series charts take named `series` plotted against shared `categories` with optional `xLabel`/`yLabel`. - `TableElement` / `Table()` gain optional `caption` (accessible table description) and `pageSize` (rows per page) fields. - Charts degrade gracefully on platforms without native chart support: the underlying data renders as a text table via the shared card fallback (new `chartElementToFallbackText` helper). - Slack adapter: card tables now render as [data table blocks](https://docs.slack.dev/reference/block-kit/blocks/data-table-block) by default — paginated and sortable — instead of plain table blocks. Header-only tables keep the plain table block; tables exceeding Slack limits (100 data rows, 20 columns, 10,000 characters) fall back to ASCII as before. - Slack adapter: card charts render as [data visualization blocks](https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block). Charts violating Slack constraints (50-character title, 12 segments/series, 20 categories, 20-character labels, one data point per category, max 2 charts per message) fall back to a text rendering instead of being rejected by the API. - The `@chat-adapter/slack/blocks` subpath gets the same treatment: `SlackChartElement` types, `chart` card children, data table rendering, and matching limits. - `postMessage` now surfaces Slack's per-block validation details when the API rejects blocks (`invalid_blocks`), instead of the bare "An API error occurred" message. -6714efc: Support AI SDK v7 as a peer dependency. - `chat` now accepts `ai@^6.0.182 || ^7.0.0` (`chat/ai` tools work with both majors). - `@chat-adapter/web` now accepts `ai@^6 || ^7`, `@ai-sdk/react@^3 || ^4`, `@ai-sdk/svelte@^4 || ^5`, and `@ai-sdk/vue@^3 || ^4`. - The `chat/ai` tool factories now declare explicit `Tool<Input, Output>` return types instead of relying on inference, so the published declarations no longer depend on `ai` internals that changed in v7. The public type surface is unchanged. ### Patch Changes -5c926f1: Preserve markdown structural whitespace when extracting normalized message text. -2531a42: Fix `detectMention` (and the Telegram adapter's `isBotMentioned`) falsely matching `@bot` when `@bot-dev` is mentioned. `\b` (word boundary) matches between a word character and a hyphen, so `/@bot\b/` incorrectly matches `@bot-dev`. Replaced with `(?![\w-])` to exclude hyphens. ## @chat-adapter/gchat@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/github@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/linear@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/messenger@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/shared@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 ## @chat-adapter/teams@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/twilio@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 - @chat-adapter/shared@4.34.0 ## @chat-adapter/state-ioredis@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 ## @chat-adapter/state-memory@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 ## @chat-adapter/state-pg@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 ## @chat-adapter/state-redis@4.34.0 ### Patch Changes - Updated dependencies [5c926f1] - Updated dependencies [2531a42] - Updated dependencies [1721fa0] - Updated dependencies [4717a38] - Updated dependencies [6714efc] - chat@4.34.0 ## @chat-adapter/tests@4.34.0 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@chat-adapter/discord
npm package:
@chat-adapter/discord
Discord adapter for Chat SDK. Configure with HTTP Interactions and Gateway WebSocket support.
Documentation: chat-sdk.dev/adapters/official/discord · Guides: vercel.com/kb/chat-sdk
Installation
pnpm add @chat-adapter/discord
Scaffold with the CLI
To scaffold a new Discord bot with this adapter preselected:
npx create-chat-sdk@latest my-bot --adapter discord memory
Visit the adapters directory to see other available official and vendor-official adapters.
Usage
The adapter auto-detects DISCORD_BOT_TOKEN, DISCORD_PUBLIC_KEY, DISCORD_APPLICATION_ID, and DISCORD_MENTION_ROLE_IDS from environment variables:
import { Chat } from "chat";
import { createDiscordAdapter } from "@chat-adapter/discord";
const discord = createDiscordAdapter();
const bot = new Chat({
userName: "mybot",
adapters: {
discord,
},
});
bot.onNewMention(async (thread, message) => {
await thread.post("Hello from Discord!");
});
Discord application setup
1. Create application
- Go to the Discord Developer Portal
- Click New Application and give it a name
- Note the Application ID from the General Information page
- Copy the Public Key from the General Information page
2. Create bot
- Go to the Bot section in the left sidebar
- Click Reset Token to generate a new bot token
- Copy and save the token (you won't see it again)
- Enable these Privileged Gateway Intents:
- Message Content Intent
- Server Members Intent (if needed)
3. Configure interactions endpoint
- Go to General Information
- Set Interactions Endpoint URL to
https://your-domain.com/api/webhooks/discord - Discord sends a PING to verify the endpoint
4. Add bot to server
- Go to OAuth2 then URL Generator
- Select scopes:
bot,applications.commands - Select bot permissions: Send Messages, Send Messages in Threads, Create Public Threads, Manage Threads, Read Message History, Add Reactions, Attach Files
- Copy the generated URL and open it to invite the bot to your server
Architecture: HTTP Interactions vs Gateway
Discord has two ways to receive events:
HTTP Interactions (default):
- Receives button clicks, slash commands, and verification pings
- Works out of the box with serverless
- Does not receive regular messages
Gateway WebSocket (required for messages):
- Receives regular messages and reactions
- Receives slash commands and button clicks when no Interactions Endpoint URL is configured
- Requires a persistent connection
- In serverless environments, use a cron job to maintain the connection
Discord sends interactions through either the Gateway or an Interactions Endpoint URL, not both. Use the HTTP endpoint for serverless apps. For resident gateway-only apps, leave the Interactions Endpoint URL unset and start the Gateway listener without webhookUrl so interactions are processed directly.
Gateway setup for serverless
1. Create Gateway route
import { after } from "next/server";
import { bot } from "@/lib/bot";
export const maxDuration = 800;
export async function GET(request: Request): Promise<Response> {
const cronSecret = process.env.CRON_SECRET;
if (!cronSecret) {
return new Response("CRON_SECRET not configured", { status: 500 });
}
const authHeader = request.headers.get("authorization");
if (authHeader !== `Bearer ${cronSecret}`) {
return new Response("Unauthorized", { status: 401 });
}
const durationMs = 600 * 1000;
const webhookUrl = `https://${process.env.VERCEL_URL}/api/webhooks/discord`;
await bot.initialize();
const discord = bot.getAdapter("discord");
return discord.startGatewayListener(
{ waitUntil: (task) => after(() => task) },
durationMs,
undefined,
webhookUrl
);
}
2. Configure Vercel Cron
{
"crons": [
{
"path": "/api/discord/gateway",
"schedule": "*/9 * * * *"
}
]
}
This runs every 9 minutes, ensuring overlap with the 10-minute listener duration.
3. Add environment variables
Add CRON_SECRET to your Vercel project settings.
Role mentions
By default, only direct user mentions (@BotName) trigger onNewMention handlers. To also trigger on role mentions (e.g., @AI):
- Create a role in your Discord server (e.g., "AI")
- Assign the role to your bot
- Copy the role ID (right-click role in server settings with Developer Mode enabled)
- Add to
mentionRoleIds:
createDiscordAdapter({
mentionRoleIds: ["1457473602180878604"],
});
Or set DISCORD_MENTION_ROLE_IDS as a comma-separated string in your environment variables.
Interaction flags
Discord interactions return a transient "thinking..." message, which then gets replaced with your content. Because of Discord's API, your message's ephemerality must be set on this initial response, not later in an onSlashCommand handler.
Use the interactionFlags option to make the loading state and your custom response visible only to the user who invoked the command:
import {
createDiscordAdapter,
DiscordInteractionResponseFlag,
} from "@chat-adapter/discord";
createDiscordAdapter({
interactionFlags: ({ command }) => {
if (command === "/admin") {
return DiscordInteractionResponseFlag.Ephemeral;
}
},
});
Later calls to event.channel.post() will share the same ephemeral message.
Calls to event.channel.postEphemeral() will fallback to a private DM.
Components v2 cards
Discord cards render as embeds by default. To render Chat SDK cards with
Discord Components v2 instead, set contentFormat:
import { DiscordContentFormat } from "@chat-adapter/discord";
createDiscordAdapter({
contentFormat: DiscordContentFormat.ComponentsV2,
});
When enabled, card messages use Discord's IS_COMPONENTS_V2 flag and render
with components such as containers, sections, text displays, media galleries,
buttons, and string selects. Plain text messages still use Discord message
content.
Discord caps a Components v2 message at 40 total components and 4000 characters
across all text. When a card exceeds either limit the adapter throws a
ValidationError rather than letting Discord reject the request.
Configuration
All options are auto-detected from environment variables when not provided.
| Option | Required | Description |
|---|---|---|
botToken |
No* | Discord bot token. Auto-detected from DISCORD_BOT_TOKEN |
publicKey |
No* | Application public key. Auto-detected from DISCORD_PUBLIC_KEY |
applicationId |
No* | Discord application ID. Auto-detected from DISCORD_APPLICATION_ID |
contentFormat |
No | Render Chat SDK cards as DiscordContentFormat.Embeds or DiscordContentFormat.ComponentsV2. Defaults to DiscordContentFormat.Embeds |
mentionRoleIds |
No | Array of role IDs that trigger mention handlers. Auto-detected from DISCORD_MENTION_ROLE_IDS (comma-separated) |
respondToGlobalMentions |
No | Treat @everyone/@here pings as mentions of the bot. Defaults to false |
interactionFlags |
No | Function returning Discord interaction flags for the initial deferred slash command response |
apiUrl |
No | Override the Discord API base URL. Auto-detected from DISCORD_API_URL |
logger |
No | Logger instance (defaults to ConsoleLogger("info")) |
*botToken, publicKey, and applicationId are required — either via config or env vars.
Discord thread channel names
Call discord.setThreadTitle(thread.id, title) to rename an existing Discord thread channel. The bot needs the Manage Threads permission.
Environment variables
DISCORD_BOT_TOKEN=your-bot-token
DISCORD_PUBLIC_KEY=your-application-public-key
DISCORD_APPLICATION_ID=your-application-id
DISCORD_MENTION_ROLE_IDS=1234567890,0987654321 # Optional
DISCORD_API_URL=... # Optional, override the Discord API base URL
CRON_SECRET=your-random-secret # For Gateway cron
Features
Messaging
| Feature | Supported |
|---|---|
| Post message | Yes |
| Edit message | Yes |
| Delete message | Yes |
| File uploads | Yes |
| Streaming | Post+Edit fallback |
Rich content
| Feature | Supported |
|---|---|
| Card format | Embeds by default, Components v2 when enabled |
| Buttons | Yes |
| Link buttons | Yes |
| Select menus | Components v2 |
| Tables | GFM |
| Fields | Yes |
| Images in cards | Yes |
| Modals | No |
Conversations
| Feature | Supported |
|---|---|
| Slash commands | Yes |
| Mentions | Yes |
| Add reactions | Yes |
| Remove reactions | Yes |
| Typing indicator | Yes |
| DMs | Yes |
| Ephemeral messages | No (DM fallback) |
Message history
| Feature | Supported |
|---|---|
| Fetch messages | Yes |
| Fetch single message | No |
| Fetch thread info | Yes |
| Fetch channel messages | Yes |
| List threads | Yes |
| Fetch channel info | Yes |
| Post channel message | Yes |
Testing
Run a local tunnel (e.g., ngrok) to test webhooks locally:
ngrok http 3000
Update the Interactions Endpoint URL in the Discord Developer Portal to your ngrok URL.
Troubleshooting
Bot not responding to messages
- Check Gateway connection: Messages require the Gateway WebSocket, not just HTTP interactions
- Verify Message Content Intent: Enable this in the Bot settings
- Check bot permissions: Ensure the bot can read messages in the channel
Role mentions not triggering
- Verify role ID: Enable Developer Mode in Discord settings, then right-click the role
- Check
mentionRoleIdsconfig: Ensure the role ID is in the array - Confirm bot has the role: The bot must have the role assigned
Signature verification failing
- Check public key format: Should be a 64-character hex string (lowercase)
- Verify endpoint URL: Must exactly match what's configured in Discord Developer Portal
- Check for body parsing: Don't parse the request body before verification
Resources
- Create a Discord support bot with Nuxt and Redis — Walks through building a Discord support bot with Nuxt, covering project setup, Discord app configuration, Gateway forwarding, AI-powered responses, and deployment.
See all guides and templates at chat-sdk.dev/resources.
AI Coding Agents
If you use an AI coding agent such as OpenAI Codex, Claude Code, or Cursor, install the Chat SDK skill so it knows the SDK APIs, adapter patterns, and project conventions before writing code.
npx skills add vercel/chat
The skill references bundled documentation in node_modules/chat/docs, plus adapter guides and starter templates in the published package.
You can also install the Vercel Plugin for a broader agent toolkit — it includes the Chat SDK skill alongside specialist agents, agent slash commands, and more:
npx plugins add vercel/vercel-plugin
The plugin is optional; the skill alone is enough to build with Chat SDK.
For agent-readable documentation, see chat-sdk.dev/llms.txt (page index) or chat-sdk.dev/llms-full.txt (full text).
License
MIT