目的
- エージェントの実行(LLM の呼び出し)はコストが高く、短時間に複数のメッセージが届いた場合にリソースが競合する可能性があります。
- 実行を直列化することで、セッションファイル、ログ、CLI の標準入力などの共有リソースへの同時アクセスを避け、上位プロバイダーのレート制限にかかるリスクを低減します。
仕組み
- 「レーン(Lane)」を認識する FIFO(先入れ先出し)キューが、各レーンごとに設定された同時実行上限に従ってリクエストを処理します。
- レーンごとのデフォルト上限: 未設定のレーンは 1、メインレーン(
main)は 4、サブエージェント(subagent)は 8 です。 runEmbeddedPiAgentは、まず セッションキー ごとのレーン(session:<key>)にエンキュー(待ち行列に追加)されます。これにより、1 つのセッションに対して一度に実行されるエージェントは必ず 1 つであることが保証されます。- 次に、各セッションの実行は グローバルレーン(デフォルトは
main)にエンキューされます。システム全体の並列数は、構成設定のagents.defaults.maxConcurrentによって制限されます。 - 詳細ログ(verbose)が有効な場合、キューでの待機時間が約 2 秒を超えた際に通知が出力されます。
- タイピング中インジケーター(対応チャネルのみ)は、キューに入った直後に作動します。そのため、順番待ちの間もユーザーにはボットが反応しているように見え、UX は損なわれません。
キューモード (チャネルごとの動作)
受信メッセージが届いた際、現在実行中のターンに対して「割り込む(ステアリング)」か、「終わるのを待ってから次で処理する(フォローアップ)」か、あるいはその両方を行うかを選択できます。steer: 現在の実行に直ちに割り込みます(次のツール実行のタイミングで、残りのツール呼び出しをキャンセルします)。ストリーミングが利用できない場合はfollowupモードにフォールバックします。followup: 現在の実行が終わった後、次のターンとしてキューに追加します。collect(デフォルト): 現在の実行が終わるまで待機し、キューに溜まったすべてのメッセージを 1 つの フォローアップターンに集約して処理します。宛先のチャネルやスレッドが異なる場合は、ルーティングを維持するために個別に処理されます。steer-backlog(steer+backlog): 現在の実行に割り込むと同時に、そのメッセージを次回のフォローアップ用にも保持します。interrupt(レガシー): 現在の実行を強制終了(abort)させ、最新のメッセージで新しく実行を開始します。queue(レガシー別名):steerと同じ動作です。
steer-backlog を使用すると、割り込んだターンとフォローアップのターンの両方で応答が生成されるため、ストリーミング対応の UI では重複したように見えることがあります。1 つのメッセージに対して 1 つの応答を確実に返したい場合は collect または steer を推奨します。
設定方法:
- セッションごとに
/queue collectコマンドを送信する。 - 構成ファイルで
messages.queue.byChannel.discord: "collect"のように指定する。
- すべてのチャネルで
collect
messages.queue):
キューのオプション
これらのオプションはfollowup, collect, steer-backlog(および steer がフォールバックした場合)に適用されます。
debounceMs: フォローアップを開始する前に、追記が止まるまで待機する時間(「あ、あとこれも」といった連続投稿を 1 つにまとめるため)。cap: 1 セッションあたりに蓄積できるキューの最大数。drop: 上限を超えた場合の処理ポリシー (old: 古い順に捨てる,new: 新しいものを捨てる,summarize: 要約する)。
summarize を選択すると、破棄されたメッセージの短いリストを保持し、それを合成されたフォローアッププロンプトとしてエージェントに渡します。
デフォルト値: debounceMs: 1000, cap: 20, drop: summarize。
セッションごとの上書き
/queue <mode>コマンドを送信すると、現在のセッションの設定として保存されます。- オプションの組み合わせも可能です:
/queue collect debounce:2s cap:25 drop:summarize /queue defaultまたは/queue resetで上書き設定を解除できます。
適用範囲と保証
- ゲートウェイの返信パイプラインを使用するすべての受信チャネル(WhatsApp web, Telegram, Slack, Discord, Signal, iMessage, webchat など)の自動応答に適用されます。
- デフォルトレーン (
main) は、通常の応答とメインのハートビートで共有されます。複数のセッションを並列で動かしたい場合はagents.defaults.maxConcurrentを増やしてください。 cronやsubagentといった追加のレーンがあり、インバウンドの応答を妨げることなくバックグラウンドジョブを並列実行できます。- セッションごとのレーンにより、特定のセッションに対して一度にアクセスするエージェント実行は常に 1 つに制限されることが保証されます。
- 外部の依存関係やワーカースレッドは使用せず、純粋な TypeScript と Promise で実装されています。
トラブルシューティング
- コマンドが止まっているように見える場合は、詳細ログを有効にして「queued for …ms」という行を確認し、キューが処理(排出)されているか確かめてください。
- キューの深さを知りたい場合も、詳細ログでキューのタイミング情報を確認してください。