واجهة REST API

كل ما تفعله تطبيقات Antimatter يمر عبر نفس واجهة HTTP، لذا يمكن لبرامجك النصية (Scripts) أن تفعل الشيء نفسه. تشرح هذه الصفحة كيفية المصادقة، الموارد التي ستستخدمها أكثر، شكل الاستجابات والأخطاء، وكيفية متابعة الأحداث مباشرة عبر WebSocket.

أساسيات

  • عنوان URL الأساسي: https://chat.example.com/api/v4. جميع نقاط النهاية أدناه نسبية له.
  • الصيغة: JSON في الداخل والخارج، باستثناء رفع الملفات (multipart). أرسل Content-Type: application/json.
  • المعرّفات: لكل كائن معرّف id مكوّن من 26 حرفاً. الأزمنة هي بالمللي ثانية منذ بداية Unix (create_at، update_at، delete_at؛ 0 تعني «لم يُحذف»).
  • المجتمعات هي فرق: تسميها الواجهة teams، مع team_id.
  • نفسك: في أي مسار يستقبل user_id، يعني me المستخدم المُسجَّل الدخول، كما في GET /users/me.

القائمة الكاملة لنقاط النهاية موجودة في رمز الخادم: تُعلن المسارات في server/channels/api4/*.go والأنواع في server/public/model. يغطي وصف OpenAPI الموجود في مجلد api/v4/source من المستودع النقاط النهائية الموروثة من Mattermost، وبعض إضافات Antimatter: نقل سلاسل الرسائل، واتصالات النماذج، والوكلاء، وقواعد الفريق، ووضع التركيز، وإجراءات الرسائل. أما النقاط النهائية الأخرى فهي موجودة في الرمز فقط.

المصادقة

كل طلب، باستثناء تسجيل الدخول وبعض نقاط النهاية العامة، يحتاج إلى رمز في ترويسة Authorization:

curl -H "Authorization: Bearer $TOKEN" https://chat.example.com/api/v4/users/me

يُقبل ثلاثة أنواع من الرموز هناك: الرموز الشخصية للوصول، رموز الجلسة ورموز الوصول OAuth. يُقبل أيضاً Authorization: Token …. الرموز في سلسلة الاستعلام (?access_token=) تُقبل فقط لرموز الوصول OAuth.

الرموز الشخصية للوصول (موصى بها للبرامج النصية)

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

  1. يُفعِّل مدير النظام تفعيل رموز الوصول الشخصية في وحدة التحكم بالنظام › التكاملات › إدارة التكاملات (ServiceSettings.EnableUserAccessTokens، AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS).
  2. لكل شخص يمكنه إنشاء الرموز، يفتح مدير النظام وحدة التحكم بالنظام › إدارة المستخدمين › المستخدمون، ثم يختار إدارة الأدوار من قائمة الشخص، ويحدد السماح لهذا الحساب بإنشاء رموز وصول شخصية. يمكن لمديري النظام دائمًا إنشاء هذه الرموز.
  3. يفتح الشخص صورة ملفه الشخصي في أعلى اليمين، ثم الملف الشخصي والإعدادات › الأمان. تحت الرموز الشخصية للوصول، يصف الغرض من الرمز ويختار إنشاء رمز. يُعرض الرمز مرة واحدة فقط: انسخه.

عبر واجهة برمجة التطبيقات: POST /users/{user_id}/tokens مع {"description": "backup script", "expires_at": 0} (وحدة expires_at هي الميلي ثانية؛ 0 يعني عدم انتهاء الصلاحية). حقل token في الاستجابة هو السر؛ أما id فهو ما تستخدمه لإلغاء الرمز (POST /users/tokens/revoke مع {"token_id": "…"}). من سطر الأوامر: amctl token generate <user> <description>.

يمكن لمدير النظام تحديد حد أقصى لصلاحية الرموز باستخدام الحد الأقصى لصلاحية رمز الوصول الشخصي (أيام) في نفس صفحة وحدة التحكم بالنظام.

رموز الجلسة

تسجيل الدخول باستخدام كلمة المرور يعيد رمز جلسة في ترويسة الاستجابة Token، وهو نفس نوع الجلسة الذي تستخدمه التطبيقات:

curl -i -X POST https://chat.example.com/api/v4/users/login \
  -H 'Content-Type: application/json' \
  -d '{"login_id": "maya", "password": "…"}'

أضف "token": "123456" لحساب يستخدم المصادقة متعددة العوامل. تنتهي صلاحية الجلسات وفقًا لإعدادات الجلسة على الخادم، ونقطة نهاية تسجيل الدخول محدودة المعدل (5 طلبات في الثانية). POST /users/logout ينهي الجلسة.

تقوم المتصفحات بالمصادقة باستخدام كوكي بدلاً من ذلك. يجب أن يرسل الطلب المصادق عليه بواسطة الكوكي أيضًا ترويسة X-CSRF-Token لأي طلب غير GET؛ أما الرمز الموجود في ترويسة Authorization فلا يحتاج إلى ترويسة CSRF.

تطبيقات OAuth 2.0

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

  1. يجب أن يكون تفعيل مزوّد خدمة OAuth 2.0 مفعَّلاً (وحدة التحكم بالنظام › التكاملات › إدارة التكاملات، ServiceSettings.EnableOAuthServiceProvider، مفعَّل افتراضياً).
  2. يفتح الشخص الذي لديه صلاحية إدارة تطبيقات OAuth (مديرو النظام افتراضيًا) التكاملات › تطبيقات OAuth 2.0 (قائمة الفريق › إعدادات الفريق › التكاملات)، ويضيف التطبيق مع عناوين URL الخاصة بالإرجاع. يحصل بعد ذلك على معرّف العميل وسر العميل.
  3. تُرسل تطبيقك المستخدمين إلى https://chat.example.com/oauth/authorize مع response_type=code، client_id، redirect_uri وstate. يدعم PKCE باستخدام code_challenge_method=S256.
  4. يُبادِل الرمز عبر POST https://chat.example.com/oauth/access_token (باستخدام grant_type=authorization_code، ثم refresh_token للتجديد)، ويستدعي واجهة برمجة التطبيقات باستخدام Authorization: Bearer <access token>.

يستطيع المستخدمون عرض التطبيقات التي منحوها صلاحية الوصول من الملف الشخصي والإعدادات › الأمان › التطبيقات التي منحتها صلاحية.

الموارد الرئيسية

العنصرنقاط النهاية
أنت والمستخدمون الآخرونGET /users/me، GET /users/{user_id}، GET /users/username/{username}، POST /users/ids (قائمة من المعرّفات)، POST /users/search، GET /users?in_team=…&in_channel=…
المجتمعاتGET /users/me/teams, GET /teams/{team_id}, GET /teams/name/{name}, PUT /teams/{team_id}/patch, GET /teams/{team_id}/members, POST /teams/{team_id}/members
قنواتGET /users/me/teams/{team_id}/channels، GET /teams/name/{team}/channels/name/{channel}، POST /channels، POST /channels/direct (معرفان لمستخدمين)، POST /channels/group، POST /channels/{channel_id}/members
الرسائلPOST /posts, GET /posts/{post_id}, PUT /posts/{post_id}/patch, DELETE /posts/{post_id}, GET /channels/{channel_id}/posts, GET /posts/{post_id}/thread, POST /teams/{team_id}/posts/search
ردود الفعلPOST /reactions مع {"user_id", "post_id", "emoji_name"}، DELETE /users/{user_id}/posts/{post_id}/reactions/{emoji_name}
الملفاتPOST /files (مultipart: channel_id وfiles)، ثم ضع المعرّفات المُعادَة في حقل file_ids الخاص بالرسالة؛ GET /files/{file_id}
التفضيلاتGET /users/me/preferences, PUT /users/me/preferences
التكاملات/hooks/incoming، /hooks/outgoing، /commands، /bots، /oauth/apps (راجع الصفحات التالية)
الخادمGET /system/ping (فحص الحالة، لا يتطلب رمزًا)، GET /config/client?format=old (الإعدادات التي تراها التطبيقات)

نشر رسالة

curl -X POST https://chat.example.com/api/v4/posts \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"channel_id": "'$CHANNEL_ID'", "message": "Backup finished: **42 GB** in 3 min"}'

تُكتب الرسائل باستخدام Markdown. أضف "root_id" (أول رسالة في سلسلة الرسائل) للرد داخل سلسلة الرسائل، و"file_ids" للملفات، و"props" للمرفقات والعناصر الإضافية الأخرى (راجع المرفقات).

العثور على معرّف القناة

curl -H "Authorization: Bearer $TOKEN" \
  https://chat.example.com/api/v4/teams/name/lumen-labs/channels/name/ops-alerts

تُستخدم الأسماء الموجودة في رابط القناة: /lumen-labs/channels/ops-alerts.

ترقيم الصفحات

تستقبل نقاط النهاية الخاصة بالقوائم معطيات page (تبدأ من 0) وper_page (60 افتراضيًا، وبحد أقصى 200). واصل طلب الصفحة التالية حتى تعود صفحة أقصر من per_page.

تستقبل رسائل القناة (GET /channels/{channel_id}/posts) أيضاً since (وقت: كل ما تغيّر منذ ذلك الحين)، أو before وafter (معرّف منشور). تعود النتائج كقائمة منشورات: {"order": [IDs, newest first], "posts": {ID: post}, "next_post_id", "prev_post_id"}.

الأخطاء

تستخدم الأخطاء رموز الحالة القياسية في HTTP (400 إدخال غير صالح، 401 غير مصادَق، 403 غير مسموح، 404 غير موجود، 501 ميزة معطّلة) مع جسم JSON:

{
  "id": "api.context.permissions.app_error",
  "message": "You do not have the appropriate permissions.",
  "detailed_error": "",
  "request_id": "jz8zm5nunpbt8f3gpqsz5dq6so",
  "status_code": 403
}

استخدم id في الكود: يُترجم message إلى لغة المستخدم. يبقى detailed_error فارغاً ما لم يعمل الخادم في وضع المطوّر (ServiceSettings.EnableDeveloper). اذكر request_id لمدير الخادم: فهو موجود في السجلات.

حدود المعدل

تحديد معدل الطلبات معطَّل افتراضياً. عند تفعيله من قِبل مدير النظام (وحدة التحكم بالنظام › البيئة › تحديد معدل الطلبات)، يحصل كل عميل على 10 طلبات في الثانية مع دفعات من 100 افتراضياً، ويُحسب ذلك حسب عنوان IP أو حسب المستخدم. تحمل الاستجابات X-RateLimit-Limit، X-RateLimit-Remaining وX-RateLimit-Reset؛ عند تجاوز الحد، يرد الخادم بـ429 مع ترويسة Retry-After بالثواني. بعض نقاط النهاية، مثل تسجيل الدخول، لها حد خاص بها بغض النظر عن الإعداد.

اكتب سكربتات تنتظر وتعيد المحاولة عند 429، وتجنّب الاستعلام الدوري: اتبع WebSocket بدلاً من ذلك.

تدفق أحداث WebSocket

اتصل بـwss://chat.example.com/api/v4/websocket. صِدّق إما برأس Authorization: Bearer في طلب الاتصال، أو بإرسال هذا كرسالة أولى:

{"seq": 1, "action": "authentication_challenge", "data": {"token": "…"}}

يرسل الخادم حدث hello، ثم حدثاً لكل ما يُسمح لك برؤيته:

{
  "event": "posted",
  "data": {"channel_id": "…", "channel_type": "O", "post": "{\"id\":\"…\",\"message\":\"Hello\",…}"},
  "broadcast": {"channel_id": "…", "team_id": "", "user_id": "", "omit_users": null},
  "seq": 4
}

لاحظ أن data.post هي الرسالة كنص JSON. الأحداث الشائعة: posted، post_edited، post_deleted، reaction_added، reaction_removed، typing، status_change، user_added، direct_added. ترسل التطبيقات أحداثها الخاصة، وتُسمّى custom_<app id>_<event>.

يمكنك أيضاً إرسال إجراءات، كلٌّ منها بمعرّف seq متزايد: user_typing مع {"channel_id", "parent_id"}، أو get_statuses. أعد الاتصال عند انقطاعه، واسترد ما فاتك باستخدام since (انظر التقطيع).

تضيف Antimatter هذه الأحداث: agent_activity_changed وagent_post_stream (انظر الوكلاء)، وai_tools_changed (انظر الوكلاء)، وcommunity_rules_updated وcommunity_rules_accepted (انظر قواعد المجتمع)، وfocus_ended (انظر وضع التركيز)، وcommunity_attributes_updated، وmember_timeouts_updated، وpost_put_on_top، وpost_removed_from_top، وserver_categories_updated، وchannel_overrides_updated، وcategory_overrides_updated. عند تسجيل الدخول الجديد إلى حسابك، يُرسل حدث session_created إلى جلساتك الأخرى (التي تتضمن session_id، وcreate_at، وplatform، وos، وbrowser، وmobile؛ دون إرسال أي رمز أمان أبداً)، وعند معالجة تحذير تسجيل الدخول هذا، يُرسل حدث session_revoked أو session_acknowledged (الذي يتضمن session_id) إلى جميع تلك الجلسات.

مكتبات العملاء

  • تأكيد: model.Client4 في server/public/model (استيراد github.com/mattermost/mattermost/server/public/model). model.NewAPIv4Client(url)، ثم client.SetToken(token)؛ model.NewWebSocketClient4(wsURL, token) يتبع الأحداث. النسخة الخاصة بـ Antimatter تضيف طرقاً لنقاط النهاية الخاصة بها، مثل UpdateMessageRequest، PutPostOnTop وExportChannel.
  • TypeScript: فئة Client4 من @mattermost/client، في webapp/platform/client، مع أنواعها في webapp/platform/types. النسخة الموجودة في مستودع Antimatter تتضمن نهايات Antimatter؛ أما الحزمة المنشورة على npm بواسطة Mattermost فلا تتضمنها.
package main

import (
	"context"
	"log"

	"github.com/mattermost/mattermost/server/public/model"
)

func main() {
	client := model.NewAPIv4Client("https://chat.example.com")
	client.SetToken("…")
	post, _, err := client.CreatePost(context.Background(), &model.Post{
		ChannelId: "…",
		Message:   "Hello from Go",
	})
	if err != nil {
		log.Fatal(err)
	}
	log.Println("posted", post.Id)
}

ما تضيفه Antimatter إلى واجهة برمجة التطبيقات

لا توجد هذه النهايات والحقول على خادم Mattermost. جميعها تتطلب جلسة.

النهايةوظيفته
GET /teams/{team_id}/user_attributes/fields
POST نفس المسار
PATCH، DELETE …/fields/{field_id}
سمات المجتمع: حقول الملف الشخصي التي يحددها مسؤولو المجتمع لأعضائه (حتى 20). يمكن للأعضاء قراءتها؛ ويُنشئها مسؤولو المجتمع ويغيّرونها.
GET /teams/{team_id}/members/{user_id}/user_attributes
PATCH نفس المسار
POST /teams/{team_id}/user_attributes/values/search
قيم سمات العضو، بصيغة {field_id: value}. يضبط الأعضاء قيمهم الخاصة (باستثناء تلك التي يديرها المسؤولون)؛ ويضبط المسؤولون قيم أي شخص. يستقبل البحث {"user_ids": [...]} (حتى 200).
GET /teams/{team_id}/timeouts
PUT /teams/{team_id}/members/{user_id}/timeout
GET /teams/{team_id}/members/{user_id}/moderation
المهل الزمنية: {"until": time, "reason": "…"} يمنع شخصًا من النشر، وإضافة ردود الفعل، ورفع الملفات في المجتمع حتى ذلك الحين (بحد أقصى 28 يومًا)؛ "until": 0 يرفع المنع. يعرض عرض الإشراف على المجتمع وقت انضمامهم وكمية منشوراتهم الأخيرة.
GET /channels/{channel_id}/on_top
PUT, DELETE /posts/{post_id}/on_top
الرسائل المثبتة في أعلى القناة (حتى 10). {"duration": ms}، بحد أقصى 30 يوماً؛ القيمة 0 تحافظ عليها حتى تُزال. يمكن لأي شخص يملك صلاحية قراءة القناة عرضها. تثبيت رسالة في الأعلى أو إزالتها يتطلب صلاحية النشر في القناة، وفي قناة المجتمع، أن يكون المرء مديراً للقناة أو للمجتمع، أو أن يملك صلاحية إدارة الرسائل (delete_others_posts) هناك. في رسالة مباشرة أو جماعية، يمكن لأعضائها ذلك. يُرفض ذلك في القنوات المؤرشفة.
GET, PUT /teams/{team_id}/rules
POST /teams/{team_id}/rules/accept
GET /teams/{team_id}/rules/stats
قواعد الفريق: انظر قواعد الفريق.
GET, POST, DELETE /users/me/focus
GET /users/me/focus/summary?since=&until=
POST /users/me/focus/summary/read
وضع التركيز: انظر وضع التركيز.
POST /channels/{channel_id}/message_requestيعمل على طلب رسالتك الخاص: {"action": "accept"}، "dismiss"، أو "request" لإعادة المحادثة إلى قائمة الطلبات. يعيد عضو القناة الخاص بك.
GET, PUT /channels/{channel_id}/overrides
GET /channels/{channel_id}/overrides/effective
GET, PUT /channels/{channel_id}/role_access
ما يمكن لدورٍ أو شخصٍ فعله في قناة، والأدوار التي ترى قناة مقيدة بدور.
GET, PUT /teams/{team_id}/server_categories
GET, PUT …/server_categories/overrides
تصنيفات القنوات المشتركة للمجتمع، والاستثناءات التي تنطبق على كل قناة ضمن تصنيف.
GET /groups/{group_id}/team_role
PUT …/team_role/permissions
الصلاحيات التي يمنحها دور المجتمع.
POST /teams/{team_id}/autolinks/previewيُجرّب قواعد الربط التلقائي للمجتمع على نص.
POST /channels/{channel_id}/export?format=csv&since=&until=تنزيل رسائل القناة بصيغة CSV (حتى 50,000 رسالة)، للأشخاص الذين يمكنهم قراءة القناة.
GET /posts/{post_id}/speechالرسالة مقروءة بصوت عالٍ، بصيغة صوتية، عند إعداد تحويل النص إلى كلام.
POST /posts/{post_id}/move_to_channelينقل سلسلة رسائل إلى قناة أخرى في نفس المجتمع: راجع نقل سلسلة رسائل.
GET, POST /ai/connections
GET, PATCH, DELETE /ai/connections/{connection_id}
GET /ai/connections/usable
الاتصالات بالنماذج، وهي مزودو الذكاء الاصطناعي الذين تستخدمهم ميزات الذكاء الاصطناعي والتطبيقات في الخادم: راجع الاتصالات بالنماذج.
GET, POST /ai/agents
GET, PATCH, DELETE /ai/agents/{agent_id}
POST /ai/agents/{agent_id}/tasks
GET /ai/agents/conversations
وكلاء الذكاء الاصطناعي، ونشاطهم، ومهام ومحادثات الدردشة بالذكاء الاصطناعي: انظر الوكلاء.
GET /ai/agents/{agent_id}/tools
GET /ai/agents/tools/catalogue
POST /ai/tools/calls/{call_id}/confirm, /decline
GET, POST /ai/mcp_servers
GET, PATCH, DELETE /ai/mcp_servers/{server_id}
POST, DELETE /ai/mcp_servers/{server_id}/oauth
أدوات الوكيل، وكتالوج الأدوات التي يجوز له استخدامها، وتأكيد أو رفض استدعاء أداة قيد الانتظار، وخوادم MCP المتاحة للوكلاء: انظر الذكاء الاصطناعي.
GET /channels/{channel_id}/message_actions
POST /posts/{post_id}/message_actions/{hook_id}
GET, POST /hooks/outgoing/{hook_id}/icon
إجراءات الرسائل: خطافات ويب صادرة يشغّلها المستخدمون من قائمة الرسالة. راجع إجراءات الرسائل.
POST /users/me/sessions/acknowledgeيتجاهل تحذير تسجيل الدخول الجديد لأحد جلساتك: {"session_id"}. لا يجوز استدعاء هذا إلا للمستخدم المسجَّل الدخول، وبالنسبة لجلساته هو فقط.
PUT /channels/{channel_id}/typeيغيّر الإعداد المسبق للقناة أو إعداداتها: انظر أنواع القنوات.
GET /channels/{channel_id}/topics
PATCH /posts/{post_id}/topic
مواضيع المنتدى، وقبول إجابة أو تعيين حالة الموضوع: انظر أنواع القنوات.

حقول جديدة

  • المجتمعات (Team، وPUT /teams/{team_id}/patch): all_channels_membership (يوجد الجميع في كل قناة يمكنهم رؤيتها)، default_channel_id (حيث يهبط المستخدمون الجدد)، welcome_channel_id (حيث تذهب رسائل الانضمام والمغادرة، فارغة إذا لم تكن هناك)، kind (community أو workplace، تظهر في الواجهة كـ نقابة ومساحة عمل: النقابة أيضًا تُفعّل all_channels_membership؛ تحصل المجتمعات الجديدة على TeamSettings.DefaultCommunityKind الخادم، community/النقابة افتراضيًا)، member_list_view (كيف تجمّع قائمة الأعضاء الأعضاء: choice، الافتراضي، يتيح لكل عضو الاختيار؛ roles أو teams يثبته)، hide_role_colors، require_team_badges، name_display (كيف يعرض المجتمع الأشخاص: فارغ للافتراضي الخاص بالخادم)، onboarding وautolinks (كلاهما سلاسل JSON).
  • القناة الافتراضية القناة الافتراضية للمجتمع الجديد هي general (عام)، وليس town-square. يقوم ترقية 0.9.0 بإعادة تسمية town-square لكل مجتمع إلى general مع الحفاظ على المعرّف، ما لم يكن للمجتمع قناة general بالفعل. تبقى الأسماء القديمة صالحة: GET /teams/{team_id}/channels/name/town-square، GET /teams/name/{team}/channels/name/town-square وchannel في خطاف الويب الوارد تعطي القناة الافتراضية للمجتمع عندما لا توجد قناة بهذا الاسم. استخدم default_channel_id، أو الاسم general، في الأكواد الجديدة.
  • روابط القنوات: يربط #channel-name قناة، كما يفعل ~channel-name. يحدد خاصية channel_mentions في المنشور القنوات المرتبطة بأي من الطريقتين؛ يبقى #word الذي لا يسمي قناة وسمًا. يكتب واجهة Antimatter الويب وتطبيق الجوال #name.
  • تستقبل القنوات المؤرشفة أعضاء جددًا (POST /channels/{channel_id}/members)، ويمكنهم قراءة سجلها. لا يستطيع أحد النشر، أو إضافة ردود فعل، أو تثبيت، أو وضع رسالة في الأعلى، أو إعادة تسمية القناة، أو تغيير أدوار أعضائها هناك.
  • الردود المضمنة: منشور يحتوي على "props": {"reply_to": "<post id>"} يستشهد بتلك الرسالة من نفس القناة. أضف "reply_to_mention": false لتجنب إخطار كاتبها. يملأ الخادم metadata.reply_to بوصف مختصر للرسالة المستشهد بها.
  • المحتوى الحساس: "props": {"spoiler": true} يخفي نص المنشور وملفاته حتى يختار القارئ رؤيتها.
  • التجاهل والحظر تفضيلات: التصنيف user_block، باسم معرف الشخص الآخر، والقيمة ignore أو block. ما إذا كانت رسالة مباشرة تنتظر كطلب موجود في notify_props.dm_request لعضو القناة لديك (pending، accepted أو dismissed).
  • يمكن أن تتضمن مرفقات الرسائل stages وchart: راجع البطاقات.
  • القنوات (Channel): يحمل props لكل قناة مجتمعية دائمًا am_type (text أو voice أو forum)، وam_mode، وam_root_posts (members أو moderators)، وam_preset (معرّف الإعداد المسبق المطابق، أو فارغ للإعدادات المخصصة)، وللمنتديات am_forum_view (topics أو imageboard). عدم وجود am_type في الحمولة يعني أنه لم يتم تعبئته، وليس أبدًا أن القناة نصية. لا تحمل الرسائل المباشرة والرسائل الجماعية أيًا من هذه الحقول. انظر أنواع القنوات.

أنواع القنوات

قناة المجتمع إما text أو voice أو forum (نوعها، ثابت عند إنشائها)، في أحد أوضاع هذا النوع، مع إعدادات فوقه. الإعداد المسبق هو حزمة مسماة من وضع وإعدادات يقدمها العميل كخيار واحد؛ لا يتم تخزين الإعدادات المسبقة، لذا فإن الإعداد المسبق للقناة (am_preset) مشتق من إعداداتها، ويقرأ "" عندما لا تطابق أي إعداد مسبق ("مخصص").

معرّف الإعداد المسبقالنوعالوضعroot_postsview
text_chattextchatmembers–
text_announcementtextchatmoderators–
voice_talkvoicetalkmembers–
voice_stagevoicestagemembers–
forum_agoraforumdiscussionmemberstopics
forum_qaforumqamemberstopics
forum_ideasforumideasmemberstopics
forum_announcementforumdiscussionmoderatorstopics
forum_imageboardforumdiscussionmembersimageboard

إنشاء وتغيير نوع القناة

يقرأ POST /channels الخاصية props.am_preset (التي تُوسَّع أولاً)، ثم يطبّق الخصائص الفردية props.am_type وam_mode وam_root_posts وam_forum_view فوقها؛ وتُحذف أي خاصية أخرى تبدأ بـ am_. يُرفض إنشاء قناة صوتية إذا لم يكن تطبيق القنوات الصوتية نشطاً (400 api.channel.type.voice_unavailable.app_error)؛ ويُرفض إنشاء رسالة مباشرة أو رسالة جماعية مع خصائص النوع (api.channel.type.direct.app_error).

curl -X POST https://chat.example.com/api/v4/channels \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"team_id": "'$TEAM_ID'", "name": "help-desk", "display_name": "Help desk", "type": "O",
       "props": {"am_preset": "forum_qa"}}'

يغيّر PUT /channels/{channel_id}/type الإعداد المسبق أو إعدادات قناة موجودة: {"preset"?, "mode"?, "root_posts"?, "view"?}، حيث يُوسَّع الإعداد المسبق أولاً كما هو الحال عند الإنشاء. يتطلب هذا الإذن manage_public_channel_properties أو manage_private_channel_properties في القناة (حدث التدقيق updateChannelType)، ويرسل القناة بعد تعبئة الحقول. يُرفض أي جسم طلب يذكر type آخر (api.channel.type.fixed.app_error): فلا يتغير النوع نفسه أبداً. الأخطاء الأخرى: api.channel.type.invalid.app_error (قيمة غير معروفة، أو وضع لا ينتمي إلى نوع القناة، أو عرض على قناة غير منتديات).

يحمل الاستيراد والتصدير الشاملان (amctl import bulk) الحقول الأربعة نفسها على سطر القناة: am_type وam_mode وam_root_posts وam_forum_view. تُستورد القناة التي لا تحتوي على هذه الحقول كقناة دردشة نصية عادية، كما كان الحال قبل أنواع القنوات.

من يبدأ المحادثات أو يفتح المواضيع

يتطلب نشر رسالة جذرية (على عكس الرد) الإذن create_root_post، الذي يظهر في محرر التجاوزات باسم بدء المحادثات (للنص والصوت) أو فتح المواضيع (للمنتديات). لا يحمل هذا الإذن أي دور: قبل التجاوزات، يحصل عليه كل من يمكنه النشر عندما تكون root_posts مضبوطة على members، ويحصل عليه فقط مشرفو القناة (مديرو النظام، ومديرو المجتمع، ومديرو القناة، وكل من لديه إدارة الرسائل هناك) عندما تكون مضبوطة على moderators. ثم يُطبَّق تجاوز الدور أو الشخص على create_root_post فوق ذلك، كما هو الحال مع أي إذن آخر. أما الرد (حيث يكون root_id مضبوطاً) فيحتاج فقط إلى الحق العادي في النشر.

تفشل المنشورات الجذرية التي لا تحقق هذا الشرط برمز 403: app.post.root_posts.moderators_only.app_error عندما تكون قيمة root_posts هي moderators ولا يكون منشئ المنشور مشرفًا على القناة، أو app.post.root_posts.denied.app_error في حالة الرفض المتجاوز. يتم فحص هذا الشرط لواجهة برمجة التطبيقات REST، والبوتات، وخطافات الويب الواردة والصادرة (على منشئ الخطاف)، واستجابات أوامر الشرطة المائلة؛ ولا يتم فحصه للمنشورات من التطبيقات (واجهة برمجة التطبيقات للمكونات الإضافية) أو نسخ سلاسل الرسائل المنقولة (بدلاً من ذلك، يتم فحص الشخص الذي ينقل سلسلة الرسائل). كما يتم تخطي هذا الفحص أثناء الاستيراد الشامل.

المنتديات تقبل المواضيع فقط

في المنتدى، يتطلب المنشور الجذري وجود props.am_thread_title (عنوان الموضوع)، بعد إزالة الفراغات الزائدة، وبطول يتراوح بين 1 و100 حرف، من كل المصادر، بما في ذلك التطبيقات وسلاسل الرسائل المنقولة: إذا كان العنوان مفقودًا، يتم إرجاع الخطأ 400 app.post.forum.title_required.app_error، وإذا كان طويلًا جدًا، يتم إرجاع الخطأ app.post.forum.title_too_long.app_error. لا تتطلب الردود عنوانًا، ويتم تجاهل أي عنوان يُرسل مع الرد. عند تحرير المنشور الجذري للموضوع بدون عنوان أو بعنوان فارغ، يبقى عنوانه الحالي كما هو؛ أما إذا كان العنوان غير فارغ، فيتم تغيير اسم الموضوع. نقل سلسلة رسائل إلى منتدى (انظر أدناه) يتطلب عنوانًا أيضًا، إما من الطلب أو من عنوان سلسلة الرسائل نفسها.

تُكتب الإجابة المقبولة لموضوع الأسئلة والأجوبة (am_accepted_answer، وهو معرّف الرد) وحالة موضوع الأفكار (am_topic_status، مع am_topic_status_by وam_topic_status_at) فقط عبر PATCH /posts/{post_id}/topic؛ ويتم تجاهل أي من هذه الحقول الثلاثة إذا أُرسلت أثناء الإنشاء أو التحديث أو التعديل الجزئي، سواء من قبل عميل أو تطبيق، ويظل القيمة المخزنة كما هي.

عرض قائمة مواضيع المنتدى

GET /channels/{channel_id}/topics?sort=votes&per_page=25

يتطلب وجود صلاحية قراءة القناة. معاملات الاستعلام هي:

  • sort: activity (الافتراضي)، newest، votes، unanswered (للأسئلة والأجوبة فقط) أو status (للأفكار فقط).
  • answered (true/false، للأسئلة والأجوبة) وstatus (أحد القيم: open، planned، in_progress، done، declined، للأفكار): استخدم هذه المعاملات للتصفية. استخدام أي منها خارج وضعه المناسب يؤدي إلى خطأ 400.
  • mine=true: يعرض فقط المواضيع التي بدأتها أنت. following=true: يعرض فقط المواضيع التي تتابعها.
  • q: يطابق العنوان أو نص المنشور الأول، بحد أقصى 200 حرف.
  • before: next_cursor الخاص بالصفحة السابقة. per_page: 25 افتراضيًا، و100 كحد أقصى. replies: من 0 إلى 5 من أحدث الردود لكل موضوع، لعرض لوحة الصور.

الإجابة: {"topics": [{"post", "reply_count", "last_reply_at", "participant_ids", "votes", "accepted_answer_id", "status", "on_top", "replies": [post, …]}], "next_cursor"}. الأصوات هي ردود الفعل 👍 (يتم احتساب +1 وthumbsup معًا)، مطروحًا منها كاتب الموضوع نفسه؛ يُعطى accepted_answer_id في منتديات الأسئلة والأجوبة فقط، وstatus في منتديات الأفكار فقط. تأتي المواضيع المثبتة في أعلى القناة أولاً.

قبول إجابة، أو تعيين حالة لموضوع

curl -X PATCH https://chat.example.com/api/v4/posts/$POST_ID/topic \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"accepted_answer_id": "'$REPLY_ID'"}'

يجب أن يكون post_id منشورًا جذريًا لموضوع في المنتدى، وإلا سيظهر الخطأ 400 app.topic.not_a_topic.app_error. يتطلب accepted_answer_id (معرّف الرد، أو "" للتراجع عنه) وجود منتدى أسئلة وأجوبة؛ ويتطلب status وجود منتدى أفكار؛ وأي استخدام في الوضع الخاطئ يؤدي إلى الخطأ 400 app.topic.mode.app_error.

  • قبول إجابة: يجب أن يكون الشخص الذي يطرح السؤال (طالما لا يزال بإمكانه النشر هناك) أو مشرفًا على القناة؛ وإلا سيظهر الخطأ 403 app.topic.accept.not_allowed.app_error. يجب أن يكون الرد ردًا فعليًا وغير نظامي ضمن ذلك الموضوع، وإلا سيظهر الخطأ 400 app.topic.accept.not_a_reply.app_error. يؤدي حذف الرد المقبول إلى مسح الإجابة.
  • تعيين حالة: مشرفو القناة فقط، وإلا سيظهر الخطأ 403 app.topic.status.not_allowed.app_error؛ وأي قيمة غير معروفة تؤدي إلى الخطأ 400 app.topic.status.invalid.app_error.

ينشر كل تغيير ردًا نظاميًا في الموضوع (لإعلام متابعيه) ويجيب بالمنشور الجذري للموضوع، كما هو الآن. في منتديات الأفكار، يؤدي التصويت لموضوع إلى جعلك تتابعه أيضًا.

نقل سلسلة رسائل

ينقل POST /posts/{post_id}/move_to_channel سلسلة رسائل، ورسالتها الأولى، وجميع ردودها، إلى قناة أخرى في نفس المجتمع. يمكن أن يكون post_id الرسالة الأولى أو أي رد.

curl -X POST https://chat.example.com/api/v4/posts/$POST_ID/move_to_channel \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"channel_id": "'$TARGET_CHANNEL_ID'", "flatten": false}'
  • channel_id (إلزامي): القناة التي تُنقل إليها سلسلة الرسائل.
  • flatten (افتراضيًا false): تجعل القيمة true الردود رسائل في القناة المستهدفة بدلاً من كونها ضمن سلسلة رسائل. يستخدم تحويلها إلى قناة في Fusion هذه الميزة. يُرفض الطلب عندما تكون القناة المستهدفة منتدىً (الخطأ 400 app.post.move_thread.forum_flatten.app_error): لأن ردودها ستتحول إلى مواضيع بدون عناوين.
  • title: عنوان الموضوع، عندما تكون القناة المستهدفة منتدىً. بدونه، يتم الاحتفاظ بعنوان سلسلة الرسائل نفسها، إن وجد؛ وغيابه في كلتا الحالتين يؤدي إلى الخطأ 400 app.post.move_thread.forum_title_required.app_error. يتم تجاهله إذا لم تكن القناة المستهدفة منتدىً.

تحافظ الرسائل على مؤلفيها، وأوقاتها، وردود الفعل، وملفاتها. تحمل نسخها خاصية silent_notification، لذا لا تُشعر أحدًا. تُحذف الرسائل الأصلية. تكون الإجابة هي الرسالة الأولى المنقولة، مع معرّفها الجديد.

من يمكنه نقل سلسلة رسائل

  • يجب أن تكون قادرًا على قراءة سلسلة الرسائل والنشر في القناة الهدف.
  • يمكن لمديري القناة، ومديري المجتمع، والأشخاص الذين لديهم إدارة الرسائل (delete_others_posts) في القناة، ومديري النظام، نقل أي سلسلة رسائل.
  • يمكن لمؤلف سلسلة الرسائل نقلها عندما تكون القناتين عامتين، أو عندما تكون جميع رسائل السلسلة ملكه. وإلا تكون الإجابة 403 مع المعرّف api.post.move_thread.private_needs_moderator.app_error.
  • يجب أن تكون القناتان ضمن المجتمع نفسه (لا رسائل مباشرة أو جماعية)، وأن تكونا مختلفتين وغير مؤرشفتين. لا يمكن نقل الرسائل النظامية أو الرسائل التي تُحذف بعد قراءتها.
  • يُرفض نقل سلسلة رسائل تتجاوز WranglerSettings.MoveThreadMaxCount رسالة (100 افتراضيًا؛ 0 يعني بلا حد).

المؤشر والملاحظة

يترك النقل رسالتين نظاميتين من النوع system_wrangler: مؤشر في القناة القديمة («نُقلت سلسلة رسائل تحتوي على 13 رسالة إلى #target») وملاحظة في القناة الهدف («نُقلت هذه السلسلة من #source»)، تحت السلسلة المنقولة أو، مع flatten، بعد رسائلها. بالإضافة إلى نص الرسالة، تتيح خصائصها للعميل رسم اسم القناة كرابط:

  • المؤشر: MovedThreadPermalink، NumMessages، MovedThreadChannelId، MovedThreadTeamName، MovedThreadPostId، و، للهدف العام، MovedThreadChannelName وMovedThreadChannelDisplayName.
  • الملاحظة: MovedFromChannelId، MovedFromTeamName، MovedFromPostId (المؤشر)، MovedFromPermalink، و، للمصدر العام، MovedFromChannelName وMovedFromChannelDisplayName.

يحمل كلاهما أيضًا TranslationID. يُستبعد اسم القناة الخاصة: يرى القارئون «قناة أخرى». يبقى POST /posts/{post_id}/move الخاص بـ Mattermost معطلًا في Antimatter؛ استخدم هذا النهاية.

قواعد الفريق

يمكن لمديري الفريق جعل أعضائه يوافقون على قواعده قبل نشرهم في قنواته. طالما كانت القواعد مفعّلة، لا يستطيع العضو الذي لم يوافق على النسخة الحالية من النشر، أو الرد، أو إرسال الملفات، أو جدولة الرسائل، أو تعديلها، أو استعادتها، أو تشغيل أمر ينشر في قنوات الفريق: يجيب الخادم برمز 403 مع المعرّف api.post.community_rules_not_accepted، وتفشل الرسالة المجدولة المستحقة حينها برمز الخطأ community_rules_not_accepted. أما القراءة، وردود الفعل، والرسائل المباشرة والجماعية فلا تُمنع؛ وكذلك لا تُمنع البوتات، وخطافات الويب الواردة، ورسائل النظام، ومديرو الفريق (صلاحية manage_team، التي يمتلكها مديرو النظام أيضًا).

النهايةوظيفته
GET /teams/{team_id}/rulesالقواعد (enabled، text بصيغة Markdown، version)، مع أحدث نسخة وافقت عليها (accepted_version) وما إذا كان يجب عليك الموافقة قبل النشر (must_accept). للأعضاء، ولأي شخص قد ينضم إلى مجتمع مفتوح.
PUT /teams/{team_id}/rulesيحفظها، مع {"enabled", "text", "ask_again"} (manage_team). يجعل ask_again نسخة جديدة يجب على الجميع الموافقة عليها مرة أخرى؛ الحفظ الأول هو النسخة 1. النص مطلوب لتفعيلها، بحد أقصى 16,000 حرف.
POST /teams/{team_id}/rules/acceptيوافق، كعضو، على version التي قرأتها؛ 409 عندما تكون نسخة أحدث قد حُفظت منذ ذلك الحين، و0 للموافقة على النسخة الحالية.
GET /teams/{team_id}/rules/statsعدد أعضاء المجتمع الذين وافقوا على النسخة الحالية (manage_team).

يُرسل حدث community_rules_updated إلى المجتمع عندما يحفظ المدير القواعد (team_id، enabled، version)، ويُرسَل community_rules_accepted إلى الشخص الذي وافق، على جميع جلساته (team_id، version).

وضع التركيز

وضع التركيز هو «لا تُزعجني» مع وقت انتهاء: يتم كتم الإشعارات (لا إشعارات دفع، ولا بريد إلكتروني، ولا إشعارات سطح المكتب أو المستمرة، بما في ذلك الرسائل العاجلة)، ويصبح السبب الحالة المخصصة مع رمز 🎯 التعبيري (dart)، وينتهي عند الوقت المحدد، وتُخفي تطبيقات Antimatter شارات «غير مقروء» الخاصة بالشخص نفسه. يمكن للشخص نفسه فقط استخدام هذه النقاط النهائية (me أو معرّفه الخاص): لا يمكن لأي شخص آخر، بما في ذلك مسؤولو النظام، بدء وضع التركيز أو إنهائه أو قراءته أو قراءة ملخصه.

النهايةوظيفته
GET /users/me/focusوضع التركيز الحالي (active، start_at، end_at، reason)، أو آخر وضع تركيز بعد انتهائه (عندما تكون ended_at محددة)، أو جميعها صفر.
POST /users/me/focusيبدأ وضع التركيز، أو أثناء وجوده يغير وقت الانتهاء والسبب: {"duration": "1h30m", "reason": "…"}، أو {"end_at": ms} بدلاً من المدة، من دقيقة إلى أسبوع في المستقبل. "duration": "tomorrow" ينتهي في الساعة 09:00 من اليوم التالي حسب المنطقة الزمنية للشخص. يتم تقريب وقت الانتهاء إلى الأسفل إلى أقرب دقيقة؛ والسبب بحد أقصى 100 حرف. يتطلب تفعيل حالات المستخدمين (ServiceSettings.EnableUserStatuses)؛ لا يمكن للبوتات استخدام وضع التركيز.
DELETE /users/me/focusينهي وضع التركيز الآن.
GET /users/me/focus/summary?since=&until=ما فاته في تلك النافذة (أي start_at وended_at للتركيز): القنوات التي تحتوي على رسائل غير مقروءة من الآخرين (الرسائل المباشرة والرسائل الجماعية أولاً، ثم تلك التي تحتوي على إشارات؛ القنوات المكتومة فقط عند وجود إشارة)، وفي حالة طي سلاسل الرسائل، السلاسل المتابَعة التي تحتوي على ردود جديدة، مع عرض عدد كل منها والإشارات والمرسل الأخير.
POST /users/me/focus/summary/readمع {"since", "until"}: يعلّم تلك القنوات والسلاسل كمقروءة حتى until فقط؛ ويبقى ما جاء بعد ذلك غير مقروء.

أثناء تركيز المستخدم، يكون لديه الخاصية focus_until (بالمللي ثانية)، والتي تستخدمها العملاء لعرض حالة التركيز؛ ولا يمكن تغييرها من خلال الملف الشخصي. ينتهي التركيز عندما ينهي الشخص التركيز، أو عند انتهاء الوقت المحدد (خلال دقيقة)، أو عندما يختار الحالة بنفسه، حيث تبقى هذه الحالة المختارة. وإلا، تعود الحالة والحالة المخصصة السابقتان. ثم تحصل جميع جلساته على الحدث focus_ended، مع start_at وend_at وended_by (user أو timer أو status).

اتصالات النماذج

اتصال النموذج هو عنوان ومفتاح مزوّد الذكاء الاصطناعي، يُضبطه مدير. تستخدمه ميزات الذكاء الاصطناعي في الخادم والتطبيقات التي تستدعي خدمة الذكاء الاصطناعي. يدير المسؤولون النظاميون الاتصالات على مستوى الخادم (manage_ai_connections)؛ ويدير مسؤولو المجتمع اتصالات مجتمعهم (manage_team_ai_connections). المفاتيح للكتابة فقط: لا يحمل أي رد مفتاحًا، بل api_key_set وapi_key_last4 فقط.

النهايةوظيفته
GET /ai/connections?scope=الاتصالات التي تديرها. scope هو server أو معرّف مجتمع؛ بدونه، كل النطاقات التي تديرها.
POST /ai/connectionsيضيف اتصالًا (يرد 201).
POST /ai/connections/test, POST /ai/connections/modelsيختبر اتصالًا، أو يعرض نماذجه، قبل حفظه. نفس الجسم عند الإضافة؛ لا يُخزَّن شيء.
GET، PATCH (أو PUT)، DELETE /ai/connections/{connection_id}يقرأ أو يعدّل أو يحذف اتصالًا. يحمل التصحيح فقط الحقول المراد تغييرها؛ اترك api_key فارغًا للحفاظ على المفتاح.
POST /ai/connections/{connection_id}/testيختبر اتصالًا محفوظًا: {"ok", "error", "status_code", "latency_ms", "model_count"}.
GET /ai/connections/{connection_id}/modelsالنماذج التي يوفرها المزوّد.
GET /ai/connections/{connection_id}/usageطلبات هذا الشهر وعدد الرموز.
GET /ai/connections/usable?channel_id=&team_id=لكل من هو مسجّل الدخول: الاتصالات التي يمكنك استخدامها هناك، مع نماذجها وقدراتها، وليس مفاتيحها أو عناوينها.

جسم اتصال جديد:

{
  "name": "Local models",
  "scope": "server",
  "provider": "openai_compatible",
  "base_url": "http://llm.internal:8000/v1",
  "api_key": "…",
  "extra_headers": {},
  "models": {"chat": "qwen3-32b", "embeddings": "", "transcription": "", "decisions": ""},
  "limits": {"requests_per_minute": 0, "monthly_token_budget": 0, "per_user_requests_per_minute": 0, "per_user_monthly_token_budget": 0},
  "sharing": {"all_teams": true, "team_ids": []},
  "audience": {"everyone": true, "group_ids": [], "roles": [], "allow_guests": false}
}

provider هو openai_compatible أو anthropic. القيمة الافتراضية لـ scope هي server؛ ومعرف مجتمع يجعله اتصالاً لذلك المجتمع. في limits، يعني 0 عدم وجود حد؛ تُحسب الطلبات لكل دقيقة على كل خادم، وميزانيات الرموز لكل شهر تقويمي (UTC) للعنقود بأكمله. يحدد sharing المجتمعات التي يمكنها استخدام اتصال على مستوى الخادم (تتطلب الرسائل المباشرة والجماعية all_teams)، ويحدد audience من يمكنه استخدامه؛ الضيوف فقط مع allow_guests. تُكتب التغييرات في سجل التدقيق. يشرح دليل المدير الإعدادات: راجع الذكاء الاصطناعي.

الوكلاء

الوكيل هو حساب بوت من النوع agent (يُحدد بالحقل is_agent في بيانات المستخدم)، ويحتوي على إعداداته الخاصة: نطاقه (server، أو معرّف المجتمع)، ونوعه (مدمج أو external)، وفي حالة الوكلاء المدمجين، يشمل ذلك اتصال النموذج، والنموذج، وموجه النظام، وإعدادات الاستدلال. يدير مسؤولو النظام الوكلاء على مستوى الخادم (manage_system)، بينما يدير مسؤولو المجتمع وكلاء مجتمعهم (manage_team). بالإضافة إلى ذلك، تُستخدم صلاحية manage_own_agent لإدارة الوكيل الذي أنشأه المستخدم، وصلاحية manage_others_agent لإدارة الوكلاء الآخرين. المعرّف المستخدم للوكيل في هذه المسارات هو معرّف المستخدم الخاص به. يتم شرح كيفية تشغيل وكيل خارجي وكيفية تعيين حالة وكيل مدمج في قسم البوتات. ترفض نقاط النهاية PUT /users/{user_id}/status ونقاط نهاية الحالة المخصصة معرّف الوكيل المدمج، حتى لمسؤولي النظام (403، api.status.agent.app_error).

النهايةوظيفته
GET /ai/agents?scope=الوكلاء الذين تديرهم: scope هو server أو معرّف مجتمع؛ وبدونه، يتم عرض كل الوكلاء الذين تديرهم.
POST /ai/agentsينشئ وكيلًا وحسابه (يرد بـ 201). ينضم وكيل المجتمع إلى مجتمعه.
GET, PATCH, DELETE /ai/agents/{agent_id}
POST …/enable, POST …/disable
يقرأ، ويعدّل، ويحذف (يتم إلغاء تنشيط حسابه، وتبقى رسائله)، ويفعل أو يعطل وكيلًا.
GET /ai/agents/connections?scope=
GET /ai/agents/connections/{connection_id}/models
اتصالات النماذج التي يجوز لوكيل ذلك النطاق استخدامها، ونماذجها.
GET, PUT /ai/agents/{agent_id}/activity
POST /ai/agents/activity/ids
ما يفعله الوكيل؛ يتم تعيينه بواسطة رمزه الخاص أو بواسطة مديرين. تأخذ الدفعة ما يصل إلى 200 معرّف مستخدم.
POST /ai/agents/{agent_id}/tasksاطلب من وكيل مدمج يمكنك استخدامه لمهمة معينة: summarize_thread أو find_action_items أو find_open_questions (على post_id لسلسلة رسائل، أو channel_id بدءًا من since)، أو summarize_channel، أو ask_channel (مع question)، أو summarize_transcription (منشور النسخ النصي لمكالمة). يصبح الطلب رسالتك في رسالتك المباشرة مع الوكيل، بلغتك، ويتم الرد عليه هناك؛ الجواب (201) هو تلك الرسالة. إذا لم تتمكن من قراءة منشور أو قناة، فسيتم الرد عليها على أنها غير موجودة.
GET /ai/agents/conversations?agent_id=&before=&per_page=محادثاتك مع الوكلاء الذين يمكنك استخدامهم، الأحدث أولاً: سلاسل الرسائل التي بدأتها في رسائلك المباشرة معهم، وسلاسل الرسائل في أماكن أخرى التي رد فيها أحدهم وأنت تتابعها. يعيد before (وقت) الصفحة التالية؛ والحد الأقصى لـ per_page هو 100.

نص وكيل جديد:

{
  "username": "researcher",
  "display_name": "Researcher",
  "description": "Answers with sources",
  "scope": "server",
  "external": false,
  "connection_id": "…",
  "model": "",
  "system_prompt": "You research questions and answer with sources.",
  "reasoning": {"enabled": false, "effort": "", "budget_tokens": 0},
  "max_tool_turns": 0,
  "access": {"everyone": true, "team_ids": [], "channel_ids": [], "roles": [], "user_ids": [], "allow_guests": false}
}

استخدام model فارغًا يعني استخدام نموذج الدردشة الخاص بالاتصال. يشير access.channel_ids إلى أعضاء تلك القنوات. لا يحتوي الوكيل الخارجي على اتصال أو نموذج أو مطالبة نظام. يعرض GET /agents الوكلاء الذين يمكنك التحدث معهم، كما يقرأهم تطبيق دردشة الذكاء الاصطناعي.