Messages and delivery

جریان‌سازی و قطعه‌بندی

OpenClaw دو لایهٔ جداگانهٔ پخش جریانی دارد:

  • پخش جریانی بلوک (کانال‌ها): هنگام نوشتن دستیار، بلوک‌های کامل‌شده را منتشر می‌کند. این‌ها پیام‌های عادی کانال هستند (نه دلتاهای توکن).
  • پخش جریانی پیش‌نمایش (Telegram/Discord/Slack): هنگام تولید، یک پیام پیش‌نمایش موقت را به‌روزرسانی می‌کند.

امروز پخش جریانی واقعیِ دلتای توکن به پیام‌های کانال وجود ندارد. پخش جریانی پیش‌نمایش مبتنی بر پیام است (ارسال + ویرایش‌ها/افزودن‌ها).

پخش جریانی بلوک (پیام‌های کانال)

پخش جریانی بلوک، خروجی دستیار را هنگام آماده‌شدن در قطعه‌های درشت ارسال می‌کند.

Code
Model output  └─ text_delta/events       ├─ (blockStreamingBreak=text_end)       │    └─ chunker emits blocks as buffer grows       └─ (blockStreamingBreak=message_end)            └─ chunker flushes at message_end                   └─ channel send (block replies)

راهنما:

  • text_delta/events: رویدادهای جریان مدل (ممکن است برای مدل‌های غیرجریانی پراکنده باشند).
  • chunker: EmbeddedBlockChunker که کران‌های حداقل/حداکثر + ترجیح شکست را اعمال می‌کند.
  • channel send: پیام‌های خروجی واقعی (پاسخ‌های بلوکی).

کنترل‌ها:

  • agents.defaults.blockStreamingDefault: "on"/"off" (پیش‌فرض خاموش).
  • بازنویسی‌های کانال: *.blockStreaming (و گونه‌های هر حساب) برای اجبار "on"/"off" برای هر کانال.
  • agents.defaults.blockStreamingBreak: "text_end" یا "message_end".
  • agents.defaults.blockStreamingChunk: { minChars, maxChars, breakPreference? }.
  • agents.defaults.blockStreamingCoalesce: { minChars?, maxChars?, idleMs? } (ادغام بلوک‌های جریانی پیش از ارسال).
  • سقف سخت کانال: *.textChunkLimit (مثلاً channels.whatsapp.textChunkLimit).
  • حالت قطعه‌بندی کانال: *.chunkMode (پیش‌فرض length، و newline پیش از قطعه‌بندی طولی، روی خطوط خالی (مرزهای پاراگراف) تقسیم می‌کند).
  • سقف نرم Discord: channels.discord.maxLinesPerMessage (پیش‌فرض 17) پاسخ‌های بلند را تقسیم می‌کند تا از بریده‌شدن UI جلوگیری شود.

معنای مرزها:

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

اگر متن بافرشده از maxChars بیشتر باشد، message_end همچنان از قطعه‌ساز استفاده می‌کند، بنابراین می‌تواند در پایان چند قطعه منتشر کند.

تحویل رسانه با پخش جریانی بلوک

رسانهٔ جریانی باید از فیلدهای ساخت‌یافتهٔ payload مانند mediaUrl یا mediaUrls استفاده کند؛ متن جریانی به‌عنوان فرمان پیوست تحلیل نمی‌شود. وقتی پخش جریانی بلوک رسانه را زود ارسال می‌کند، OpenClaw آن تحویل را برای آن نوبت به خاطر می‌سپارد. اگر payload نهایی دستیار همان URL رسانه را تکرار کند، تحویل نهایی به‌جای ارسال دوبارهٔ پیوست، رسانهٔ تکراری را حذف می‌کند.

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

الگوریتم قطعه‌بندی (کران‌های پایین/بالا)

قطعه‌بندی بلوک توسط EmbeddedBlockChunker پیاده‌سازی شده است:

  • کران پایین: تا وقتی بافر >= minChars نشده منتشر نکن (مگر با اجبار).
  • کران بالا: تقسیم پیش از maxChars را ترجیح بده؛ اگر اجباری بود، در maxChars تقسیم کن.
  • ترجیح شکست: paragraphnewlinesentencewhitespace → شکست سخت.
  • حصارهای کد: هرگز داخل حصارها تقسیم نکن؛ هنگام اجبار در maxChars، حصار را ببند + دوباره باز کن تا Markdown معتبر بماند.

maxChars به textChunkLimit کانال محدود می‌شود، بنابراین نمی‌توانید از سقف‌های هر کانال فراتر بروید.

