Discord support triage board for unanswered questions

By General Input

See every question in your Discord support channels that nobody has answered yet, oldest first, with a clock on each row showing how long it has been waiting.

Integrations

  • Discord
  • Linear
  • Notion

Type

App

Categories

  • Customer Support
  • Engineering

Build me an app that my community and support team opens every morning: a triage board of every question asked in our Discord support channels that nobody has answered yet, oldest first, with a response-age clock on each row so we can see what has blown past our informal SLA.

Start with a setup view. Let me connect Discord and pick the server, then use Get Guild Channels to list the channels so I can tick the support channels I want tracked, and Get Guild Roles to list the server roles so I can mark which ones are helper roles (moderators, support, staff). Also let me set the SLA threshold in hours and the emoji used to mark a question handled. Save all of this so the team does not reconfigure it each visit. Every Discord ID is a snowflake string, so store and compare IDs as strings, never as numbers.

To build the board, a handler should walk the selected channels with Get Channel Messages and also call List Active Guild Threads for the server so questions asked inside threads are picked up alongside plain channel messages, keeping only threads whose parent is one of my selected channels. Message pagination is cursor-based with before and after and caps at 100 per page, so page backwards from the newest message using the last id as before, and stop once messages are older than a configurable lookback window (default seven days). Use Get a Message when the app needs to refresh a single conversation's root message rather than refetching a whole channel.

A row counts as unanswered when the last message in that conversation came from the person who asked, or when nobody holding one of the configured helper roles has replied to it. Group consecutive messages in a channel into a conversation by their thread when there is one, and otherwise by the asker and a short time window, so a person asking three messages in a row is one row and not three. Ignore bot messages when deciding whether something was answered.

Each row shows the asker's handle and avatar, the channel or thread name, the first line or two of the question, when it was asked, and a response-age clock counting the time since the asker's last message. Style the clock so it escalates visually as it grows and turns red once it is past the SLA threshold. Sort oldest first by default. Give me filters for channel, for age bucket (under 1 hour, 1 to 4 hours, 4 to 24 hours, over a day) and for whether the question looks like a bug versus a how-to, classified from the wording of the question with an obvious way for a person to correct the label on a row.

Opening a row shows the full conversation inline, every message in order with author, helper role badge, timestamp and any attachments, so I can answer without switching to Discord. Give the row a reply box that sends with Send a Message into that channel or thread, a button that marks it handled using Add Reaction with the configured emoji (which moves the row into a Handled section rather than deleting it), and a button that uses Create Thread from Message when a question deserves its own space, after which further replies from the app go into that new thread. Discord has no documented direct-message operation, so every reply must go into the channel or the thread and the UI should never imply otherwise.

Add an escalate button on each row. It opens a small form that uses Linear List Teams so I can choose the team, prefills the issue title from the question, and builds the description from the full thread text, the asker's Discord handle and a permalink back to the message in the form https://discord.com/channels/<guild_id>/<channel_id>/<message_id>. Submitting calls Create Issue. Store the returned issue id, key and URL against that conversation so we never escalate the same thread twice: afterwards the row shows the Linear issue key and its current status instead of the escalate button, refreshed with Get Issue when the board loads, and clicking the key opens the issue in Linear.

Give every row a Draft an answer button that kicks off a background agent. The agent reads the full conversation from Discord, searches our documentation with Notion Search by Title using key terms from the question, pulls the most promising pages with Retrieve Page as Markdown, and writes a suggested reply plus the list of source pages (title and link) back into the app against that row. The agent must never post to Discord. The finished draft lands in that row's reply box for a human to edit and send, the row shows the agent's status while it works and once a draft is ready, and I can re-run it if the draft misses.

Persist the setup, the handled marks, the corrected bug versus how-to labels, the escalation records and the drafted answers, so the board keeps its state between visits and across the team. Refresh data when the board loads and give me a manual refresh button with the time of the last refresh. Respect the rate limits: Discord allows about 50 requests per second globally with per-route buckets and returns retry_after on a 429, and Notion allows roughly 3 requests per second, so batch and back off rather than hammering either. Show a friendly empty state when nothing is waiting, because an empty board is the goal.

Related prompts

Explore more prompts
Catch feature flags that never got switched on in productionScreen chartered vessels for AIS gaps and sanctions red flagsCompare candidate store locations with drive time trade areasBrowse every competitor ad and build a Notion swipe fileWeekly alert noise review board for incident.io on-callMorning triage board for your Kernel browser agent runsTrack every half finished LaunchDarkly rollout in one boardAudience persona studio for brand and product marketersFind the customers stuck contacting support again and againArtwork desk for the Notion posts still missing an image