Messages and delivery
صف فرمانها
OpenClaw اجراهای پاسخ خودکار ورودی (در همه کانالها) را از طریق یک صف کوچک درونپردازهای بهصورت ترتیبی اجرا میکند تا از تداخل چند اجرای عامل جلوگیری شود، درحالیکه همچنان موازیسازی ایمن میان نشستها را امکانپذیر میسازد.
چرا
- اجراهای پاسخ خودکار ممکن است پرهزینه باشند (فراخوانیهای LLM) و هنگامی که چند پیام ورودی با فاصله زمانی کم میرسند، با یکدیگر تداخل پیدا کنند.
- اجرای ترتیبی از رقابت بر سر منابع مشترک (فایلهای نشست، گزارشها، ورودی استاندارد CLI) جلوگیری میکند و احتمال اعمال محدودیت نرخ از سوی سرویس بالادستی را کاهش میدهد.
نحوه کار
- یک صف FIFO آگاه از مسیر، هر مسیر را با سقف همزمانی قابلپیکربندی تخلیه میکند (پیشفرض 1 برای مسیرهای پیکربندینشده؛ پیشفرض
mainبرابر 4 وsubagentبرابر 8 است). runEmbeddedAgentبر اساس کلید نشست (مسیرsession:<key>) در صف قرار میدهد تا تضمین کند در هر نشست فقط یک اجرای فعال وجود دارد.- سپس هر اجرای نشست در یک مسیر سراسری (بهطور پیشفرض
main) قرار میگیرد تا موازیسازی کلی بهagents.defaults.maxConcurrentمحدود شود. - وقتی ثبت گزارش تفصیلی فعال باشد، اجراهای صفشده درصورتیکه پیش از شروع بیش از حدود 2s منتظر مانده باشند، اعلان کوتاهی صادر میکنند.
- نشانگرهای تایپ همچنان بلافاصله هنگام ورود به صف فعال میشوند (اگر کانال پشتیبانی کند)، بنابراین تجربه کاربر هنگام انتظار اجرا برای نوبت خود بدون تغییر میماند.
پیشفرضها
وقتی تنظیم نشده باشد، همه سطوح کانال ورودی از موارد زیر استفاده میکنند:
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 همچنین بازه سکوت هدایت Codex را در حالت steer تنظیم میکند:
debounceMs: بازه سکوت پیش از تخلیه پیگیریهای صفشده یا دستههای تجمیعشده؛ در حالتsteerدر Codex، بازه سکوت پیش از ارسالturn/steerدستهای. اعداد بدون واحد بر حسب میلیثانیه هستند؛ واحدهایms،s،m،hوdدر گزینههای/queueپذیرفته میشوند.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 یک
هویت لغو تحت مالکیت Gateway را برای runId آن کارخواه تا زمانی که محتوای
صفشده اجرا یا حذف شود نگه میدارد. این هویت، محتوای ادغامشده در یک
خلاصه سرریز را دنبال میکند.
chat.abortبا یکrunIdمشخص، اگر درخواستکننده مجاز باشد (همان قواعد مالکیت اجراهای فعال)، آن نوبت را تا زمانی که هنوز در صف است لغو میکند.chat.abortبرای نشستی بدونrunId، ابتدا نوبتهای صفشده مجاز را لغو میکند و سپس اجراهای فعال مجاز را لغو میکند. این ترتیب مانع از آن میشود که تخلیه صف، کاری را وارد نشستی نیمهمتوقف کند.- پاککردن کل صف نشست بدون بررسیهای هر درخواستکننده، مسیر توقف برای نشستهای چندمالکی نیست.
- انتظارهای صفشده برای
sessions.listبهعنوان اجرای فعال عامل نمایش داده نمیشوند و مالک معنای مهلت زمانی اجرای فعال نیستند؛ فقط مرحله فعال چنین معنایی دارد.
کارخواههای مبتنی بر Gateway (از جمله openclaw tui) درخواستهای میانه اجرا را هدایت میکنند و
اجازه میدهند Gateway حالت صف را اعمال کند. Esc//stop از لغو در سطح نشست
استفاده میکند تا ازدسترفتن دستگیرههای محلی نتواند باعث اجرای یک درخواست همچنان صفشده شود.
openclaw chat و openclaw tui --local همان چهار حالت را در
زمان اجرای تعبیهشده اعمال میکنند. steer محلی، وقتی زمان اجرای تعبیهشده فعال
هدایت را بپذیرد، آن را تزریق میکند و در غیر این صورت به یک پیگیری تبدیل میشود؛ followup و
collect همچنان کار محلی در انتظار باقی میمانند؛ interrupt اجرای محلی فعال را
پیش از آغاز جدیدترین پیام لغو میکند. فرمان صریح /steer <message>
یک فرمان حالت محلی نیست.
دامنه و تضمینها
- برای اجراهای عامل پاسخ خودکار در همه کانالهای ورودی که از پایپلاین پاسخ Gateway استفاده میکنند اعمال میشود (وب WhatsApp، Telegram، Slack، Discord، Signal، iMessage، گفتوگوی وب و غیره).
- مسیر پیشفرض (
main) برای ورودیها و Heartbeatهای اصلی در سطح پردازه مشترک است؛ برای اجازهدادن به اجرای موازی چند نشست،agents.defaults.maxConcurrentرا تنظیم کنید. - ممکن است مسیرهای دیگری نیز وجود داشته باشند (برای مثال
cron،cron-nested،nested،subagent) تا کارهای پسزمینه بتوانند بدون مسدودکردن پاسخهای ورودی بهصورت موازی اجرا شوند. نوبتهای عامل Cron ایزولهشده، هنگام استفاده اجرای داخلی عامل ازcron-nested، یک جایگاهcronرا در اختیار میگیرند. جریانهای مشترک غیر Cron درnestedرفتار مسیر خود را حفظ میکنند. این اجراهای جداشده بهعنوان وظایف پسزمینه ردیابی میشوند. - مسیرهای هر نشست تضمین میکنند که در هر لحظه فقط یک اجرای عامل با یک نشست مشخص کار کند.
- بدون وابستگی خارجی یا رشتههای کارگر پسزمینه؛ فقط TypeScript و promiseها.
عیبیابی
- اگر فرمانها متوقف به نظر میرسند، گزارشهای تفصیلی را فعال کنید و برای تأیید تخلیهشدن صف، بهدنبال خطوط "queued for ...ms" بگردید.
- اجراهای سرور برنامه Codex که نوبتی را میپذیرند و سپس ارسال پیشرفت را متوقف میکنند، توسط سازگارگر Codex قطع میشوند تا مسیر نشست فعال بهجای انتظار برای مهلت زمانی اجرای بیرونی آزاد شود.
- وقتی تشخیص فعال باشد، نشستهایی که پس از آستانه هشدار داخلی همچنان در
processingباقی میمانند و هیچ پیشرفت مشاهدهشدهای در پاسخ، ابزار، وضعیت، بلوک یا ACP ندارند، بر اساس فعالیت فعلی دستهبندی میشوند:- کار فعال با پیشرفت اخیر بهصورت
session.long_runningثبت میشود. فراخوانیهای خاموش مدل که مالک دارند نیز تا آستانه لغو داخلی در وضعیتsession.long_runningباقی میمانند تا ارائهدهندگان کند یا غیرجریانی خیلی زود متوقف گزارش نشوند. - کار فعال بدون پیشرفت اخیر بهصورت
session.stalledثبت میشود؛ فراخوانیهای مدل دارای مالک، فراخوانیهای ابزار مسدودشده و اجراهای تعبیهشده متوقف، در آستانه لغو یا پس از آن بهsession.stalledتغییر میکنند. فعالیت قدیمی مدل/ابزار بدون مالک بهعنوان فعالیت طولانیمدت پنهان نمیشود. session.stuckبرای ثبت منقضیشده قابلبازیابی نشست کنار گذاشته شده است؛ از جمله نشستهای صفشده بیکار دارای فعالیت قدیمی مدل/ابزار بدون مالک.session.stuckهمیشه بازیابیای را فعال میکند که میتواند مسیر نشست تحتتأثیر را آزاد کند. دستهبندیsession.stalledپس از آستانه لغو (فراخوانی ابزار مسدودشده، فراخوانی مدل متوقف یا اجرای تعبیهشده متوقف) نیز میتواند بازیابی با لغو فعال را راهاندازی کند؛ بنابراین هر دو دستهبندی میتوانند انسداد صف را برطرف کنند، نه فقطsession.stuck.- فاصله میان خطوط گزارش هشدار تکراری
session.stuckوsession.long_runningتا زمانی که نشست بدون تغییر بماند، بهصورت نمایی افزایش مییابد؛ تلاشهای بازیابی صرفنظر از این افزایش فاصله، همچنان در هر تیک Heartbeat اجرا میشوند.
- کار فعال با پیشرفت اخیر بهصورت