رفتن به محتوا

پل گفتگو

ارائه‌دهنده مقدار سیمی ترابری نوع فضا
Slack slack Socket Mode (WSS رو به بیرون) slack

Slack تنها ارائه‌دهنده است. ChatProvider یک enum تک‌مقداری است و cc_server یک افزونه ثبت می‌کند. schema، هر جست‌وجو و هر ایندکس یکتا با provider کلید می‌خورند، پس شناسه‌ها هرگز از مرز ارائه‌دهنده‌ها نمی‌گذرند و افزودن یکی، تغییری تنها در سمت سرور است.

یک برنامهٔ سمت ارائه‌دهنده به‌ازای هر فضای کاری × ارائه‌دهنده.

نام دستور به ازای هر برنامه است (cc به‌طور پیش‌فرض، یعنی /cc). مدیر می‌تواند نامش را عوض کند؛ پل از آن پس همان نامی را به کار می‌برد که آخرین بار با آن فراخوانی شده است.

دستور اثر
/cc help (یا /cc بدون فعل) آنچه ربات می‌تواند انجام دهد را فهرست می‌کند
/cc link <code> یک کد یک‌بارمصرف را نقد می‌کند و هویت گفتگوی فرستنده را پیوند می‌زند
/cc ticket <title> یک تیکت محلی را که عضو پیوندشده گزارش کرده ثبت می‌کند
/cc ticket <title> | <description> همان کار، با هرچه پس از نخستین | بیاید به‌عنوان توضیح
فعل ناشناخته فعل ناشناخته را همراه با متن راهنما گزارش می‌کند

راه‌های رسیدن به یک عامل:

کنش رفتار
@bot … در یک کانال یک رشتهٔ Slack و فضایی متناظر در Control Center باز می‌کند؛ عامل در همان رشتهٔ Slack پاسخ می‌دهد
پاسخ در یک رشتهٔ پل‌شدهٔ Slack همان فضای Control Center را ادامه می‌دهد — بدون نیاز به منشن
پیام معمولی در یک کانال نادیده گرفته می‌شود (نه خطاب به ربات است و نه در یک رشتهٔ پل‌شدهٔ Slack)
پیام مستقیم به ربات یک فضای Control Center به‌ازای هر گفتگوی مستقیم؛ هنگام کار عامل یک عنوان رشتهٔ Slack و یک وضعیت «is thinking…» تنظیم می‌کند

توسط توصیف‌گر ارائه‌دهنده اعلام می‌شوند؛ همان چیزی که دیالوگ اتصال را تولید می‌کند و ارسال را اعتبارسنجی می‌کند.

شناسهٔ فیلد برچسب الزامی پیشوند محل قرارگیری
botToken توکن OAuth کاربر ربات بله xoxb- OAuth & Permissions
appToken توکن سطح برنامه بله xapp- Basic Information → App-Level Tokens، با مجوز connections:write
configRefreshToken توکن تازه‌سازی پیکربندی برنامه خیر xoxe توکن‌های پیکربندی برنامه در api.slack.com/apps

configRefreshToken اعتبارنامهٔ مدیریت برنامه است: بدون آن اتصال کار می‌کند، اما ربات را نمی‌توان از Control Center ساخت یا ویرایش کرد. با هر بار استفاده می‌چرخد و مقدار چرخیده بی‌درنگ ذخیره می‌شود.

فاصله‌های ابتدا و انتهای مقدارها حذف می‌شود، کلیدهای اعلام‌نشده دور ریخته می‌شوند و ناسازگاری پیشوند با همان یک جمله در کلاینت و سرور رد می‌شود. فیلدهای الزامی باید در هر اتصال حاضر باشند؛ فیلد اختیاری‌ای که خالی بماند همان چیزی را نگه می‌دارد که از قبل ذخیره شده است.

مجوزهای توکن ربات:

app_mentions:read
assistant:write
channels:history
chat:write
commands
groups:history
im:history
users:read
users:read.email

اشتراک‌های رویداد ربات:

app_home_opened
app_mention
message.channels
message.groups
message.im

تنظیمات ساختاری‌ای که Control Center هنگام ساخت یا ویرایش برنامه تحمیل می‌کند: Socket Mode فعال، بدون request URL، تب Messages فعال و قابل‌نوشتن، وضعیت always_online ربات، مجوزها و رویدادهای الزامی که با هرچه برنامه از قبل دارد ادغام می‌شوند (هرگز کم نمی‌شوند) و یک دستور اسلش با توضیح File a ticket or link your Control Center account — همان نشانه‌ای که دستور خودِ Control Center را در یک manifest برون‌بری‌شده مشخص می‌کند.

