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. The same agent block can power a workflow node, Cloud in-app chat, and one or more channels at the same time. Channel bindings come from your deployed definition: deploy with git push or swirls deploy and routing updates immediately.
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
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, mcp, portal. |
agent | identifier | Yes | Name of a top-level agent block that handles inbound messages. A bare identifier, not a quoted string. |
connection | identifier | No | Name of a top-level connection block supplying the OAuth credential. Its provider must match platform. Forbidden on platform: mcp channels. |
connector | identifier | Yes, on platform: mcp | Name of a top-level connector block naming the inbound OAuth application. Valid only on platform: mcp channels. |
mode | enum | No | How inbound events are routed. One of mention, dm, all, ambient. Defaults to mention. Forbidden on platform: mcp channels. ambient is available on Portal channels only. |
engagement_timeout | quoted duration | No | How long the agent stays engaged with a thread after being mentioned in it. Defaults to "30m". See Response policy fields. |
cooldown | quoted duration | No | Minimum gap between the agent's unprompted posts. Defaults to "15s". See Response policy fields. |
max_unprompted_per_hour | integer | No | Ceiling on unprompted posts per hour; 0 disables them. Defaults to 6. See Response policy fields. |
enabled | boolean | No | When false, the binding is inactive. Defaults to enabled. |
label | string | No | Display name shown in the dashboard. |
description | string | No | Description shown in the dashboard. |
Platforms
platform | Where the agent runs |
|---|---|
slack | Responds in Slack channels and DMs. |
linear | Responds on Linear issues and comments. Requires connection: to post replies. |
discord | Responds in Discord servers and DMs. |
web | Standalone authenticated chatbox at /chat/web/:projectId/:channelName, plus SDK embeds keyed by channel name. |
mcp | Exposes the agent as a remote MCP server that external clients (Claude Desktop, Claude Code, ChatGPT) connect to as a custom connector. See MCP channels. |
portal | Makes the channel a room inside a Portal: a shared timeline your whole team can post in, with the agent as a member. The only platform that supports mode: ambient. |
For OAuth-backed platforms (slack, linear, discord), set connection: to name a connection block whose provider matches platform, and authorize that connection on the project Connections page in Swirls Cloud. The web surface does not require a connection.
platform: mcp is different from the other four: it requires connector: instead of connection:, forbids mode:, and the agent is reached by an external client's own tool rather than a chat platform Swirls integrates with. See MCP channels for the full DSL, the credential flow, and connecting from Claude Desktop, Claude Code, and ChatGPT.
The web chatbox requires a signed-in Swirls user with an active organization. To put agent chat in front of your own app's users, proxy it through your server: see Embed agent chat.
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 | Every top-level message in the room, not just mentions. A reply inside a thread still needs a mention (or an active engagement, see below), so a side conversation doesn't re-prompt the agent on every line. |
ambient | The agent watches the channel and responds only when it judges a message is addressed to it; otherwise it stays silent. See When the agent responds. Available today on Portal rooms only; other platforms report "not yet supported." |
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. For a Portal room where people talk about many things and the agent should only jump in when it's actually relevant, ambient is the one to reach for.
For platform: web, mode is optional and ignored by the chat service. Web channels are not routed by platform:mode:agent; each web channel gets its own standalone chatbox link keyed by channel name. You can declare multiple web channels for the same agent (for example separate support and sales chatboxes).
Cloud in-app chat lists all deployed agents and does not require a web channel. Use a platform: web channel when you want a dedicated standalone chatbox link or SDK embed.
When the agent responds
Every channel needs a rule for when its agent speaks, and mentions come first no matter what else is going on. Tag the agent by name and it answers, in a thread or in the open room, every time, even in a room the agent has gone quiet in for rate limits. A direct message gets the same guarantee: it always reaches the agent.
Tag the agent once in a thread and it stays with that conversation. Every reply in the thread reads as addressed to it, so your team keeps talking without re-tagging it on every line. The same thing happens when the agent starts a thread itself: people replying under its own message don't need to tag it either. The agent lets go on its own once the thread has sat quiet for a while (thirty minutes by default, tunable with engagement_timeout), and anyone in the thread can end the conversation sooner by muting the agent there. Mentioning the agent again always brings it back, even in a thread that was muted.
Sometimes two people need to talk past the agent in a room it's watching, without leaving the room to do it. Mark a single message as an aside in the composer, and the agent treats it as if it were never sent: no reply, no note taken, and the thread's standing with the agent is unchanged.
For a room where the agent should watch every message and use its own judgment, set mode: ambient. The agent watches the channel and responds only when it judges a message is addressed to it; otherwise it stays silent. A message that's clearly for the agent gets an answer; one that's clearly for someone else gets nothing; the room in between sometimes gets a quick reaction instead of a full reply, so the agent can acknowledge something without cluttering the conversation. Nothing the agent skips is lost: every message still lands in the room's history, so the moment someone does address the agent directly, it has the full conversation to work from. Ambient mode is available today on Portal rooms; other platforms will tell you it isn't supported yet if you set it.
To keep a busy all or ambient room from being dominated by the agent, two limits apply automatically to anything it wasn't directly asked to answer: it waits at least a few seconds between posts, and it caps how many unprompted messages it sends per hour. Both are tunable per channel (below), and neither one ever holds back a mention or a DM.
Response policy fields
These fields tune how the agent behaves in all and ambient rooms. All are optional; an empty declaration uses the managed defaults.
| Field | Type | Default | Description |
|---|---|---|---|
engagement_timeout | quoted duration | "30m" | How long the agent stays with a thread after being mentioned in it (or after starting it) before it stops treating replies as addressed to it. A whole number followed by s, m, or h ("30m", "2h"), from "1s" up to "24h". |
cooldown | quoted duration | "15s" | Minimum gap between the agent's own posts in the channel. Applies only to posts nobody asked for by name; a mention or DM is never delayed by it. "0s" is allowed and removes the gap entirely. Up to "24h". |
max_unprompted_per_hour | integer | 6 | Ceiling on how many unprompted posts the agent makes per rolling hour. 0 stops unprompted posts entirely; mentions and DMs are never counted against it. |
Durations are quoted strings, not bare numbers: write cooldown: "15s", not cooldown: 15s. The parser catches the unquoted form and tells you how to fix it.
channel ops {
platform: portal
agent: support
mode: ambient
engagement_timeout: "30m"
cooldown: "15s"
max_unprompted_per_hour: 6
}Good to know:
engagement_timeout,cooldown, andmax_unprompted_per_hourare rejected onplatform: mcpchannels. An MCP channel answers the request it was called with; there's no room for it to watch or wait its turn in.
Routing and uniqueness
Non-web platforms route inbound events by the tuple platform : mode : agent. Two enabled channels cannot share the same tuple, because the runtime would not know which binding wins.
Web channels are different: each enabled web channel must have a unique channel block name. Multiple web channels can point at the same agent.
// Valid: same agent, different platforms.
channel slack_concierge {
platform: slack
agent: concierge
mode: mention
}
channel web_concierge {
label: "Concierge (Web)"
platform: web
agent: concierge
enabled: true
}// Valid: multiple web chatboxes for the same agent (unique channel names).
channel web_support {
platform: web
agent: concierge
}
channel web_sales {
platform: web
agent: concierge
}// Invalid: two enabled web channels with the same block name.
channel web_concierge {
platform: web
agent: concierge
}
channel web_concierge {
platform: web
agent: researcher
}// Valid: same platform and mode, different agents.
channel slack_concierge {
platform: slack
agent: concierge
mode: mention
}
channel slack_researcher {
platform: slack
agent: researcher
mode: mention
}// Invalid: two enabled bindings for slack:mention:concierge.
channel a {
platform: slack
agent: concierge
mode: mention
}
channel b {
platform: 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
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
agent: "concierge"
}// Correct
channel good {
platform: 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
For Slack, Linear, and Discord, 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.
For web channels, two enabled channels cannot share the same channel block name. Rename one or disable it.
Unquoted durations
engagement_timeout and cooldown take quoted duration literals, not a bare number and unit.
// Incorrect
channel ops {
platform: portal
agent: support
cooldown: 15s
}// Correct
channel ops {
platform: portal
agent: support
cooldown: "15s"
}Further reading
- Agents: The
agentblock, roles, tools, sandboxes, and subagent teams. - Embed agent chat: Put a web channel in front of your own app's users.
- Connections: The
connectionblock and OAuth authorization in Swirls Cloud. - Secrets and auth:
secretblocks and provider key setup. - Multi-file workflows: Declaring agents and channels across files.