channel/setTopic
Sets or updates the topic of a Slack channel. The topic is displayed prominently at the top of the channel and serves as a live status line. Ideal for dynamic status information that changes frequently. Requires channels:manage scope.
When to Use
- Incident status updates: Set the incident channel topic with severity level, current status (investigating / mitigating / resolved), and the responsible engineer's name so all responders have instant context.
- Deployment status: Update the deployment channel topic after each deploy to show the current version, environment, and deployment time (
v2.4.1 deployed to prod at 14:32 UTC). - Sprint goal broadcasting: At the start of each sprint, update the team channel topic with the sprint goal and key dates so it is always visible to team members.
- On-call rotation: Automatically update the ops channel topic when the on-call rotation changes to always show who is currently on-call.
Configuration
Connection
| Field | Type | Required | Description |
|---|---|---|---|
botToken | string | Required | Bot Token starting with xoxb-. Requires channels:manage scope. |
Operation Fields
| Field | Type | Required | Description |
|---|---|---|---|
channelId | string | Required | The channel to update. Starts with C (public) or G (private). |
topic | string | Required | The new topic text. Max 250 characters. Supports basic Slack formatting: <URL|label>, @user, #channel. |
Topic vs. Purpose: The topic is a live status line — update it frequently to reflect what is happening right now. The purpose is a stable description of what the channel is for. Use
channel/setTopic for current-state information and channel/setPurpose for channel documentation.
Sample Configuration
{
"operation": "channel/setTopic",
"connection": {
"botToken": "{{credentials.slackBotToken}}"
},
"fields": {
"channelId": "{{$json.channelId}}",
"topic": "{{$json.topic}}"
}
}
Validation Errors
| Error Code | Cause | Resolution |
|---|---|---|
channel_not_found | Invalid channel ID or bot not in private channel. | Verify the channel ID. For private channels, the bot must be a member. |
missing_scope | Bot token lacks channels:manage scope. | Re-authorize the Slack app with the required scope. |
is_archived | The channel is archived. | Unarchive the channel first, then update the topic. |
Output
Success Port
| Field | Type | Description |
|---|---|---|
channelId | string | The channel that was updated. |
topic | string | The new topic text as confirmed by Slack. |
status | string | success or error. |
errorCode | string | Slack error code when status is error. |
payload | object | Full raw Slack API response. |
Error Port
On failure with Continue on Error enabled, routes to the error port with status: "error" and populated errorCode.
Sample Output
{
"channelId": "C08INCIDENTS",
"topic": "P1 ACTIVE | DB connection exhausted | Owner: @john | Status: Mitigating | Started: 14:32 UTC",
"status": "success",
"errorCode": "",
"payload": {
"ok": true,
"topic": "P1 ACTIVE | DB connection exhausted | Owner: @john | Status: Mitigating | Started: 14:32 UTC"
}
}
Expression Reference
| Expression | Result |
|---|---|
{{$node["channel-settopic"].json.topic}} | Confirmed new topic — use in audit logs. |
{{'P' + $json.severity + ' ACTIVE | ' + $json.description + ' | Owner: @' + $json.ownerHandle}} | Template for an incident channel topic with severity and owner. |
{{'v' + $json.version + ' deployed to ' + $json.env + ' at ' + new Date().toUTCString()}} | Template for a deployment status topic. |
{{'Sprint ' + $json.sprintNumber + ': ' + $json.sprintGoal + ' | Ends: ' + $json.sprintEndDate}} | Template for a sprint goal topic. |
Node Policies & GuardRails
| Policy Area | Recommendation |
|---|---|
| Scope requirements | Requires channels:manage scope for public channels. Private channels may need groups:write. |
| Rate limiting | Tier 2 (20+ req/min). For high-frequency topic updates (e.g., real-time status), debounce updates — send at most one update per 30 seconds to avoid flooding the channel with system messages. |
| No hard-coded IDs | Always source channelId from upstream expressions. Never hard-code channel IDs. |
| Topic length limit | Keep topics under 250 characters. Use a template that prioritizes the most important fields (status, owner, time) and truncates secondary details. |
| Topic vs. purpose | Use topic for dynamic, frequently-changing status. Use purpose for stable, descriptive documentation. Do not duplicate content between the two. |
| System message noise | Each topic update generates a system message in the channel ("Bot updated the channel topic"). For high-frequency updates, consider batching changes to reduce noise. |
Examples
Example 1 — Incident Channel Topic with Live Status
When an incident fires or its status changes, updates the incident channel topic with current severity, status, and owner.
// Triggered by PagerDuty status change event
// $json.severity, $json.description, $json.ownerHandle, $json.status, $json.startedAt
{
"operation": "channel/setTopic",
"fields": {
"channelId": "{{$json.incidentChannelId}}",
"topic": "{{
$json.severity + ' ' + $json.status.toUpperCase() +
' | ' + $json.description.substring(0, 80) +
' | Owner: @' + $json.ownerHandle +
' | Started: ' + $json.startedAt
}}"
}
}
Example 2 — Deployment Channel Post-Deploy Update
After a successful deployment pipeline completes, updates the deploy channel topic to reflect the current production version.
// Triggered by CI/CD pipeline success event
// $json.version, $json.environment, $json.deployedBy
{
"operation": "channel/setTopic",
"fields": {
"channelId": "C08DEPLOYS01",
"topic": "{{
'PROD: v' + $json.version +
' | Deployed: ' + new Date().toUTCString() +
' | By: ' + $json.deployedBy
}}"
}
}
Example 3 — Weekly On-Call Rotation Update
Scheduled Monday morning workflow that updates the ops channel topic with the week's on-call engineer.
// HTTP Request → get on-call schedule for this week
// $json.oncallName, $json.oncallHandle, $json.weekEndDate
{
"operation": "channel/setTopic",
"fields": {
"channelId": "C08OPSALERTS",
"topic": "{{
'On-call this week: @' + $json.oncallHandle +
' (' + $json.oncallName + ')' +
' | Rotation ends: ' + $json.weekEndDate +
' | PagerDuty: https://pagerduty.example.com/oncall'
}}"
}
}