Skip to content

feat(discord): Add Ephemeral Support#514

Open
DeanMauro wants to merge 2 commits into
vercel:mainfrom
DeanMauro:feat/discord-ephemeral
Open

feat(discord): Add Ephemeral Support#514
DeanMauro wants to merge 2 commits into
vercel:mainfrom
DeanMauro:feat/discord-ephemeral

Conversation

@DeanMauro
Copy link
Copy Markdown

@DeanMauro DeanMauro commented May 15, 2026

Summary

Resolves #515. This PR adds support for ephemeral messages in Discord.

Because Discord's loading state (the initial "thinking..." response produced by DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE) sets the visibility for the entire message and cannot be changed once set, the EPHEMERAL message flag must be set in the initial response (i.e. in this.respondToInteraction()). See here for more detail.

I've added a hook to the adapter that can conditionally set these flags, for example for particular slash commands.

    const discord = createDiscordAdapter({
      applicationId,
      botToken: env.DISCORD_BOT_TOKEN,
      publicKey: env.DISCORD_PUBLIC_KEY,
      mentionRoleIds: getMentionRoleIds(env.DISCORD_MENTION_ROLE_IDS),
      userName: env.BOT_USER_NAME,
      logger,
      flags: (context) => {
        if (context.command === '/ephemeral') {
          return DiscordMessageFlag.Ephemeral;
        }
      }
    });

Slash commands use the post() method regardless.

chat.onSlashCommand('/public', async event => {
   await event.channel.post("This is a public response. Anyone can see it.");
});

chat.onSlashCommand('/ephemeral', async event => {
   await event.channel.post("This is a private response. Only the user who issued the command can see it.");
});

The result looks like this:

Public
https://github.com/user-attachments/assets/039e13cc-279c-4440-b09a-3ecd3975fd81

Ephemeral
https://github.com/user-attachments/assets/8d5fde57-647d-4055-986a-d4866e9adbd7

Both the loading state and the final message are Ephemeral if the flag is set; public otherwise. Using postEphemeral() falls back to sending a private DM.

Notes

  • I tried other methods like deleting the loading state message and creating a new one below it as a follow up and it just looks sloppy.
  • Also considered a straight ephemeral: boolean field in the adapter config but that's too limiting for those who want per-command control.

Test plan

Created a public and private slash command and tested with a test app.

Checklist

  • All commits are signed and verified
  • pnpm validate passes
  • Changeset added (or N/A — see CONTRIBUTING.md)
  • Documentation updated (or N/A)

@DeanMauro DeanMauro requested a review from a team as a code owner May 15, 2026 21:41
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 15, 2026

@DeanMauro is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@DeanMauro DeanMauro mentioned this pull request May 15, 2026
1 task
@DeanMauro DeanMauro force-pushed the feat/discord-ephemeral branch from 450ee9d to 169e054 Compare May 16, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discord: Add Ephemeral Support

1 participant