Skip to content

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

Terminal window
truthvouch config slack --token xoxb-your-token

Or via environment variable:

Terminal window
export TRUTHVOUCH_SLACK_TOKEN=xoxb-your-token

Features

Alert Notifications

Receive alerts in Slack channels:

from truthvouch.integrations.slack import SlackAlertHandler
handler = SlackAlertHandler(
token="xoxb-your-token",
channel="#ai-governance"
)
# Configure alerts
handler.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 24h

Interactive Message Buttons

from slack_sdk import WebClient
from slack_sdk.models.blocks import ActionsBlock, ButtonElement
client = WebClient(token="xoxb-your-token")
# Send message with actions
client.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, request
from slack_sdk import WebClient
from slack_sdk.signature import SignatureVerifier
from 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 #urgent
router.add_route(
severity="critical",
channel="#urgent",
mention="@on-call"
)
# Route high to #alerts with mention
router.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 alert
response = client.chat_postMessage(
channel="#alerts",
text="Hallucination detected"
)
thread_ts = response["ts"]
# Follow up with details in thread
client.chat_postMessage(
channel="#alerts",
thread_ts=thread_ts,
text="Updated confidence: 32% (was 45%)"
)
# Ask for review in thread
client.chat_postMessage(
channel="#alerts",
thread_ts=thread_ts,
text="Awaiting human review..."
)

Workflows and Automation

Create Slack Workflow

Slack Workflows can integrate TruthVouch:

  1. Go to Workspace Settings → Workflows
  2. Create new workflow triggered by message
  3. Add step to call TruthVouch API
  4. Process verification result
  5. 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 stats
stats = 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 commands
top_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"}, 403

Token Management

Never hardcode tokens:

import os
from 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:write scope
  • 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