CtrlK
BlogDocsLog inGet started
Tessl Logo

slack-notifier

Use this skill when you want to send Slack messages — alerts, formatted reports, approval requests, or scheduled summaries — using Block Kit for rich formatting.

64

Quality

78%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Fix and improve this skill with Tessl

tessl review fix ./external/goose-recipes/slack-notifier/SKILL.md
SKILL.md
Quality
Evals
Security

Slack Notifier

Overview

Send rich Slack messages with Block Kit formatting: alerts with context, summary reports, approval request buttons, and threaded updates. Adapted from Block's Goose integration recipes.

Setup

pip install slack-sdk anthropic
# Create Slack app at api.slack.com, get Bot Token with chat:write scope
export SLACK_BOT_TOKEN=xoxb-...

Basic Message

from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

slack = WebClient(token=os.environ["SLACK_BOT_TOKEN"])

def send_message(channel: str, text: str) -> str:
    result = slack.chat_postMessage(channel=channel, text=text)
    return result["ts"]  # thread timestamp for follow-ups

def send_thread_reply(channel: str, thread_ts: str, text: str) -> None:
    slack.chat_postMessage(channel=channel, thread_ts=thread_ts, text=text)

Rich Alert Block

def send_alert(channel: str, title: str, message: str,
               severity: str = "warning", fields: dict | None = None) -> str:
    colors = {"critical": "#FF0000", "warning": "#FFA500", "info": "#36A64F", "success": "#36A64F"}
    icons = {"critical": "🔴", "warning": "🟡", "info": "🔵", "success": "✅"}

    blocks = [
        {
            "type": "header",
            "text": {"type": "plain_text", "text": f"{icons.get(severity, '📢')} {title}"}
        },
        {
            "type": "section",
            "text": {"type": "mrkdwn", "text": message}
        }
    ]

    if fields:
        fields_block = {
            "type": "section",
            "fields": [
                {"type": "mrkdwn", "text": f"*{k}*\n{v}"}
                for k, v in fields.items()
            ]
        }
        blocks.append(fields_block)

    blocks.append({"type": "divider"})
    blocks.append({
        "type": "context",
        "elements": [{"type": "mrkdwn", "text": f"<!date^{int(time.time())}^{{date_short_pretty}} {{time}}|{datetime.now().isoformat()}> | ProwlrBot"}]
    })

    result = slack.chat_postMessage(
        channel=channel,
        text=title,  # fallback for notifications
        attachments=[{"color": colors.get(severity, "#808080"), "blocks": blocks}]
    )
    return result["ts"]

Approval Request

def request_approval(channel: str, title: str, description: str,
                     approve_action: str = "approve", deny_action: str = "deny") -> str:
    result = slack.chat_postMessage(
        channel=channel,
        text=f"Approval needed: {title}",
        blocks=[
            {"type": "header", "text": {"type": "plain_text", "text": f"⏳ {title}"}},
            {"type": "section", "text": {"type": "mrkdwn", "text": description}},
            {
                "type": "actions",
                "elements": [
                    {
                        "type": "button",
                        "text": {"type": "plain_text", "text": "✅ Approve"},
                        "style": "primary",
                        "action_id": approve_action
                    },
                    {
                        "type": "button",
                        "text": {"type": "plain_text", "text": "❌ Deny"},
                        "style": "danger",
                        "action_id": deny_action
                    }
                ]
            }
        ]
    )
    return result["ts"]

AI-Generated Summary + Post

import anthropic

def post_ai_summary(channel: str, data: str, summary_type: str = "daily") -> str:
    ac = anthropic.Anthropic()
    response = ac.messages.create(
        model="claude-opus-4-6",
        max_tokens=512,
        system="You write concise Slack summaries. Use bullet points. Use *bold* for important items. 10 lines max.",
        messages=[{"role": "user", "content": f"Summarize this {summary_type} data:\n{data}"}]
    )
    summary = response.content[0].text
    return send_message(channel, summary)

Quick Reference

FunctionPurpose
send_messagePlain text message
send_alertRich alert with severity color
request_approvalInteractive approve/deny buttons
send_thread_replyReply in thread
post_ai_summaryAI-generated summary
Repository
ProwlrBot/prowlr-marketplace
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.