Messages and delivery
コマンドキュー
インバウンド自動返信実行(全チャネル)は、小さなインプロセスキューを通してシリアライズし、複数のエージェント実行が衝突するのを防ぎつつ、セッション間では安全な並列処理を許可します。
理由
- 自動返信実行は高コストになる場合があり(LLM 呼び出し)、複数のインバウンドメッセージが近いタイミングで届くと衝突することがあります。
- シリアライズにより、共有リソース(セッションファイル、ログ、CLI stdin)の競合を避け、上流のレート制限に達する可能性を下げます。
仕組み
- レーン対応の FIFO キューが、設定可能な並行数上限で各レーンを処理します(未設定レーンのデフォルトは 1、main のデフォルトは 4、subagent は 8)。
runEmbeddedAgentは セッションキー(レーンsession:<key>)ごとにエンキューし、セッションごとにアクティブな実行が 1 つだけになることを保証します。- 各セッション実行はその後 グローバルレーン(デフォルトは
main)にキュー投入されるため、全体の並列度はagents.defaults.maxConcurrentによって制限されます。 - 詳細ログが有効な場合、キュー内の実行は開始までに約 2 秒以上待つと短い通知を出します。
- 入力中インジケーターは、チャネルがサポートしている場合、エンキュー時にすぐ発火するため、順番待ちの間もユーザー体験は変わりません。
デフォルト
未設定の場合、すべてのインバウンドチャネルサーフェスは次を使用します。
mode: "steer"debounceMs: 500cap: 20drop: "summarize"
同一ターンのステアリングがデフォルトです。実行中に届いたプロンプトは、その実行がステアリングを受け入れられる場合、アクティブなランタイムに注入されるため、2 つ目のセッション実行は開始されません。アクティブな実行がステアリングを受け入れられない場合、OpenClaw はアクティブな実行が終了するまで待ってからプロンプトを開始します。
キューモード
/queue は、セッションにすでにアクティブな実行がある間、通常のインバウンドメッセージをどう扱うかを制御します。
steer: メッセージをアクティブなランタイムに注入します。OpenClaw は、保留中のすべてのステアリングメッセージを 現在のアシスタントターンがツール呼び出しの実行を終えた後、次の LLM 呼び出しの前に配信します。Codex app-server は 1 つにまとめられた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: キュー内の後続処理または collect バッチを処理する前の静止ウィンドウです。Codexsteerモードでは、まとめられた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はセッションオーバーライドをクリアします。
スコープと保証
- Gateway 返信パイプラインを使用するすべてのインバウンドチャネル(WhatsApp web、Telegram、Slack、Discord、Signal、iMessage、webchat など)にまたがる自動返信エージェント実行に適用されます。
- デフォルトレーン(
main)は、インバウンドと main Heartbeat に対してプロセス全体で共有されます。複数セッションを並列に許可するには、agents.defaults.maxConcurrentを設定します。 - 追加のレーン(例:
cron、cron-nested、nested、subagent)が存在する場合があるため、バックグラウンドジョブはインバウンド返信をブロックせずに並列実行できます。分離された Cron エージェントターンは、内側のエージェント実行がcron-nestedを使用している間、cronスロットを保持します。どちらもcron.maxConcurrentRunsを使用します。共有の非 Cronnestedフローは、それぞれ独自のレーン挙動を維持します。これらの切り離された実行は バックグラウンドタスク として追跡されます。 - セッション単位のレーンは、特定のセッションに一度に触れるエージェント実行が 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診断は、セッションが変化しない間バックオフします。