Library · Assistants and chatbots

AI in messaging apps: Telegram, Slack, WhatsApp and Teams on autopilot

Builder65 minUpdated: October 2026
56 of 105 in the library

Time: about 25 min reading + 40 min practice


The gist

Messaging apps aren't just chats anymore. They're full business platforms: sales, support, onboarding, teamwork. There's one problem: all of it takes live people, who get tired, get sick and go on vacation. AI changes the equation. In this lesson we build smart bots for Telegram, Slack, WhatsApp and Microsoft Teams: a customer writes → Claude analyzes it → replies in seconds → if it's complicated → escalates to a person.

🎨 Picture this: The perfect community manager never sleeps, answers instantly, remembers every customer and runs 500 conversations at once. That's not a person. It's an AI bot in your messaging app.


Key concepts

  • Telegram Bot API: the official interface for bots; python-telegram-bot is the standard in Python
  • Webhook vs Polling: two ways to receive messages; webhooks are faster and cheaper in production
  • Slack Bolt SDK: the official SDK: events, shortcuts and slash commands in one place
  • WhatsApp Business API: three routes: Twilio (reliable), 360dialog (specialized), Meta Cloud API (direct)
  • Microsoft Teams: notifications through a webhook in the Workflows app, and Microsoft's official Teams MCP (preview)
  • ManyChat: a no-code builder for direct message flows (Instagram, WhatsApp, Messenger, Telegram and more)
  • Unified Messaging Hub: one entry point for all channels; Claude triages and routes
  • Escalation logic: when the bot answers on its own and when it hands off to a live person

Theory

Which messaging app fits which business

🎨 Picture this: Messaging apps are like stores in different parts of town. Telegram is the business district, Slack is the corporate office park, WhatsApp is the neighborhood market where everyone knows each other, Teams is a big company's headquarters.

App Audience Best for Difficulty
Telegram International communities, tech, creators Communities, content, leads, sales Low
Slack Teams, SaaS, B2B Internal processes, notifications, DevOps Medium
WhatsApp Latin America, Europe, worldwide Customer support, small business Medium
Teams Corporate B2B Enterprise clients, Office 365 integration High

The rule for choosing: go where your audience already is. Don't create a new channel; plug into an existing one.


A Telegram bot: from zero to a smart assistant

Step 1: Create the bot

Send /newbot to @BotFather → enter a name and a username → get a token. This token = control over the bot.

Step 2: Basic integration with Claude

python
import os
import logging
from telegram import Update
from telegram.ext import (
    Application, CommandHandler, MessageHandler,
    filters, ContextTypes
)
import anthropic
from dotenv import load_dotenv

load_dotenv()

claude = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]

# Conversation history kept in memory
# In production, replace with Redis or SQLite
conversation_history: dict[int, list] = {}

SYSTEM_PROMPT = """You are the AI assistant for Acme Realty, a real estate agency.
You answer questions about real estate in Ecuador: prices, neighborhoods, the buying process.
Tone: a friendly expert, not a salesperson.
If a question needs a consultation with an agent, say so clearly and offer to take their contact info.
Keep it short: 1–3 sentences for simple questions, up to 5 paragraphs for complex ones.
Language: English."""


async def cmd_start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """The /start command: greet a new user."""
    user = update.effective_user
    await update.message.reply_text(
        f"Hi, {user.first_name}! 👋\n\n"
        "I can help with questions about real estate in Cuenca, Ecuador. "
        "Ask about prices, neighborhoods or the buying process, and I'll answer right away.\n\n"
        "If you'd like a personal consultation, just say so."
    )


