0Pricing
AI Agents · Leçon

Envoyer des messages et des blocs enrichis

Texte brut, Markdown, JSON Block Kit — mettez en forme les messages Slack.

Envoyer des messages et des blocs enrichis est une leçon AI Agents gratuite sur CoddyKit. Ceci est la leçon 3 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.

Messages texte simples avec say()

La manière la plus simple de publier un message Slack consiste à utiliser say(text). Le texte prend en charge mrkdwn, la variante Slack du langage Markdown. Utilisez *bold*, _italic_, ~strike~, `code` et des mentions comme <@USERID>.

@app.event('app_mention')
def handle_mention(event, say):
    user = event['user']

    # Simple text response with mrkdwn formatting
    say(
        text=(
            f'Hello <@{user}>!\n'
            '*Agent Report:*\n'
            '- Tasks completed: `42`\n'
            '- Errors: `0`\n'
            '- _Runtime: 3.2 seconds_'
        ),
        mrkdwn=True  # enabled by default
    )

    # Slack mentions
    say(f'<@{user}> your request is being processed')
    say('Posting to <!channel>: all hands meeting tomorrow')

Introduction à Block Kit

Block Kit est le cadre d’interface utilisateur de Slack pour créer des messages riches et interactifs. Au lieu d’un simple texte, vous composez les messages à partir de blocs typés : section, header, divider, actions, context. Les blocs sont transmis sous forme de liste au paramètre blocks de say() ou de chat_postMessage().

@app.event('app_mention')
def handle_mention(event, say):
    blocks = [
        {
            'type': 'header',
            'text': {'type': 'plain_text', 'text': 'Agent Status Report'}
        },
        {
            'type': 'divider'
        },
        {
            'type': 'section',
            'text': {
                'type': 'mrkdwn',
                'text': '*Status:* Running\n*Tasks:* 42 completed'
            }
        }
    ]

    say(
        text='Agent Status Report',  # fallback for notifications
        blocks=blocks
    )

Blocs de section avec champs de texte

Le bloc section est le plus polyvalent. Il peut afficher du texte (mrkdwn ou plain_text), une liste de paires clé-valeur ou un élément complémentaire (bouton, image ou menu supplémentaire). Utilisez fields pour présenter des paires clé-valeur côte à côte, ce qui est idéal pour les tableaux de bord.

def build_task_summary_blocks(tasks):
    blocks = [
        {
            'type': 'header',
            'text': {'type': 'plain_text', 'text': 'Daily Task Summary'}
        },
        {
            'type': 'section',
            'text': {
                'type': 'mrkdwn',
                'text': f'Processed *{len(tasks)} tasks* today.'
            }
        },
        {
            'type': 'section',
            'fields': [
                {'type': 'mrkdwn', 'text': f'*Completed:*\n{sum(1 for t in tasks if t["status"]=="done")}'},
                {'type': 'mrkdwn', 'text': f'*Failed:*\n{sum(1 for t in tasks if t["status"]=="error")}'},
                {'type': 'mrkdwn', 'text': f'*Pending:*\n{sum(1 for t in tasks if t["status"]=="pending")}'},
                {'type': 'mrkdwn', 'text': f'*Avg Time:*\n3.2s'}
            ]
        }
    ]
    return blocks

# --- demo ---
tasks = [
    {'status': 'done'}, {'status': 'done'}, {'status': 'error'}, {'status': 'pending'}
]
blocks = build_task_summary_blocks(tasks)
for b in blocks:
    print(b)

Blocs d’en-tête et de séparation

Utilisez les blocs header pour les grands titres de section et les blocs divider pour séparer visuellement les éléments. Le bloc d’en-tête ne prend en charge que plain_text, et non mrkdwn. Combinez-les pour créer des messages de rapport bien structurés.

def build_report_message(title, sections):
    blocks = []

    # Header
    blocks.append({
        'type': 'header',
        'text': {'type': 'plain_text', 'text': title, 'emoji': True}
    })

    for section_title, content in sections:
        # Divider between sections
        blocks.append({'type': 'divider'})

        # Section header as bold mrkdwn
        blocks.append({
            'type': 'section',
            'text': {'type': 'mrkdwn', 'text': f'*{section_title}*\n{content}'}
        })

    return blocks

blocks = build_report_message(
    title='Weekly Agent Report',
    sections=[
        ('Emails Processed', '142 emails classified, 38 replies drafted'),
        ('Tasks Completed', '89 tasks completed, 3 failures logged')
    ]
)

# --- demo ---
for b in blocks:
    print(b)

Blocs d’actions avec boutons

