AI Agents · درس

إرسال الرسائل والكتل المنسقة

النص العادي وMarkdown وJSON الخاص بـ Block Kit — تنسيق رسائل Slack

الدرس 3 من 413 خطوة

إرسال الرسائل والكتل المنسقة درس مجاني في AI Agents على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Agents، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Agents 4 دروس في المجموع.

الرسائل النصية البسيطة باستخدام say()

أبسط طريقة لنشر رسالة في Slack هي say(text). ويدعم النص mrkdwn — وهي صيغة Markdown الخاصة بـ Slack. استخدموا *bold* و_italic_ و~strike~ و`code` وإشارات مثل <@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')

مقدمة إلى Block Kit

يُعد Block Kit إطار واجهة المستخدم في Slack لبناء رسائل غنية وتفاعلية. بدلًا من النص العادي، تؤلفون الرسائل من كتل ذات أنواع محددة: section وheader وdivider وactions وcontext. تمرَّر الكتل كقائمة إلى معامل blocks في say() أو 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
    )

كتل section مع حقول نصية

تُعد كتلة section الأكثر تنوعًا. ويمكنها عرض نص (mrkdwn أو plain_text)، أو قائمة من أزواج المفتاح والقيمة، أو عنصر ملحق (زر أو صورة أو قائمة تجاوز). استخدموا fields لأزواج المفتاح والقيمة المتجاورة — فهي مناسبة جدًا للوحات المعلومات.

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)

كتل header وdivider

استخدموا كتل header لعناوين الأقسام الكبيرة، وكتل divider للفصل البصري. لا تدعم كتلة header سوى plain_text (ولا تدعم mrkdwn). ادمجوا بينهما لإنشاء رسائل تقارير منظمة جيدًا.

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)

كتل actions مع الأزرار

تحتوي كتل Actions على عناصر تفاعلية مثل الأزرار. لكل زر action_id (يُستخدم لتوجيه النقرات إلى المعالجات)، وtext، وvalue اختياري يحمل بيانات. استخدموا style: 'primary' لزر الإجراء الرئيسي، وstyle: 'danger' للإجراءات المدمّرة.

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)

كتل Context للبيانات الوصفية

تعرض كتل Context نصًا صغيرًا ثانويًا في أسفل الرسالة — وهي مثالية للبيانات الوصفية مثل الطوابع الزمنية والمصادر ومعلومات إصدار الوكيل. وهي تدعم mrkdwn والصور (للأيقونات الصغيرة).

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 في الحقول النصية

تدعم mrkdwn في Slack مجموعة فرعية من Markdown. وتشمل خيارات التنسيق الرئيسية لرسائل الوكيل: الخط العريض، والمائل، والتعليمات البرمجية، والروابط، والإشارات إلى القنوات، والإشارات إلى المستخدمين، والقوائم. استخدموا هذه الخيارات لجعل المحتوى المُنشأ بالذكاء الاصطناعي مقروءًا في 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)

الرسائل المؤقتة باستخدام respond()

الرسائل المؤقتة لا يراها سوى المستخدم الذي شغّل الإجراء — وليس أعضاء القناة الآخرين. استخدموها لتحديثات الحالة ورسائل الخطأ والتأكيدات التي لا تحتاج إلى إغراق القناة بها. وهي متاحة فقط عبر respond() (أوامر الشرطة المائلة) أو 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)
    )

تحديث الرسائل بعد إرسالها

بعد نشر رسالة، يمكنكم تحديثها باستخدام client.chat_update() مع القناة والطابع الزمني للرسالة (ts). يفيد ذلك في تحديثات التقدم — انشروا رسالة أولية مثل 'Processing...'، ثم حدّثوها بالنتيجة عند الانتهاء.

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

النشر في قنوات محددة

استخدموا client.chat_postMessage(channel=channel_id, text=...) للنشر في أي قناة يملك روبوتكم صلاحية الوصول إليها. اعثروا على معرّفات القنوات في Slack API أو بالنقر بزر الفأرة الأيمن على قناة. استخدموا conversations_list() للبحث عن القنوات حسب الاسم برمجيًا.

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

نمط منشئ رسائل Block Kit

استخدموا دالة منشئ تقبل البيانات وتُرجع قائمة من الكتل. يفصل ذلك تنسيق الرسائل عن منطق الأعمال، ويجعل كتل الرسائل قابلة لإعادة الاستخدام عبر معالجات الأحداث المختلفة.

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)

اختبار سريع: أنواع الكتل

اختبروا مدى فهمكم لـ Slack Block Kit.

مراجعة الرسائل الغنية

يمكن لوكيلكم الآن نشر رسائل Slack احترافية وتفاعلية:

  • say(text) — نص mrkdwn بسيط؛ ويدعم *bold* و_italic_ و`code` والإشارات
  • say(blocks=[...]) — استخدام Block Kit لتخطيط منظم
  • header — عنوان قسم كبير (plain_text فقط)
  • section — متن نصي مع حقول اختيارية (شبكة مفتاح-قيمة) أو ملحق واحد
  • divider — خط فاصل أفقي
  • actions — حاوية للأزرار والعناصر التفاعلية
  • context — نص صغير للبيانات الوصفية في الأسفل
  • respond(response_type='ephemeral') — رسالة لا يراها سوى المستخدم الذي شغّل الإجراء
  • chat_update(ts=...) — تحديث رسالة منشورة سابقًا بمحتوى جديد
البدء مجانًا

تعلم AI Agents مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
60
الدروس
239

الأسئلة الشائعة

هل درس «إرسال الرسائل والكتل المنسقة» مجاني؟

نعم — نص درس «إرسال الرسائل والكتل المنسقة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Agents، انتقل إلى CoddyKit PRO. تتضمن دورة AI Agents 4 دروس في المجموع.

ماذا ستتعلم في «إرسال الرسائل والكتل المنسقة»؟

النص العادي وMarkdown وJSON الخاص بـ Block Kit — تنسيق رسائل Slack تتمرن على AI Agents مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ AI Agents؟

لا تُشترط خبرة سابقة. AI Agents على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «إرسال الرسائل والكتل المنسقة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس AI Agents هذا؟

نعم. كل درس في AI Agents يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. أساسيات Slack Bolt SDK
  2. الاستماع إلى الأحداث وأوامر الشرطة المائلة
  3. إرسال الرسائل والكتل المنسقة
  4. بناء bot لإشعارات الفريق
← العودة إلى AI Agents