Command Queue (2026-01-16)
OpenClaw는 inbound auto-reply run (모든 channel)을 작은 in-process queue로 직렬화합니다. 목적은 여러 agent run이 서로 충돌하는 것을 막으면서도, 서로 다른 session 간에는 안전한 병렬성을 유지하는 것입니다.Why
- auto-reply run은 LLM call 때문에 비용이 크고, 여러 inbound message가 가까운 시점에 들어오면 서로 충돌할 수 있습니다
- 직렬화하면 shared resource (session file, log, CLI stdin) 경쟁을 줄이고 upstream rate limit 가능성도 낮출 수 있습니다
How it works
- lane-aware FIFO queue가 각 lane을 drain하며, configurable concurrency cap을
적용합니다
(설정 없는 lane 기본 1,
main기본 4,subagent기본 8) runEmbeddedPiAgent는 session key 기준으로 enqueue합니다 (lanesession:<key>) 따라서 하나의 session에서는 동시에 하나의 active run만 허용됩니다- 각 session run은 다시 global lane
(기본은
main)에 queue되어 전체 병렬성이agents.defaults.maxConcurrent로 제한됩니다 - verbose logging이 켜져 있으면, 시작 전 약 2초 이상 기다린 run은 짧은 notice를 남깁니다
- typing indicator는 enqueue 직후 즉시 켜집니다 (channel이 지원하는 경우) 따라서 순서를 기다리는 동안에도 user experience는 유지됩니다
Queue modes (per channel)
inbound message는 현재 run을 조정하거나, followup turn을 기다리게 하거나, 둘 다 할 수 있습니다.steer: 현재 run에 즉시 inject (다음 tool boundary 이후 pending tool call 취소) streaming이 아니면followup으로 fallbackfollowup: 현재 run이 끝난 뒤 다음 agent turn으로 enqueuecollect: queued message를 하나의 followup turn으로 coalesce (기본값). 다만 서로 다른 channel/thread를 향한 message는 routing 보존을 위해 개별 drainsteer-backlog(aliassteer+backlog): 지금 steer하고, message도 followup용으로 보존interrupt(legacy): 해당 session의 active run을 abort한 뒤 최신 message 실행queue(legacy alias):steer와 동일
collect 또는 steer를 우선 고려하세요.
세션 단위 standalone command로 /queue collect를 보내거나,
messages.queue.byChannel.discord: "collect"처럼 설정할 수 있습니다.
기본값
(config에서 unset일 때):
- 모든 surface →
collect
messages.queue에서 설정합니다.
Queue options
이 옵션은followup, collect, steer-backlog에 적용되며,
steer가 followup으로 fallback될 때도 적용됩니다.
debounceMs: followup turn을 시작하기 전 quiet period를 기다림 (“continue, continue” 같은 연속 입력을 흡수)cap: session당 최대 queued message 수drop: overflow policy (old,new,summarize)
summarize는 drop된 message를 짧은 bullet list로 보존해 synthetic followup prompt로
inject합니다.
기본값은 debounceMs: 1000, cap: 20, drop: summarize입니다.
Per-session overrides
- standalone command
/queue <mode>를 보내면 현재 session의 mode가 저장됩니다 - option을 조합할 수 있습니다:
/queue collect debounce:2s cap:25 drop:summarize /queue default또는/queue reset은 session override를 지웁니다
Scope and guarantees
- Gateway reply pipeline을 사용하는 모든 inbound channel의 auto-reply agent run에 적용됩니다 (WhatsApp web, Telegram, Slack, Discord, Signal, iMessage, webchat 등)
- default lane인
main은 inbound와 main heartbeat에 대해 process-wide입니다. 여러 session을 병렬로 처리하려면agents.defaults.maxConcurrent를 조정하세요 cron,subagent같은 additional lane이 있을 수 있어 background job은 inbound reply를 막지 않고 병렬로 돌 수 있습니다- per-session lane은 같은 session에 동시에 하나의 agent run만 접근하도록 보장합니다
- external dependency나 background worker thread 없이, 순수 TypeScript + promise로 구현됩니다
Troubleshooting
- command가 멈춘 것처럼 보이면 verbose log를 켜고
"queued for …ms"line이 보이는지 확인하세요. queue가 실제로 drain 중인지 판단할 수 있습니다 - queue depth가 필요하면 verbose log를 켜고 queue timing line을 확인하세요