Messages and delivery
صف فرمانها
OpenClaw اجراهای پاسخ خودکار ورودی (در همه کانالها) را از طریق یک صف کوچک درونپردازهای بهصورت ترتیبی اجرا میکند تا از تداخل چند اجرای عامل جلوگیری شود و در عین حال، موازیسازی ایمن میان نشستها امکانپذیر باشد.
چرا
- اجراهای پاسخ خودکار ممکن است پرهزینه باشند (فراخوانیهای LLM) و وقتی چند پیام ورودی با فاصله زمانی کوتاه میرسند، ممکن است با هم تداخل کنند.
- اجرای ترتیبی از رقابت بر سر منابع مشترک (فایلهای نشست، گزارشها، ورودی استاندارد CLI) جلوگیری میکند و احتمال مواجهه با محدودیت نرخ سرویسهای بالادستی را کاهش میدهد.
نحوه کار
- یک صف FIFO آگاه از مسیر، هر مسیر را با سقف همزمانی قابلتنظیم تخلیه میکند (پیشفرض برای مسیرهای پیکربندینشده ۱ است؛ پیشفرض
mainبرابر ۴ وsubagentبرابر ۸ است). runEmbeddedAgentبر اساس کلید نشست (مسیرsession:<key>) در صف قرار میگیرد تا تضمین شود در هر نشست فقط یک اجرای فعال وجود دارد.- سپس هر اجرای نشست در یک مسیر سراسری (بهطور پیشفرض
main) قرار میگیرد تا موازیسازی کلی بهوسیلهagents.defaults.maxConcurrentمحدود شود. - وقتی ثبت گزارش تفصیلی فعال است، اجراهای در صف اگر پیش از شروع بیش از حدود ۲ ثانیه منتظر مانده باشند، اعلان کوتاهی منتشر میکنند.
- نشانگرهای در حال تایپ همچنان بلافاصله هنگام قرارگیری در صف فعال میشوند (اگر کانال از آن پشتیبانی کند)، بنابراین تجربه کاربر هنگام انتظار اجرا برای رسیدن نوبتش تغییری نمیکند.
پیشفرضها
وقتی تنظیم نشده باشند، همه سطوح کانالهای ورودی از این مقادیر استفاده میکنند:
mode: "steer"debounceMs: 500cap: 20drop: "summarize"
هدایت در همان نوبت، رفتار پیشفرض است. درخواستی که میان اجرای جاری برسد، اگر اجرا بتواند هدایت را بپذیرد، به زماناجرای فعال تزریق میشود؛ بنابراین اجرای نشست دومی آغاز نمیشود. اگر اجرای فعال نتواند هدایت را بپذیرد، OpenClaw پیش از آغاز درخواست منتظر پایان اجرای فعال میماند.
حالتهای صف
/queue تعیین میکند وقتی نشستی از قبل اجرای فعالی دارد، پیامهای ورودی عادی چگونه مدیریت شوند:
steer: پیامها را به زماناجرای فعال تزریق میکند. OpenClaw همه پیامهای هدایت در انتظار را پس از آنکه نوبت فعلی دستیار اجرای فراخوانیهای ابزار خود را به پایان رساند و پیش از فراخوانی بعدی LLM تحویل میدهد؛ سرور برنامه Codex یکturn/steerدستهای دریافت میکند. اگر اجرا بهطور فعال در حال پخش جریانی نباشد یا هدایت در دسترس نباشد، OpenClaw پیش از آغاز درخواست منتظر پایان اجرای فعال میماند.followup: هدایت نمیکند. هر پیام را برای نوبت بعدی عامل، پس از پایان اجرای جاری، در صف قرار میدهد.collect: هدایت نمیکند. پیامهای در صف را پس از پنجره سکوت در یک نوبت پیگیری واحد ادغام میکند. اگر پیامها کانالها/رشتههای متفاوتی را هدف بگیرند، برای حفظ مسیریابی بهصورت جداگانه تخلیه میشوند.interrupt: اجرای فعال آن نشست را لغو میکند و سپس جدیدترین پیام را اجرا میکند.
برای زمانبندی و رفتار وابستگی ویژه هر زماناجرا، به صف هدایت مراجعه کنید. برای فرمان صریح /steer <message>، به هدایت مراجعه کنید.
از طریق messages.queue بهصورت سراسری یا برای هر کانال پیکربندی کنید:
{ messages: { queue: { mode: "steer", debounceMs: 500, cap: 20, drop: "summarize", byChannel: { discord: "collect" }, }, },}گزینههای صف
گزینهها بر تحویل موارد در صف اعمال میشوند. debounceMs در حالت steer پنجره سکوت هدایت Codex را نیز تعیین میکند:
debounceMs: پنجره سکوت پیش از تخلیه پیگیریهای در صف یا دستههای جمعآوریشده؛ در حالتsteerدر Codex، پنجره سکوت پیش از ارسالturn/steerدستهای. اعداد بدون واحد بر حسب میلیثانیه هستند؛ گزینههای/queueواحدهایms،s،m،hوdرا میپذیرند.cap: حداکثر تعداد پیامهای در صف برای هر نشست. مقادیر کمتر از1نادیده گرفته میشوند.drop: "summarize"(پیشفرض): در صورت نیاز قدیمیترین موارد صف را حذف میکند، خلاصههای فشرده را نگه میدارد و آنها را بهصورت یک درخواست پیگیری مصنوعی تزریق میکند.drop: "old": در صورت نیاز قدیمیترین موارد صف را بدون حفظ خلاصهها حذف میکند.drop: "new": وقتی صف از قبل پر است، جدیدترین پیام را رد میکند.
پیشفرضها: debounceMs: 500، cap: 20، drop: summarize.
هدایت و پخش جریانی
وقتی پخش جریانی کانال روی partial یا block تنظیم شده باشد، ممکن است هدایت تا رسیدن اجرای فعال به مرزهای زماناجرا، بهشکل چند پاسخ کوتاه و قابلمشاهده ظاهر شود:
partial: ممکن است پیشنمایش زودتر نهایی شود و پس از پذیرفتهشدن هدایت، پیشنمایش جدیدی آغاز شود.block: بلوکهایی بهاندازه پیشنویس میتوانند ظاهر ترتیبی مشابهی ایجاد کنند.- بدون پخش جریانی، وقتی زماناجرا نتواند هدایت در همان نوبت را بپذیرد، هدایت پس از اجرای فعال به یک پیگیری تبدیل میشود.
steer ابزارهای در حال اجرا را لغو نمیکند. وقتی جدیدترین پیام باید اجرای جاری را لغو کند، از /queue interrupt استفاده کنید.
تقدم
OpenClaw برای انتخاب حالت، این ترتیب را اعمال میکند:
- بازنویسی درونخطی یا ذخیرهشده
/queueبرای هر نشست. messages.queue.byChannel.<channel>.messages.queue.mode.- پیشفرض
steer.
برای گزینهها، گزینههای درونخطی یا ذخیرهشده /queue بر پیکربندی اولویت دارند. سپس تأخیر ویژه کانال (messages.queue.debounceMsByChannel)، پیشفرضهای تأخیر Plugin، گزینههای سراسری messages.queue و پیشفرضهای داخلی، به همین ترتیب اعمال میشوند. cap و drop گزینههای سراسری/نشست هستند، نه کلیدهای پیکربندی مختص کانال.
بازنویسیهای هر نشست
- برای ذخیره حالت صف نشست جاری،
/queue <steer|followup|collect|interrupt>را بهصورت یک فرمان مستقل ارسال کنید. - گزینهها را میتوان ترکیب کرد:
/queue collect debounce:0.5s cap:25 drop:summarize /queue defaultیا/queue resetبازنویسی نشست را پاک میکند.
لغو نوبتهای در صف
تا زمانی که یک درخواست در صف پیگیری/جمعآوری قرار دارد (برای مثال، یک chat.send از TUI یا
گپ وب که هنگام فعالبودن نوبتی دیگر میرسد)، Gateway برای runId آن کارخواه یک
شناسه لغو تحت مالکیت Gateway نگه میدارد تا زمانی که محتوای در صف
اجرا یا حذف شود. این شناسه، محتوایی را که در یک خلاصه سرریز ادغام شده است نیز دنبال میکند.
chat.abortبا یکrunIdمشخص، در صورتی که درخواستکننده مجاز باشد، آن نوبت را تا زمانی که هنوز در صف است لغو میکند (با همان قواعد مالکیت اجراهای فعال).chat.abortبرای یک نشست بدونrunIdابتدا نوبتهای مجاز در صف را لغو میکند و سپس اجراهای فعال مجاز را لغو میکند. این ترتیب مانع میشود تخلیه صف، کار را به نشستی با توقف نیمهکاره منتقل کند.- پاککردن کل صف نشست بدون بررسی جداگانه هر درخواستکننده، مسیر توقف برای نشستهای چندمالکی نیست.
- انتظارهای در صف در
sessions.listبهعنوان اجراهای فعال عامل نمایش داده نمیشوند و مالک معنای مهلت زمانی اجرای فعال نیستند؛ فقط مرحله فعال چنین معنایی دارد.
کارخواهها (از جمله TUI) درخواستهای میان اجرا را ارسال میکنند و اجازه میدهند Gateway
حالت صف را اعمال کند. Esc//stop از لغو در محدوده نشست استفاده میکند تا گمشدن دستگیرههای محلی
باعث نشود یک درخواست همچنان در صف باقی بماند و اجرا شود.
دامنه و تضمینها
- بر اجراهای عامل پاسخ خودکار در همه کانالهای ورودی که از خط لوله پاسخ Gateway استفاده میکنند اعمال میشود (وب WhatsApp، Telegram، Slack، Discord، Signal، iMessage، گپ وب و غیره).
- مسیر پیشفرض (
main) در سراسر پردازه برای ورودیها و Heartbeatهای اصلی مشترک است؛ برای اجرای همزمان چند نشست،agents.defaults.maxConcurrentرا تنظیم کنید. - ممکن است مسیرهای دیگری نیز وجود داشته باشند (برای مثال
cron،cron-nested،nestedوsubagent) تا کارهای پسزمینه بدون مسدودکردن پاسخهای ورودی بهصورت موازی اجرا شوند. نوبتهای عامل Cron ایزولهشده هنگام استفاده اجرای عامل درونیشان ازcron-nested، یک جایگاهcronرا نگه میدارند؛ هر دو ازcron.maxConcurrentRunsاستفاده میکنند. جریانهای مشترک غیر Cron از نوعnestedرفتار مسیر خود را حفظ میکنند. این اجراهای جداشده بهعنوان وظایف پسزمینه ردیابی میشوند. - مسیرهای هر نشست تضمین میکنند که در هر لحظه فقط یک اجرای عامل به نشست مشخصی دسترسی داشته باشد.
- بدون وابستگی خارجی یا رشتههای کارگر پسزمینه؛ فقط TypeScript و promiseها.
عیبیابی
- اگر به نظر میرسد فرمانها گیر کردهاند، گزارشهای تفصیلی را فعال کنید و برای تأیید تخلیهشدن صف بهدنبال خطوط
"queued for ...ms"بگردید. - اجراهای سرور برنامه Codex که نوبتی را میپذیرند و سپس انتشار پیشرفت را متوقف میکنند، بهوسیله سازگارکننده Codex متوقف میشوند تا مسیر نشست فعال بهجای انتظار برای مهلت زمانی اجرای بیرونی آزاد شود.
- وقتی عیبیابی فعال است، نشستهایی که پس از
diagnostics.stuckSessionWarnMsهمچنان در وضعیتprocessingمیمانند و هیچ پیشرفتی در پاسخ، ابزار، وضعیت، بلوک یا ACP برای آنها مشاهده نشده است، بر اساس فعالیت جاری دستهبندی میشوند:- کار فعال با پیشرفت اخیر با عنوان
session.long_runningثبت میشود. فراخوانیهای بیصدای مدل که مالک دارند نیز تاdiagnostics.stuckSessionAbortMsدر وضعیتsession.long_runningباقی میمانند تا ارائهدهندگان کند یا بدون پخش جریانی زودهنگام متوقفشده گزارش نشوند. - کار فعال بدون پیشرفت اخیر با عنوان
session.stalledثبت میشود؛ فراخوانیهای مدل دارای مالک، فراخوانیهای ابزار مسدودشده و اجراهای تعبیهشده متوقفشده، در آستانه لغو یا پس از آن بهsession.stalledتغییر وضعیت میدهند. فعالیت کهنه مدل/ابزار بدون مالک بهعنوان اجرای طولانی پنهان نمیشود. session.stuckبرای ثبت وضعیت کهنه و قابلبازیابی نشست، از جمله نشستهای بیکار در صف با فعالیت کهنه مدل/ابزار بدون مالک، رزرو شده است.session.stuckهمیشه بازیابیای را فعال میکند که میتواند مسیر نشست تحتتأثیر را آزاد کند. دستهبندیsession.stalledپس ازdiagnostics.stuckSessionAbortMs(فراخوانی ابزار مسدودشده، فراخوانی مدل متوقفشده یا اجرای تعبیهشده متوقفشده) نیز میتواند بازیابی از طریق لغو فعال را راهاندازی کند؛ بنابراین هر دو دستهبندی میتوانند صف را از حالت گیرکرده خارج کنند، نه فقطsession.stuck.- خطوط گزارش هشدار تکراری
session.stuckوsession.long_runningتا زمانی که نشست بدون تغییر بماند، با عقبنشینی نمایی منتشر میشوند؛ تلاشهای بازیابی بدون توجه به این عقبنشینی، در هر تیک Heartbeat همچنان اجرا میشوند.
- کار فعال با پیشرفت اخیر با عنوان