وضعیت مقدار سیمی معنا
متصل نیست disconnected هیچ اعتبارنامه‌ای برای این فضای کاری × ارائه‌دهنده ذخیره نشده است
در حال اتصال… connecting اعتبارنامه‌ها ذخیره شده‌اند، ترابری در حال برقراری یا برقراری دوباره است
زنده connected ترابری برپاست و رویدادها را دریافت می‌کند
خطای اتصال error ذخیره شده اما ناموفق است؛ خطای خودِ ارائه‌دهنده هم در کنارش نمایش داده می‌شود

اتصال دوباره با عقب‌نشینی نمایی و jitter انجام می‌شود، با سقف ۳۰ ثانیه. چرخش socket که خود ارائه‌دهنده آغاز کند بی‌درنگ دوباره وصل می‌شود، بدون تشدید عقب‌نشینی. اعتبارنامهٔ ردشده (invalid_auth، not_authed، token_revoked، account_inactive، token_expired، invalid_app_id) یا مجوز غایب پایانی است: پل تا رسیدن اعتبارنامه‌های تازه دیگر تلاش نمی‌کند.

پل بر پایهٔ پرمایه‌ترین سطح نوشته شده است و هر بار یک قابلیت را تنزل می‌دهد.

قابلیت Slack اثر در صورت نبود
streaming بله کل پاسخ یک‌بار، در پایان، فرستاده می‌شود
streamingRequiresThread بله مقصد پاسخی که لنگر رشته ندارد، پاسخ‌ها را کامل می‌فرستد
ephemeralMessages بله پاسخ یک دستور اسلش که دستگیرهٔ پاسخ قابل‌استفاده‌ای ندارد دور ریخته می‌شود (ردها همیشه درون رشته فرستاده می‌شوند)
threadStatus بله بدون خط گذرای «is thinking…»
threadTitle بله رشتهٔ گفتگو عنوان پیش‌فرضش را نگه می‌دارد
slashCommands بله بدون سطح /cc
taskCards بله فقط متن — بدون کارتی بالای پاسخ و بدون پیوند «View in Control Center»
maxMessageLength ۳۹٬۰۰۰ پاسخ‌های بلندتر با اشاره‌ای به Control Center بریده می‌شوند
maxStreamChunkLength ۳٬۸۰۰ افزودن‌ها روی مرز پاراگراف، خط یا فاصله شکسته می‌شوند

اعلام استریم، وعدهٔ استریم نیست: استریم Slack به قابلیت Agents & AI Apps روی یک طرح پولی نیاز دارد. ردی که هنگام فراخوانی رخ دهد (streaming_not_supported، feature_not_enabled، paid_only، …) در تمام عمر اتصال به یاد می‌ماند و به‌صورت streamingAvailable: false آشکار می‌شود. کارت‌های وظیفهٔ Slack سوار همان فراخوانی‌اند، پس Slackی که حالت نمایش کارت را رد کند استریمش را نگه می‌دارد و فقط کارت را از دست می‌دهد، یک‌بار، در تمام عمر اتصال.

یک استریم همچنین باید خواننده‌ای را که برایش است نام ببرد. Slack برای باز کردن آن در یک کانال هم به کاربر گیرنده و هم به تیم او نیاز دارد (پیام مستقیم چنین نیست) و در غیر این صورت با missing_recipient_user_id / missing_recipient_team_id رد می‌کند — ردی در سطح هر فراخوانی، پس پل به تلاش ادامه می‌دهد و نوبت در این میان به‌شکل یک پاسخ کامل فرستاده می‌شود. گیرنده همان کسی است که پرسیده، برگرفته از پیام ورودی (تیم خودش، نه تیم برنامه، پس یک کانال Slack Connect درست حل می‌شود). برای نوبتی که کسی از گفتگو شروعش نکرده — کاری که در Control Center روی گفتگویی از قبل پل‌شده راه افتاده — گیرنده عضوی است که پیوندش پل را ساخته؛ اگر او از آن پس حساب گفتگویش را جدا کرده باشد، آن نوبت کامل فرستاده می‌شود نه استریم‌شده.