هم‌آمیزی (ادغام بلوک‌های جریانی)

وقتی پخش جریانی بلوک فعال باشد، OpenClaw می‌تواند قطعه‌های بلوکی متوالی را ادغام کند و سپس آن‌ها را ارسال کند. این کار «هرزپیام تک‌خطی» را کاهش می‌دهد و همچنان خروجی تدریجی فراهم می‌کند.

  • هم‌آمیزی پیش از تخلیه، منتظر وقفه‌های بیکاری (idleMs) می‌ماند.
  • بافرها با maxChars محدود می‌شوند و اگر از آن فراتر بروند تخلیه خواهند شد.
  • minChars از ارسال قطعه‌های بسیار کوچک جلوگیری می‌کند تا متن کافی انباشته شود (تخلیهٔ نهایی همیشه متن باقی‌مانده را ارسال می‌کند).
  • جداکننده از blockStreamingChunk.breakPreference مشتق می‌شود (paragraph\n\n، newline\n، sentence → فاصله).
  • بازنویسی‌های کانال از طریق *.blockStreamingCoalesce در دسترس هستند (از جمله پیکربندی‌های هر حساب).
  • مقدار پیش‌فرض minChars برای هم‌آمیزی، مگر در صورت بازنویسی، برای Signal/Slack/Discord به 1500 افزایش می‌یابد.

ریتم انسانی بین بلوک‌ها

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

  • پیکربندی: agents.defaults.humanDelay (بازنویسی برای هر عامل از طریق agents.list[].humanDelay).
  • حالت‌ها: off (پیش‌فرض)، natural (800-2500ms)، custom (minMs/maxMs).
  • فقط روی پاسخ‌های بلوکی اعمال می‌شود، نه پاسخ‌های نهایی یا خلاصه‌های ابزار.

«قطعه‌ها را پخش کن یا همه‌چیز را»

این به موارد زیر نگاشت می‌شود:

  • پخش قطعه‌ها: blockStreamingDefault: "on" + blockStreamingBreak: "text_end" (هم‌زمان با پیشرفت منتشر کن). کانال‌های غیر از Telegram همچنین به *.blockStreaming: true نیاز دارند.
  • پخش همه‌چیز در پایان: blockStreamingBreak: "message_end" (یک‌بار تخلیه کن، اگر بسیار طولانی باشد احتمالاً چند قطعه).
  • بدون پخش جریانی بلوک: blockStreamingDefault: "off" (فقط پاسخ نهایی).

نکتهٔ کانال: پخش جریانی بلوک خاموش است مگر اینکه *.blockStreaming صراحتاً روی true تنظیم شود. کانال‌ها می‌توانند بدون پاسخ‌های بلوکی، یک پیش‌نمایش زنده را پخش کنند (channels.<channel>.streaming).

یادآوری محل پیکربندی: پیش‌فرض‌های blockStreaming* زیر agents.defaults قرار دارند، نه پیکربندی ریشه.

حالت‌های پخش جریانی پیش‌نمایش

کلید کانونی: channels.<channel>.streaming

حالت‌ها:

  • off: پخش جریانی پیش‌نمایش را غیرفعال می‌کند.
  • partial: یک پیش‌نمایش واحد که با آخرین متن جایگزین می‌شود.
  • block: پیش‌نمایش در گام‌های قطعه‌بندی‌شده/افزوده‌شده به‌روزرسانی می‌شود.
  • progress: پیش‌نمایش پیشرفت/وضعیت هنگام تولید، پاسخ نهایی در پایان.

streaming.mode: "block" برای کانال‌های قابل ویرایش مانند Discord و Telegram یک حالت پخش جریانی پیش‌نمایش است. این حالت تحویل بلوکی کانال را در آنجا فعال نمی‌کند. وقتی پاسخ‌های بلوکی عادی می‌خواهید، از streaming.block.enabled یا کلید قدیمی کانال blockStreaming استفاده کنید. Microsoft Teams استثناست: ترابری بلوک پیش‌نمایش پیش‌نویس ندارد، بنابراین streaming.mode: "block" به‌جای پخش جریانی بومی جزئی/پیشرفت، به تحویل بلوکی Teams نگاشت می‌شود.

نگاشت کانال

کانال off partial block progress
Telegram پیش‌نویس پیشرفت قابل ویرایش
Discord پیش‌نویس پیشرفت قابل ویرایش
Slack
Mattermost
MS Teams جریان پیشرفت بومی

