البوتات والرسائل التفاعلية

حساب البوت هو مستخدم مُعد لبرنامج ما. يمتلك اسمًا وصورة ورموز وصول خاصة به، ويعرض وسم BOT بجانب اسمه. تغطي هذه الصفحة أيضًا وكلاء الذكاء الاصطناعي الذين تديرهم بنفسك، والأجزاء التفاعلية من الرسائل: الأزرار والقوائم ومربعات الحوار، والتي يمكن لأي تكامل استخدامها.

لماذا حساب بوت

  • رسائله تأتي من هوية واضحة، مع وسم BOT، بدلاً من أن تأتي من حساب زميل.
  • تستمر رموزه في العمل عندما يتغير دور الشخص الذي قام بإعدادها أو يغادر (ما لم يُعطّل الخادم البوتات المملوكة لأصحاب حسابات معطّلة، راجع أدناه).
  • لا يمكن للبوتات تسجيل الدخول باستخدام كلمة مرور، ولا ترى أبداً تطبيق الويب.

تنشئ التطبيقات بوتاتها الخاصة، مثل بوتات قائمة المهام (Todo) أو أدلة التشغيل (Playbooks)، عبر واجهة برمجة التطبيقات الخاصة بالإضافات (EnsureBotUser). وكلاء الذكاء الاصطناعي هم أيضًا حسابات بوت، من نوع خاص، وتُعرض مع وسم AGENT: راجع الوكلاء.

تفعيل حسابات البوت

يقوم مدير النظام بتفعيل تفعيل إنشاء حسابات البوت في وحدة التحكم بالنظام › التكاملات › حسابات البوتات (ServiceSettings.EnableBotAccountCreation، AM_SERVICESETTINGS_ENABLEBOTACCOUNTCREATION). تكون هذه الخاصية معطّلة افتراضياً. لا يمكن إنشاء البوتات إلا لمديري النظام، ما لم يمنحوا هذا الحق لأدوار أخرى في إعدادات الصلاحيات.

على نفس الصفحة، تعطيل حسابات البوت عند تعطيل المالك (ServiceSettings.DisableBotsWhenOwnerIsDeactivated، مفعّل افتراضياً) يُعطّل البوت عندما يُعطَّل حساب مالكه.

إنشاء بوت

  1. افتح قائمة الفريق، ثم إعدادات الفريق، وانقر على التكاملات في نهاية تبويباتها، ثم حسابات البوتات وإضافة حساب بوت.
  2. أدخل اسم المستخدم (حروف صغيرة، أرقام، نقاط، شرطات وعلامات تحتية)، وإختارياً أيقونة البوت، والاسم المعروض، والوصف.
  3. اختر الدور: عضو، أو مدير النظام لبوت يدير الخادم. امنح البوت الحد الأدنى من الصلاحيات التي يحتاجها.
  4. علّم post:channels للسماح له بالنشر في كل قناة عامة، أو post:all لكل القنوات، بما في ذلك القنوات الخاصة والرسائل المباشرة، دون أن يكون عضواً.
  5. حدد موعد انتهاء صلاحية الرمز الافتراضي، ثم اختر إنشاء حساب بوت.
  6. انسخ رمز الوصول المعروض. لن يُعرض مرة أخرى.

لاحقاً، إنشاء رمز جديد في صف البوت يضيف رمزاً، ويمكن تعطيل أو حذف كل رمز. تعمل رموز البوت حتى عندما تكون رموز الوصول الشخصية معطّلة للأشخاص.

يمكن للبوت حمل سمات الخادم (تلك المُعدّة في وحدة التحكم بالنظام › خصائص النظام)، والتي يتم تعيينها في نموذج إضافة/تحرير البوت أو من خلال تعديل السمات… ضمن قائمة ⋯ الخاصة بالبوت. يحدد سماته من يديره: مالكه، إذا كان لديه صلاحية إدارة البوتات، أو أي شخص لديه صلاحية إدارة بوتات الآخرين؛ أما السمات المُدارة من قبل المشرف فتتطلب وجود مشرف نظام. بوت الوكيل الذكي لا ينتمي إلى أحد، لذا لا يمكن تعيين سماته إلا لمن لديه صلاحية إدارة بوتات الآخرين أو مشرف النظام.