async def cmd_contact(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """The /contact command: collect contact details."""
    await update.message.reply_text(
        "Leave your email or phone number, "
        "and an agent will get back to you within 2 hours during business hours."
    )
    # In a real bot, a ConversationHandler goes here to receive and save the contact


async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """The main handler for incoming messages."""
    user_id = update.effective_user.id
    user_text = update.message.text

    # Start the history if this is the first message
    if user_id not in conversation_history:
        conversation_history[user_id] = []

    # Add the user's message
    conversation_history[user_id].append({
        "role": "user",
        "content": user_text
    })

    # Limit the history to the last 10 messages
    if len(conversation_history[user_id]) > 10:
        conversation_history[user_id] = conversation_history[user_id][-10:]

    # Show "typing..." for a good user experience
    await context.bot.send_chat_action(
        chat_id=update.effective_chat.id,
        action="typing"
    )

    # Request to Claude (current models: the "What's current" page)
    response = claude.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=1024,
        system=SYSTEM_PROMPT,
        messages=conversation_history[user_id]
    )

    assistant_reply = "".join(b.text for b in response.content if b.type == "text")

    # Save the reply to the history
    conversation_history[user_id].append({
        "role": "assistant",
        "content": assistant_reply
    })

    await update.message.reply_text(assistant_reply)


async def handle_error(update: object, context: ContextTypes.DEFAULT_TYPE):
    """Log errors."""
    logging.error("Exception while handling update:", exc_info=context.error)


def main():
    app = Application.builder().token(BOT_TOKEN).build()

    app.add_handler(CommandHandler("start", cmd_start))
    app.add_handler(CommandHandler("contact", cmd_contact))
    app.add_handler(MessageHandler(
        filters.TEXT & ~filters.COMMAND, handle_message
    ))
    app.add_error_handler(handle_error)

    print("Telegram bot running (polling mode)...")
    app.run_polling(allowed_updates=Update.ALL_TYPES)


if __name__ == "__main__":
    main()

Telegram: four main bot patterns

1. FAQ bot: answers standard questions about the product, prices, shipping. The system prompt contains the whole knowledge base. It takes on the routine questions and lifts a noticeable share of the load off the support team.

2. Lead qualifier: asks a new user a series of questions (budget, timeline, goals), gauges how "warm" the lead is, and either offers a meeting or sends them into a nurture sequence.

3. Booking bot: integrates with Calendly through the API, offers open time slots and creates the booking right in the chat. The customer never leaves Telegram.

4. Content publisher: Claude generates a post on a schedule, and the bot publishes it to a channel. Planning a week of content takes 20 minutes, once, on Monday.


Slack: automating team processes

Slack with the Bolt SDK isn't just a chat. It's a platform for smart team bots.

Typical scenarios:

  • Standup summary: the bot collects survey answers, Claude formats a summary → posts it to a channel
  • PR notifications: when a Pull Request is opened, Claude reads the diff and writes a short summary of the changes
  • Tasks by command: /task Build a landing page → Claude creates a task in Notion/Linear → returns the link
  • @mention replies: the bot "listens" to channels and answers when someone @mentions it
python
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
import anthropic
import os

app = App(token=os.environ["SLACK_BOT_TOKEN"])
claude = anthropic.Anthropic()


@app.event("app_mention")
def handle_mention(event, say):
    """Replies when someone addresses the bot with an @mention."""
    user_text = event["text"]

    # Strip the bot's @mention from the text
    clean_text = user_text.split(">", 1)[-1].strip() if ">" in user_text else user_text

    response = claude.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=512,
        system="You are the development team's assistant. Keep answers short and specific.",
        messages=[{"role": "user", "content": clean_text}]
    )

    say(f"<@{event['user']}> {''.join(b.text for b in response.content if b.type == 'text')}")


@app.command("/standup")
def handle_standup(ack, say, command):
    """
    /standup: generates a standup form.
    The user fills it in, and the bot collects the answers and makes a summary.
    """
    ack()
    say({
        "blocks": [
            {
                "type": "section",
                "text": {
                    "type": "mrkdwn",
                    "text": f"*Standup for {command['user_name']}*\n"
                            "Answer three questions:"
                }
            },
            {
                "type": "input",
                "block_id": "done",
                "element": {
                    "type": "plain_text_input",
                    "action_id": "done_input",
                    "placeholder": {"type": "plain_text", "text": "What did you do yesterday?"}
                },
                "label": {"type": "plain_text", "text": "Done"}
            }
        ]
    })


