Slack Integration
Connect Agents to Slack for messaging and notifications
Connect Agents to Slack to post automated messages, send notifications, and share meeting insights with your team.
Overview
The Slack integration enables workflows to:
- Post messages to public and private channels
- Send direct messages to users
- Share formatted content with rich formatting
- Deliver notifications based on meeting events
Prerequisites
Before connecting Slack:
- Slack workspace where you have permission to install apps
- Channel access to channels you want to post to
- Admin approval (if your workspace requires app approval)
Connecting Slack
Step 1: Navigate to Integrations
- Go to Workspace Settings
- Select Integrations
- Find Slack in the list
Step 2: Authorize Connection
- Click Connect
- Review the requested permissions
- Select the workspace to install to
- Click Allow
Step 3: Invite Bot to Channels
After installation, the Agents bot needs to be invited to channels:
- Go to the Slack channel
- Type
/invite @Meetingflow(or your bot's name) - The bot can now post to that channel
Required Permissions
The Slack integration requests these OAuth scopes:
| Scope | Purpose |
|---|---|
chat:write | Post messages to channels |
chat:write.public | Post to public channels without joining |
users:read | Look up users for DMs |
users:read.email | Find users by email |
channels:read | List available channels |
groups:read | List private channels (if invited) |
Available Actions
Slack Post
Post a message to a Slack channel or direct message.
Configuration:
| Parameter | Type | Required | Description |
|---|---|---|---|
| channel | string | Yes | Channel ID or name (e.g., C0123456789 or #general) |
| text | string | Yes | Message content (supports Slack mrkdwn) |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
| mrkdwn | boolean | true | Enable Slack markdown formatting |
| unfurl_links | boolean | false | Show link previews |
| unfurl_media | boolean | false | Show media previews |
Channel Configuration
Channel IDs vs Names
You can specify channels two ways:
Channel ID (recommended):
C0123456789
- Most reliable
- Works even if channel is renamed
- Found in channel details → Copy Link
Channel Name:
#general
- More readable
- May break if channel is renamed
- Include the
#prefix
Finding Channel IDs
- Open Slack
- Right-click on the channel
- Select Copy Link
- The ID is the last part of the URL:
https://workspace.slack.com/archives/C0123456789
Private Channels
For private channels:
- Invite the bot first:
/invite @Meetingflow - Use the channel ID (not name)
- Bot must be a member to post
Direct Messages
To send a DM, use the user's Slack ID as the channel:
U0123456789
Or the bot can look up users by email if configured.
Message Formatting
Slack mrkdwn
Slack uses its own markdown syntax called "mrkdwn":
| Format | Syntax | Result |
|---|---|---|
| Bold | *bold* | bold |
| Italic | _italic_ | italic |
| Strikethrough | ~strike~ | |
| Code | `code` | code |
| Code block | code | Code block |
| Quote | > quote | Quoted text |
| Link | <https://url|text> | Clickable link |
| User mention | <@U0123456789> | @username |
| Channel mention | <#C0123456789> | #channel |
Formatting Examples
Basic formatting:
*Meeting Summary* for {{ json.meeting.title }}
_Key Points:_
• {{ json.summary.point1 }}
• {{ json.summary.point2 }}
> "{{ json.keyQuote }}"
<{{ json.meeting.link }}|View full notes>
With sections:
:clipboard: *Post-Meeting Update*
*Meeting:* {{ json.meeting.title }}
*Date:* {{ json.meeting.startTime | date: "%B %d, %Y" }}
*Attendees:* {{ json.meeting.attendees | map: "name" | join: ", " }}
---
*Summary:*
{{ json.summary }}
*Action Items:*
{% for item in json.actionItems %}
• {{ item }}
{% endfor %}
Emoji
Use emoji shortcodes:
:white_check_mark: Task completed
:warning: Attention needed
:rocket: Launch update
:calendar: Meeting scheduled
Example Workflows
Post-Meeting Summary
[Event: MEETING_ENDED]
│
▼
[Load Meeting]
│
▼
[AI: Summarize meeting]
│
▼
[Slack Post]
Message Template:
:memo: *Meeting Summary*
*{{ json.meeting.title }}*
{{ json.meeting.startTime | date: "%B %d at %I:%M %p" }}
{{ json.summary }}
{% if json.actionItems.size > 0 %}
*Action Items:*
{% for item in json.actionItems %}
• {{ item }}
{% endfor %}
{% endif %}
Deal Alert to Sales Channel
[Event: MEETING_ENDED]
│
▼
[Load Meeting]
│
▼
[AI: Analyze deal urgency]
│
▼
[If: is urgent?]
│
├── Yes ──▶ [Slack Post: #urgent-deals]
│
└── No ───▶ [Slack Post: #deal-updates]
Scheduled Pipeline Report
[Scheduled: Every Monday 9 AM]
│
▼
[AI: Generate pipeline summary]
│
▼
[Slack Post: #sales-team]
Message Template:
:chart_with_upwards_trend: *Weekly Pipeline Report*
Good morning team! Here's your pipeline update:
*Active Deals:* {{ json.activeDeals }}
*Total Value:* ${{ json.totalValue | round: 0 }}
*Meetings This Week:* {{ json.meetingsScheduled }}
*Top Opportunities:*
{% for deal in json.topDeals %}
• {{ deal.name }} - ${{ deal.amount }} ({{ deal.stage }})
{% endfor %}
Have a great week! :muscle:
Best Practices
1. Use Channel IDs
Channel IDs are more reliable than names:
- ✅
C0123456789 - ⚠️
#sales-team(may break if renamed)
2. Keep Messages Concise
Slack messages work best when they're scannable:
- Use bullet points for lists
- Bold important information
- Keep summaries to 3-5 sentences
- Use emoji sparingly for visual hierarchy
3. Include Context
Always include enough context for the message to be useful:
*{{ json.meeting.title }}*
{{ json.meeting.startTime | date: "%B %d" }} • {{ json.meeting.attendees.size }} attendees
{{ json.summary }}
4. Handle Missing Data
Check for data before including it:
{% if json.actionItems.size > 0 %}
*Action Items:*
{% for item in json.actionItems %}
• {{ item }}
{% endfor %}
{% else %}
_No action items identified_
{% endif %}
5. Test in a Test Channel
Before posting to production channels:
- Create a
#workflow-testingchannel - Configure workflow to post there
- Verify formatting and content
- Update to production channel
Troubleshooting
Common Errors
| Error | Cause | Solution |
|---|---|---|
| "channel_not_found" | Invalid channel ID or bot not invited | Verify channel ID and invite bot |
| "not_in_channel" | Bot not in private channel | Invite bot with /invite |
| "invalid_auth" | Token expired | Reconnect Slack integration |
| "rate_limited" | Too many messages | Add delays between posts |
| "msg_too_long" | Message > 40,000 chars | Shorten message or split |
Bot Not Posting
If messages aren't appearing:
- Check bot membership - Is bot in the channel?
- Check channel ID - Is the ID correct?
- Check permissions - Does bot have
chat:write? - Check execution logs - Any error messages?
Formatting Issues
If formatting looks wrong:
- Verify you're using Slack mrkdwn (not regular markdown)
- Check for unescaped special characters
- Test in Slack's message composer first
- Ensure
mrkdwn: truein configuration
Rate Limits
Slack has rate limits:
| Method | Limit |
|---|---|
chat.postMessage | 1 per second per channel |
| General | 50+ per minute |
If you hit limits:
- Add Wait nodes between posts
- Batch messages where possible
- Spread workflows across time
Advanced Features
Link Unfurling
Control how links appear:
unfurl_links: false # Don't expand links into previews
unfurl_media: false # Don't expand images/videos
Usually keep these false for cleaner messages.
Threading (Future)
Threading support may be added in future versions to reply to existing messages.
Block Kit (Future)
Support for Slack Block Kit rich formatting may be added for more complex layouts.
Security Considerations
Token Storage
- OAuth tokens are encrypted at rest
- Tokens are scoped to minimal required permissions
- Tokens are refreshed as needed
Channel Access
The bot can only post to:
- Public channels (without being invited)
- Private channels where it's been invited
- DMs to users in the workspace
Message Content
Be careful not to include:
- Sensitive customer data
- Internal-only information in public channels
- PII without appropriate consent