Channels
Expose an agent as a chat assistant on Slack, Linear, Discord, or the web.
What it is. The glue between an agent and the chat interface you already use.
Use it when your team lives in Slack or Linear, or you want the agent answering on Discord or embedded in your own website.
Works with agents (the actor behind the channel) and connections (the brokered OAuth grant for the platform).
A channel block binds an agent to a chat platform. Once a channel is enabled, the agent answers messages on that platform. Each inbound message starts an agent turn, and the agent's reply is posted back to the conversation.
Channels are how a hosted agent becomes a live assistant rather than only a workflow step. When those hosted surfaces are enabled for a project, the same agent block can power a workflow node, a chat session, and one or more channels at the same time.
The channel block
The channel block is a top-level declaration. It points at an agent by name and declares which platform delivers messages.
secret vendor_keys {
vars: [OPENROUTER_API_KEY]
}
agent concierge {
label: "Concierge"
secrets: vendor_keys
model: "openai/gpt-4o-mini"
maxSteps: 8
system: @ts {
return "You are a helpful concierge. Prefer tools over guessing."
}
}
channel slack_concierge {
label: "Concierge (Slack)"
platform: slack
integration: slack
agent: concierge
mode: mention
enabled: true
}Field reference
| Field | Type | Required | Description |
|---|---|---|---|
platform | enum | Yes | Where messages are delivered. One of slack, linear, discord, web. |
integration | enum | Yes | Credential source for the binding. Must match platform. Same allowed values. |
agent | identifier | Yes | Name of a top-level agent block that handles inbound messages. A bare identifier, not a quoted string. |
mode | enum | No | How inbound events are routed. One of mention, dm, all. Defaults to mention. |
enabled | boolean | No | When false, the binding is inactive. Defaults to enabled. |
label | string | No | Display name shown in the Portal. |
description | string | No | Description shown in the Portal. |
Platforms
platform | Where the agent runs |
|---|---|
slack | Responds in Slack channels and DMs. |
linear | Responds on Linear issues and comments. |
discord | Responds in Discord servers and DMs. |
web | Responds in the embedded web chat surface. |
The integration field selects which connected credential delivers and sends messages. It must equal platform. A channel with platform: slack and integration: linear is a validation error.
Modes
mode controls which inbound events reach the agent.
mode | The agent responds to |
|---|---|
mention (default) | Only messages that @-mention the agent. |
dm | Only direct messages. |
all | Both mentions and direct messages. |
For a focused assistant on a busy Slack workspace, mention keeps the agent quiet until called. For a private one-on-one assistant, dm is the common choice. The web surface typically uses dm.
Routing and uniqueness
The runtime routes an inbound event by the tuple platform : mode : agent. Two enabled channels cannot share the same tuple, because the runtime would not know which binding wins.
// Valid: same agent, different platforms.
channel slack_concierge {
platform: slack
integration: slack
agent: concierge
mode: mention
}
channel web_concierge {
platform: web
integration: web
agent: concierge
mode: dm
}// Valid: same platform and mode, different agents.
channel slack_concierge {
platform: slack
integration: slack
agent: concierge
mode: mention
}
channel slack_researcher {
platform: slack
integration: slack
agent: researcher
mode: mention
}// Invalid: two enabled bindings for slack:mention:concierge.
channel a {
platform: slack
integration: slack
agent: concierge
mode: mention
}
channel b {
platform: slack
integration: slack
agent: concierge
mode: mention
}A disabled channel (enabled: false) does not count toward this check. You can keep an inactive duplicate around without a conflict.
Common mistakes
platform and integration mismatch
The two fields must be equal. They are separate so the binding can name both the surface and its credential source, but a mismatch is rejected.
// Incorrect
channel bad {
platform: slack
integration: web
agent: concierge
}// Correct
channel good {
platform: slack
integration: slack
agent: concierge
}agent as a quoted string
The agent field takes a bare identifier that names an agent block, not a quoted string.
// Incorrect
channel bad {
platform: web
integration: web
agent: "concierge"
}// Correct
channel good {
platform: web
integration: web
agent: concierge
}Binding to an undefined agent
The agent must resolve to an agent block in the workspace, whether in the same file or another file in a multi-file workflow. A name with no matching block is a validation error.
Duplicate enabled routing
Two enabled channels with the same platform : mode : agent tuple conflict. Change the mode, point one at a different agent, or set enabled: false on one of them.
Further reading
- Agents: The
agentblock, roles, tools, sandboxes, and subagent teams. - Secrets and auth:
secretblocks and provider key setup. - Multi-file workflows: Declaring agents and channels across files.
Agents
Declare stateful LLM agents with tools, profiles, and sandboxes, then invoke them from any workflow.
Embed agent chat in your app
Connect a signed-in user of your app to a Swirls agent over the web channel, with conversations and history backed by the Swirls API. OIDC federation keeps access tokens on your server.