@app.command("/summarize")
def handle_summarize(ack, say, command):
    """
    /summarize [text]: summarizes a long message.
    Handy for long PR descriptions or documents in channels.
    """
    ack()
    text_to_summarize = command.get("text", "")

    if not text_to_summarize:
        say("Add the text after the command: `/summarize [your text]`")
        return

    response = claude.messages.create(
        model="claude-haiku-4-5",
        max_tokens=300,
        messages=[{
            "role": "user",
            "content": f"Summarize this text in 3–5 bullet points:\n\n{text_to_summarize}"
        }]
    )

    say(f"📋 *Summary:*\n{''.join(b.text for b in response.content if b.type == 'text')}")


if __name__ == "__main__":
    handler = SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"])
    print("Slack bot running...")
    handler.start()

WhatsApp Business API: the biggest reach

WhatsApp is one of the most widely used messaging apps in the world, with billions of users. For businesses in Latin America and Europe, it's often the only channel customers prefer.

Mind Meta's rules: since January 15, 2026, Meta hasn't allowed general-purpose AI assistants (like ChatGPT) on the WhatsApp Business Platform, with exceptions for a few countries. A bot that answers your own business's customers is a different case, but check WhatsApp Business's current policies and what your provider allows before you launch.

Three ways to connect:

Provider Pros Cons Price
Twilio Reliable, excellent documentation You pay both the provider and Meta Twilio's rates + Meta's fees
360dialog Specializes in WhatsApp Less documentation 360dialog's rates + Meta's fees
Meta Cloud API Direct access, no provider markup Complicated business verification Meta's fees only

Since July 1, 2025, Meta charges for every delivered template message (it depends on the message category and the recipient's country); replies to a customer within the customer service window are free. See current rates on Meta's page and with your provider.

Code with Twilio + Claude:

python
from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse
from twilio.rest import Client
import anthropic
import os

app = Flask(__name__)
twilio_client = Client(
    os.environ["TWILIO_ACCOUNT_SID"],
    os.environ["TWILIO_AUTH_TOKEN"]
)
claude = anthropic.Anthropic()

# Conversation history (in production: Redis with a 24h TTL)
wa_conversations: dict[str, list] = {}

WA_SYSTEM = """You are a company's AI assistant on WhatsApp.
Keep replies short (WhatsApp isn't email).
If a question needs a person, say: 'I'm passing you to a specialist, expect a reply within an hour.'
Be friendly but professional."""


@app.route("/webhook/whatsapp", methods=["POST"])
def whatsapp_webhook():
    """Handles incoming WhatsApp messages."""
    from_number = request.form.get("From", "")
    body = request.form.get("Body", "").strip()

    if not body:
        return str(MessagingResponse())

    # Conversation history
    if from_number not in wa_conversations:
        wa_conversations[from_number] = []

    wa_conversations[from_number].append(
        {"role": "user", "content": body}
    )

    # Limit the context to the last 8 messages
    history = wa_conversations[from_number][-8:]

    # Claude generates a reply
    response = claude.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=512,
        system=WA_SYSTEM,
        messages=history
    )

    reply = "".join(b.text for b in response.content if b.type == "text")

    wa_conversations[from_number].append(
        {"role": "assistant", "content": reply}
    )

    # If Claude hands off to a person, notify someone inside the company
    if "specialist" in reply.lower() or "passing you" in reply.lower():
        notify_manager(from_number, body, reply)

    # Reply to the user
    resp = MessagingResponse()
    resp.message(reply)
    return str(resp)