عبر واجهة برمجة التطبيقات:

# create the bot (you become its owner)
curl -X POST https://chat.example.com/api/v4/bots \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"username": "deploy-bot", "display_name": "Deploy", "description": "Posts deployments"}'

# give it a token
curl -X POST https://chat.example.com/api/v4/users/$BOT_USER_ID/tokens \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"description": "deploy pipeline"}'

من سطر الأوامر، وتسجّل الدخول كمدير (وليس في الوضع المحلي): amctl bot create deploy-bot --display-name Deploy --with-token --expires-in 90d. نقاط النهاية الأخرى: GET /api/v4/bots، PUT /api/v4/bots/{bot_user_id}، POST /api/v4/bots/{bot_user_id}/disable و/enable، وPOST /api/v4/bots/{bot_user_id}/assign/{user_id} لتغيير مالكه.

أضِف البوت إلى المجتمعات والقنوات

البوت الجديد لا ينتمي إلى أي مجتمع. أضِفه كما تُضيف شخصًا، من إدارة أعضاء المجتمع أو عبر واجهة برمجة التطبيقات:

curl -X POST https://chat.example.com/api/v4/teams/$TEAM_ID/members \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"team_id": "'$TEAM_ID'", "user_id": "'$BOT_USER_ID'"}'

curl -X POST https://chat.example.com/api/v4/channels/$CHANNEL_ID/members \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"user_id": "'$BOT_USER_ID'"}'

يمكن للبوت الذي يحمل صلاحية post:channels أو post:all النشر دون أن يكون عضوًا، لكنه يستقبل أحداث WebSocket فقط للقنوات التي ينتمي إليها.

النشر باسم البوت

استخدم رمز البوت مع أي استدعاء لواجهة برمجة التطبيقات؛ POST /api/v4/posts هو الأكثر شيوعًا (انظر الموارد الرئيسية). للكتابة إلى شخص ما مباشرةً، افتح قناة الرسالة المباشرة أولاً:

# returns the channel; use its "id" as channel_id
curl -X POST https://chat.example.com/api/v4/channels/direct \
  -H "Authorization: Bearer $BOT_TOKEN" -H 'Content-Type: application/json' \
  -d '["'$BOT_USER_ID'", "'$USER_ID'"]'

للرد على ما يقوله الناس، تابع WebSocket باستخدام رمز البوت وأجب عن أحداث posted التي تهمك. تجاهل رسائل البوت نفسه لتجنب الحلقات.

تُرسل رسالة يمكن لشخص واحد فقط رؤيتها (رسالة عابرة) عبر POST /api/v4/posts/ephemeral و{"user_id", "post": {"channel_id", "message"}}. تتطلب صلاحية create_post_ephemeral، والتي يمتلكها مديرو النظام فقط بشكل افتراضي. عادةً ما ترسل التكاملات رسائل عابرة كإجابات على أوامر الشرطة المائلة والأزرار.

الوكلاء

الوكيل هو حساب بوت من النوع agent: حيث يكون للمستخدمين "is_agent": true، وللبوتات "kind": "agent"، ويعرض الواجهة وسم AGENT بدلاً من BOT. يتم إنشاء الوكلاء فقط بواسطة مشرفي النظام (وكلاء على مستوى الخادم)، من خلال وحدة التحكم بالنظام › الذكاء الاصطناعي › اتصالات النماذج، ومشرفي المجتمعات (وكلاء مجتمعاتهم)، من خلال تبويب الذكاء الاصطناعي في إعدادات المجتمع، أو باستخدام /api/v4/ai/agents (راجع واجهة برمجة التطبيقات). البوت الذي يتم إنشاؤه عبر POST /bots أو بواسطة تطبيق يكون دائماً بوتاً عادياً.

