slack-webhook
Use when sending Slack alerts or notifications. Automatically uses the configured SLACK_WEBHOOK_URL from environment.
When & Why to Use This Skill
This Claude skill enables seamless integration with Slack via webhooks, allowing AI agents to send real-time alerts, automated notifications, and rich-text messages using Slack's Block Kit. It simplifies the process of pushing critical updates from automated workflows directly into Slack channels, enhancing team collaboration and ensuring rapid response to system events.
Use Cases
- Incident Response: Automatically notify DevOps or SRE teams when system anomalies, high error rates, or performance drops are detected.
- Business Intelligence Alerts: Send real-time notifications to sales or marketing channels when key metrics like conversion rates or sign-ups deviate from expected values.
- Workflow Automation: Alert project stakeholders when specific tasks are completed or when an automated process requires manual human intervention.
- Customer Support Escalation: Notify support leads in Slack when high-priority tickets are created or when sentiment analysis detects a frustrated customer.
| name | slack-webhook |
|---|---|
| description | Use when sending Slack alerts or notifications. Automatically uses the configured SLACK_WEBHOOK_URL from environment. |
Slack Webhook Integration
Send alerts and notifications to Slack using the configured webhook.
Quick Start
The webhook URL is automatically loaded from the SLACK_WEBHOOK_URL environment variable.
import os
import json
from urllib.request import Request, urlopen
def send_slack_alert(message: dict) -> bool:
"""Send a message to Slack via webhook.
Args:
message: Slack Block Kit message payload
Returns:
True if sent successfully, False otherwise
"""
webhook_url = os.environ.get('SLACK_WEBHOOK_URL')
if not webhook_url:
raise ValueError("SLACK_WEBHOOK_URL environment variable not set")
request = Request(
webhook_url,
data=json.dumps(message).encode('utf-8'),
headers={'Content-Type': 'application/json'}
)
with urlopen(request, timeout=10) as response:
return response.status == 200
Message Formats
Simple Text Message
message = {
"text": "Hello from the agent!"
}
send_slack_alert(message)
Alert with Block Kit (Recommended)
message = {
"blocks": [
{
"type": "header",
"text": {"type": "plain_text", "text": "🔴 Anomaly Detected"}
},
{
"type": "section",
"fields": [
{"type": "mrkdwn", "text": "*Metric:*\nConversion Rate"},
{"type": "mrkdwn", "text": "*Severity:*\nCritical"}
]
},
{
"type": "section",
"fields": [
{"type": "mrkdwn", "text": "*Expected:*\n4.2%"},
{"type": "mrkdwn", "text": "*Actual:*\n1.8%"}
]
},
{"type": "divider"},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Potential Causes:*\n• Checkout flow issue\n• Payment gateway error\n• Landing page test impact"
}
},
{
"type": "context",
"elements": [
{"type": "mrkdwn", "text": "🤖 Alert generated by AI Agent"}
]
}
]
}
Anomaly Alert Template
def build_anomaly_alert(
metric_name: str,
date: str,
expected: float,
actual: float,
severity: str = "Warning",
potential_causes: list = None
) -> dict:
"""Build a formatted anomaly alert message.
Args:
metric_name: Name of the metric (e.g., "Conversion Rate")
date: Date of the anomaly
expected: Expected value
actual: Actual value
severity: "Critical" or "Warning"
potential_causes: List of potential cause strings
Returns:
Slack Block Kit message payload
"""
emoji = "🔴" if severity == "Critical" else "🟡"
pct_change = ((actual - expected) / expected) * 100
direction = "drop" if pct_change < 0 else "spike"
blocks = [
{
"type": "header",
"text": {"type": "plain_text", "text": f"{emoji} Anomaly Detected: {metric_name}"}
},
{
"type": "section",
"fields": [
{"type": "mrkdwn", "text": f"*Date:*\n{date}"},
{"type": "mrkdwn", "text": f"*Severity:*\n{severity}"}
]
},
{
"type": "section",
"fields": [
{"type": "mrkdwn", "text": f"*Expected:*\n{expected:,.2f}"},
{"type": "mrkdwn", "text": f"*Actual:*\n{actual:,.2f}"}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*Change:* {pct_change:+.1f}% {direction}"
}
}
]
if potential_causes:
causes_text = "\n".join([f"• {cause}" for cause in potential_causes])
blocks.extend([
{"type": "divider"},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*Potential Causes:*\n{causes_text}"
}
}
])
blocks.append({
"type": "context",
"elements": [
{"type": "mrkdwn", "text": "🤖 Alert generated by AI Agent"}
]
})
return {"blocks": blocks}
Usage Example
# Build and send an anomaly alert
alert = build_anomaly_alert(
metric_name="Trial Conversion Rate",
date="2025-11-28",
expected=37.6,
actual=10.5,
severity="Critical",
potential_causes=[
"Onboarding flow broken",
"Integration setup failing",
"New user segment with different behavior"
]
)
success = send_slack_alert(alert)
if success:
print("✅ Alert sent to Slack")
else:
print("❌ Failed to send alert")
Testing
To test without sending (dry run):
import json
print(json.dumps(alert, indent=2))
Error Handling
from urllib.error import URLError, HTTPError
try:
send_slack_alert(message)
except ValueError as e:
print(f"Configuration error: {e}")
except HTTPError as e:
print(f"Slack API error: {e.code} - {e.reason}")
except URLError as e:
print(f"Network error: {e.reason}")