فقط Slack:

  • channels.slack.streaming.nativeTransport فراخوانی‌های API پخش جریانی بومی Slack را وقتی channels.slack.streaming.mode="partial" باشد تغییر وضعیت می‌دهد (پیش‌فرض: true).
  • پخش جریانی بومی Slack و وضعیت رشتهٔ دستیار Slack به هدف رشتهٔ پاسخ نیاز دارند. DMهای سطح بالا آن پیش‌نمایش رشته‌مانند را نشان نمی‌دهند، اما همچنان می‌توانند از پست‌ها و ویرایش‌های پیش‌نمایش پیش‌نویس Slack استفاده کنند.

مهاجرت کلید قدیمی:

  • Telegram: مقادیر قدیمی streamMode و مقادیر اسکالر/بولی streaming شناسایی می‌شوند و مسیرهای سازگاری doctor/پیکربندی آن‌ها را به streaming.mode مهاجرت می‌کنند.
  • Discord: streamMode + بولی streaming همچنان aliasهای زمان اجرا برای enum streaming باقی می‌مانند؛ برای بازنویسی پیکربندی پایدارشده، openclaw doctor --fix را اجرا کنید.
  • Slack: streamMode همچنان alias زمان اجرا برای streaming.mode باقی می‌ماند؛ بولی streaming همچنان alias زمان اجرا برای streaming.mode به‌علاوهٔ streaming.nativeTransport باقی می‌ماند؛ nativeStreaming قدیمی همچنان alias زمان اجرا برای streaming.nativeTransport باقی می‌ماند. برای بازنویسی پیکربندی پایدارشده، openclaw doctor --fix را اجرا کنید.

رفتار زمان اجرا

Telegram:

  • از به‌روزرسانی‌های پیش‌نمایش sendMessage + editMessageText در DMها و گروه‌ها/موضوع‌ها استفاده می‌کند.
  • پیش‌نمایش‌های کوتاه اولیه همچنان برای تجربهٔ اعلان پوش به‌صورت debounce مدیریت می‌شوند، اما Telegram اکنون آن‌ها را پس از تأخیری محدود محقق می‌کند تا اجراهای فعال از نظر بصری ساکت نمانند.
  • متن نهایی، پیش‌نمایش فعال را درجا ویرایش می‌کند؛ نهایی‌های طولانی همان پیام را برای قطعهٔ اول دوباره استفاده می‌کنند و فقط قطعه‌های باقی‌مانده را ارسال می‌کنند.
  • حالت block پیش‌نمایش را در streaming.preview.chunk.maxChars به یک پیام جدید می‌چرخاند (پیش‌فرض 800، محدود به سقف ویرایش 4096 کاراکتری Telegram)؛ حالت‌های دیگر یک پیش‌نمایش را تا 4096 کاراکتر رشد می‌دهند.
  • حالت progress پیشرفت ابزار را در یک پیش‌نویس وضعیت قابل ویرایش نگه می‌دارد، وقتی پخش جریانی پاسخ فعال است اما هنوز خط ابزاری در دسترس نیست برچسب وضعیت را محقق می‌کند، آن پیش‌نویس را در پایان پاک می‌کند، و پاسخ نهایی را از طریق تحویل عادی ارسال می‌کند.
  • اگر ویرایش نهایی پیش از تأیید متن کامل‌شده شکست بخورد، OpenClaw از تحویل نهایی عادی استفاده می‌کند و پیش‌نمایش کهنه را پاک‌سازی می‌کند.
  • وقتی پخش جریانی بلوک Telegram صراحتاً فعال شده باشد، پخش جریانی پیش‌نمایش رد می‌شود (برای جلوگیری از پخش جریانی دوگانه).
  • /reasoning stream می‌تواند استدلال را در پیش‌نمایشی گذرا بنویسد که پس از تحویل نهایی حذف می‌شود.

Discord:

  • از ارسال + ویرایش پیام‌های پیش‌نمایش استفاده می‌کند.
  • حالت block از قطعه‌بندی پیش‌نویس (draftChunk) استفاده می‌کند.
  • وقتی پخش جریانی بلوک Discord صراحتاً فعال شده باشد، پخش جریانی پیش‌نمایش رد می‌شود.
  • رسانهٔ نهایی، خطا، و payloadهای پاسخ صریح، پیش‌نمایش‌های در انتظار را بدون تخلیهٔ پیش‌نویس جدید لغو می‌کنند و سپس از تحویل عادی استفاده می‌کنند.

