Coda dei comandi (2026-01-16)
Serializziamo le esecuzioni di risposta automatica in entrata (tutti i canali) tramite una piccola coda in-process per impedire che più esecuzioni dell’agente entrino in conflitto, consentendo comunque un parallelismo sicuro tra le sessioni.Perché
- Le esecuzioni di risposta automatica possono essere costose (chiamate LLM) e possono entrare in conflitto quando arrivano più messaggi in entrata a breve distanza l’uno dall’altro.
- La serializzazione evita la competizione per risorse condivise (file di sessione, log, stdin della CLI) e riduce la probabilità di limiti di velocità upstream.
Come funziona
- Una coda FIFO consapevole delle corsie svuota ogni corsia con un limite di concorrenza configurabile (predefinito 1 per le corsie non configurate;
mainè predefinita a 4,subagenta 8). runEmbeddedPiAgentaccoda per chiave di sessione (corsiasession:<key>) per garantire una sola esecuzione attiva per sessione.- Ogni esecuzione di sessione viene quindi accodata in una corsia globale (
mainper impostazione predefinita) in modo che il parallelismo complessivo sia limitato daagents.defaults.maxConcurrent. - Quando il logging verbose è abilitato, le esecuzioni accodate emettono un breve avviso se hanno atteso più di ~2s prima di iniziare.
- Gli indicatori di digitazione continuano comunque a essere attivati immediatamente all’accodamento (quando supportati dal canale), quindi l’esperienza utente resta invariata mentre si attende il proprio turno.
Modalità della coda (per canale)
I messaggi in entrata possono indirizzare l’esecuzione corrente, attendere un turno di followup o fare entrambe le cose:steer: inserisce immediatamente nell’esecuzione corrente (annulla le chiamate agli strumenti in sospeso dopo il successivo limite dello strumento). Se non c’è streaming, ripiega su followup.followup: accoda per il turno successivo dell’agente dopo la fine dell’esecuzione corrente.collect: unisce tutti i messaggi accodati in un singolo turno di followup (predefinito). Se i messaggi hanno come destinazione canali/thread diversi, vengono svuotati singolarmente per preservare l’instradamento.steer-backlog(aliassteer+backlog): indirizza ora e conserva il messaggio per un turno di followup.interrupt(legacy): interrompe l’esecuzione attiva per quella sessione, quindi esegue il messaggio più recente.queue(alias legacy): uguale asteer.
collect/steer se vuoi
una risposta per ogni messaggio in entrata.
Invia /queue collect come comando standalone (per sessione) oppure imposta messages.queue.byChannel.discord: "collect".
Valori predefiniti (quando non impostati nella configurazione):
- Tutte le superfici →
collect
messages.queue:
Opzioni della coda
Le opzioni si applicano afollowup, collect e steer-backlog (e a steer quando ripiega su followup):
debounceMs: attende una pausa di quiete prima di avviare un turno di followup (evita “continue, continue”).cap: numero massimo di messaggi accodati per sessione.drop: criterio di overflow (old,new,summarize).
debounceMs: 1000, cap: 20, drop: summarize.
Override per sessione
- Invia
/queue <mode>come comando standalone per memorizzare la modalità per la sessione corrente. - Le opzioni possono essere combinate:
/queue collect debounce:2s cap:25 drop:summarize /queue defaulto/queue resetcancella l’override della sessione.
Ambito e garanzie
- Si applica alle esecuzioni dell’agente con risposta automatica in tutti i canali in entrata che usano la pipeline di risposta del gateway (WhatsApp web, Telegram, Slack, Discord, Signal, iMessage, webchat, ecc.).
- La corsia predefinita (
main) è a livello di processo per i messaggi in entrata + heartbeat principali; impostaagents.defaults.maxConcurrentper consentire più sessioni in parallelo. - Possono esistere corsie aggiuntive (ad esempio
cron,subagent) in modo che i job in background possano essere eseguiti in parallelo senza bloccare le risposte in entrata. Queste esecuzioni separate sono tracciate come attività in background. - Le corsie per sessione garantiscono che solo un’esecuzione dell’agente alla volta tocchi una determinata sessione.
- Nessuna dipendenza esterna o thread worker in background; solo TypeScript + promise.
Risoluzione dei problemi
- Se i comandi sembrano bloccati, abilita i log verbose e cerca le righe “queued for …ms” per confermare che la coda si stia svuotando.
- Se hai bisogno della profondità della coda, abilita i log verbose e osserva le righe relative ai tempi della coda.