Command Queue (16.01.2026)

Wir serialisieren eingehende Auto-Reply-Läufe (alle Channels) über eine kleine In-Process-Queue. So verhindern wir, dass mehrere Agent-Läufe kollidieren, und ermöglichen trotzdem sichere Parallelität zwischen Sessions.

Warum

  • Auto-Reply-Läufe können teuer sein (LLM-Aufrufe) und kollidieren, wenn mehrere Nachrichten kurz hintereinander eintreffen.
  • Durch Serialisierung vermeiden wir Konflikte um gemeinsame Ressourcen (Session-Dateien, Logs, CLI stdin) und reduzieren das Risiko von Rate Limits.

So funktioniert es

  • Eine Lane-aware FIFO-Queue verarbeitet jede Lane mit einem konfigurierbaren Concurrency-Limit (Standard: 1 für unkonfigurierte Lanes; main hat 4, subagent hat 8).
  • runEmbeddedPiAgent reiht nach Session Key ein (Lane session:<key>), damit pro Session nur ein aktiver Lauf existiert.
  • Jeder Session-Lauf wird dann in eine globale Lane (main standardmäßig) eingereiht, sodass die Gesamtparallelität durch agents.defaults.maxConcurrent begrenzt wird.
  • Bei aktiviertem Verbose-Logging erscheint ein kurzer Hinweis, wenn ein Lauf mehr als ~2s gewartet hat.
  • Typing-Indikatoren werden sofort beim Einreihen ausgelöst (wenn der Channel das unterstützt), damit die User Experience unverändert bleibt.

Queue-Modi (pro Channel)

Eingehende Nachrichten können den aktuellen Lauf steuern, auf eine Folgerunde warten oder beides:

  • steer: Sofort in den aktuellen Lauf injizieren (bricht ausstehende Tool-Aufrufe nach der nächsten Tool-Grenze ab). Ohne Streaming wird auf followup zurückgefallen.
  • followup: Für die nächste Agent-Runde nach Ende des aktuellen Laufs einreihen.
  • collect: Alle wartenden Nachrichten zu einer einzigen Folgerunde zusammenfassen (Standard). Bei Nachrichten für verschiedene Channels/Threads werden sie einzeln verarbeitet, um das Routing zu erhalten.
  • steer-backlog (auch steer+backlog): Jetzt steuern und die Nachricht für eine Folgerunde aufbewahren.
  • interrupt (veraltet): Den aktiven Lauf für diese Session abbrechen, dann die neueste Nachricht ausführen.
  • queue (veralteter Alias): Entspricht steer.

Bei steer-backlog bekommst du nach dem gesteuerten Lauf eine Folgeantwort, was bei Streaming wie Duplikate aussehen kann. Nutze lieber collect/steer, wenn du eine Antwort pro eingehender Nachricht willst.

Sende /queue collect als eigenständigen Befehl (pro Session) oder setze messages.queue.byChannel.discord: "collect".

Standardwerte (wenn nicht konfiguriert):

  • Alle Oberflächen → collect

Konfiguriere global oder pro Channel über messages.queue:

{
  messages: {
    queue: {
      mode: "collect",
      debounceMs: 1000,
      cap: 20,
      drop: "summarize",
      byChannel: { discord: "collect" },
    },
  },
}

Queue-Optionen

Diese Optionen gelten für followup, collect und steer-backlog (und für steer, wenn es auf followup zurückfällt):

  • debounceMs: Wartet auf Ruhe, bevor eine Folgerunde startet (verhindert “weiter, weiter”).
  • cap: Maximale Anzahl wartender Nachrichten pro Session.
  • drop: Überlauf-Strategie (old, new, summarize).

Summarize behält eine kurze Aufzählung der verworfenen Nachrichten und fügt sie als synthetischen Followup-Prompt ein. Standardwerte: debounceMs: 1000, cap: 20, drop: summarize.

Session-spezifische Überschreibungen

  • Sende /queue <mode> als eigenständigen Befehl, um den Modus für die aktuelle Session zu speichern.
  • Optionen lassen sich kombinieren: /queue collect debounce:2s cap:25 drop:summarize
  • /queue default oder /queue reset löscht die Session-Überschreibung.

Geltungsbereich und Garantien

  • Gilt für Auto-Reply-Agent-Läufe über alle eingehenden Channels, die die Gateway-Reply-Pipeline nutzen (WhatsApp Web, Telegram, Slack, Discord, Signal, iMessage, Webchat usw.).
  • Die Standard-Lane (main) gilt prozessweit für eingehende Nachrichten + Haupt-Heartbeats; setze agents.defaults.maxConcurrent, um mehrere Sessions parallel zu erlauben.
  • Zusätzliche Lanes können existieren (z.B. cron, subagent), damit Hintergrund-Jobs parallel laufen können, ohne eingehende Antworten zu blockieren.
  • Pro-Session-Lanes garantieren, dass nur ein Agent-Lauf gleichzeitig eine bestimmte Session bearbeitet.
  • Keine externen Abhängigkeiten oder Hintergrund-Worker-Threads; reines TypeScript + Promises.

Troubleshooting

  • Wenn Befehle hängen zu bleiben scheinen, aktiviere Verbose-Logs und suche nach “queued for …ms”-Zeilen, um zu bestätigen, dass die Queue abgearbeitet wird.
  • Für die Queue-Tiefe aktiviere Verbose-Logs und beobachte die Queue-Timing-Zeilen.