Slack:

  • partial می‌تواند در صورت دسترس‌بودن از پخش جریانی بومی Slack (chat.startStream/append/stop) استفاده کند.
  • block از پیش‌نمایش‌های پیش‌نویس به سبک افزودن استفاده می‌کند.
  • progress از متن پیش‌نمایش وضعیت استفاده می‌کند، سپس پاسخ نهایی.
  • DMهای سطح بالا بدون رشتهٔ پاسخ، به‌جای پخش جریانی بومی Slack از پست‌ها و ویرایش‌های پیش‌نمایش پیش‌نویس استفاده می‌کنند.
  • پخش جریانی بومی و پیش‌نمایش پیش‌نویس، پاسخ‌های بلوکی را برای آن نوبت سرکوب می‌کنند، بنابراین یک پاسخ Slack فقط از یک مسیر تحویل پخش می‌شود.
  • payloadهای رسانه/خطای نهایی و نهایی‌های پیشرفت، پیام‌های پیش‌نویس دورریختنی ایجاد نمی‌کنند؛ فقط نهایی‌های متن/بلوک که می‌توانند پیش‌نمایش را ویرایش کنند، متن پیش‌نویس در انتظار را تخلیه می‌کنند.

Mattermost:

  • فکر کردن، فعالیت ابزار، و متن پاسخ جزئی را در یک پست پیش‌نمایش پیش‌نویس واحد پخش می‌کند که وقتی ارسال پاسخ نهایی امن باشد، درجا نهایی می‌شود.
  • اگر پست پیش‌نمایش حذف شده باشد یا در زمان نهایی‌سازی به هر شکل دیگری در دسترس نباشد، به ارسال یک پست نهایی تازه برمی‌گردد.
  • payloadهای رسانه/خطای نهایی، به‌جای تخلیهٔ یک پست پیش‌نمایش موقت، به‌روزرسانی‌های پیش‌نمایش در انتظار را پیش از تحویل عادی لغو می‌کنند.

Matrix:

  • وقتی متن نهایی بتواند رویداد پیش‌نمایش را دوباره استفاده کند، پیش‌نمایش‌های پیش‌نویس درجا نهایی می‌شوند.
  • نهایی‌های فقط‌رسانه، خطا، و عدم‌تطابق هدف پاسخ، پیش از تحویل عادی به‌روزرسانی‌های پیش‌نمایش در انتظار را لغو می‌کنند؛ پیش‌نمایش کهنه‌ای که از قبل دیده می‌شود، redacted می‌شود.

به‌روزرسانی‌های پیش‌نمایش پیشرفت ابزار

پخش جریانی پیش‌نمایش همچنین می‌تواند شامل به‌روزرسانی‌های پیشرفت ابزار باشد - خط‌های وضعیت کوتاهی مانند «جست‌وجو در وب»، «خواندن فایل»، یا «فراخوانی ابزار» - که هنگام اجرای ابزارها، پیش از پاسخ نهایی، در همان پیام پیش‌نمایش ظاهر می‌شوند. در حالت app-server Codex، پیام‌های مقدمه/توضیح Codex از همین مسیر پیش‌نمایش استفاده می‌کنند، بنابراین یادداشت‌های پیشرفت کوتاه مانند «دارم بررسی می‌کنم...» می‌توانند بدون تبدیل‌شدن به بخشی از پاسخ نهایی، در پیش‌نویس قابل ویرایش پخش شوند. این کار نوبت‌های چندمرحله‌ای ابزار را از نظر بصری زنده نگه می‌دارد، نه اینکه بین نخستین پیش‌نمایش فکر کردن و پاسخ نهایی ساکت بمانند.

ابزارهای طولانی‌اجرا ممکن است پیش از بازگشت، پیشرفت نوع‌دار منتشر کنند. برای مثال، web_fetch هنگام شروع یک تایمر پنج‌ثانیه‌ای را مسلح می‌کند: اگر واکشی همچنان در انتظار باشد، پیش‌نمایش می‌تواند Fetching page content... را نشان دهد؛ اگر واکشی پیش از آن تمام یا لغو شود، هیچ خط پیشرفتی منتشر نمی‌شود. نتیجهٔ نهایی بعدی ابزار همچنان به‌صورت عادی به مدل تحویل داده می‌شود.

