Skip to content
Guides

The OpenClaw command queue

Lanes and concurrency, the four queue modes, steering a running reply, per-session overrides, and the background work budget

6 min read

OpenClaw serialises inbound auto-reply runs from every channel through a tiny in-process queue, so that multiple agent runs do not collide on shared resources such as session state, logs and CLI input, while sessions still run in parallel. Here is how the lanes work, the defaults, the four modes that decide what a message does while a run is already active, the options and their precedence, the durability guarantees, the background budget shared with maintenance work, and the classifications the diagnostics use when something looks stuck.

Lanes and defaults

  • A lane-aware FIFO drains each lane under a concurrency cap: one for unconfigured lanes, eight for the sub-agent lane, and for the main lane the available CPU parallelism bounded between eight and sixteen; the main lane is capped overall by the max-concurrent default.
  • CLI, embedded and Codex runs share the same session-key lane, so each turn waits there before acquiring the session’s execution claim and changing runtimes cannot start a competing turn; each session run is then queued into the global lane.
  • Typing indicators fire on enqueue where the channel supports them, so the experience is unchanged while a run waits; with verbose logging a queued run notes when it waited more than about two seconds.
  • Unset, every inbound surface uses steer mode, a built-in half-second debounce, a cap of twenty queued messages, and a drop policy that summarises what it drops.
Same-turn steering is the default.

The four modes

Steer injects a message into the active runtime: an already-running tool finishes, sequential calls that have not started are skipped, the steer becomes visible before the next tool launch or model decision, and the Codex app server receives one batched steer applied at the next model boundary; if the run cannot accept steering, OpenClaw waits for it to end and then starts the prompt. Followup does not steer and enqueues each message for a later turn. Collect coalesces queued messages into a single followup turn after the quiet window, draining different threads individually to preserve routing. Interrupt aborts the active run for that session and runs the newest message. With partial or block streaming, steering can look like several short replies as the run reaches its boundaries, and steer never aborts in-flight tools, so interrupt is the mode for a message that should stop the current work. A plain-text answer to a pending agent question goes to that question before ordinary queue handling, is checked against the question creator’s permissions, and is reported as uncertain rather than resent when a commit may have happened without confirmation.

Options, precedence, durability

  • The options: a debounce quiet window with time units, which in Codex steer mode also sets the steering window; a cap of at least one; and a drop policy of summarise, which keeps compact summaries of dropped entries as a synthetic followup, old, which drops silently, or new, which rejects the newest message when full. Mode precedence is the per-session override, then the per-channel setting, then the global mode, then steer; options set per session win over config, followed by channel-specific debounce, plugin defaults and built-ins.
  • Per session, a standalone queue command stores the mode, options combine on one line, and default or reset clears the override. A prompt sitting in the followup or collect queue keeps a Gateway-owned cancel identity, so an abort with its run id cancels it while queued, and an abort for a session without an id cancels authorised queued turns first and then active runs, so draining the queue never promotes work into a half-stopped session.
  • Ordinary Control UI input to an existing session is stored in the per-agent database before the Gateway acknowledges it, collect mode appends the combined turn and marks its sources consumed in one transaction, and a Gateway stop before a queued input reaches the transcript leaves it as interrupted input that needs an explicit resend; the in-memory queue is not replayed, but channel messages retained by durable ingress stay retryable when a queued attempt is abandoned before adoption.

OpenClaw sessions explains the session each lane protects, and OpenClaw slash commands the command surface the queue directive belongs to.

Lanes for background work

The main lane is process-wide for inbound turns; heartbeat runs use a bounded nested cron lane for global admission so slow background work does not block replies, isolated cron turns hold a cron slot while their inner execution uses the nested lane, and sub-agent and nested flows have lanes of their own, all tracked as background tasks with no worker threads or external dependencies. Skill Workshop reviews and plugin background completions, dreaming included, share a separate budget of three concurrent runs, one at most for reviews and up to three for a plugin, and a scheduler that awaits background work does not hold a slot itself; the busyness overlay reports it all in one background row. When commands seem stuck, verbose logs show the queued-for lines; diagnostics classify a session that stays processing as long-running when progress is recent, stalled when it is not, and stuck for recoverable stale bookkeeping, and both stuck and stalled past the abort threshold can trigger recovery that releases the session lane. OpenClaw subagents covers the lane with the cap of eight, and OpenClaw dreaming the nightly work that lives in the background budget.

On Diali

On Diali the queue runs with the upstream defaults inside each assistant: sending two messages in a row steers the running reply rather than starting a second one, and the interrupt mode is one command away when you want the first message dropped. Hosted OpenClaw on Diali is the assistant.

  • One run per session at a time; sessions in parallel.
  • Steer, followup, collect, interrupt.
  • Three background runs, shared with dreaming and the Workshop.
Get started

Stop reading about it, build one

Set up an agent, pick a channel, and have it working inside the app you already keep open.