هر نوبت عامل یک کارت گروه‌بندی‌شده (task_display_mode: plan) با یک ردیف برای هر گام. هر ردیف یک task_update شامل id + title + status است، به‌علاوهٔ یک details یک‌باره وقتی اندیشه آماده می‌شود. details و output با شناسهٔ یکسان بدون جداکننده به هم می‌چسبند، پس details یک‌بار فرستاده می‌شوند و output هرگز استریم نمی‌شود. عنوان طرح همان درخواست است؛ پاسخ یک افزودن بعدی جداگانه است که یک تکهٔ markdown_text را حمل می‌کند.

بخش محتوا
عنوان طرح آنچه پرسیده شده
ردیف راه‌اندازی Working on it…، سپس Cloning …، سپس Starting the agent… — یک ردیف، با عنوان جایگزین‌شده
ردیف اندیشه Thinking…، وقتی عامل شروع به استدلال می‌کند اضافه می‌شود؛ اندیشه همان details این ردیف است که یک‌بار و هنگام پایان استدلال فرستاده می‌شود
ردیف‌های ابزار یک ردیف برای هر ابزار (Bash which swift)، با شناسهٔ یکتا تا کنار هم بنشینند
وضعیت تا وقتی آن ردیف اجرا می‌شود در جریان؛ با شروع ردیف بعدی یا پایان نوبت کامل؛ و خطا برای شکست، وقفه و سقف نوبت
فراخوان به اقدام View in Control Center به‌شکل ردیفی در انتها وقتی نوبت تمام می‌شود — تا وقتی کار در جریان است غایب، و وقتی سرور نشانی عمومی قابل‌دسترسی ندارد هم غایب

کارتی که هرگز چه چیزی را حمل نمی‌کند: خروجی ابزار، آرگومانی بیرون از همان فهرست مجاز، یا هر چیزی که از پایگاه داده خوانده شده باشد. متن استدلال فقط details ردیف Thinking… است (با سقف ۲۵۶ نویسه)، نه بدنهٔ پیام. کارتی که حرف تازه‌ای برای گفتن نداشته باشد دوباره فرستاده نمی‌شود. یک منشن استریم را بی‌درنگ باز می‌کند تا رشتهٔ Slack ساکت نماند؛ نوبتی که پس از آن هیچ متنی تولید نکرده باشد همان کارت را با یک یادداشت کوتاه تمام می‌کند، به‌جای فرستادن پیام دوم. نوبت بی‌واژه روی فضایی که هرگز استریمی باز نکرده (بدون کارت، یا استریمی که از قبل رد شده) باز هم یک پیام می‌فرستد که کارت تمام‌شده و یادداشت را حمل می‌کند.

کارت‌های استریم‌شده و فرستاده‌شده دو محمولهٔ متفاوت‌اند:

شکل ساختار متن
استریم‌شده plan_update به‌علاوهٔ تکه‌های task_update با کلید id رشتهٔ ساده، با سقف ۲۵۶ نویسه در هر تکه
فرستاده‌شده یک بلوک plan که task_cardهای با کلید task_id را در بر می‌گیرد متن غنی

مدیریت شکست:

وضعیت رفتار
ارائه‌دهنده کارت را در یک افزودن رد می‌کند همان افزودن بی‌درنگ و بدون کارت دوباره تلاش می‌شود؛ متن همچنان زنده می‌رسد و کارت‌ها در تمام عمر اتصال کنار گذاشته می‌شوند
ارائه‌دهنده متن را هم رد می‌کند استریم بسته می‌شود و پاسخ کامل فرستاده می‌شود
استریم پس از رسیدن بخشی از پاسخ می‌شکند استریم بسته می‌شود و هیچ‌چیز دوباره فرستاده نمی‌شود

برای اینکه چرا محموله این‌گونه تقسیم شده است، پل‌های گفتگو را ببینید.

راه‌اندازی، پیش از آنکه نوبتی وجود داشته باشد

بخش با عنوان “راه‌اندازی، پیش از آنکه نوبتی وجود داشته باشد”

کارت وقتی باز می‌شود که یک منشن پذیرفته شود، پیش از کلون و پیش از نخستین توکن؛ نوبتی که پس از آن می‌آید همان کارت و همان استریم را برمی‌گیرد. روایت پس از آن از SpaceProvisioningChanged روی باس رویداد دامنه می‌آید — همان پیشرفتی که بنر آماده‌سازی برنامهٔ رومیزی از ردیف فضا می‌خواند.

