0Pricing
AI Agents · Leçon

Écouter les événements et les commandes slash

app_mention, commandes slash et gestionnaires d’actions dans Slack Bolt.

Écouter les événements et les commandes slash est une leçon AI Agents gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Agents, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Agents comprend 4 leçons au total.

Vue d’ensemble des abonnements aux événements Slack

Slack envoie à votre application des événements lorsque quelque chose se produit — lorsqu’un message est publié, que quelqu’un mentionne votre bot ou qu’un utilisateur rejoint un canal. Vous vous abonnez à des types d’événements précis dans le tableau de bord de l’application Slack, puis vous enregistrez des gestionnaires dans Bolt à l’aide du décorateur @app.event().

from slack_bolt import App
import os

app = App(
    token=os.environ['SLACK_BOT_TOKEN'],
    signing_secret=os.environ['SLACK_SIGNING_SECRET']
)

# Register event handlers with @app.event()
# The string argument must match the Slack event type exactly

@app.event('app_mention')
def handle_mention(event, say, logger):
    logger.info(f'Mention event: {event}')
    say(f'Hello <@{event["user"]}>!')

@app.event('message')
def handle_message(event, say):
    # Fires for every message in subscribed channels
    if event.get('subtype') is None:  # ignore bot messages
        print(f'Message: {event["text"]}')

Gérer les événements app_mention

L’événement app_mention se déclenche lorsqu’une personne saisit @YourBot dans un canal. event['text'] contient le message complet, mention comprise. Supprimez le préfixe de mention pour obtenir la véritable requête de l’utilisateur.

import re

@app.event('app_mention')
def handle_mention(event, say, client):
    # event['text'] example: '<@U0123BOT> summarize this'
    text = event.get('text', '')
    user_id = event['user']
    channel = event['channel']

    # Remove the @mention to get the clean query
    clean_text = re.sub(r'<@[A-Z0-9]+>', '', text).strip()
    print(f'User {user_id} asked: {clean_text}')

    if not clean_text:
        say(f'Hi <@{user_id}>! How can I help you today?')
        return

    # Process the query
    response = process_user_query(clean_text, user_id)
    say(response)

Accéder à la charge utile de l’événement

Chaque gestionnaire d’événement reçoit le dictionnaire event, qui contient la charge utile brute de l’événement Slack. Champs principaux : event['user'] (identifiant utilisateur), event['channel'] (identifiant du canal), event['text'] (contenu du message), event['ts'] (horodatage/identifiant du message).

@app.event('app_mention')
def handle_mention(event, say, client):
    print('Event type:', event.get('type'))
    print('User ID:', event.get('user'))     # e.g. 'U0123ABC'
    print('Channel:', event.get('channel'))   # e.g. 'C0456DEF'
    print('Text:', event.get('text'))          # full message text
    print('Timestamp:', event.get('ts'))       # '1234567890.123456'
    print('Thread TS:', event.get('thread_ts')) # if in a thread

    # Get full user info from the user ID
    user_info = client.users_info(user=event['user'])
    real_name = user_info['user']['real_name']
    email = user_info['user']['profile'].get('email', '')
    say(f'Hello {real_name}!')

Commandes à barre oblique — Enregistrement et réponse

Les commandes à barre oblique permettent aux utilisateurs de déclencher des actions de l’agent depuis n’importe quel canal Slack. Enregistrez l’URL de la commande dans le tableau de bord de l’application Slack, sous Commandes à barre oblique, puis gérez-la avec @app.command('/command-name'). Appelez toujours ack() immédiatement : Slack interrompt la requête au bout de 3 secondes si vous ne le faites pas.

@app.command('/summarize')
def handle_summarize(ack, body, say, respond):
    # CRITICAL: ack() must be called within 3 seconds
    ack()  # acknowledge the command immediately

    # body contains the command payload
    user_id = body['user_id']
    channel_id = body['channel_id']
    text = body.get('text', '').strip()  # text after the command

    print(f'User {user_id} ran /summarize with: "{text}"')

    if not text:
        respond('Usage: /summarize <text or URL to summarize>')
        return

    # Process and respond
    summary = generate_summary(text)
    say(f'Summary by <@{user_id}>:\n{summary}')

ack() — La règle des 3 secondes