Les blocs Actions contiennent des éléments interactifs tels que des boutons. Chaque bouton possède un action_id (utilisé pour acheminer les clics vers les gestionnaires), un text et un value facultatif contenant des données. Utilisez style: 'primary' pour la CTA principale et style: 'danger' pour les actions destructrices.

def build_approval_message(task_id, task_description):
    blocks = [
        {
            'type': 'section',
            'text': {
                'type': 'mrkdwn',
                'text': f'*Task ready for approval:*\n{task_description}'
            }
        },
        {
            'type': 'actions',
            'elements': [
                {
                    'type': 'button',
                    'text': {'type': 'plain_text', 'text': 'Approve'},
                    'style': 'primary',
                    'action_id': 'approve_task',
                    'value': task_id
                },
                {
                    'type': 'button',
                    'text': {'type': 'plain_text', 'text': 'Reject'},
                    'style': 'danger',
                    'action_id': 'reject_task',
                    'value': task_id
                }
            ]
        }
    ]
    return blocks

# --- demo ---
blocks = build_approval_message('task_42', 'Deploy backend v2.3 to production')
for b in blocks:
    print(b)

Blocs de contexte pour les métadonnées

Les blocs Context affichent un petit texte secondaire en bas d’un message — idéal pour des métadonnées comme les horodatages, les sources ou les informations de version de l’agent. Ils prennent en charge mrkdwn et les images, notamment pour les petites icônes.

import datetime

def add_context_footer(blocks, agent_version='v1.2'):
    timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M UTC')
    blocks.append({
        'type': 'context',
        'elements': [
            {
                'type': 'mrkdwn',
                'text': f'Generated by Agent {agent_version} | {timestamp}'
            }
        ]
    })
    return blocks

# Full message with context footer
blocks = [
    {
        'type': 'section',
        'text': {'type': 'mrkdwn', 'text': 'Analysis complete. See results below.'}
    }
]
blocks = add_context_footer(blocks)
print(f'Message has {len(blocks)} blocks')

mrkdwn dans les champs de texte

Le mrkdwn de Slack prend en charge un sous-ensemble du langage Markdown. Les principales options de mise en forme pour les messages de l’agent sont le gras, l’italique, le code, les liens, les mentions de canaux, les mentions d’utilisateurs et les listes. Utilisez-les pour rendre le contenu généré par l’IA lisible dans Slack.

def format_ai_response_as_mrkdwn(title, bullet_points, code_snippet=None):
    lines = [f'*{title}*']

    for point in bullet_points:
        lines.append(f'• {point}')

    if code_snippet:
        lines.append(f'```{code_snippet}```')  # code block

    return '\n'.join(lines)

content = format_ai_response_as_mrkdwn(
    title='Security Issues Found',
    bullet_points=[
        'SQL injection risk in `user_search()` function',
        'Hardcoded API key in `config.py` line 42',
        'Missing HTTPS on login endpoint'
    ],
    code_snippet='SELECT * FROM users WHERE id = " + userId + "\n# ^ UNSAFE: use parameterized queries'
)

print(content)

Messages éphémères avec respond()

Les messages éphémères ne sont visibles que par l’utilisateur qui a déclenché l’action, et non par les autres membres du canal. Utilisez-les pour les mises à jour d’état, les messages d’erreur et les confirmations qui ne doivent pas encombrer le canal. Ils sont disponibles uniquement via respond() (commandes à barre oblique) ou chat_postEphemeral().

@app.command('/check-status')
def handle_status(ack, respond, body, client):
    ack()
    user_id = body['user_id']
    channel_id = body['channel_id']

    # Ephemeral: only the user who ran /check-status sees this
    respond(
        text='Checking agent status...',
        response_type='ephemeral'
    )

    status = get_agent_status()

    # Or use chat_postEphemeral for more control
    client.chat_postEphemeral(
        channel=channel_id,
        user=user_id,
        text=f'Agent Status: {status}',
        blocks=build_status_blocks(status)
    )

Mettre à jour les messages après leur envoi

Après avoir publié un message, vous pouvez le mettre à jour avec client.chat_update() en fournissant le canal et l’horodatage du message (ts). Cette possibilité est utile pour les mises à jour de progression : publiez d’abord un message initial « Traitement en cours… », puis remplacez-le par le résultat une fois l’opération terminée.