سطوح پشتیبانی‌شده:

  • Discord، Slack، Telegram و Matrix به‌طور پیش‌فرض، زمانی که جریان‌سازی پیش‌نمایش فعال است، به‌روزرسانی‌های پیشرفت ابزار و مقدمه‌های Codex را در ویرایش پیش‌نمایش زنده جاری می‌کنند. Microsoft Teams در چت‌های شخصی از جریان پیشرفت بومی خود استفاده می‌کند.
  • Telegram از زمان v2026.4.22 با به‌روزرسانی‌های پیش‌نمایش پیشرفت ابزار فعال منتشر شده است؛ فعال نگه‌داشتن آن‌ها رفتار منتشرشده را حفظ می‌کند.
  • Mattermost از قبل فعالیت ابزار را در تنها پست پیش‌نمایش پیش‌نویس خود ادغام می‌کند (بالا را ببینید).
  • ویرایش‌های پیشرفت ابزار از حالت جریان‌سازی پیش‌نمایش فعال پیروی می‌کنند؛ وقتی جریان‌سازی پیش‌نمایش off باشد یا وقتی جریان‌سازی بلوکی پیام را در اختیار گرفته باشد، از آن‌ها صرف‌نظر می‌شود. در Telegram، streaming.mode: "off" فقط نهایی است: گفت‌وگوی عمومی پیشرفت نیز به‌جای تحویل به‌صورت پیام‌های وضعیت مستقل، سرکوب می‌شود، درحالی‌که درخواست‌های تأیید، payloadهای رسانه‌ای و خطاها همچنان به‌طور معمول مسیریابی می‌شوند.
  • برای حفظ جریان‌سازی پیش‌نمایش اما پنهان کردن خطوط پیشرفت ابزار، streaming.preview.toolProgress را برای آن کانال روی false بگذارید. برای قابل‌مشاهده نگه‌داشتن خطوط پیشرفت ابزار درحالی‌که متن دستور/اجرا پنهان می‌شود، streaming.preview.commandText را روی "status" یا streaming.progress.commandText را روی "status" بگذارید؛ مقدار پیش‌فرض "raw" است تا رفتار منتشرشده حفظ شود. این سیاست میان کانال‌های پیش‌نویس/پیشرفت که از رندرکننده پیشرفت فشرده OpenClaw استفاده می‌کنند مشترک است، از جمله Discord، Matrix، Microsoft Teams، Mattermost، پیش‌نمایش‌های پیش‌نویس Slack و Telegram. برای غیرفعال کردن کامل ویرایش‌های پیش‌نمایش، streaming.mode را روی off بگذارید.
  • پاسخ‌های نقل‌قول انتخاب‌شده Telegram یک استثنا هستند: وقتی replyToMode برابر "off" نباشد و متن نقل‌قول انتخاب‌شده وجود داشته باشد، OpenClaw جریان پیش‌نمایش پاسخ را برای آن نوبت رد می‌کند تا خطوط پیش‌نمایش پیشرفت ابزار نتوانند رندر شوند. پاسخ‌های پیام فعلی بدون متن نقل‌قول انتخاب‌شده همچنان جریان‌سازی پیش‌نمایش را حفظ می‌کنند. برای جزئیات، مستندات کانال Telegram را ببینید.

مسیر پیشرفت توضیحات

فراتر از پیشرفت ابزار، رندرکننده پیشرفت فشرده می‌تواند یک مسیر دیگر را در پیش‌نویس نمایش دهد:

  • streaming.progress.commentaryتوضیحات پیش از ابزار مدل (💬) را رندر می‌کند — روایت کوتاه «بررسی می‌کنم… سپس…» — که در پیش‌نویس پیشرفت با خطوط ابزار درهم‌گذاری می‌شود.
json
{  "channels": {    "discord": {      "streaming": { "mode": "progress", "progress": { "commentary": true } }    }  }}

خطوط پیشرفت را قابل‌مشاهده نگه دارید اما متن خام دستور/اجرا را پنهان کنید:

json
{  "channels": {    "telegram": {      "streaming": {        "mode": "partial",        "preview": {          "toolProgress": true,          "commandText": "status"        }      }    }  }}

از همین شکل زیر کلید کانال پیشرفت فشرده دیگری استفاده کنید، برای مثال channels.discord، channels.matrix، channels.msteams، channels.mattermost، یا پیش‌نمایش‌های پیش‌نویس Slack. برای حالت پیش‌نویس پیشرفت، همین سیاست را زیر streaming.progress قرار دهید:

json
{  "channels": {    "telegram": {      "streaming": {        "mode": "progress",        "progress": {          "toolProgress": true,          "commandText": "status"        }      }    }  }}

مرتبط

Was this useful?
On this page

On this page