وضعیت آماده‌سازی روایت
منشن پذیرفته شد Working on it…
گام repo Cloning <repo>…
گام prCheckout Checking out the pull request in <repo>…
گام script Running the setup script for <repo>…
گام agent Setting up <agent>…
provisioning، بدون گام تا این لحظه Preparing the workspace…
ready Starting the agent…
استدلال عامل Thinking…
failed Workspace setup failed — details are in Control Center.
cancelled Workspace setup was stopped — details are in Control Center.

روایت راه‌اندازی به هر چهار شرط نیاز دارد:

شرط
ارائه‌دهنده کارت‌ها را نمایش دهد
استریم روی این اتصال در دسترس باشد
فضا یک درخواست گفتگوی در جریان داشته باشد
هیچ کارتی از قبل نوبتی را در آنجا گزارش نکند

درخواست تا وقتی نوبتی شروع شود یا راه‌اندازی شکست بخورد در جریان می‌ماند. رویداد ready بدون کارتی که از قبل باز باشد، یک فضای گرم است و بی‌صدا رها می‌شود، و راه‌اندازی‌ای که کسی در گفتگو منتظرش نیست — گفتگویی که در برنامه باز شده، یا گفتگویی رهاشده که هنگام راه‌اندازی از سر گرفته می‌شود — هیچ کارتی تولید نمی‌کند.

محصولات گفتگو در یک پیوند فقط http(s) را می‌پذیرند و نه چیز دیگری، پس یک فراخوان به اقدام نمی‌تواند مستقیماً طرح برنامهٔ رومیزی را نام ببرد.

ویژگی مقدار
مسیر GET /open/workspaces/<workspaceId>/(spaces|tickets)/<id>
منشأ برگرفته از نشانی عمومی سرور (ws → http، wss → https)؛ loopback حفظ می‌شود
پاسخ یک صفحهٔ HTML کوچک no-store که به control-center://workspaces/<workspaceId>/(spaces|tickets)/<id> می‌رود و یک دکمهٔ دستی نشان می‌دهد
اعتبارسنجی شناسه‌ها باید با [A-Za-z0-9_.-]{1,128} بخوانند؛ هر چیز دیگری 404 است
دسترسی عمومی و بی‌اثر — هیچ پایگاه داده‌ای نمی‌خواند، پس اوراکل وجود نیست؛ برنامه‌ای که باز می‌کند خودش مجوزدهی را انجام می‌دهد
فیلد حد یادداشت‌ها
appName ۱–۳۵ نویسه به‌طور پیش‌فرض Control Center · <workspace name>
botDisplayName ۱–۸۰ نویسه به‌طور پیش‌فرض control-center
description ≤ ۱۴۰ نویسه
agentDescription ≤ ۳۰۰ نویسه بالای یک پیام مستقیم با ربات نمایش داده می‌شود
command ≤ ۳۲ نویسه بهنجار می‌شود: اسلش‌های ابتدایی حذف، به حروف کوچک تبدیل، [^a-z0-9_-] پاک و در صورت خالی بودن به cc برمی‌گردد
agentEnabled — اینکه تجربهٔ پیام مستقیم/عامل عرضه می‌شود یا نه

کادر خالی یعنی «دست به آن نزن»، نه «پاکش کن». محدودیت‌ها از آنِ Slack است که تنگ‌ترین میان محصولات مدل‌سازی‌شده است.

ویژگی مقدار
طول ۶ نویسه
الفبا 23456789ABCDEFGHJKLMNPQRSTVWXYZ (بدون 0/O، 1/I، U)
عمر ۱۵ دقیقه
استفاده یک‌بار
ذخیره‌سازی در حافظه — راه‌اندازی دوبارهٔ سرور کدهای باقی‌مانده را باطل می‌کند
دامنه یک فضای کاری و یک ارائه‌دهنده؛ ضرب یک کد تازه، کد پیشین عضو را باطل می‌کند

نقد کد بدون توجه به بزرگی و کوچکی حروف تطبیق داده می‌شود. کدهای ناشناخته، منقضی، متعلق به فضای کاری دیگر و متعلق به ارائه‌دهندهٔ اشتباه، همگی به‌عمد یکسان شکست می‌خورند.

روش مقدار سیمی چگونه
کد code عضو /cc link <code> را نقد کرد
ایمیل email ایمیل تأییدشدهٔ ارائه‌دهنده با کاربری که از قبل عضو فضای کاری است تطبیق داده شد

