A data connector for slack integration.
Project description
Rustic AI Slack Integration Module
Bidirectional Slack integration for Rustic AI guilds with real-time Socket Mode support.
Features
✅ Socket Mode (Real-time) - Receive Slack events via WebSocket (no public endpoint needed!)
✅ Natural Language Interface - Send messages and manage channels using conversational requests
✅ Direct API Access - Send messages, list channels, create channels programmatically
✅ Bidirectional Communication - Bot responds to @mentions and DMs automatically
✅ Thread Support - Replies stay in threads for organized conversations
✅ Simple Token Management - Environment variable token storage
✅ LLM Tool Calling - Automatic conversion of natural language to Slack API calls
✅ Multi-workspace Support - Manage multiple Slack workspaces
Installation
cd slack
poetry install --with dev --all-extras
Quick Start
1. Create Slack App with Socket Mode
- Visit https://api.slack.com/apps
- Create new app → "From scratch"
- Socket Mode → Enable Socket Mode
- Generate App-Level Token:
- Token Name: "Socket Mode Token"
- Scopes:
connections:write - Copy token (starts with
xapp-)
- Event Subscriptions → Enable Events
- Subscribe to bot events:
app_mention- Bot is @mentionedmessage.channels- Messages in channelsmessage.im- Direct messages
- Subscribe to bot events:
- OAuth & Permissions → Add bot token scopes:
app_mentions:readchat:writechannels:readchannels:historyim:historyusers:read
- Install to workspace
- Copy the Bot User OAuth Token (starts with
xoxb-)
2. Set Environment Variables
export SLACK_BOT_TOKEN="xoxb-your-bot-token-here"
export SLACK_APP_TOKEN="xapp-your-app-token-here" # NEW - For Socket Mode
export OPENAI_API_KEY="sk-your-key-here" # For LLM agent
3. Load the Guild
from rustic_ai.core.guild.builders import GuildBuilder
# Build guild from JSON spec - Socket Mode connects automatically!
guild = GuildBuilder.from_json_file("slack/slack_guild.json").launch("my_org")
# Check logs for:
# INFO - SlackSocketModeAgent ready, starting Socket Mode listener...
# INFO - Connecting to Slack via Socket Mode...
# INFO - Socket Mode connected and listening for events!
4. Interact with Bot
In Slack (Socket Mode - Inbound)
# In any Slack channel where bot is a member:
@mybot what's the weather?
# Bot automatically:
# 1. Receives event via Socket Mode
# 2. Processes with LLM
# 3. Responds in thread
From Web App or Code (Outbound)
Send messages via guild:
Option A: Natural Language (via LLM)
from rustic_ai.core.guild.agent_ext.depends.llm.models import (
ChatCompletionRequest,
UserMessage
)
# Send to guild
request = ChatCompletionRequest(
messages=[
UserMessage(content="Send 'Hello team!' to #general")
]
)
# Publish request to guild...
Option B: Direct API Call
from rustic_ai.slack.models.messages import SlackSendMessageRequest
request = SlackSendMessageRequest(
workspace_id="default_workspace",
channel="#general",
text="Hello from Rustic AI!"
)
# Publish request to guild...
Architecture
Bidirectional Flow
┌─────────────────────────────────────────────────────────────────┐
│ OUTBOUND (Guild → Slack) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ User Request (Web App) │
│ │ │
│ ▼ │
│ ChatCompletionRequest ("send hello to #general") │
│ │ │
│ ▼ │
│ SlackLLM Agent (LLMAgent with tools) │
│ │ (converts to API call) │
│ ▼ │
│ SlackSendMessageRequest │
│ │ │
│ ▼ │
│ SlackConnector Agent │
│ │ (uses SLACK_BOT_TOKEN) │
│ ▼ │
│ POST https://slack.com/api/chat.postMessage │
│ │ │
│ ▼ │
│ ✅ Message appears in Slack │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ INBOUND (Slack → Guild) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ User in Slack: "@mybot hello" │
│ │ │
│ ▼ │
│ Slack sends event via Socket Mode WebSocket │
│ │ │
│ ▼ │
│ SlackSocketModeAgent (WebSocket listener) │
│ │ (receives app_mention event) │
│ ▼ │
│ Publishes SlackEventMessage to SLACK_INBOUND topic │
│ │ │
│ ▼ │
│ SlackEventHandlerAgent │
│ │ (cleans @mention, adds context) │
│ ▼ │
│ ChatCompletionRequest("hello") │
│ │ │
│ ▼ │
│ SlackLLM Agent (processes request) │
│ │ │
│ ▼ │
│ SlackSendMessageRequest (with thread_ts for threading) │
│ │ │
│ ▼ │
│ SlackConnectorAgent │
│ │ │
│ ▼ │
│ POST https://slack.com/api/chat.postMessage │
│ │ │
│ ▼ │
│ ✅ Bot replies in Slack thread │
│ │
└─────────────────────────────────────────────────────────────────┘
Agents
SlackSocketMode (slack_socket_mode) - NEW!
- Connects to Slack via Socket Mode WebSocket
- Receives real-time events (mentions, messages, reactions)
- Publishes events to guild message bus
- No public endpoint required
SlackEventHandler (slack_event_handler) - NEW!
- Processes incoming Slack events
- Cleans up @mentions and formats messages
- Routes events to appropriate handlers (LLM, custom agents)
- Maintains context for threaded replies
SlackConnector (slack_connector)
- Handles all Slack API operations (outbound)
- Reads token from
SLACK_BOT_TOKENenv var - Supports messages, channels, users, files, reactions
- Uses thread context from session state for replies
SlackLLM (slack_llm)
- Natural language interface using LLMAgent
- Configured with Slack tools (send_message, list_channels, create_channel)
- Converts user requests to API calls
- Processes both web app requests and Slack events
API Reference
Message Operations
# Send message
SlackSendMessageRequest(
workspace_id="default_workspace",
channel="#general", # or channel ID "C123ABC"
text="Hello Slack!",
)
# Update message
SlackUpdateMessageRequest(
workspace_id="default_workspace",
channel="C123ABC",
ts="1234567890.123456",
text="Updated message",
)
# Delete message
SlackDeleteMessageRequest(
workspace_id="default_workspace",
channel="C123ABC",
ts="1234567890.123456",
)
# Get message history
SlackGetMessagesRequest(
workspace_id="default_workspace",
channel="C123ABC",
limit=100,
)
Channel Operations
# List channels
SlackListChannelsRequest(
workspace_id="default_workspace",
types="public_channel,private_channel", # comma-separated
exclude_archived=True,
limit=100,
)
# Create channel
SlackCreateChannelRequest(
workspace_id="default_workspace",
name="new-channel", # lowercase, hyphens only
is_private=False,
)
# Join channel
SlackJoinChannelRequest(
workspace_id="default_workspace",
channel="C123ABC",
)
# Invite to channel
SlackInviteToChannelRequest(
workspace_id="default_workspace",
channel="C123ABC",
users=["U123ABC"],
)
Guild Specification
The guild is defined in slack_guild.json with:
- 2 agents: SlackConnector + SlackLLM
- 3 tools for LLM:
send_message→ SlackSendMessageRequestlist_channels→ SlackListChannelsRequestcreate_channel→ SlackCreateChannelRequest
- Topic-based routing:
SLACK_CHAT- LLM conversationsSLACK_API- Direct API operationsuser_message_broadcast- Responses to user
Token Management
Environment Variable (Primary)
export SLACK_BOT_TOKEN="xoxb-your-token"
SlackConnector checks SLACK_BOT_TOKEN first.
Guild State (Fallback)
# Set in guild state
await guild.set_state("slack_bot_token", "xoxb-new-token")
# Clear cache to reload
slack_connector = guild._agents_by_name["SlackConnector"]
slack_connector._clients.clear()
slack_connector._token = None
Socket Mode vs HTTP Webhooks
This module uses Socket Mode instead of HTTP webhooks for receiving events:
| Feature | Socket Mode ✅ | HTTP Webhooks |
|---|---|---|
| Public endpoint | Not needed | Required (HTTPS) |
| Firewall | Works behind firewall | Requires inbound access |
| Development | Local testing easy | Need ngrok/public URL |
| Connection | WebSocket (persistent) | HTTP POST (per event) |
| Setup complexity | Simple (2 tokens) | Complex (webhook verification) |
| Security | WSS connection | Signature verification |
| Best for | Internal tools, dev | Public apps, production |
Why Socket Mode?
- ✅ No public server needed
- ✅ Works on localhost
- ✅ Simpler setup
- ✅ Faster development
- ✅ Consistent with WebSocket architecture
Configuration
Required Scopes
# Socket Mode
connections:write # Socket Mode connection (app-level token)
# Bot Token Scopes
app_mentions:read # Receive @bot mentions
chat:write # Post messages
channels:read # View channel info
channels:history # View channel messages
im:history # View DM messages
users:read # View user info
Environment Variables
SLACK_BOT_TOKEN=xoxb-your-token # Required
SLACK_APP_TOKEN=xapp-your-token # Required (Socket Mode)
OPENAI_API_KEY=sk-your-key # Required for LLM agent
Testing
# Run tests
cd slack
poetry run pytest
# Run specific test
poetry run pytest tests/test_connector_agent.py
Examples
Example 1: Send Notification
from rustic_ai.slack.models.messages import SlackSendMessageRequest
request = SlackSendMessageRequest(
workspace_id="default_workspace",
channel="#notifications",
text="Deployment completed successfully!"
)
Example 2: List Channels
from rustic_ai.slack.models.channels import SlackListChannelsRequest
request = SlackListChannelsRequest(
workspace_id="default_workspace",
types="public_channel",
limit=50
)
Example 3: Natural Language
from rustic_ai.core.guild.agent_ext.depends.llm.models import (
ChatCompletionRequest,
UserMessage
)
request = ChatCompletionRequest(
messages=[
UserMessage(content="Create a new channel called project-alpha")
]
)
Troubleshooting
"No Slack bot token found"
# Check if set
echo $SLACK_BOT_TOKEN
# Set it
export SLACK_BOT_TOKEN="xoxb-your-token"
"Channel not found"
Invite the bot to the channel first:
# In Slack:
/invite @YourBot
"Missing scope"
- Go to https://api.slack.com/apps
- Your App → OAuth & Permissions
- Add missing scope under "Bot Token Scopes"
- Reinstall to workspace
- Update
SLACK_BOT_TOKEN
Module Structure
slack/
├── src/rustic_ai/slack/
│ ├── agents/
│ │ └── connector_agent.py # SlackConnectorAgent
│ ├── client/
│ │ └── slack_client.py # SlackAPIClient
│ ├── models/
│ │ ├── messages.py # Message models
│ │ ├── channels.py # Channel models
│ │ └── users.py # User models
│ └── __init__.py
├── tests/
│ ├── test_connector_agent.py
│ └── ...
├── slack_guild.json # Guild specification
├── pyproject.toml
└── README.md
License
Apache-2.0
Built with ❤️ for Rustic AI
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rusticai_slack-0.0.1.tar.gz.
File metadata
- Download URL: rusticai_slack-0.0.1.tar.gz
- Upload date:
- Size: 22.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.2 CPython/3.13.12 Linux/6.17.0-1013-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9daae991c57b087d2e2b42a3e39dcd1663d7168b84beed215b3e576d8663363
|
|
| MD5 |
380aefe78c65bb0a9ae259387214a187
|
|
| BLAKE2b-256 |
f6fb6fc9a9319b47490947cc7a0e2c39e9c66eaa98588f3557d2defd5142d2ba
|
File details
Details for the file rusticai_slack-0.0.1-py3-none-any.whl.
File metadata
- Download URL: rusticai_slack-0.0.1-py3-none-any.whl
- Upload date:
- Size: 24.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.2 CPython/3.13.12 Linux/6.17.0-1013-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
082c892efb0be8df015bada90f858773a8b233fa6cea51d5020c1fce2da40b93
|
|
| MD5 |
683bf25b83c14e41c854acc95e734e93
|
|
| BLAKE2b-256 |
f47f8d9b9bcd20823f107273c79c206d1475ca731468c74a3db21dcb51b71032
|