@app.command('/analyze')
def handle_analyze(ack, say, respond, body, client):
    ack()
    text = body.get('text', '')
    channel = body['channel_id']

    # Post initial message
    initial = client.chat_postMessage(
        channel=channel,
        text='Analyzing... this may take a moment.'
    )
    message_ts = initial['ts']

    # Do the work
    import threading
    def do_work():
        result = slow_ai_analysis(text)
        # Update the original message with the result
        client.chat_update(
            channel=channel,
            ts=message_ts,
            text=f'Analysis complete: {result}',
            blocks=build_result_blocks(result)
        )

    threading.Thread(target=do_work, daemon=True).start()

Publier dans des canaux spécifiques

Utilisez client.chat_postMessage(channel=channel_id, text=...) pour publier dans n’importe quel canal auquel votre bot a accès. Trouvez les identifiants des canaux dans l’API Slack ou en cliquant avec le bouton droit sur un canal. Utilisez conversations_list() pour rechercher des canaux par leur nom de manière programmatique.

def post_alert_to_channel(client, channel_name, alert_message):
    # Look up channel ID by name
    result = client.conversations_list(
        types='public_channel,private_channel',
        limit=200
    )

    channel_id = None
    for ch in result['channels']:
        if ch['name'] == channel_name:
            channel_id = ch['id']
            break

    if not channel_id:
        print(f'Channel #{channel_name} not found')
        return None

    # Post the alert
    response = client.chat_postMessage(
        channel=channel_id,
        text=alert_message,
        unfurl_links=False,  # don't expand URLs
        unfurl_media=False
    )
    print(f'Posted to #{channel_name}: ts={response["ts"]}')
    return response

# --- demo: minimal stand-in for the Slack client ---
class _FakeClient:
    def conversations_list(self, **kwargs):
        return {'channels': [{'name': 'alerts', 'id': 'C123'}, {'name': 'general', 'id': 'C456'}]}
    def chat_postMessage(self, **kwargs):
        print(f"[slack] postMessage to {kwargs['channel']}: {kwargs['text']}")
        return {'ts': '1699999999.000100'}

post_alert_to_channel(_FakeClient(), 'alerts', 'Disk usage above 90% on web-1')

Modèle de générateur de messages Block Kit

Utilisez une fonction de construction qui accepte des données et renvoie une liste de blocs. Cela sépare la mise en forme des messages de la logique métier et rend vos blocs réutilisables dans différents gestionnaires d’événements.

def build_alert_blocks(level, title, details, link=None):
    level_emoji = {'info': ':information_source:',
                   'warning': ':warning:', 'error': ':x:'}.get(level, '')

    blocks = [
        {
            'type': 'header',
            'text': {'type': 'plain_text', 'text': f'{level_emoji} {title}'}
        },
        {
            'type': 'section',
            'text': {'type': 'mrkdwn', 'text': details}
        }
    ]

    if link:
        blocks.append({
            'type': 'actions',
            'elements': [{
                'type': 'button',
                'text': {'type': 'plain_text', 'text': 'View Details'},
                'url': link,
                'action_id': 'view_details'
            }]
        })

    import datetime
    blocks.append({
        'type': 'context',
        'elements': [{'type': 'mrkdwn',
                      'text': datetime.datetime.now().strftime('%Y-%m-%d %H:%M UTC')}]
    })
    return blocks

# --- demo ---
blocks = build_alert_blocks('warning', 'High latency', 'p95 latency is 3.2s', link='https://dash.example.com')
for b in blocks:
    print(b)

Vérification rapide : types de blocs

Vérifiez votre compréhension de Block Kit Slack.

Récapitulatif des messages enrichis

Votre agent peut maintenant publier des messages Slack professionnels et interactifs :

  • say(text) — texte mrkdwn simple ; prend en charge *gras*, _italique_, `code` et les mentions
  • say(blocks=[...]) — Block Kit pour une mise en page structurée
  • header — grand titre de section, avec plain_text uniquement
  • section — corps de texte avec des champs facultatifs, sous forme de grille clé-valeur, ou un élément complémentaire
  • divider — ligne de séparation horizontale
  • actions — conteneur pour les boutons et les éléments interactifs
  • context — petit texte de métadonnées en bas du message
  • respond(response_type='ephemeral') — message visible uniquement par l’utilisateur qui a déclenché l’action
  • chat_update(ts=...) — mettre à jour un message déjà publié avec un nouveau contenu

Questions Fréquemment Posées

La leçon « Envoyer des messages et des blocs enrichis » est-elle gratuite ?

Oui — le texte complet de « Envoyer des messages et des blocs enrichis » 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 « Envoyer des messages et des blocs enrichis » ?

Texte brut, Markdown, JSON Block Kit — mettez en forme les messages Slack. 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 3 sur 4.

Combien de temps prend la leçon « Envoyer des messages et des blocs enrichis » ?

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