همه محدود به فضای کاری‌اند. سرور بی‌حالت است، پس هر فراخوانی workspace_id خودش را در آرگومان‌ها حمل می‌کند؛ دیسپچر عملیاتی محدود به فضای کاری را که آن را جا انداخته باشد، پیش از باز شدن هر پایگاه داده‌ای رد می‌کند. اعتبارنامه‌ها فقط به داخل می‌روند — خواندن‌های وضعیت هرگز آن‌ها را برنمی‌گردانند.

عملیات نوع کمترین نقش کلاس‌های اقدام
chat.providers خواندن guest —
chat.status خواندن guest —
chat.connect تغییر admin secretAccess، networkEgress
chat.disconnect مخرب admin secretAccess
chat.listUserLinks خواندن guest —
chat.beginUserLink تغییر member —
chat.unlinkUser تغییر member برای خودتان، admin برای هر کس دیگر —
chat.createApp تغییر admin secretAccess، networkEgress
chat.setupLink خواندن admin —
chat.botProfile خواندن admin networkEgress
chat.updateBotProfile تغییر admin networkEgress

عملیات خواندن کف guest را از نوعشان به ارث می‌برند؛ تغییرهای بدون کف صریح به member نیاز دارند.

chat.setupLink یک URL ساخت برنامهٔ ارائه‌دهنده را از نمایهٔ ربات ترکیب می‌کند. هیچ کلاس اقدامی اعلام نمی‌کند، چون هیچ رازی نمی‌خواند و به جایی وصل نمی‌شود — تنها فراخوانی را مرورگر خودِ کاربر انجام می‌دهد.

یک پرس‌وجوی واکنشی این سطح را کامل می‌کند:

پرس‌وجو نوع منتشر می‌کند
chat.watchUserLinks تماشا فهرست اعضا، که با ساخته یا حذف شدن هر پیوند دوباره فرستاده می‌شود

وجود دارد چون پیوند زدن در سمت دیگر رخ می‌دهد: عضو کد یک‌بارمصرف را در ربات می‌نویسد، پس هیچ پاسخی از کلاینت نمی‌تواند جواب را برگرداند. هم فهرست اعضای تنظیمات و هم دیالوگ بازِ «پیوند حساب من» آن را دنبال می‌کنند و دیالوگ همان لحظه‌ای که پیوند خودِ عضو می‌نشیند به یک تأییدیه سوئیچ می‌کند.

chat.beginUserLink همیشه کدی برای هویت خودِ فراخوان می‌ضربد. chat.updateBotProfile تنها وقتی یک remaining_step برمی‌گرداند که گامی باقی مانده باشد (معمولاً یک نصب دوباره)؛ نبودنش یعنی ویرایش اعمال شده است.

chat.providers برای هر ارائه‌دهندهٔ عرضه‌شده یک ورودی برمی‌گرداند — توصیف‌گر به‌علاوهٔ وضعیت اتصال، وقتی وجود داشته باشد. هر چیزی که رابط تنظیمات رندر می‌کند از همان محموله می‌آید و همین است که افزودن یک ارائه‌دهنده را به تغییری تنها در سمت سرور تبدیل می‌کند.

چه چیزی کجا
اعتبارنامه‌های اتصال <dataDir>/<workspaceId>/chat_credentials/<provider>.json
راه‌اندازی هدایت‌شدهٔ نیمه‌تمام <dataDir>/<workspaceId>/chat_credentials/<provider>_setup.json
فایل‌های قدیمی Slack <dataDir>/<workspaceId>/slack_credentials.json و slack_app_setup.json، که یک‌بار خوانده و در جای خود مهاجرت داده می‌شوند

اعتبارنامه‌ها کنار پایگاه دادهٔ فضای کاری زندگی می‌کنند، نه درون آن: حذف یک فضای کاری توکن‌های گفتگویش را با خود می‌برد و workspace.export یا یک پشتیبان، workspace.db را کپی می‌کند — پس فضای کاری‌ای که به کس دیگری سپرده می‌شود هیچ توکن ربات زنده‌ای با خود نمی‌برد. نوشتن‌ها اتمی‌اند (فایل موقت به‌علاوهٔ تغییر نام) و به فقط-مالک محدود می‌شوند.

هر دو در پایگاه دادهٔ فضای کاری زندگی می‌کنند که یک خط پایهٔ v1 فشرده‌شده دارد — پس خواندن میان‌فضایی کامپایل نمی‌شود.

chat_space_links — یک گفتگوی بیرونی ↔ یک فضای Control Center:

ستون یادداشت‌ها
id UUID v4
workspace_id دامنهٔ فضای کاری
provider ChatProvider.wire
external_team_id تیم Slack T…، برای ارائه‌دهندگانی که این مفهوم را ندارند خالی
external_channel_id کانال Slack C…، گروه G…، پیام مستقیم D…
external_thread_id لنگر رشتهٔ Slack، یا null وقتی کل گفتگو لنگر است (پیام‌های مستقیم ربات)
cc_space_id REFERENCES spaces(id) ON DELETE CASCADE
created_by_user_id، created_at، last_activity_at

یکتا روی (workspace_id, provider, external_channel_id, external_thread_id)، با یک ایندکس جزئی که همان را برای شناسه‌های رشتهٔ null اعمال می‌کند (SQLite مقدارهای NULL را متمایز می‌شمارد).

chat_user_links — یک عضو بیرونی ↔ یک کاربر Control Center:

ستون یادداشت‌ها
id UUID v4
workspace_id دامنهٔ فضای کاری
provider ChatProvider.wire
external_team_id، external_user_id عضو Slack U…
user_id کاربر Control Center (سراسری، پس بدون کلید خارجی)
method code یا email
linked_at

یکتا روی (workspace_id, provider, external_team_id, external_user_id) و روی (workspace_id, provider, user_id) — انتساب تک‌مقداری در هر دو جهت، در حالی که یک نفر می‌تواند روی چند ارائه‌دهنده پیوند شده باشد.

پیوند تشخیص هویت است، نه اعطای دسترسی: عضویت در هر رویداد ورودی دوباره بررسی می‌شود، پس پیوندی که به عضوی تعلق دارد که از آن پس حذف شده، به یک رد می‌انجامد.

یک فضای پل‌شده با SpaceKind ارائه‌دهنده (slack) ساخته می‌شود. مثل یک فضای معمولی رو به انسان رفتار می‌کند — مثل topic اطلاع‌رسانی و بخش‌بندی می‌شود — و isExternalChat همان بررسی‌ای است که هر رفتار (آینه‌سازی، نشان‌گذاری، نگه‌داشت) از آن می‌گذرد.

هر پیامی که پل وارد می‌کند یک مهر metadata['chat'] با خود دارد:

{
"chat": {
"provider": "slack",
"teamId": "T024BE7LD",
"channelId": "C0G9QF9GW",
"threadId": "1700000000.000100",
"messageId": "1700000000.000200",
"userId": "U024BE7LH",
"userLabel": "sam"
}
}

این مهر همچنین نگهبان پژواک است: آینهٔ خروجی از هر پیامی که آن را داشته باشد می‌گذرد و همین است که نمی‌گذارد پیام گفتگوی ورودی بی‌درنگ دوباره به همان‌جا فرستاده شود.

رفتار جزئیات
آنچه به بیرون رله می‌شود فقط متن عامل، به‌علاوهٔ خط وضعیت کارت وظیفه. متن استدلال و خروجی ابزار در Control Center می‌مانند
آهنگ استریم در طول اجرای یک نوبت به یک تخلیه در ثانیه محدود می‌شود؛ کارت و متنی که توضیح می‌دهد در همان فراخوانی سفر می‌کنند
پیام‌های انسانی نوشته‌شده در Control Center به رشتهٔ پیوندشده آینه می‌شوند، با نام نمایشی نویسنده در آغاز
نوبت‌های خالی به‌شکل یک یادداشت کوتاه گزارش می‌شوند (اجرا شکست خورده، متوقف شده یا در سقف نوبتش ایستاده) نه سکوت
حذف تکراری با شناسهٔ رویداد خودِ ارائه‌دهنده کلید می‌خورد؛ ۵۱۲ مورد آخر به یاد می‌مانند
عامل درِ ورودی یک گفتگوی پل‌شدهٔ تازه، عامل CEO فضای کاری را بیدار می‌کند، وگرنه نخستین عامل آن، وگرنه هیچ‌کس
نام‌گذاری فضا #channel · <request> برای رشتهٔ یک کانال Slack، Slack DM · <request> برای یک پیام مستقیم، با سقف ۴۸ نویسه برای عنوان‌ها
انزوای شکست یک رویداد خراب هرگز پل را از کار نمی‌اندازد؛ اتصال به خدمت‌رسانی به هر گفتگوی دیگر ادامه می‌دهد