feat(channels): add Discord adapter (#625) - #656
Merged
Merged
Conversation
Implements DiscordAdapter conforming to the ChannelAdapter interface, using Discord Incoming Webhooks for outbound messages and the Interactions endpoint for inbound slash commands. Changes: - platform/internal/channels/discord.go: DiscordAdapter + splitMessage helper (Discord enforces 2000-char limit; long messages are split at newline/space boundaries). ParseWebhook handles type-1 PING (returns nil so the router layer can respond), type-2 APPLICATION_COMMAND, and type-3 MESSAGE_COMPONENT payloads. ValidateConfig rejects non-discord webhook URLs (SSRF guard matches Slack pattern). - platform/internal/channels/discord_test.go: 20 unit tests covering Type/DisplayName, ValidateConfig (valid + 5 invalid cases), SendMessage error paths, ParseWebhook (PING / slash command / DM user / unknown type / invalid JSON), StartPolling, GetAdapter registry lookup, ListAdapters inclusion, and splitMessage edge cases. - platform/internal/channels/registry.go: register "discord" adapter. - .env.example: document DISCORD_WEBHOOK_URL. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
molecule-ai Bot
pushed a commit
to Molecule-AI/molecule-ai-org-template-molecule-dev
that referenced
this pull request
Apr 17, 2026
Adds a Discord channel entry to community-manager/workspace.yaml so the Community Manager workspace can send alerts and receive slash commands via Discord. Requires DISCORD_WEBHOOK_URL set as a global secret. Companion to EnterOS-AI/enter-os-core#656 (Discord adapter). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This was referenced Apr 17, 2026
molecule-ai Bot
pushed a commit
that referenced
this pull request
Apr 21, 2026
- Mark discord as ✅ Implemented (was: Planned) - Add Discord Setup section with webhook config, Canvas steps, API example - Document slash command inbound + webhook outbound architecture Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3 tasks
molecule-ai Bot
added a commit
that referenced
this pull request
Apr 21, 2026
…er-clean feat(channels): add Discord adapter (#625)
molecule-ai Bot
pushed a commit
that referenced
this pull request
Apr 21, 2026
- Mark discord as ✅ Implemented (was: Planned) - Add Discord Setup section with webhook config, Canvas steps, API example - Document slash command inbound + webhook outbound architecture Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This was referenced Apr 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the Discord channel adapter so Community Manager (and any other workspace) can send messages to Discord and receive inbound slash commands.
platform/internal/channels/discord.go—DiscordAdapterimplementingChannelAdapter:ValidateConfig: requireswebhook_urlstarting withhttps://discord.com/api/webhooks/(matches the Slack SSRF-guard pattern)SendMessage: POSTs{"content": text}to the webhook; splits messages >2000 chars at newline/space boundaries (Discord hard limit)ParseWebhook: handles type-1 PING (returns nil — router layer must respond{"type":1}), type-2 APPLICATION_COMMAND, type-3 MESSAGE_COMPONENT; extracts text as/commandname option1 option2; prefersmember.useroveruser(guild vs DM)StartPolling: returns nil (Discord uses Interactions webhook, not long-polling)platform/internal/channels/discord_test.go— 20 unit tests (ValidateConfig × 6, SendMessage error paths × 2, ParseWebhook × 5, StartPolling, registry × 2, splitMessage × 4)platform/internal/channels/registry.go— register"discord": &DiscordAdapter{}.env.example— documentDISCORD_WEBHOOK_URLOrg-template change (separate repo)
community-manager/workspace.yamlinmolecule-ai-org-template-molecule-devwill be updated in a companion PR to wireDISCORD_WEBHOOK_URLinto the Community Manager's channel config. Community Manager is the natural owner — its role description explicitly calls out Discord triage.Setup instructions
POST /settings/secrets{"key":"DISCORD_WEBHOOK_URL","value":"https://discord.com/api/webhooks/..."}https://<platform-host>/webhooks/discordTest plan
go test ./platform/internal/channels/...passes (all 20 new Discord tests + existing)GET /channels/adaptersreturns{"type":"discord","display_name":"Discord"}in listtype=discordand a valid webhook URL; verifyPOST /workspaces/:id/channels/:id/testsends a test message to DiscordCloses #625
🤖 Generated with Claude Code