Slack Integration
Connect TruthVouch to Slack to receive real-time alerts, manage AI governance policies, and verify content directly from Slack. Use slash commands to query verification results and interactive buttons for quick actions.
Setup
1. Create Slack App
Visit api.slack.com/apps and create a new app:
- App Name: “TruthVouch”
- Development Workspace: Your workspace
2. Enable Features
In your app settings:
- Permissions: Add OAuth scopes
chat:write(send messages)commands:write(slash commands)apps:read(app info)users:read(user info)
3. Install App
- Get your Bot User OAuth Token (starts with
xoxb-) - Install app to your workspace
4. Configure TruthVouch
truthvouch config slack --token xoxb-your-tokenOr via environment variable:
export TRUTHVOUCH_SLACK_TOKEN=xoxb-your-tokenFeatures
Alert Notifications
Receive alerts in Slack channels:
from truthvouch.integrations.slack import SlackAlertHandler
handler = SlackAlertHandler( token="xoxb-your-token", channel="#ai-governance")
# Configure alertshandler.configure_rule( name="Hallucination Alerts", trigger="confidence < 0.7", channel="#ai-governance", mention="@ops")Slash Commands
Query verification directly from Slack:
/truthvouch verify "Is the Earth flat?"/truthvouch policy list/truthvouch kb search "OpenAI"/truthvouch audit last 24hInteractive Message Buttons
from slack_sdk import WebClientfrom slack_sdk.models.blocks import ActionsBlock, ButtonElement
client = WebClient(token="xoxb-your-token")
# Send message with actionsclient.chat_postMessage( channel="#alerts", blocks=[ { "type": "section", "text": { "type": "mrkdwn", "text": "Potential hallucination detected in AI response" } }, { "type": "section", "text": { "type": "mrkdwn", "text": "*Claim:* The Earth is flat\n*Confidence:* 5%" } }, { "type": "actions", "elements": [ { "type": "button", "text": {"type": "plain_text", "text": "Acknowledge"}, "action_id": "acknowledge_alert" }, { "type": "button", "text": {"type": "plain_text", "text": "Review Full Details"}, "action_id": "review_alert" }, { "type": "button", "text": {"type": "plain_text", "text": "Suppress Rule"}, "action_id": "suppress_rule" } ] } ])Advanced Configuration
Custom Slash Command Handler
from flask import Flask, requestfrom slack_sdk import WebClientfrom slack_sdk.signature import SignatureVerifierfrom truthvouch.client import TruthVouchClient
app = Flask(__name__)slack_client = WebClient(token="xoxb-your-token")tv_client = TruthVouchClient(api_key="your-api-key")verifier = SignatureVerifier(signing_secret="your-signing-secret")
@app.route("/slack/commands", methods=["POST"])def handle_slash_command(): # Verify request if not verifier.is_valid_request(request.get_data(), request.headers): return {"error": "Invalid request"}, 403
command_data = request.form
# Route by command if command_data["command"] == "/truthvouch": args = command_data["text"].split() action = args[0] if args else "help"
if action == "verify": text = " ".join(args[1:]) return handle_verify_command(text, command_data) elif action == "policy": return handle_policy_command(args[1:], command_data) else: return send_help(command_data)
return {"error": "Unknown command"}, 400
def handle_verify_command(text: str, command_data: dict) -> dict: """Handle /truthvouch verify command."""
# Show loading state slack_client.chat_postEphemeral( channel=command_data["channel_id"], user=command_data["user_id"], text="Verifying...:hourglass:" )
# Perform verification result = tv_client.verify_fact(text=text)
# Build response color = "good" if result.confidence > 0.7 else "danger" confidence_text = f"{result.confidence:.0%}"
slack_client.chat_postMessage( channel=command_data["channel_id"], blocks=[ { "type": "section", "text": { "type": "mrkdwn", "text": f"*Verification Result*\n```{text}```" } }, { "type": "section", "fields": [ { "type": "mrkdwn", "text": f"*Confidence*\n{confidence_text}" }, { "type": "mrkdwn", "text": f"*Status*\n{'✓ Verified' if result.confidence > 0.7 else '✗ Uncertain'}" } ] }, { "type": "section", "text": { "type": "mrkdwn", "text": f"*Sources:*\n" + "\n".join([ f"• <{c['url']}|{c['title']}>" for c in result.citations[:3] ]) } } ] )
return {"response_type": "in_channel"}
@app.route("/slack/actions", methods=["POST"])def handle_actions(): """Handle button clicks and other interactions."""
payload = json.loads(request.form["payload"])
action = payload["actions"][0]["action_id"] user_id = payload["user"]["id"] channel_id = payload["channel"]["id"]
if action == "acknowledge_alert": slack_client.chat_postMessage( channel=channel_id, text=f"<@{user_id}> acknowledged the alert" )
elif action == "review_alert": slack_client.chat_postMessage( channel=channel_id, text=f"<@{user_id}> is reviewing the alert" )
return {}Alert Routing
Route alerts to different channels by severity:
from truthvouch.integrations.slack import SlackAlertRouter
router = SlackAlertRouter(token="xoxb-your-token")
# Route critical to #urgentrouter.add_route( severity="critical", channel="#urgent", mention="@on-call")
# Route high to #alerts with mentionrouter.add_route( severity="high", channel="#alerts", mention="@team")
# Route medium to #logs (no mention)router.add_route( severity="medium", channel="#logs")Thread Conversations
Keep related alerts in conversation threads:
from slack_sdk import WebClient
client = WebClient(token="xoxb-your-token")
# Post initial alertresponse = client.chat_postMessage( channel="#alerts", text="Hallucination detected")
thread_ts = response["ts"]
# Follow up with details in threadclient.chat_postMessage( channel="#alerts", thread_ts=thread_ts, text="Updated confidence: 32% (was 45%)")
# Ask for review in threadclient.chat_postMessage( channel="#alerts", thread_ts=thread_ts, text="Awaiting human review...")Workflows and Automation
Create Slack Workflow
Slack Workflows can integrate TruthVouch:
- Go to Workspace Settings → Workflows
- Create new workflow triggered by message
- Add step to call TruthVouch API
- Process verification result
- Send notification
Workflow Template
name: "Verify Message Content"trigger: "message"steps: - name: "Extract message text" action: "extract_text" input: "{{message.text}}"
- name: "Call TruthVouch" action: "http_request" url: "https://api.truthvouch.com/api/v1/shield/verify" method: "POST" headers: Authorization: "Bearer {{env.TRUTHVOUCH_API_KEY}}" body: text: "{{message.text}}"
- name: "Check confidence" condition: "response.confidence < 0.7" then: - name: "Post warning" action: "post_message" channel: "#alerts" text: "⚠️ Unverified claim: {{message.text}}"Monitoring and Analytics
Track Slack integration health:
from truthvouch.integrations.slack import SlackMetrics
metrics = SlackMetrics(token="xoxb-your-token")
# Get statsstats = metrics.get_stats(days=7)print(f"Commands executed: {stats['commands_count']}")print(f"Alerts sent: {stats['alerts_count']}")print(f"Avg response time: {stats['avg_response_ms']}ms")
# Get top commandstop_commands = metrics.get_top_commands(limit=5)for cmd, count in top_commands: print(f"{cmd}: {count}")Security
Signing Secrets
Verify all requests come from Slack:
from slack_sdk.signature import SignatureVerifier
verifier = SignatureVerifier( signing_secret="your-signing-secret")
@app.route("/slack/events", methods=["POST"])def verify_request(): if not verifier.is_valid_request( body=request.get_data(), headers=request.headers ): return {"error": "Unauthorized"}, 403Token Management
Never hardcode tokens:
import osfrom dotenv import load_dotenv
load_dotenv()
token = os.getenv("SLACK_BOT_TOKEN")signing_secret = os.getenv("SLACK_SIGNING_SECRET")
if not token or not signing_secret: raise ValueError("Missing Slack credentials")Troubleshooting
Q: Commands not triggering
- Verify bot has
commands:writescope - Check command routing configuration
- Test with curl first
Q: Slow response times
- Cache verification results
- Use async/await to avoid blocking
- Check rate limits (120 requests/minute for Slack)
Q: Alerts not appearing
- Verify channel exists and bot is member
- Check notification settings
- Test webhook connectivity
Next Steps
- Review ChatOps Overview
- Explore Alert Channels
- Check Webhook Integration