理由
- 自動返信実行は高コストになることがあり(LLM 呼び出し)、複数の受信メッセージが短い間隔で届くと衝突する可能性があります。
- 直列化により、共有リソース(セッションファイル、ログ、CLI 標準入力)の競合を避け、上流のレート制限に達する可能性を下げます。
仕組み
- レーン対応の FIFO キューが、設定可能な並行数上限で各レーンを処理します(未設定レーンのデフォルトは 1、
mainのデフォルトは 4、subagentは 8)。 runEmbeddedAgentは セッションキー(レーンsession:<key>)でエンキューし、セッションごとにアクティブな実行が 1 つだけになることを保証します。- 各セッション実行はその後 グローバルレーン(デフォルトでは
main)にキュー投入されるため、全体の並列度はagents.defaults.maxConcurrentによって制限されます。 - 詳細ログが有効な場合、キュー内の実行は開始までに約 2 秒を超えて待機すると短い通知を出力します。
- 入力中インジケーターは、チャネルが対応している場合、エンキュー時に即座に送信されるため、実行が順番待ちしている間もユーザー体験は変わりません。
デフォルト
未設定の場合、すべての受信チャネルサーフェスは次を使用します。mode: "steer"debounceMs: 500cap: 20drop: "summarize"
キューモード
/queue は、セッションにすでにアクティブな実行がある間、通常の受信メッセージをどう扱うかを制御します。
steer: メッセージをアクティブなランタイムへ注入します。OpenClaw は、現在のアシスタントターンがツール呼び出しの実行を終えた後、次の LLM 呼び出しの前に、保留中のすべてのステアリングメッセージを配信します。Codex app-server はバッチ化された 1 つのturn/steerを受け取ります。実行がアクティブにストリーミングしていない場合、またはステアリングを利用できない場合、OpenClaw はアクティブな実行が終了するまで待ってからプロンプトを開始します。followup: ステアリングしません。現在の実行が終了した後のエージェントターン用に、各メッセージをエンキューします。collect: ステアリングしません。静穏ウィンドウの後、キュー内のメッセージを 単一の フォローアップターンにまとめます。メッセージが異なるチャネルやスレッドを対象にしている場合、ルーティングを維持するため個別に処理されます。interrupt: そのセッションのアクティブな実行を中止してから、最新のメッセージを実行します。
/steer <message> コマンドについては、ステアを参照してください。
グローバルまたはチャネルごとに messages.queue で設定します。
キューオプション
オプションはキュー配信に適用されます。debounceMs は steer モードで Codex ステアリングの静穏ウィンドウも設定します。
debounceMs: キュー内のフォローアップまたは collect バッチを処理する前の静穏ウィンドウです。Codex のsteerモードでは、バッチ化された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はセッションオーバーライドをクリアします。
キュー内ターンのキャンセル
プロンプトがフォローアップまたは collect キュー内にある間(たとえば、別のターンがアクティブな間に TUI や ウェブチャットのchat.send が到着した場合)、Gateway はキュー内の
コンテンツが実行されるか削除されるまで、そのクライアント runId の
Gateway 所有のキャンセル ID を保持します。この ID は、オーバーフロー要約に折りたたまれたコンテンツにも追従します。
- 特定の
runIdを指定したchat.abortは、リクエスターが認可されている場合(アクティブな実行と同じ所有権ルール)、そのターンがまだ キュー内にある間にキャンセルします。 runIdなしでセッションに対するchat.abortは、まず 認可されたキュー内ターン をキャンセルし、その後、認可されたアクティブな実行を中止します。この順序により、キュー処理が作業を半停止状態のセッションへ昇格させることを防ぎます。- リクエスターごとのチェックなしにセッションキュー全体をクリアすることは、複数所有者セッションの 停止経路ではありません。
- キュー待機は
sessions.listでアクティブなエージェント実行として投影されず、 アクティブ実行のタイムアウトセマンティクスも所有しません。所有するのはアクティブフェーズのみです。
/stop はセッションスコープの中止を使用するため、失われたローカルハンドルによって、まだキュー内にあるプロンプトが実行され続けることはありません。
スコープと保証
- Gateway 返信パイプラインを使用するすべての受信チャネル(WhatsApp web、Telegram、Slack、Discord、Signal、iMessage、ウェブチャットなど)にまたがる自動返信エージェント実行に適用されます。
- デフォルトレーン(
main)は、受信 + main Heartbeat に対してプロセス全体で共有されます。複数セッションを並列に許可するには、agents.defaults.maxConcurrentを設定してください。 - 追加レーン(例:
cron、cron-nested、nested、subagent)が存在する場合があり、バックグラウンドジョブは受信返信をブロックせずに並列実行できます。分離された Cron エージェントターンは、内側のエージェント実行がcron-nestedを使用している間、cronスロットを保持します。どちらもcron.maxConcurrentRunsを使用します。共有された非 Cron のnestedフローは独自のレーン動作を維持します。これらの切り離された実行はバックグラウンドタスクとして追跡されます。 - セッションごとのレーンにより、特定のセッションに同時に触れるエージェント実行が 1 つだけであることを保証します。
- 外部依存関係やバックグラウンドワーカースレッドはありません。純粋な TypeScript + promises です。
トラブルシューティング
- コマンドが停止しているように見える場合は、詳細ログを有効にし、キューが処理されていることを確認するために “queued for …ms” 行を探してください。
- ターンを受け付けた後に進捗の出力を停止した Codex app-server 実行は、外側の実行タイムアウトを待つ代わりにアクティブなセッションレーンを解放できるよう、Codex アダプターによって中断されます。
- 診断が有効な場合、
diagnostics.stuckSessionWarnMsを超えてprocessingのままで、返信、ツール、ステータス、ブロック、ACP 進捗が観測されないセッションは、現在のアクティビティによって分類されます。- 最近の進捗ログがあるアクティブな作業は
session.long_runningです。所有者のある無音のモデル呼び出しも、低速または非ストリーミングのプロバイダーが早すぎる段階で停止として報告されないよう、diagnostics.stuckSessionAbortMsまではsession.long_runningのままです。 - 最近の進捗ログがないアクティブな作業は
session.stalledです。所有者のあるモデル呼び出し、ブロックされたツール呼び出し、停止した埋め込み実行は、中止しきい値以降にsession.stalledへ切り替わります。所有者のない古いモデルまたはツールアクティビティは、長時間実行中として隠されません。 session.stuckは、所有者のない古いモデルまたはツールアクティビティを伴うアイドル状態のキュー内セッションを含め、回復可能な古いセッション管理情報のために予約されています。session.stuckは常に、影響を受けたセッションレーンを解放できる回復をトリガーします。diagnostics.stuckSessionAbortMsを超えたsession.stalled分類(ブロックされたツール呼び出し、停止したモデル呼び出し、または停止した埋め込み実行)もアクティブ中止回復をトリガーできるため、session.stuckだけでなく両方の分類がキューの詰まりを解消できます。- 繰り返される
session.stuckとsession.long_runningの警告ログ行は、セッションが変わらない間は指数バックオフします。回復試行は、そのバックオフに関係なく、すべての Heartbeat tick で引き続き実行されます。
- 最近の進捗ログがあるアクティブな作業は