def notify_manager(customer_number: str, question: str, bot_reply: str):
    """Notify a manager on Telegram when the bot can't help."""
    import requests
    telegram_token = os.environ.get("TELEGRAM_BOT_TOKEN")
    manager_chat = os.environ.get("MANAGER_TELEGRAM_CHAT_ID")

    if not telegram_token or not manager_chat:
        return

    message = (
        f"🔔 *Escalation from WhatsApp*\n\n"
        f"Customer: `{customer_number}`\n"
        f"Question: {question}\n\n"
        f"Bot replied: {bot_reply[:200]}..."
    )
    requests.post(
        f"https://api.telegram.org/bot{telegram_token}/sendMessage",
        json={
            "chat_id": manager_chat,
            "text": message,
            "parse_mode": "Markdown"
        }
    )


if __name__ == "__main__":
    app.run(port=5001, debug=False)

Microsoft Teams: the corporate channel

If your clients are corporations, they work in Teams. Two scenarios:

Scenario 1: Webhook notifications to a Teams channel

The simplest route is the Workflows app in Teams (it runs on Power Automate): it gives you an address you can send a request with a message to. Microsoft is retiring the old Incoming Webhooks built on Office 365 connectors, so set up new notifications through Workflows.

python
import requests
import json
import os

TEAMS_WEBHOOK_URL = os.environ["TEAMS_WEBHOOK_URL"]


def send_teams_notification(title: str, message: str,
                             color: str = "0078D4",
                             facts: list[dict] = None) -> bool:
    """
    Sends a notification card to a Teams channel through the webhook address from Workflows.
    Workflows accepts both MessageCard and Adaptive Card: check the format in a test channel.
    color: hex color of the side stripe (0078D4 = Microsoft blue)
    facts: a list of {"name": "...", "value": "..."} for a data table
    """
    card = {
        "@type": "MessageCard",
        "@context": "http://schema.org/extensions",
        "themeColor": color,
        "summary": title,
        "sections": [{
            "activityTitle": title,
            "activityText": message,
        }]
    }

    if facts:
        card["sections"][0]["facts"] = facts

    response = requests.post(
        TEAMS_WEBHOOK_URL,
        headers={"Content-Type": "application/json"},
        data=json.dumps(card)
    )
    return response.ok   # any successful response (200, 202)


# Example: a new deal notification
def notify_deal_closed(client_name: str, amount: float,
                        property_address: str) -> None:
    """A notification to the sales channel in Teams when a deal closes."""
    send_teams_notification(
        title="🎉 New deal closed!",
        message=f"An agent signed a contract with a client.",
        color="00B050",   # green
        facts=[
            {"name": "Client", "value": client_name},
            {"name": "Amount", "value": f"${amount:,.0f}"},
            {"name": "Property", "value": property_address},
        ]
    )

How to set up a webhook in Teams through Workflows:

  1. In Teams → Channel → ⋯ (the three dots) → Workflows
  2. Pick the "Send webhook alerts to a channel" template
  3. Set the parameters and save
  4. Copy the webhook address → save it to an environment variable

Scenario 2: Microsoft's Teams MCP

Microsoft has an official MCP server for Teams (part of Microsoft Agent 365, in preview). It lets an agent read chats and channels, post messages and reply in threads. It's a hosted server, not a package you install with npx: an organization admin sets up the connection (registering an app in Microsoft Entra and granting permissions), and tool names may change during the preview. For current tools and the connection setup, see Microsoft's documentation. Check the same documentation for which MCP clients are supported.

When to use which:

  • Webhook through Workflows: notifications from business processes (CRM, deploys, deals). Fast, no app registration.
  • Teams MCP: an interactive agent that reads and replies in channels. Requires registering an app in Entra and admin permissions.

ManyChat: when you don't need code

For business owners who don't program, there's ManyChat. A visual builder for direct message flows: Instagram, Messenger, WhatsApp, TikTok, Telegram.