Slack exige que votre application appelle ack() (accusé de réception) pour chaque commande à barre oblique et charge utile interactive entrante dans un délai de 3 secondes. Si vous ne le faites pas, Slack affiche une erreur à l’utilisateur. Pour les opérations longues, appelez ack immédiatement, démarrez le traitement dans un fil d’exécution en arrière-plan, puis répondez avec respond() en fournissant le résultat.

import threading

@app.command('/analyze')
def handle_analyze(ack, body, respond):
    ack()  # Must be within 3 seconds!

    text = body.get('text', '').strip()
    if not text:
        respond('Please provide text to analyze.')
        return

    # For slow operations: run in background thread
    def process_in_background():
        result = slow_ai_analysis(text)  # may take 10+ seconds
        respond(f'Analysis complete:\n{result}')

    thread = threading.Thread(target=process_in_background)
    thread.daemon = True
    thread.start()

    # respond() is safe to call from a different thread
    # ack() already sent, Slack won't time out

say() ou respond() — Quand utiliser chaque fonction

Deux fonctions republient des messages dans Slack :

  • say() — publie dans le canal où l’événement s’est produit ; le message est visible par tout le monde
  • respond() — disponible uniquement dans les gestionnaires de commandes à barre oblique ; peut publier des messages éphémères, visibles uniquement par l’utilisateur qui a lancé la commande

Utilisez respond(response_type='in_channel') pour les réponses publiques et respond(response_type='ephemeral') pour les réponses privées.

@app.command('/status')
def handle_status(ack, respond, body):
    ack()

    # Ephemeral: only visible to the user who ran the command
    respond(
        text='Agent status: Running | Queue: 3 tasks | Uptime: 4h 22m',
        response_type='ephemeral'  # private to command user
    )

@app.command('/broadcast')
def handle_broadcast(ack, say, respond, body):
    ack()
    text = body.get('text', '')

    # Public: visible to everyone in the channel
    say(
        text=f'<@{body["user_id"]}> broadcast: {text}',
        channel=body['channel_id']
    )

    # Confirm privately to the sender
    respond('Broadcast sent!', response_type='ephemeral')

Événements de message et sous-types

L’événement générique message se déclenche pour tous les messages, y compris les messages de bots, les modifications et les suppressions. Utilisez le champ subtype pour filtrer. Sous-types courants : bot_message, message_changed, message_deleted. Si subtype est absent, il s’agit d’un message utilisateur standard.

@app.event('message')
def handle_message(event, say, client):
    subtype = event.get('subtype')

    # Ignore bot messages to prevent loops
    if subtype == 'bot_message':
        return

    # Ignore message edits and deletes
    if subtype in ('message_changed', 'message_deleted'):
        return

    # Only process direct messages (DMs) to the bot
    channel_type = event.get('channel_type', '')
    if channel_type == 'im':
        text = event.get('text', '').strip()
        user = event['user']
        print(f'DM from {user}: {text}')
        say(f'You said: {text}')

Écouter les réactions

L’événement reaction_added se déclenche lorsqu’une personne ajoute un émoji de réaction à un message. Vous pouvez vous en servir pour déclencher des actions de l’agent — par exemple, ajouter une réaction 📌 pour enregistrer un message ou une réaction ✅ pour marquer une tâche comme terminée.

@app.event('reaction_added')
def handle_reaction(event, client, say):
    reaction = event['reaction']  # e.g. 'thumbsup', 'white_check_mark'
    user_id = event['user']  # who reacted
    item = event['item']  # what was reacted to

    print(f'User {user_id} reacted :{reaction}: to {item["type"]}')

    if reaction == 'white_check_mark' and item['type'] == 'message':
        # Fetch the original message
        result = client.conversations_history(
            channel=item['channel'],
            oldest=item['ts'],
            latest=item['ts'],
            inclusive=True,
            limit=1
        )
        messages = result.get('messages', [])
        if messages:
            text = messages[0].get('text', '')
            print(f'Task completed: {text[:100]}')

Charges utiles d’action des composants interactifs

Lorsqu’un utilisateur clique sur un bouton ou sélectionne un élément de menu, Slack envoie une charge utile d’action. Gérez-la avec @app.action('action_id'). L’identifiant de l’action est la chaîne que vous avez définie lors de la création du composant Block Kit. Appelez toujours ack() immédiatement.

