Channels
Connect agents to chat platforms or publish agents and workflows through MCP.
A channel block binds an agent to a chat platform. Each inbound message that matches the channel's routing rules starts an agent turn, and the reply returns to the conversation. Supported OAuth platforms use a connection to authenticate replies.
With platform: mcp, a channel can publish selected workflows, an agent, or both. Use MCP channels when a customer should run a workflow directly from an external assistant.
The same agent can serve workflow nodes, Cloud chat, and multiple channels. Deploy with git push or swirls deploy to update the channel bindings.
The channel block
The channel block is a top-level declaration. Chat channels point at an agent by name and declare which platform delivers messages. MCP channels declare an agent, a nonempty workflows list, or both.
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, swirls. |
agent | identifier | Except workflow-only MCP channels | Name of a top-level agent block that handles inbound messages. A bare identifier, not a quoted string. |
workflows | identifier list | MCP without an agent | Workflows published as MCP tools. Each requires an explicit workflow grant. See MCP channels. |
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 Swirls app 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 | What the channel exposes |
|---|---|
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 | Publishes an agent, workflows, or both as a remote MCP server that external clients (Claude Desktop, Claude Code, ChatGPT) connect to as a custom connector. See MCP channels. |
swirls | Makes the channel a shared room rendered by a Surface app channel: page. 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 requires connector:, forbids connection: and mode:, and exposes tools to an external MCP client. An agent is optional when the channel publishes workflows. See MCP channels for declarations, permissions, and client setup.
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 Surface app rooms only; other platforms report "not yet supported." |
Use mention for explicit requests in a shared channel, dm for direct messages, or ambient when the agent should decide which messages in a shared app room need a response.
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
Mentions and direct messages reach the agent even when the channel's limits on unprompted posts have been reached.
Mentioning an agent in a thread, or replying to a thread it started, engages it in that conversation. Subsequent replies do not need another mention. Engagement expires after the thread is idle for engagement_timeout (30 minutes by default). Muting ends engagement sooner; a new mention re-engages the agent.
Mark a message as an aside in the composer to exclude it from the agent's context and response handling. An aside does not change the thread's engagement state.
In ambient mode, the agent evaluates whether a message needs a response, a reaction, or neither. Messages remain in the room history for later turns. Ambient mode is currently supported only in shared Swirls app rooms; other platforms reject it.
In all and ambient modes, cooldown limits the frequency of unprompted posts and max_unprompted_per_hour caps their number. Neither limit delays mentions or direct messages.
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: swirls
agent: support
mode: ambient
engagement_timeout: "30m"
cooldown: "15s"
max_unprompted_per_hour: 6
}
engagement_timeout,cooldown, andmax_unprompted_per_hourare rejected onplatform: mcpchannels. MCP channels handle client requests without room-based response routing.
Routing and uniqueness
Slack, Linear and Discord 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, MCP and Surface channels are addressed by name: enabled channels must have unique channel block names. Several channels may expose the same agent or publish the same workflows.
// 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, MCP, and Surface 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: swirls
agent: support
cooldown: 15s
}// Correct
channel ops {
platform: swirls
agent: support
cooldown: "15s"
}Further reading
- MCP channels: Publish workflow tools or agent conversations for external assistants.
- 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.