What ManyChat can do:

  • Visual message sequences with conditions (if/else, no code)
  • Integration with Google Sheets, Zapier, Make
  • Audience segmentation by tags
  • A/B testing of messages
  • Broadcasts for mass messaging

ManyChat + Claude through Zapier: ManyChat's own AI features depend on your plan, and connecting Claude specifically is usually easier through Zapier: ManyChat → Webhook → Zapier → Claude API → reply back to ManyChat. A bit more involved, but no code.


Unified Messaging Hub: one system for every channel

🎨 Picture this: A taxi dispatch center. All calls go to one place. The dispatcher assigns the cars. A Unified Hub is your dispatch center for messages from every channel.

python
from flask import Flask, request, jsonify
import anthropic
import json
import os

app = Flask(__name__)
claude = anthropic.Anthropic()

ROUTING_SYSTEM = """You are a router for customer messages. Analyze the request and return JSON:
{
  "intent": "faq|lead|complaint|consultation|other",
  "urgency": "low|medium|high",
  "language": "en|es|ru",
  "should_escalate": true|false,
  "suggested_response": "a short answer if intent=faq"
}"""


def route_message(message: str, channel: str, user_id: str) -> dict:
    """
    Analyzes an incoming message and decides where it goes.
    channel: telegram|whatsapp|slack|teams
    """
    response = claude.messages.create(
        model="claude-haiku-4-5",   # Haiku for routing: fast and cheap; check that the model is still available
        max_tokens=256,
        system=ROUTING_SYSTEM,
        messages=[{
            "role": "user",
            "content": f"Channel: {channel}\nMessage: {message}"
        }]
    )

    try:
        return json.loads("".join(b.text for b in response.content if b.type == "text"))
    except json.JSONDecodeError:
        return {
            "intent": "other",
            "urgency": "medium",
            "language": "en",
            "should_escalate": False,
            "suggested_response": ""
        }


@app.route("/hub/incoming", methods=["POST"])
def unified_incoming():
    """
    A single entry point for messages from all channels.
    Each source (Telegram bot, WhatsApp webhook, Slack event)
    sends its message here in a standard format.
    """
    data = request.json
    channel = data.get("channel", "unknown")
    user_id = data.get("user_id", "")
    message = data.get("message", "")

    # 1. Routing with Claude Haiku (cheap and fast)
    routing = route_message(message, channel, user_id)

    # 2. Handling logic by intent
    if routing["should_escalate"]:
        # Hand off to a live person
        escalate_to_manager(channel, user_id, message, routing)
        reply = "I'm passing your question to a specialist. We'll reply within 1 hour."

    elif routing["intent"] == "faq" and routing["suggested_response"]:
        # Use the ready answer from routing
        reply = routing["suggested_response"]

    else:
        # A full answer from Claude Sonnet
        response = claude.messages.create(
            model="claude-sonnet-5-5",
            max_tokens=512,
            system="You are a friendly assistant. Reply in the customer's language.",
            messages=[{"role": "user", "content": message}]
        )
        reply = "".join(b.text for b in response.content if b.type == "text")

    return jsonify({
        "reply": reply,
        "routing": routing,
        "channel": channel
    })


def escalate_to_manager(channel: str, user_id: str,
                         message: str, routing: dict) -> None:
    """Notifies a manager on Telegram."""
    bot_token = os.environ.get("TELEGRAM_BOT_TOKEN")
    manager_chat = os.environ.get("MANAGER_TELEGRAM_CHAT_ID")
    if not bot_token or not manager_chat:
        return

    import requests
    requests.post(
        f"https://api.telegram.org/bot{bot_token}/sendMessage",
        json={
            "chat_id": manager_chat,
            "text": (
                f"🔔 *Escalation*\n"
                f"Channel: {channel} | User: `{user_id}`\n"
                f"Urgency: {routing.get('urgency', '?')}\n"
                f"Message: {message[:300]}"
            ),
            "parse_mode": "Markdown"
        }
    )


