Slack, Discord, and GitHub Channels
Purpose and Scope
Slack, Discord, and GitHub channels are Flue’s pattern for accepting provider-originated HTTP events without turning Flue into a full replacement for each provider SDK. A channel verifies the incoming request, parses it into provider-native data, and then calls application code that decides whether to dispatch an agent, invoke a workflow, or return a provider-specific response. This page focuses on verified ingress, route placement, and the handoff from provider callbacks to durable Flue work, rather than outbound bot behavior or provider installation flows.
Sources: apps/docs/src/content/docs/guide/channels.md
The important design boundary is ownership. The channel package owns authentication of the inbound HTTP request, protocol handshakes, body parsing, typed provider payloads, and the route namespace beneath the provider name. Your application owns outbound credentials, SDK clients, authorization policy, OAuth or installation state, durable business persistence, and any agent tools that send messages or mutate provider state. That boundary is why Slack uses Slack’s Web API client, Discord uses a Discord REST client, and GitHub projects normally use Octokit for outbound calls instead of expecting Flue channel packages to wrap every provider API.
Sources: apps/docs/src/content/docs/guide/channels.md
Relevant Source Files
- apps/docs/src/content/docs/guide/channels.md — Defines the shared channel model: verified provider events enter through HTTP, blueprints create files such as source-root channel modules, route namespaces are derived from files under channels, and application code owns outbound SDK clients and business policy.
Shared Channel Model
Use the channel guide’s mental model before choosing a provider. A channel module is normally created with the CLI blueprint flow, such as asking the blueprint to add a first-party provider channel. The generated module lives under the source root in a file like a Slack, Discord, or GitHub channel file. It exports a named channel binding for Flue discovery and may also export ordinary application objects, such as an SDK client, helper functions, or tools that an agent can call after the incoming event has been authenticated.
Sources: apps/docs/src/content/docs/guide/channels.md
File-based routing gives each provider an isolated namespace. The immediate filename under the channels directory defines the route prefix, and the channel package then contributes one or more provider-specific webhook paths beneath that prefix. For example, the guide documents GitHub under a webhook route and Slack under an events route, while the provider ecosystem docs show Discord interactions as a similar provider-owned surface. This placement matters during deployment because external provider dashboards must point to the mounted Flue application plus the provider route, not to an arbitrary application endpoint.
Sources: apps/docs/src/content/docs/guide/channels.md
Provider Patterns
Slack is the richest of the three ingress surfaces because Slack can send Events API callbacks, interactivity payloads, and slash commands. The official Slack channel flow adds a Slack channel blueprint, installs the Flue Slack package and Slack Web API SDK, and creates a channel module. The event handler typically filters for event callbacks and app mentions, builds a thread-scoped conversation key from Slack team, channel, and timestamp data, and dispatches an agent with a Slack-shaped input. Optional interactivity and slash-command callbacks publish additional routes only when enabled, so unused surfaces do not need to be exposed.
Discord uses a request-response interaction model. The official Discord blueprint creates a channel module that verifies interactions with the Discord public key, exports a project-owned REST client, and dispatches only supported commands. A common handler checks the interaction type and command name, derives a trusted destination from the interaction, rejects unsupported or private destinations with an ephemeral message, and dispatches the agent using a destination-derived conversation key. The handler then returns a Discord interaction response that acknowledges acceptance while the agent continues work through application-owned message tools.
GitHub follows the webhook delivery model. A GitHub channel is typically mounted as a webhook endpoint under the GitHub channel namespace, receives JSON deliveries, and lets application code branch on the provider event name and native payload shape. The channel boundary is especially important for GitHub because choosing which events to subscribe to, which repositories or installations are authorized, and how to deduplicate delivery identifiers are application decisions. The channel should admit verified work quickly, while longer triage, issue comment analysis, pull request actions, or repository automation should be dispatched into Flue agents or workflows.
Implementation Flow
A practical setup starts by adding the provider blueprint, reviewing the generated channel module, and configuring the provider’s secret material. Slack needs a signing secret for inbound verification and a bot token for outbound Web API calls. Discord needs a public key for inbound interaction verification and a bot token for REST calls. GitHub needs a webhook secret for request verification and, when outbound behavior is required, an application-owned Octokit or GitHub App credential. Keep these values in the deployment environment rather than hard-coding them in channel modules.
flue add channel slack
flue add channel discord
flue add channel githubAfter the module exists, connect the handler to Flue work at the narrowest useful boundary. For chat-style providers, that often means deriving a stable conversation key from the provider destination so a Slack thread or Discord channel continues the same durable agent instance. For GitHub, it may mean deriving keys from an issue, pull request, or repository event. The input passed to the agent should preserve enough provider-native identifiers for later tools to respond, but the authorization checks for using those identifiers belong in application code and tools, not in the conversation key itself.
Sources: apps/docs/src/content/docs/guide/channels.md
Edge Cases and Responsibilities
Verified ingress does not automatically solve retries, duplicate deliveries, provider rate limits, or outbound authorization. Slack Events API retries, GitHub redeliveries, and repeated Discord interactions should be considered separately from signature verification. If duplicate processing matters, persist provider delivery identifiers or interaction identifiers in your own database before admitting durable work. If an agent can post back to Slack, Discord, or GitHub, expose only the narrowly scoped tool it needs, check the destination against trusted context, and rely on the provider SDK for the actual API call.
Sources: apps/docs/src/content/docs/guide/channels.md
Custom or less common provider behavior should follow the same checklist. Verify against the exact unconsumed request body, preserve provider-native events instead of normalizing away important fields, test valid and invalid signatures, and test protocol handshakes and responses on the Node or Cloudflare target you will deploy. The generic channel blueprint described by the guide exists for providers without a first-party package, but the same responsibilities apply to first-party Slack, Discord, and GitHub integrations when you modify the generated files.
Sources: apps/docs/src/content/docs/guide/channels.md
Next Steps
Use this page when deciding where provider event handling ends and application logic begins. Continue with the broader Channels guide for discovery and routing, the CLI add reference for blueprint-driven scaffolding, and the Agent API or Workflows guide for dispatch targets. If you are implementing response tools, read the Tools guide next so outbound Slack replies, Discord messages, or GitHub comments remain typed, authorized, and scoped to the verified event context that introduced the work.