AI Agents · Lekcja

Wysyłanie wiadomości i rozbudowanych bloków

Zwykły tekst, Markdown i JSON Block Kit — formatowanie wiadomości Slack.

Lekcja 3 z 413 kroki

Wysyłanie wiadomości i rozbudowanych bloków to bezpłatna lekcja AI Agents na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Agents, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Agents zawiera 4 lekcji w sumie.

Proste wiadomości tekstowe za pomocą say()

Najprostszy sposób opublikowania wiadomości w Slacku to say(text). Tekst obsługuje format mrkdwn — odmianę markdown używaną przez Slack. Można używać *bold*, _italic_, ~strike~, `code` oraz wzmianek takich jak <@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')

Wprowadzenie do Block Kit

Block Kit to framework interfejsu użytkownika Slacka służący do tworzenia rozbudowanych, interaktywnych wiadomości. Zamiast zwykłego tekstu wiadomości tworzy się z typowanych bloków: section, header, divider, actions, context. Bloki przekazuje się jako listę do parametru blocks funkcji say() lub 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
    )

Bloki section z polami tekstowymi

Blok section jest najbardziej uniwersalny. Może wyświetlać tekst (mrkdwn lub plain_text), listę par klucz-wartość albo element dodatkowy (przycisk, obraz, menu przepełnienia). Należy użyć fields do wyświetlania par klucz-wartość obok siebie — to świetne rozwiązanie w panelach informacyjnych.

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)

Bloki header i divider

Bloków header należy używać w przypadku dużych tytułów sekcji, a bloków divider do wizualnego oddzielania treści. Blok header obsługuje wyłącznie plain_text (bez mrkdwn). Połączenie tych bloków pozwala tworzyć dobrze uporządkowane wiadomości raportowe.

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)

Bloki actions z przyciskami

Bloki actions zawierają elementy interaktywne, takie jak przyciski. Każdy przycisk ma action_id (używany do kierowania kliknięć do modułów obsługi), text oraz opcjonalne value zawierające dane. Należy użyć style: 'primary' dla głównego CTA i style: 'danger' dla działań destrukcyjnych.

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)

Bloki context na metadane

Bloki context wyświetlają mały tekst pomocniczy u dołu wiadomości — idealnie nadają się do metadanych, takich jak znaczniki czasu, źródła czy informacje o wersji agenta. Obsługują mrkdwn oraz obrazy (na przykład małe ikony).

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 w polach tekstowych

Format mrkdwn Slacka obsługuje podzbiór składni markdown. Najważniejsze opcje formatowania wiadomości agenta to: pogrubienie, kursywa, kod, łącza, wzmianki kanałów, wzmianki użytkowników i listy. Należy ich używać, aby treści generowane przez AI były czytelne w Slacku.

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)

Wiadomości ulotne za pomocą respond()

Wiadomości ulotne są widoczne tylko dla użytkownika, który wywołał działanie — nie dla innych członków kanału. Należy używać ich do aktualizacji statusu, komunikatów o błędach i potwierdzeń, które nie powinny zaśmiecać kanału. Są dostępne wyłącznie za pośrednictwem respond() (polecenia ukośnikowe) lub 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)
    )

Aktualizowanie wiadomości po wysłaniu

Po opublikowaniu wiadomości można ją zaktualizować za pomocą client.chat_update(), przekazując kanał i znacznik czasu wiadomości (ts). Jest to przydatne przy aktualizacjach postępu — należy opublikować początkową wiadomość „Processing...”, a następnie po zakończeniu zaktualizować ją wynikiem.

@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()

Publikowanie na określonych kanałach

Należy użyć client.chat_postMessage(channel=channel_id, text=...), aby publikować na dowolnym kanale, do którego bot ma dostęp. Identyfikatory kanałów można znaleźć w API Slacka lub klikając kanał prawym przyciskiem myszy. Funkcja conversations_list() pozwala programowo wyszukiwać kanały według nazwy.

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')

Wzorzec konstruktora wiadomości Block Kit

Należy użyć funkcji konstruktora, która przyjmuje dane i zwraca listę bloków. Oddziela to formatowanie wiadomości od logiki biznesowej i pozwala ponownie wykorzystywać bloki w różnych modułach obsługi zdarzeń.

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)

Szybki test: typy bloków

Sprawdź swoją wiedzę na temat Block Kit Slacka.

Podsumowanie rozbudowanych wiadomości

Państwa agent potrafi teraz publikować profesjonalne, interaktywne wiadomości w Slacku:

  • say(text) — prosty tekst w formacie mrkdwn; obsługuje *bold*, _italic_, `code` i wzmianki
  • say(blocks=[...]) — Block Kit do tworzenia uporządkowanego układu
  • header — duży tytuł sekcji (tylko plain_text)
  • section — treść tekstowa z opcjonalnymi polami (siatka klucz-wartość) lub jednym elementem dodatkowym
  • divider — pozioma linia oddzielająca
  • actions — kontener na przyciski i elementy interaktywne
  • context — mały tekst z metadanymi u dołu wiadomości
  • respond(response_type='ephemeral') — wiadomość widoczna tylko dla użytkownika wywołującego działanie
  • chat_update(ts=...) — aktualizowanie wcześniej opublikowanej wiadomości nową treścią
Bezpłatny start

Ucz się AI Agents dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
60
Lekcje
239

Często zadawane pytania

Czy lekcja „Wysyłanie wiadomości i rozbudowanych bloków” jest bezpłatna?

Tak — pełny tekst „Wysyłanie wiadomości i rozbudowanych bloków” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Agents, przejdź na CoddyKit PRO. Kurs AI Agents zawiera 4 lekcji w sumie.

Co nauczysz się w „Wysyłanie wiadomości i rozbudowanych bloków”?

Zwykły tekst, Markdown i JSON Block Kit — formatowanie wiadomości Slack. Ćwiczysz AI Agents z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć AI Agents?

Nie wymagamy żadnego doświadczenia. AI Agents w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Wysyłanie wiadomości i rozbudowanych bloków”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji AI Agents?

Tak. Każda lekcja AI Agents zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Podstawy Slack Bolt SDK
  2. Nasłuchiwanie zdarzeń i poleceń slash
  3. Wysyłanie wiadomości i rozbudowanych bloków
  4. Tworzenie bota do powiadomień zespołowych
← Powrót do AI Agents