A Slack bot that listens for your messages and automatically rewrites them to be more professional and concise using LLM-powered editing.
- Automatic message editing: Detects your messages and rewrites them in real-time
- LLM-powered: Uses OpenAI-compatible models for intelligent rewriting
- 3-tier quality control: Combines heuristic checks, semantic embeddings, and iterative refinement
- Flexible configuration: Set up via environment variables or YAML config
- Thread context: Considers conversation context when rewriting
- Professional signature: All edits are clearly marked
┌─────────────┐ ┌──────────────────┐ ┌──────────────┐
│ Slack │────▶│ Bolt Server │────▶│ LLM Rewriter│
│ Socket │ │ (Event Handler)│ │ + QC Layer │
│ Mode │ └──────────────────┘ └──────────────┘
└─────────────┘ │
▼
┌──────────────┐
│ Edit Message│
│ in Channel │
└──────────────┘
- Visit Slack API Apps Page
- Click "Create New App" → "From scratch"
- Enter app name (e.g., "Professional Message Bot")
- Select your workspace
- Click "Create App"
- In left sidebar, click "Enable Socket Mode"
- Toggle the switch to ON
- Click "Save Changes"
- In left sidebar, click "Event Subscriptions"
- Toggle the switch to ON
- Navigate to "Subscrube to events on behalf of users"
- Add these 4 Workspace Events :
| Event | Purpose |
|---|---|
message.channels |
Receive event of new messages in channels |
message.groups |
Receive event of new messages in groups |
message.im |
Receive event of new messages in direct messages |
message.mpim |
Receive event of new messages in multi-member direct messages |
- In left sidebar, click "Basic Information"
- Scroll to "App-Level Tokens" section
- Click "Generate Token"
- Select permission:
commands:read - Click "Review", then "Generate"
- Copy the App-Level Token (starts with
xapp-)⚠️ Important: You cannot view this token again! Store it securely now.
-
Still in "Basic Information" section
-
Scroll to "App Credentials" section
-
Click "Reveal" next to "Signing Secret"
-
Copy the Signing Secret
⚠️ You can only reveal this once per session
-
Click "Save Changes"
- In the left sidebar, click "OAuth & Permissions"
- Under "Scopes" section, click "Add an OAuth Scope"
- Add these 5 User Token Scopes (required for message read & editing):
| Scope | Purpose |
|---|---|
chat:write |
Allows the bot to edit/replace messages |
channels:history |
Read messages sent to public channels |
groups:history |
Read messages sent to users' private channels |
im:history |
Read messages sent to direct messages |
mpim:history |
Read messages sent to multi-member direct messages |
- Click "Save Changes" at bottom of page
- Click "Install to Workspace" button
- Click "Allow" to authorize permissions
- Copy the "User OAuth Token" (starts with
xoxp-)
The bot will only edit messages from your account. Get your Slack user ID:
# Option 1: Using curl
curl -s https://slack.com/api/auth.test \
-H "Authorization: Bearer YOUR_BOT_TOKEN" | jq .user_id
# Option 2: Using Python
python3 << 'EOF'
import requests
import json
response = requests.get(
'https://slack.com/api/auth.test',
headers={'Authorization': 'Bearer YOUR_BOT_TOKEN'}
)
data = response.json()
print(f"Your Slack User ID: {data['user_id']}")
EOF
# Option 3: From Slack desktop/mobile app
# Click your profile picture → "View profile" → Copy the User ID shownExample output: U0123456789
Copy the example .env file and fill in your credentials:
cp .env.example .envEdit .env with these required values:
# Slack credentials (from steps above)
SLACK_BOT_TOKEN=xoxb-your-bot-token-here
SLACK_SIGNING_SECRET=your-signing-secret-here
SLACK_APP_TOKEN=xapp-your-app-level-token-here
# Your Slack user ID (the bot will only edit your messages)
BOT_USER_ID=U0123456789
# LLM Configuration (can use environment variables or YAML file)
LLM_API_KEY=your-llm-api-key-here
LLM_ENDPOINT=https://api.openai.com/v1/chat/completions
LLM_MODEL=gpt-4o
LLM_PROVIDER=openai
# Optional: Override default config file path
# LLM_CONFIG_FILE=config/llm_config.yaml
# Logging (optional)
WORKSPEAK_LOG_FILE=logs/workSpeak.log
WORKSPEAK_LOG_LEVEL=INFOEnvironment Variable Priority:
- Environment variables (highest priority)
- YAML config file (default:
config/llm_config.yaml) - Hardcoded defaults (lowest priority)
# Create virtual environment (if needed)
python3 -m venv venv
source venv/bin/activate
# Install requirements
pip install -r requirements.txt# Direct run
python -m slack_message_bot
# Or with bash
bash run.shThe bot will:
- Connect to Slack via Socket Mode
- Listen for messages from your user ID
- Fetch thread context if available
- Rewrite the message using the LLM
- Apply quality control checks
- Update the original message with a signature
# CLI chat-like interface. NO Slack integration - translation only. Good for quick custom messages for evaluation
python -m slack_message_bot --mode cli
# Run a batch evaluation of messages defined in a txt file then terminates. Accepts broad formatting for messages in the file - refer to sample_messages.txt as an example
python -m slack_message_bot --mode batch --input sample_messages.txtSee EVALUATION_GUIDE.md for more details
-
Environment variables (highest priority)
LLM_API_KEY=... LLM_ENDPOINT=https://... LLM_MODEL=gpt-4o LLM_PROVIDER=openai
-
YAML config file
- Default:
config/llm_config.yaml - Override with:
LLM_CONFIG_FILE=/path/to/config.yaml
- Default:
-
OpenAI-compatible endpoints
The bot works with any OpenAI-compatible endpoint:
# Groq
endpoint: https://api.groq.com/openai/v1/chat/completions
model: llama-3.1-70b-versatile
# Together AI
endpoint: https://api.together.xyz/v1/chat/completions
model: mistralai/Mixtral-8x7B-Instruct-v0.1
# vLLM (self-hosted)
endpoint: https://your-vllm-server/v1/chat/completions
model: your-locally-served-modelThe bot uses a multi-tier quality assurance system:
- Metadata removal (token counts, costs, iteration info)
- Artifact filtering (exploration text, summaries, reasoning)
- Tone detection (slang, abbreviations)
- Conciseness ratio (word count comparison)
- Uses
sentence-transformers(all-MiniLM-L6-v2) - Cosine similarity between original and rewritten
- Default fallback if embeddings unavailable
- If score is in "grey zone" (0.60-0.85), re-attempt rewrite
- Maximum 3 iterations
- Returns best result or original text if no improvement
| Score | Action |
|---|---|
| ≥0.85 | Accept rewrite |
| 0.60-0.85 | Retry rewrite |
| <0.60 | Keep original |
Logs are written to logs/workSpeak.log (configurable via WORKSPEAK_LOG_FILE).
Quality decisions are logged:
2026-04-19 23:45:12 - slack_message_bot.app - INFO - [Quality] Decision: accepted (score: 0.87)
2026-04-19 23:45:12 - slack_message_bot.app - INFO - [Original] hey guys lol omg meeting is super important
2026-04-19 23:45:12 - slack_message_bot.app - INFO - [Rewritten] Hello team, confirming an important meeting
When rewriting messages in a thread, the bot fetches up to 5 recent messages in the thread to provide context. This helps maintain conversation coherence.
# Run tests (using existing venv pytest)
.venv/bin/python -m pytest tests/ -vtest_config.py: LLM configuration loadingtest_llm_backend.py: Prompt formattingtest_rewriter.py: Post-processing, quality checkstest_integration.py: Integration tests
- Verify
BOT_USER_IDis set to your Slack user ID - Check logs:
cat logs/workSpeak.log - Ensure the app has
chat:writeandchat:write.customizescopes - Message must be in a channel or DM where the bot can see it
- Verify
LLM_API_KEYis valid - Test endpoint manually:
curl -X POST https://api.openai.com/v1/chat/completions \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"model": "gpt-4o", "messages": [{"role": "user", "content": "test"}]}' - Check logs for error details
- Quality score may be too low (<0.60)
- Original message may already be professional
- Try sending a more informal message to test
DISCLAIMER.md before using this tool
MIT License - feel free to use and modify as needed.