Microsoft Teams Integration
Integrate TruthVouch with Microsoft Teams to deliver governance alerts, run verification queries, and manage AI policies directly from Teams. Use Adaptive Cards for rich formatting and interactive workflows.
Setup
1. Register Azure App
In Azure Portal:
- Go to Azure Active Directory → App registrations
- Click “New registration”
- Name: “TruthVouch”
- Supported account types: “Accounts in this organizational directory”
- Redirect URI:
https://api.truthvouch.com/auth/callback
2. Configure Permissions
Add these Microsoft Graph permissions:
Chat.SendChannelMessage.SendTeam.ReadBasic.AllUser.Read
3. Create Client Secret
- Go to Certificates & secrets
- Create new client secret
- Copy value (store securely)
4. Configure TruthVouch
truthvouch config teams \ --tenant-id your-tenant-id \ --client-id your-client-id \ --client-secret your-client-secretAlert Notifications
Send Adaptive Card
from truthvouch.integrations.teams import TeamsAlertHandlerimport json
handler = TeamsAlertHandler( client_id="your-client-id", client_secret="your-client-secret", tenant_id="your-tenant-id")
# Define card templatecard = { "type": "message", "attachments": [ { "contentType": "application/vnd.microsoft.card.adaptive", "contentUrl": None, "content": { "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.4", "body": [ { "type": "Container", "items": [ { "type": "ColumnSet", "columns": [ { "width": "auto", "items": [ { "type": "Image", "url": "https://truthvouch.com/logo.svg", "size": "Small" } ] }, { "width": "stretch", "items": [ { "type": "TextBlock", "text": "TruthVouch Alert", "weight": "Bolder", "size": "Large" } ] } ] } ] }, { "type": "Container", "style": "Emphasis", "items": [ { "type": "TextBlock", "text": "Hallucination Detected", "weight": "Bolder", "color": "Attention" } ] }, { "type": "Container", "items": [ { "type": "FactSet", "facts": [ { "name": "Query:", "value": "Is the Earth flat?" }, { "name": "Response:", "value": "Yes, the Earth is flat" }, { "name": "Confidence:", "value": "5% (CRITICAL)" }, { "name": "Category:", "value": "Science" } ] } ] } ], "actions": [ { "type": "Action.OpenUrl", "title": "View in Dashboard", "url": "https://dashboard.truthvouch.com/alerts/alert123" }, { "type": "Action.Submit", "title": "Acknowledge", "data": {"action": "acknowledge"} }, { "type": "Action.Submit", "title": "Suppress Rule", "data": {"action": "suppress"} } ] } } ]}
# Send to Teams channelhandler.send_to_channel( team_id="team-id", channel_id="channel-id", card=card)Configure Alert Rules
# Route alerts to specific channelshandler.configure_alert_rule( name="Critical Hallucinations", trigger="confidence < 0.5", teams=[ { "team_id": "team-abc123", "channel_id": "general", "mention": "@on-call" } ], enabled=True)
# Route by categoryhandler.configure_alert_rule( name="Healthcare Alerts", trigger="category = 'healthcare' AND confidence < 0.9", teams=[ { "team_id": "team-abc123", "channel_id": "compliance", "mention": "@compliance-team" } ], enabled=True)Proactive Messages
Send notifications via Teams bot:
# Send to individual userhandler.send_to_user( user_id="user-id", message="Your verification result is ready: 85% confidence")
# Send to chat threadhandler.send_to_chat( chat_id="chat-id", message="Waiting for your review...")Message Extensions
Enable TruthVouch as a Teams message extension:
from flask import Flask, request
app = Flask(__name__)
@app.route("/teams/invoke", methods=["POST"])def handle_message_extension(): """Handle Teams message extension invoke."""
payload = request.get_json()
if payload["type"] == "composeExtension/fetchTask": # Return task module for verification UI return { "task": { "type": "continue", "value": { "title": "Verify Content", "height": 500, "width": 600, "url": "https://app.truthvouch.com/teams/verify" } } }
elif payload["type"] == "composeExtension/submitAction": # Process verification submission text = payload["data"]["text"] result = tv_client.verify_fact(text=text)
# Return results return { "composeExtension": { "type": "result", "attachmentLayout": "list", "attachments": [ { "contentType": "application/vnd.microsoft.teams.card.o365connector", "contentUrl": None, "content": { "@type": "MessageCard", "@context": "https://schema.org/extensions", "summary": f"Verification: {result.confidence:.0%}", "themeColor": "0078D7", "sections": [ { "activityTitle": "Verification Result", "facts": [ { "name": "Confidence", "value": f"{result.confidence:.0%}" } ] } ] } } ] } }Webhooks
Set up Teams webhook for incoming notifications:
from truthvouch.integrations.teams import TeamsWebhookHandler
# Get webhook URL from Teamswebhook_url = "https://outlook.webhook.office.com/webhookb2/..."
handler = TeamsWebhookHandler(webhook_url=webhook_url)
# Send JSON payloadalert = { "type": "message", "attachments": [{ "contentType": "application/vnd.microsoft.card.adaptive", "content": { "type": "AdaptiveCard", "version": "1.4", "body": [{ "type": "TextBlock", "text": "Alert received", "weight": "Bolder" }] } }]}
handler.send(alert)Interactive Forms
Create verification workflows:
@app.route("/teams/task", methods=["POST"])def render_task(): """Render interactive form for content verification."""
return { "task": { "type": "continue", "value": { "title": "Verify Content", "height": 500, "width": 600, "card": { "contentType": "application/vnd.microsoft.card.adaptive", "content": { "type": "AdaptiveCard", "version": "1.4", "body": [ { "type": "TextBlock", "text": "Submit content for verification", "weight": "Bolder" }, { "type": "Input.Text", "id": "content", "placeholder": "Enter claim to verify...", "isMultiline": True }, { "type": "Input.ChoiceSet", "id": "category", "label": "Category", "choices": [ {"title": "General", "value": "general"}, {"title": "Healthcare", "value": "healthcare"}, {"title": "Financial", "value": "financial"} ] } ], "actions": [ { "type": "Action.Submit", "title": "Verify" } ] } } } } }Best Practices
Formatting
- Use Adaptive Cards for rich formatting
- Include facts for quick scanning
- Add action buttons for common operations
- Use color to indicate severity
Notifications
- Route critical alerts to on-call channel
- Use @mentions sparingly (avoid fatigue)
- Group related alerts in threads
- Include deep links to dashboard
Rate Limiting
- Respect Teams rate limits (50 req/min)
- Batch multiple alerts
- Implement backoff for retries
Troubleshooting
Q: Cards not rendering properly
- Validate schema against Adaptive Card spec
- Check Teams client version
- Use schema validator tool
Q: Mentions not working
- Verify bot has permission to mention
- Check user ID format
- Ensure user is in channel
Q: Webhook delivery failing
- Verify webhook URL is valid and active
- Check payload format
- Implement retry logic with backoff
Next Steps
- Review ChatOps Overview
- Explore Slack Integration
- Check Alert Management