if __name__ == "__main__":
    app.run(port=5002, debug=False)

Making money: selling bots to clients

This is a separate service. Small businesses need bots but don't know how to build them.

Typical packages and what goes into the price:

Package What's included What goes into the price
Basic FAQ bot Telegram bot, 20–50 questions in the knowledge base hours for setup and filling the knowledge base; maintenance: prompt edits and monitoring
Lead qualifier Telegram + CRM integration hours for the CRM integration; maintenance: checking that leads come through
WhatsApp bot WhatsApp Business API + Claude setup and business verification; maintenance + Meta's and the provider's fees
Full system All channels + CRM + Unified Hub + analytics total hours across all channels + hosting and token costs

Prices depend on your market, your niche and how much time you put in. Income in this niche isn't guaranteed: work out your costs and the demand in your market using the lessons Packaging your offer and Pricing and monetization.


Practice

Assignment: a Telegram AI assistant + a Teams webhook in 5 steps

Step 1: Create a Telegram bot (10 min)

  1. @BotFather → /newbot → name → username → token
  2. Create the project:
bash
mkdir ai-messenger-bot && cd ai-messenger-bot
python -m venv venv && source venv/bin/activate
pip install python-telegram-bot anthropic python-dotenv flask requests
  1. Create .env:
bash
TELEGRAM_BOT_TOKEN=your_token
ANTHROPIC_API_KEY=sk-ant-...
TEAMS_WEBHOOK_URL=https://...  # we'll add this in step 3
MANAGER_TELEGRAM_CHAT_ID=your_chat_id

Step 2: Adapt the code to your niche (10 min)

Copy handle_message() from the theory section. Change SYSTEM_PROMPT: describe your business or your client's niche. Run it:

bash
python bot.py

Find the bot in Telegram by its username → send /start → ask 7–10 questions as if you were a customer. Judge the quality, and refine the system prompt if needed.

Step 3: Set up a webhook in Teams (5 min)

  1. In your Teams (or ask your client): Channel → ⋯ → Workflows → the "Send webhook alerts to a channel" template
  2. Name it "AI Assistant Bot" and save
  3. Copy the webhook address → add it to .env as TEAMS_WEBHOOK_URL
  4. Run a test:
python
from dotenv import load_dotenv
load_dotenv()
notify_deal_closed("John Miller", 85000, "45 Calle Larga, Cuenca")

Check the Teams channel: a card should appear.

Step 4: Add escalation to Telegram (5 min)

Copy the notify_manager() function from the WhatsApp section. Build it into the Telegram bot: when a user writes "I want to talk to a person" or "call me," Claude returns an escalation flag and you notify yourself.

Step 5: Document it as a case study (5 min)

  • A screenshot of a conversation with the bot
  • A screenshot of the Teams notification
  • A description: which business it's for, what problem it solves
  • A cost breakdown for the client (setup + maintenance)
  • Add it to your portfolio

Bonus assignment:

Add a /contact command to the Telegram bot. When a user calls it, the bot asks for an email/phone number, saves it to a Google Sheet with the gspread library and notifies you on Telegram. That's your first lead capture tool.


Tools and resources


Key takeaways

A messaging channel without an AI bot is like a website without a contact form: the customer shows up, nobody's there, the customer leaves. A bot catches inquiries that would otherwise be lost.

A well-configured Telegram bot takes on the routine questions and frees up your staff for the hard ones. The token cost of a typical conversation is a small fraction of what a person's working time costs, but calculate it for your own volume. For current prices and versions, see What's current.

You can sell bots to clients as a product, not just as one-off work: the core is reusable, and you swap the system prompt and branding for each niche. How much it brings in depends on your market and niche; there are no guarantees.


Further reading

→ No-code AI: v0, Webflow AI and Framer for business owners

The mark stays in this browser only and is never sent anywhere. My progress