يتم الرد على الوكيل المدمج بواسطة الخادم، باستخدام اتصال نموذج. الوكيل الخارجي هو ملكك لتشغيله: برنامج في مكان آخر (مثل وكيل برمجي في مشروع ما) يسجل الدخول كوكيل ويجيب كما لو كان شخصًا حقيقيًا. لا يجيب Antimatter نيابة عنه.

تُحدد حالة الوكيل المدمج بواسطة الخادم: متصل عندما تستجيب اتصال نموذج الوكيل، غائب عندما لا تستجيب (توقف، انتهاء مهلة، رفض مفتاح)، غير متصل عندما يكون الوكيل مغلقاً أو لا يملك اتصالاً أو نموذجاً قابلاً للاستخدام. يتم التحقق من الحالة عند تغيير الوكيل أو اتصاله، وعند اختبار الاتصال، وفي كل استدعاء لنموذج الوكيل، وكل 10 دقائق. لا يمكن لأي شخص تعيين حالة الوكيل المدمج: حيث تُرجع نقاط النهاية PUT /users/{id}/status ونقاط نهاية الحالة المخصصة 403 (api.status.agent.app_error)، حتى لمشرفي النظام، وترفض واجهة برمجة التطبيقات للإضافات UpdateUserStatus، وSetUserStatusTimedDND، وUpdateUserCustomStatus، وRemoveUserCustomStatus ذلك بنفس الطريقة. أما حالة الوكيل الخارجي فتتبع اتصاله الخاص، ولا يمكن تغييرها إلا بواسطة رمزه الخاص.

تشغيل وكيل خارجي

  1. يضيف المشرف الوكيل في وحدة التحكم بالنظام › الذكاء الاصطناعي › اتصالات النماذج (أو تبويب الذكاء الاصطناعي الخاص بالمجتمع)، مع تحديد النوع وكيل خارجي، ويختار من يمكنه التحدث إليه. تعرض الصفحة بعد ذلك كيفية الاتصال به.
  2. امنحه رمز وصول: يفتح مسؤول النظام التكاملات › حسابات البوتات، ويعثر على حساب الوكيل ويختار إنشاء رمز جديد، أو يستدعي واجهة برمجة التطبيقات الخاصة بالرموز باستخدام معرّف المستخدم للوكيل:
    curl -X POST https://chat.example.com/api/v4/users/$AGENT_USER_ID/tokens \
      -H "Authorization: Bearer $ADMIN_TOKEN" -H 'Content-Type: application/json' \
      -d '{"description": "agent"}'
  3. يستدعي البرنامج واجهة برمجة التطبيقات ويفتح WebSocket باستخدام Authorization: Bearer <token>، ويقرأ إشاراته ورسائله المباشرة من أحداث posted، ويجيب باستخدام POST /posts، ضمن سلسلة رسائل الرسالة.
  4. يعرض للأشخاص ما يفعله من خلال تعيين نشاطه:
    curl -X PUT https://chat.example.com/api/v4/ai/agents/$AGENT_USER_ID/activity \
      -H "Authorization: Bearer $AGENT_TOKEN" -H 'Content-Type: application/json' \
      -d '{"state": "working", "text": "Running the tests", "thread_post_id": "'$ROOT_ID'"}'

معرّف الوكيل في هذه المسارات هو معرّف المستخدم الخاص به. حافظ على سرية رمز الوصول: يمكن لأي شخص لديه هذا الرمز النشر باسم الوكيل.

النشاط

  • state: idle، thinking، working، waiting (في انتظار شخص ما)، blocked أو offline. تعود الحالات المشغولة (thinking، working، waiting، blocked) إلى idle بعد expires_in_seconds: 10 دقائق افتراضيًا، و24 ساعة كحد أقصى.
  • text: بضع كلمات حول المهمة، سطر واحد لا يتجاوز 200 حرف. تعرض الواجهة هذا النص في قائمة الأعضاء وفي بطاقة الملف الشخصي.
  • thread_post_id: سلسلة الرسائل التي يعمل فيها الوكيل، والتي يجب أن يكون البرنامج قادرًا على قراءتها. يُرسل هذا المعرف فقط لأولئك الذين يحق لهم قراءة سلسلة الرسائل.

