HeartBot / pyspur /docs /chatbots /slack.mdx
shibbir24's picture
Upload 520 files
e6410cf verified
---
title: 'Using Chatbots with Slack'
description: 'How to integrate your PySpur chatbots with Slack'
---
# Integrating PySpur Chatbots with Slack
This guide explains how to connect your PySpur chatbots to Slack, allowing users to interact with your chatbot directly through Slack channels and threads.
## Understanding Slack Integration Options
PySpur offers two distinct ways to work with Slack:
1. **Workflow Output to Slack** - Using the `SlackNotifyNode` to send one-time results from a workflow to a Slack channel
2. **Interactive Chatbot in Slack** - Creating a fully interactive chatbot that users can converse with through Slack
It's important to understand the difference between these approaches:
| Feature | SlackNotifyNode | Interactive Chatbot |
|---------|-----------------|---------------------|
| Interaction | One-way (workflow → Slack) | Two-way conversation |
| Session Management | None | Full conversation history |
| Use Case | Sending alerts, summaries, notifications | Q&A, support, interactive assistance |
| Implementation | Simple workflow node | Custom Slack app with API integration |
## Setting Up an Interactive Chatbot in Slack
Follow these steps to integrate your PySpur chatbot with Slack for interactive conversations:
### 1. Create a Slack App
1. Go to [api.slack.com/apps](https://api.slack.com/apps) and click "Create New App"
2. Choose "From scratch" and provide a name and workspace
3. In the app settings, enable the following:
- Socket Mode (under "Socket Mode")
- Event Subscriptions (under "Event Subscriptions")
- Bot Token Scopes (under "OAuth & Permissions"):
- `app_mentions:read`
- `channels:history`
- `chat:write`
- `groups:history`
- `im:history`
- `mpim:history`
### 2. Collect Required Tokens
You'll need three tokens from your Slack app:
- **Bot Token** (`SLACK_BOT_TOKEN`): Found under "OAuth & Permissions""Bot User OAuth Token"
- **Signing Secret** (`SLACK_SIGNING_SECRET`): Found under "Basic Information""App Credentials"
- **App Token** (`SLACK_APP_TOKEN`): Generate under "Basic Information""App-Level Tokens" (with `connections:write` scope)
### 3. Create Your Integration Script
Create a Python script similar to the example below. This script:
- Initializes a Slack Bolt app
- Listens for mentions and thread replies
- Creates PySpur sessions for users
- Forwards messages to your PySpur chatbot workflow
- Returns responses back to Slack
```python
# slack_integration.py
import logging
import os
import sys
from logging import getLogger
import requests
from dotenv import load_dotenv
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
# Load environment variables from .env file
load_dotenv()
# Replace with your bot's user ID and workflow ID
BOT_USER_ID = "U08HMJ15AHF" # Your bot's user ID in Slack
WORKFLOW_ID = "S58" # Your chatbot workflow ID in PySpur
PYSPUR_API_URL = "http://localhost:6080/api" # Change to your PySpur API URL
# Configure logger
logger = getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(
logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
)
logger.addHandler(handler)
# Initialize Slack app
app = App(
token=os.environ.get("SLACK_BOT_TOKEN"),
signing_secret=os.environ.get("SLACK_SIGNING_SECRET"),
logger=logger,
)
# Handler for @mentions
@app.event("app_mention")
def handle_app_mention(event, say, logger):
logger.info(f"Received mention: {event}")
thread_ts = event.get("thread_ts") or event.get("ts")
user_external_id = event.get("user")
try:
# Create or get user
user_data = {
"external_id": user_external_id,
"user_metadata": {"platform": "slack"}
}
user_response = requests.post(f"{PYSPUR_API_URL}/user/", json=user_data)
if user_response.status_code not in [200, 409]: # 409 means user already exists
logger.error(f"Failed to create user: {user_response.text}")
say(text="Sorry, I encountered an error processing your request.", thread_ts=thread_ts)
return
user_id = user_response.json().get("id")
# Create a new session or get existing one
session_data = {
"workflow_id": WORKFLOW_ID,
"user_id": user_id,
"external_id": thread_ts
}
session_response = requests.post(f"{PYSPUR_API_URL}/session/", json=session_data)
if session_response.status_code != 200:
logger.error(f"Failed to create session: {session_response.text}")
say(text="Sorry, I encountered an error processing your request.", thread_ts=thread_ts)
return
# Get the message text
message = app.client.conversations_history(
channel=event["channel"], ts=thread_ts
)
# Call the workflow API
url = f"{PYSPUR_API_URL}/wf/{WORKFLOW_ID}/run/?run_type=blocking"
data = {
"initial_inputs": {
"input_node": {
"user_message": message["messages"][0]["text"],
"session_id": session_response.json()["id"],
"message_history": []
}
}
}
response = requests.post(url, json=data)
response_data = response.json()
# Get the assistant's message from the output node
assistant_message = response_data.get("output_node", {}).get("assistant_message", "")
# Send the response back to Slack
if assistant_message:
say(text=assistant_message, thread_ts=thread_ts)
else:
say(text="I encountered an issue processing your request.", thread_ts=thread_ts)
except Exception as e:
logger.error(f"Error processing request: {e}")
say(text="Sorry, I encountered an error processing your request.", thread_ts=thread_ts)
# Handler for thread replies
@app.event("message")
def handle_thread_replies(event, say, logger):
# Only process thread replies (not the first message) and ignore bot messages
if (
"thread_ts" in event
and event.get("ts") != event.get("thread_ts")
and not event.get("bot_id")
):
thread_ts = event["thread_ts"]
channel_id = event["channel"]
user_external_id = event.get("user")
try:
# Create or get user
user_data = {
"external_id": user_external_id,
"user_metadata": {"platform": "slack"}
}
user_response = requests.post(f"{PYSPUR_API_URL}/user/", json=user_data)
if user_response.status_code not in [200, 409]:
logger.error(f"Failed to create user: {user_response.text}")
say(text="Sorry, I encountered an error processing your request.", thread_ts=thread_ts)
return
user_id = user_response.json().get("id")
# Create a new session or get existing one
session_data = {
"workflow_id": WORKFLOW_ID,
"user_id": user_id,
"external_id": thread_ts
}
session_response = requests.post(f"{PYSPUR_API_URL}/session/", json=session_data)
if session_response.status_code != 200:
logger.error(f"Failed to create session: {session_response.text}")
say(text="Sorry, I encountered an error processing your request.", thread_ts=thread_ts)
return
# Get all replies in the thread
result = app.client.conversations_replies(channel=channel_id, ts=thread_ts)
# Format messages as a conversation history
chat_messages = []
for message in result["messages"]:
role = "assistant" if message.get("user") == BOT_USER_ID else "user"
chat_messages.append({"role": role, "content": message.get("text", "")})
# Get message history and current message
message_history = chat_messages[:-1] if len(chat_messages) > 1 else []
user_message = chat_messages[-1]["content"] if chat_messages else ""
# Call the workflow API
url = f"{PYSPUR_API_URL}/wf/{WORKFLOW_ID}/run/?run_type=blocking"
data = {
"initial_inputs": {
"input_node": {
"user_message": user_message,
"session_id": session_response.json()["id"],
"message_history": message_history,
}
}
}
response = requests.post(url, json=data)
response_data = response.json()
# Get the assistant's message
assistant_message = response_data.get("output_node", {}).get("assistant_message", "")
# Send the response back to Slack
if assistant_message:
say(text=assistant_message, thread_ts=thread_ts)
else:
say(text="I encountered an issue processing your request.", thread_ts=thread_ts)
except Exception as e:
logger.error(f"Error processing thread reply: {e}")
say(text="Sorry, I had trouble processing your message.", thread_ts=thread_ts)
if __name__ == "__main__":
# Start the app using Socket Mode
handler = SocketModeHandler(app, os.environ.get("SLACK_APP_TOKEN"))
handler.start()
```
### 4. Set Up Environment Variables
Create a `.env` file with your tokens:
```
SLACK_BOT_TOKEN=xoxb-your-token
SLACK_SIGNING_SECRET=your-signing-secret
SLACK_APP_TOKEN=xapp-your-app-token
```
### 5. Run Your Integration
1. Install required packages:
```
pip install slack-bolt python-dotenv requests
```
2. Make sure your PySpur server is running
3. Start your Slack integration:
```
python slack_integration.py
```
## How It Works
This integration creates a bidirectional connection between Slack and your PySpur chatbot:
1. **User Input**: When a user mentions your bot or replies in a thread, the Slack app captures this input.
2. **Session Management**: The script creates or retrieves a PySpur session for the user, using the thread timestamp as the external ID to track conversations.
3. **Message History**: For thread replies, the script retrieves the entire conversation history and formats it in the proper structure for your chatbot.
4. **PySpur API Call**: The user message and conversation history are sent to your PySpur workflow through the API.
5. **Response**: The assistant's response from your workflow is posted back to the Slack thread.
## Key Differences from SlackNotifyNode
This approach differs significantly from the `SlackNotifyNode`:
- **SlackNotifyNode** is a one-way communication channel where your workflow sends a message to Slack when it completes. It's ideal for notifications, alerts, or sharing results of automated processes.
- **Interactive Slack Integration** creates a two-way communication channel where users can have ongoing conversations with your chatbot. The integration manages sessions, tracks conversation history, and maintains context across multiple interactions.
## Example Use Cases
- **Support Bot**: Create a support chatbot that answers user questions about your product
- **Data Query Assistant**: Allow users to query company data through natural language in Slack
- **Task Manager**: Build a bot that helps users create and track tasks through conversation
- **Knowledge Base**: Develop a bot that retrieves and explains information from your documentation
## Troubleshooting
- **Bot not responding**: Ensure your bot has been invited to the channel and has the necessary permissions
- **Missing messages**: Check your log output for any API errors
- **Session errors**: Verify that your PySpur server is running and accessible
- **Token issues**: Double-check that all environment variables are set correctly