@app.action('approve_task')
def handle_approve(ack, body, respond, client):
    ack()  # acknowledge within 3 seconds

    action = body['actions'][0]  # the button that was clicked
    action_id = action['action_id']  # 'approve_task'
    value = action.get('value', '')  # data attached to the button
    user_id = body['user']['id']

    print(f'User {user_id} clicked {action_id} with value: {value}')

    # Update the original message to show it was approved
    client.chat_update(
        channel=body['container']['channel_id'],
        ts=body['container']['message_ts'],
        text=f'Task approved by <@{user_id}>',
        blocks=[]  # remove buttons after action
    )
    respond('Task approved!', response_type='ephemeral')

Filtrer les événements par canal ou utilisateur

Dans les grands espaces de travail, votre bot peut recevoir des événements provenant de nombreux canaux. Filtrez-les dès le début de votre gestionnaire afin de ne traiter que les événements pertinents. Vérifiez event['channel'] par rapport à une liste de canaux autorisés, ou utilisez event['user'] pour ignorer certains utilisateurs, comme les autres bots.

import os

# Only respond in designated channels
ALLOWED_CHANNELS = set(
    os.environ.get('ALLOWED_CHANNELS', '').split(',')
)

BOT_USER_IDS = set()  # will be populated at startup

@app.event('app_mention')
def handle_mention(event, say, client):
    channel = event.get('channel', '')
    user = event.get('user', '')

    # Skip if channel not in allowed list (if list is configured)
    if ALLOWED_CHANNELS and channel not in ALLOWED_CHANNELS:
        return

    # Skip if the 'user' is actually a bot
    if user in BOT_USER_IDS:
        return

    text = event.get('text', '').strip()
    say(f'Processing: {text[:50]}')

Prise en charge des réponses dans les fils

Pour répondre dans un fil plutôt que dans le canal principal, transmettez thread_ts à say(). Utilisez event.get('thread_ts', event['ts']) pour obtenir l’horodatage du fil — thread_ts n’existe que si le message se trouve déjà dans un fil ; sinon, utilisez le propre ts du message pour démarrer un nouveau fil.

@app.event('app_mention')
def handle_mention_in_thread(event, say):
    user = event['user']
    text = event.get('text', '').strip()

    # Reply in the same thread (or start a new one)
    thread_ts = event.get('thread_ts') or event.get('ts')

    response_text = f'<@{user}>, processing your request...'

    say(
        text=response_text,
        thread_ts=thread_ts  # keeps the reply in the thread
    )

    # Do the actual work
    result = do_agent_work(text)

    say(
        text=f'Done! Result:\n{result}',
        thread_ts=thread_ts
    )

Vérification rapide : délai d’exécution de ack()

Vérifiez votre compréhension de la gestion des événements Slack.

Récapitulatif des événements et des commandes à barre oblique

Votre agent Slack peut maintenant répondre à toutes les interactions des utilisateurs :

  • @app.event('app_mention') — gérer les mentions de @bot ; supprimer le préfixe de mention avec une expression régulière
  • @app.command('/cmd') — gérer les commandes à barre oblique ; toujours appeler ack() dans les 3 secondes
  • say() — publier dans le canal ; respond() — répondre à une commande à barre oblique, avec la possibilité d’une réponse éphémère
  • @app.action('id') — gérer les clics sur les boutons et les interactions avec les composants interactifs
  • @app.event('reaction_added') — déclencher une action lors de l’ajout d’une réaction émoji
  • Utilisez thread_ts dans say() pour conserver les réponses dans les fils
  • Filtrez rapidement par canal ou utilisateur afin d’éviter de traiter les événements non pertinents

Questions Fréquemment Posées

La leçon « Écouter les événements et les commandes slash » est-elle gratuite ?

Oui — le texte complet de « Écouter les événements et les commandes slash » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Agents, passe à CoddyKit PRO. Le cours AI Agents comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Écouter les événements et les commandes slash » ?

app_mention, commandes slash et gestionnaires d’actions dans Slack Bolt. Tu pratiques AI Agents avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer AI Agents ?

Aucune expérience préalable n'est requise. AI Agents sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Écouter les événements et les commandes slash » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon AI Agents ?

Oui. Chaque leçon AI Agents inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Bases du SDK Slack Bolt
  2. Écouter les événements et les commandes slash
  3. Envoyer des messages et des blocs enrichis
  4. Créer un bot de notifications d’équipe
← Retour à AI Agents