يمكن لمن يرى الوكيل قراءة نشاطه (عبر GET /ai/agents/{agent_id}/activity، أو POST /ai/agents/activity/ids مع قائمة معرفات)، ويستقبل حدث WebSocket باسم agent_activity_changed، دون سلسلة الرسائل. تضبط الوكلاء المدمجة نشاطها بنفسها.

بينما يكتب الوكيل المدمج إجابته، يرسل الخادم النص المتزايد في أحداث agent_post_stream إلى القناة: post_id، channel_id، root_id، user_id، message (النص حتى تلك اللحظة) وcontrol (start، text، end، error أو cancel). يجلب حدث post_edited الرسالة النهائية. يرى العملاء الذين يتجاهلون البث الإجابة بمجرد حفظها.

رسائل تفاعلية: أزرار وقوائم

يمكن لأي رسالة تحتوي على مرفقات أن تحمل إجراءات: أزرار، وقوائم للاختيار من بينها. تعمل هذه الإجراءات في الرسائل المنشورة عبر واجهة برمجة التطبيقات، وخطافات الويب، وإجابات أوامر الشرطة المائلة. عندما يستخدم أحدها، تستدعي Antimatter عنوان URL الخاص بتكاملك.

{
  "channel_id": "…",
  "message": "Deploy **api 2.4.0** to production?",
  "props": {
    "attachments": [{
      "actions": [
        {
          "id": "approve",
          "type": "button",
          "name": "Approve",
          "style": "primary",
          "integration": {"url": "https://deploy.example.com/actions", "context": {"release": "2.4.0", "action": "approve"}}
        },
        {
          "id": "env",
          "type": "select",
          "name": "Pick an environment",
          "options": [{"text": "Staging", "value": "staging"}, {"text": "Production", "value": "production"}],
          "integration": {"url": "https://deploy.example.com/actions", "context": {"release": "2.4.0", "action": "env"}}
        }
      ]
    }]
  }
}
  • type: button أو select.
  • id: أحرف وأرقام وشرطات وعلامات تحتية، مختلفة لكل إجراء في الرسالة. يتم توليده إذا تركته فارغًا.
  • style (للأزرار): default، primary، success، good، warning، danger، أو لون سداسي.
  • options (للقوائم)، أو data_source: users أو channels لاختيار شخص أو قناة. default_option يختار قيمة مسبقًا.
  • integration.url: الوجهة التي يُرسَل إليها النقر. يمكن للتطبيق (الإضافة) استخدام مساره الخاص، مثل /plugins/com.example.deploy/actions. أما integration.context فهو خاص بك: يعود مع النقر، ولا يراه العملاء أبداً.

الطلب الذي يستقبله تكاملك

{
  "user_id": "…",
  "user_name": "priya",
  "channel_id": "…",
  "channel_name": "releases",
  "team_id": "…",
  "team_domain": "lumen-labs",
  "post_id": "…",
  "trigger_id": "…",
  "type": "button",
  "context": {"release": "2.4.0", "action": "approve"}
}

في حالة القائمة، يكون type هو select، ويحتوي context.selected_option على القيمة المختارة.

ردّك

{
  "update": {"message": "Deploy of **api 2.4.0** approved by @priya", "props": {}},
  "ephemeral_text": "Done. The deploy starts in a minute."
}
  • update: يستبدل نص الرسالة وخصائصها، مثلاً لإزالة الأزرار بعد استخدامها (مع props فارغة).
  • ephemeral_text: رسالة لا يراها إلا الشخص الذي نقر.
  • goto_location: عنوان URL يُفتح.
  • جسم فارغ لا يُغيّر شيئاً.

