Skip to content

Feature: Add Discord channel support #16

Description

@sesam

Summary

Add Discord as a new channel alongside the existing Telegram and Slack integrations. The current architecture already anticipates Discord — types.ts references Discord in both the acknowledge method comment (line 19: "Discord: typing indicator") and the Destination interface (line 52: "Discord thread"), so this would be a natural next step.

Motivation

Discord is one of the most widely used community/team platforms, especially in developer and AI communities. Adding it as a channel would significantly expand Utah's reach and make it usable in many more contexts.

Proposed implementation

The channel-agnostic design of the agent loop, reply dispatch, and acknowledgment means no changes are needed outside src/channels/ (except registering the handler in index.ts).

New files to create in src/channels/discord/

File Purpose Complexity
api.ts Discord REST API client — send messages (POST /channels/{id}/messages) and typing indicators (POST /channels/{id}/typing). Could use @discordjs/rest or raw fetch. Low
handler.ts Implements ChannelHandler with sendReply, acknowledge, and setup Low
transform.ts Maps Discord webhook payloads to AgentMessageData — e.g. d.channel_idchatId, d.author.idsenderId, d.contenttext Medium
setup.ts Webhook/bot registration + Ed25519 signature verification for incoming requests Medium–High
format.ts Markdown conversion — mostly pass-through since Discord supports standard MD, but needs 2000-char message chunking Low

File to modify

  • src/channels/index.ts — register the new DiscordHandler in the channel registry

Environment variables

DISCORD_BOT_TOKEN=...
DISCORD_APPLICATION_ID=...
DISCORD_PUBLIC_KEY=...   # for Ed25519 webhook signature verification

Discord-specific considerations

  1. Signature verification (Ed25519): Discord requires verifying X-Signature-Ed25519 and X-Signature-Timestamp headers on every incoming webhook request. This is stricter than Telegram and should be handled in the transform or a middleware layer.

  2. Interaction acknowledgment: Discord's Interactions Endpoint requires responding to PING events with an immediate PONG, which needs handling in the transform or an edge function.

  3. Message length limit: Discord caps messages at 2000 characters, so format.ts needs chunking logic for longer agent replies.

  4. Bot vs. Webhook approach: A bot-based approach (connecting to the Gateway) is more flexible for receiving messages than a pure webhook setup. Worth deciding which path to take.

Estimated effort

For a TypeScript dev familiar with Discord's API, roughly half a day to a full day of work. The hardest part is the Ed25519 signature verification and interaction acknowledgment — the rest maps cleanly onto the existing channel abstractions.

Happy to take a stab at this if the team is open to contributions!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions