Messages and delivery

پیام‌ها

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

جریان پیام (سطح بالا)

Inbound message
  -> routing/bindings -> session key
  -> queue (if a run is active)
  -> agent run (streaming + tools)
  -> outbound replies (channel limits + chunking)

تنظیمات کلیدی در پیکربندی قرار دارند:

  • messages.* برای پیشوندها، صف‌گذاری و رفتار گروه.
  • agents.defaults.* برای پیش‌فرض‌های استریمینگ بلوکی و قطعه‌بندی.
  • بازنویسی‌های کانال (channels.whatsapp.*، channels.telegram.* و غیره) برای سقف‌ها و کلیدهای استریمینگ.

برای طرح‌واره کامل، پیکربندی را ببینید.

حذف تکراری‌های ورودی

کانال‌ها می‌توانند پس از اتصال دوباره، همان پیام را دوباره تحویل دهند. OpenClaw یک کش کوتاه‌مدت را با کلید کانال/حساب/همتا/نشست/شناسه پیام نگه می‌دارد تا تحویل‌های تکراری اجرای عامل دیگری را فعال نکنند.

دیبانس ورودی

پیام‌های پیاپی و سریع از فرستنده یکسان می‌توانند از طریق messages.inbound در یک نوبت عامل تجمیع شوند. دیبانس برای هر کانال + مکالمه جداگانه اعمال می‌شود و از جدیدترین پیام برای رشته‌بندی/شناسه‌های پاسخ استفاده می‌کند.

پیکربندی (پیش‌فرض سراسری + بازنویسی‌های هر کانال):

{
  messages: {
    inbound: {
      debounceMs: 2000,
      byChannel: {
        whatsapp: 5000,
        slack: 1500,
        discord: 1500,
      },
    },
  },
}

نکته‌ها:

  • دیبانس فقط روی پیام‌های فقط متنی اعمال می‌شود؛ رسانه/پیوست‌ها بلافاصله تخلیه می‌شوند.
  • فرمان‌های کنترلی دیبانس را دور می‌زنند تا مستقل بمانند — به‌جز وقتی کانالی صریحا تجمیع DMهای هم‌فرستنده را فعال کند (برای مثال BlueBubbles coalesceSameSenderDms)، که در آن فرمان‌های DM در پنجره دیبانس منتظر می‌مانند تا بار split-send بتواند به همان نوبت عامل بپیوندد.

نشست‌ها و دستگاه‌ها

نشست‌ها متعلق به Gateway هستند، نه کلاینت‌ها.

  • گفتگوهای مستقیم در کلید نشست اصلی عامل ادغام می‌شوند.
  • گروه‌ها/کانال‌ها کلیدهای نشست خودشان را می‌گیرند.
  • ذخیره‌ساز نشست و رونوشت‌ها روی میزبان Gateway قرار دارند.

چندین دستگاه/کانال می‌توانند به یک نشست نگاشت شوند، اما تاریخچه به‌طور کامل به همه کلاینت‌ها همگام‌سازی نمی‌شود. توصیه: برای گفتگوهای طولانی از یک دستگاه اصلی استفاده کنید تا از واگرایی زمینه جلوگیری شود. Control UI و TUI همیشه رونوشت نشستِ پشتیبانی‌شده توسط Gateway را نشان می‌دهند، بنابراین منبع حقیقت هستند.

جزئیات: مدیریت نشست.

فراداده نتیجه ابزار

content نتیجه ابزار، نتیجه‌ای است که مدل می‌بیند. details نتیجه ابزار، فراداده زمان اجرا برای رندر UI، عیب‌یابی، تحویل رسانه و Pluginها است.

OpenClaw این مرز را صریح نگه می‌دارد:

  • toolResult.details پیش از بازپخش ارائه‌دهنده و ورودی Compaction حذف می‌شود.
  • رونوشت‌های نشست ذخیره‌شده فقط details محدود را نگه می‌دارند؛ فراداده بیش‌ازحد بزرگ با خلاصه‌ای فشرده که با persistedDetailsTruncated: true علامت‌گذاری شده جایگزین می‌شود.
  • Pluginها و ابزارها باید متنی را که مدل باید بخواند در content بگذارند، نه فقط در details.

بدنه‌های ورودی و زمینه تاریخچه

OpenClaw بدنه پرامپت را از بدنه فرمان جدا می‌کند:

  • BodyForAgent: متن اصلی روبه‌مدل برای پیام فعلی. Pluginهای کانال باید این بخش را روی متن فعلیِ دارای پرامپتِ فرستنده متمرکز نگه دارند.
  • Body: جایگزین قدیمی پرامپت. این ممکن است شامل پوشش‌های کانال و wrapperهای اختیاری تاریخچه باشد، اما کانال‌های فعلی نباید وقتی BodyForAgent در دسترس است به آن به‌عنوان ورودی اصلی مدل تکیه کنند.
  • CommandBody: متن خام کاربر برای تجزیه دستور/فرمان.
  • RawBody: نام مستعار قدیمی برای CommandBody (برای سازگاری نگه داشته شده است).

وقتی کانالی تاریخچه ارائه می‌دهد، از wrapper مشترک استفاده می‌کند:

  • [Chat messages since your last reply - for context]
  • [Current message - respond to this]

برای گفتگوهای غیرمستقیم (گروه‌ها/کانال‌ها/اتاق‌ها)، بدنه پیام فعلی با برچسب فرستنده پیشوند می‌گیرد (همان سبکی که برای ورودی‌های تاریخچه استفاده می‌شود). این کار پیام‌های بلادرنگ و صف‌گذاری‌شده/تاریخچه را در پرامپت عامل سازگار نگه می‌دارد.

بافرهای تاریخچه فقط معلق هستند: آن‌ها پیام‌های گروهی را شامل می‌شوند که اجرای نوبت را فعال نکرده‌اند (برای مثال، پیام‌های gated با mention) و پیام‌هایی را که از قبل در رونوشت نشست هستند حذف می‌کنند.

حذف directive فقط روی بخش پیام فعلی اعمال می‌شود تا تاریخچه دست‌نخورده بماند. کانال‌هایی که تاریخچه را wrap می‌کنند باید CommandBody (یا RawBody) را روی متن اصلی پیام تنظیم کنند و Body را به‌عنوان پرامپت ترکیبی نگه دارند. تاریخچه ساختاریافته، پاسخ، فورواردشده و فراداده کانال هنگام مونتاژ پرامپت به‌صورت بلوک‌های زمینه نامطمئن با نقش کاربر رندر می‌شوند. بافرهای تاریخچه از طریق messages.groupChat.historyLimit (پیش‌فرض سراسری) و بازنویسی‌های هر کانال مانند channels.slack.historyLimit یا channels.telegram.accounts.<id>.historyLimit قابل پیکربندی هستند (برای غیرفعال‌سازی، 0 تنظیم کنید).

صف‌گذاری و پیگیری‌ها

اگر یک اجرا از قبل فعال باشد، پیام‌های ورودی می‌توانند صف‌گذاری شوند، به اجرای فعلی هدایت شوند، یا برای یک نوبت پیگیری گردآوری شوند.

  • از طریق messages.queuemessages.queue.byChannel) پیکربندی کنید.
  • حالت پیش‌فرض steer است، با دیبانس پیگیری 500ms وقتی هدایت به تحویل پیگیری صف‌گذاری‌شده برمی‌گردد.
  • حالت‌ها: steer، followup، collect، steer-backlog، interrupt و حالت قدیمی یکی‌در‌هر‌بار queue.

جزئیات: صف فرمان و صف هدایت.

مالکیت اجرای کانال

Pluginهای کانال ممکن است پیش از ورود پیام به صف نشست، ترتیب را حفظ کنند، ورودی را دیبانس کنند و backpressure انتقال را اعمال کنند. آن‌ها نباید timeout جداگانه‌ای پیرامون خود نوبت عامل تحمیل کنند. وقتی پیام به یک نشست مسیردهی شد، کارهای طولانی‌مدت توسط چرخه عمر نشست، ابزار و زمان اجرا اداره می‌شوند تا همه کانال‌ها نوبت‌های کند را به‌شکل سازگار گزارش و بازیابی کنند.

استریمینگ، قطعه‌بندی و batch کردن

استریمینگ بلوکی پاسخ‌های جزئی را همان‌طور که مدل بلوک‌های متن تولید می‌کند ارسال می‌کند. قطعه‌بندی محدودیت‌های متن کانال را رعایت می‌کند و از شکستن کدهای fenced جلوگیری می‌کند.

تنظیمات کلیدی:

  • agents.defaults.blockStreamingDefault (on|off، پیش‌فرض خاموش)
  • agents.defaults.blockStreamingBreak (text_end|message_end)
  • agents.defaults.blockStreamingChunk (minChars|maxChars|breakPreference)
  • agents.defaults.blockStreamingCoalesce (batch کردن مبتنی بر بیکاری)
  • agents.defaults.humanDelay (مکث شبیه انسان بین پاسخ‌های بلوکی)
  • بازنویسی‌های کانال: *.blockStreaming و *.blockStreamingCoalesce (کانال‌های غیر از Telegram به *.blockStreaming: true صریح نیاز دارند)

جزئیات: استریمینگ + قطعه‌بندی.

نمایش‌پذیری استدلال و توکن‌ها

OpenClaw می‌تواند استدلال مدل را نمایش دهد یا پنهان کند:

  • /reasoning on|off|stream نمایش‌پذیری را کنترل می‌کند.
  • محتوای استدلال وقتی توسط مدل تولید می‌شود همچنان در مصرف توکن حساب می‌شود.
  • Telegram از استریم استدلال به یک حباب پیش‌نویس موقت پشتیبانی می‌کند که پس از تحویل نهایی حذف می‌شود؛ برای خروجی استدلال پایدار از /reasoning on استفاده کنید.

جزئیات: دستورهای تفکر + استدلال و مصرف توکن.

پیشوندها، رشته‌بندی و پاسخ‌ها

قالب‌بندی پیام خروجی در messages متمرکز شده است:

  • messages.responsePrefix، channels.<channel>.responsePrefix و channels.<channel>.accounts.<id>.responsePrefix (آبشار پیشوند خروجی)، به‌علاوه channels.whatsapp.messagePrefix (پیشوند ورودی WhatsApp)
  • رشته‌بندی پاسخ از طریق replyToMode و پیش‌فرض‌های هر کانال

جزئیات: پیکربندی و مستندات کانال.

پاسخ‌های بی‌صدا

توکن بی‌صدای دقیق NO_REPLY / no_reply یعنی «پاسخ قابل مشاهده برای کاربر تحویل نده». وقتی یک نوبت همچنین رسانه ابزار معلق داشته باشد، مانند صدای TTS تولیدشده، OpenClaw متن بی‌صدا را حذف می‌کند اما همچنان پیوست رسانه را تحویل می‌دهد. OpenClaw این رفتار را بر اساس نوع مکالمه تعیین می‌کند:

  • مکالمه‌های مستقیم به‌طور پیش‌فرض سکوت را مجاز نمی‌دانند و یک پاسخ بی‌صدای خالی را به جایگزین کوتاه قابل مشاهده بازنویسی می‌کنند.
  • گروه‌ها/کانال‌ها به‌طور پیش‌فرض سکوت را مجاز می‌دانند.
  • هماهنگ‌سازی داخلی به‌طور پیش‌فرض سکوت را مجاز می‌داند.

OpenClaw همچنین از پاسخ‌های بی‌صدا برای خرابی‌های runner داخلی استفاده می‌کند که پیش از هر پاسخ assistant در گفتگوهای غیرمستقیم رخ می‌دهند، تا گروه‌ها/کانال‌ها متن‌های کلیشه‌ای خطای Gateway را نبینند. گفتگوهای مستقیم به‌طور پیش‌فرض متن کوتاه خرابی را نشان می‌دهند؛ جزئیات خام runner فقط وقتی /verbose برابر on یا full باشد نشان داده می‌شوند.

پیش‌فرض‌ها زیر agents.defaults.silentReply و agents.defaults.silentReplyRewrite قرار دارند؛ surfaces.<id>.silentReply و surfaces.<id>.silentReplyRewrite می‌توانند آن‌ها را برای هر سطح بازنویسی کنند.

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

مرتبط