ينتظر الخادم ما تسمح به مهلة انتهاء طلبات التكامل (٣٠ ثانية افتراضيًا). يجب أن يُسمح بالعناوين النصية للتكاملات على عناوين الشبكات الخاصة من قِبل مدير النظام، تمامًا كما هو الحال مع خطوط الويب.

الحوارات

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

curl -X POST https://chat.example.com/api/v4/actions/dialogs/open \
  -H 'Content-Type: application/json' \
  -d '{
    "trigger_id": "'$TRIGGER_ID'",
    "url": "https://deploy.example.com/dialog",
    "dialog": {
      "callback_id": "new-release",
      "title": "New release",
      "introduction_text": "Fill in the release details.",
      "submit_label": "Create",
      "notify_on_cancel": false,
      "state": "anything you want back",
      "elements": [
        {"display_name": "Version", "name": "version", "type": "text", "placeholder": "2.4.0"},
        {"display_name": "Notes", "name": "notes", "type": "textarea", "optional": true},
        {"display_name": "Environment", "name": "env", "type": "select",
         "options": [{"text": "Staging", "value": "staging"}, {"text": "Production", "value": "production"}]},
        {"display_name": "Owner", "name": "owner", "type": "select", "data_source": "users"},
        {"display_name": "Notify the channel", "name": "notify", "type": "bool", "default": "true"}
      ]
    }
  }'
نوع العنصرما يعرضه
textحقل من سطر واحد. subtype: text، email، number، password، tel أو url. تحدّد min_length وmax_length حدوده.
textareaحقل متعدد الأسطر.
selectقائمة: options، أو data_source من نوع users، channels، أو dynamic مع data_source_url. يسمح multiselect بعدة قيم.
boolخانة اختيار.
radioاختيار واحد من بين options.
date, datetimeتاريخ، أو تاريخ ووقت.
action_buttonزر يستدعي action_button_url بشكل مستقل، منفصلاً عن إرسال النافذة الحوارية. يظهر help_text الخاص به أسفله.
collapsibleمجموعة قابلة للطي من العناصر. عند استخدام sub_type: "grid"، يتم ترتيب الحاويات الفرعية كجدول بدلاً من التكديس: كل حاوية تمثل صفاً، وعناصرها تمثل خلايا ذلك الصف.

يقبل كل عنصر display_name، name، help_text، placeholder، default وoptional.

يحدد submit_buttons في الحوار عنصر select ثابتًا: تصبح خياراته أزرار إرسال الحوار، زرًا لكل خيار، بدلاً من زر إرسال واحد، ولا يظهر عنصر select نفسه. يطلب size ("small" أو "medium" أو "large"؛ "small" إذا تُرك فارغًا) حوارًا أوسع. يعيد refresh_on_return (يتطلب source_url) جلب الحوار من source_url مرة واحدة عند إغلاق حوار فُتح فوقه، ليتمكن من عرض التغييرات. لا يمنع size أو sub_type غير المعترف بهما فتح الحوار: بل يعود إلى الافتراضي ويسجل الخادم ذلك فقط.

عندما يُرسل الشخص النموذج، يرسل Antimatter طلب POST إلى url الخاص بالحوار:

{
  "type": "dialog_submission",
  "callback_id": "new-release",
  "state": "anything you want back",
  "user_id": "…",
  "channel_id": "…",
  "team_id": "…",
  "submission": {"version": "2.4.0", "notes": "", "env": "staging", "owner": "…", "notify": true},
  "cancelled": false
}

أجب بجسم فارغ لإغلاق الحوار، أو اتركه مفتوحاً وأظهر ما هو خاطئ:

{"errors": {"version": "This version already exists."}}

{"error": "…"} يعرض رسالة للنموذج بأكمله. مع notify_on_cancel، يُرسل إغلاق الحوار "cancelled": true. تعمل الحوارات بنفس الطريقة في التطبيقات: يستقبل OpenInteractiveDialog في واجهة برمجة تطبيقات الإضافة الطلب نفسه.