Messages and delivery
File d’attente des commandes
Nous sérialisons les exécutions de réponse automatique entrantes (tous les canaux) via une petite file d’attente dans le processus afin d’éviter les collisions entre plusieurs exécutions d’agent, tout en permettant un parallélisme sûr entre les sessions.
Pourquoi
- Les exécutions de réponse automatique peuvent être coûteuses (appels LLM) et entrer en collision lorsque plusieurs messages entrants arrivent presque en même temps.
- La sérialisation évite la concurrence pour des ressources partagées (fichiers de session, journaux, stdin de la CLI) et réduit le risque de limites de débit en amont.
Fonctionnement
- Une file FIFO consciente des voies vide chaque voie avec une limite de concurrence configurable (1 par défaut pour les voies non configurées ;
mainvaut 4 par défaut,subagent8). runEmbeddedPiAgentmet en file d’attente par clé de session (voiesession:<key>) afin de garantir une seule exécution active par session.- Chaque exécution de session est ensuite placée dans une voie globale (
mainpar défaut) afin que le parallélisme global soit limité paragents.defaults.maxConcurrent. - Lorsque la journalisation détaillée est activée, les exécutions en file émettent un court avis si elles ont attendu plus d’environ 2 s avant de démarrer.
- Les indicateurs de saisie se déclenchent toujours immédiatement à l’ajout en file (quand le canal le prend en charge), de sorte que l’expérience utilisateur reste inchangée pendant l’attente du tour.
Valeurs par défaut
Quand rien n’est défini, toutes les surfaces de canaux entrants utilisent :
mode: "steer"debounceMs: 500cap: 20drop: "summarize"
steer est la valeur par défaut, car elle maintient le tour du modèle actif réactif sans
démarrer une seconde exécution de session. Elle vide tous les messages de pilotage arrivés
avant la frontière suivante du modèle. Si l’exécution actuelle ne peut pas accepter de pilotage,
OpenClaw revient à une entrée de file de suivi.
Modes de file
Les messages entrants peuvent piloter l’exécution actuelle, attendre un tour de suivi, ou faire les deux :
steer: place les messages de pilotage dans le runtime actif. Pi livre tous les messages de pilotage en attente après la fin de l’exécution des appels d’outils du tour actuel de l’assistant, avant l’appel LLM suivant ; Codex app-server reçoit un seulturn/steergroupé. Si l’exécution n’est pas en streaming actif ou si le pilotage est indisponible, OpenClaw revient à une entrée de file de suivi.queue(ancien) : ancien pilotage un par un. Pi livre un message de pilotage en file à chaque frontière du modèle ; Codex app-server reçoit des requêtesturn/steerséparées. Préférezsteer, sauf si vous avez besoin du comportement sérialisé précédent.followup: met chaque message en file pour un tour d’agent ultérieur après la fin de l’exécution actuelle.collect: regroupe les messages en file dans un seul tour de suivi après la fenêtre de silence. Si les messages ciblent des canaux/fils différents, ils sont vidés individuellement pour préserver le routage.steer-backlog(aussi appelésteer+backlog) : pilote maintenant et conserve le même message pour un tour de suivi.interrupt(ancien) : abandonne l’exécution active pour cette session, puis exécute le message le plus récent.
Steer-backlog signifie que vous pouvez obtenir une réponse de suivi après l’exécution pilotée ; les
surfaces en streaming peuvent donc ressembler à des doublons. Préférez collect/steer si vous voulez
une réponse par message entrant.
Pour le minutage propre au runtime et le comportement des dépendances, consultez
File de pilotage. Pour la commande explicite /steer <message>,
consultez Piloter.
Configurez globalement ou par canal via messages.queue :
{
messages: {
queue: {
mode: "steer",
debounceMs: 500,
cap: 20,
drop: "summarize",
byChannel: { discord: "collect" },
},
},
}
Options de file
Les options s’appliquent à followup, collect et steer-backlog (ainsi qu’à steer ou à l’ancien queue lorsque le pilotage revient à un suivi) :
debounceMs: fenêtre de silence avant de vider les suivis en file. Les nombres seuls sont des millisecondes ; les unitésms,s,m,hetdsont acceptées par les options de/queue.cap: nombre maximal de messages en file par session. Les valeurs inférieures à1sont ignorées.drop: "summarize": valeur par défaut. Supprime les entrées en file les plus anciennes selon les besoins, conserve des résumés compacts et les injecte comme invite de suivi synthétique.drop: "old": supprime les entrées en file les plus anciennes selon les besoins, sans conserver de résumés.drop: "new": rejette le message le plus récent lorsque la file est déjà pleine.
Valeurs par défaut : debounceMs: 500, cap: 20, drop: summarize.
Priorité
Pour la sélection du mode, OpenClaw résout :
- Remplacement
/queueen ligne ou stocké par session. messages.queue.byChannel.<channel>.messages.queue.mode.- Valeur par défaut
steer.
Pour les options, les options /queue en ligne ou stockées l’emportent sur la configuration. Ensuite,
le debounce propre au canal (messages.queue.debounceMsByChannel), les valeurs par défaut de debounce du Plugin,
les options globales de messages.queue et les valeurs par défaut intégrées sont
appliqués. cap et drop sont des options globales/de session, pas des clés de configuration
par canal.
Remplacements par session
- Envoyez
/queue <mode>comme commande autonome pour stocker le mode de la session actuelle. - Les options peuvent être combinées :
/queue collect debounce:0.5s cap:25 drop:summarize /queue defaultou/queue resetefface le remplacement de session.
Portée et garanties
- S’applique aux exécutions d’agent de réponse automatique sur tous les canaux entrants qui utilisent le pipeline de réponse du Gateway (WhatsApp web, Telegram, Slack, Discord, Signal, iMessage, webchat, etc.).
- La voie par défaut (
main) s’applique à tout le processus pour les entrées + les Heartbeats principaux ; définissezagents.defaults.maxConcurrentpour autoriser plusieurs sessions en parallèle. - Des voies supplémentaires peuvent exister (par exemple
cron,cron-nested,nested,subagent) afin que les tâches d’arrière-plan puissent s’exécuter en parallèle sans bloquer les réponses entrantes. Les tours d’agent cron isolés occupent un emplacementcrontandis que leur exécution d’agent interne utilisecron-nested; les deux utilisentcron.maxConcurrentRuns. Les fluxnestednon cron partagés conservent leur propre comportement de voie. Ces exécutions détachées sont suivies comme des tâches d’arrière-plan. - Les voies par session garantissent qu’une seule exécution d’agent touche une session donnée à la fois.
- Aucune dépendance externe ni thread de travail en arrière-plan ; TypeScript pur + promesses.
Dépannage
- Si les commandes semblent bloquées, activez les journaux détaillés et recherchez les lignes "queued for ...ms" pour confirmer que la file se vide.
- Si vous avez besoin de la profondeur de file, activez les journaux détaillés et surveillez les lignes de minutage de file.
- Les exécutions Codex app-server qui acceptent un tour puis cessent d’émettre une progression sont interrompues par l’adaptateur Codex afin que la voie de session active puisse se libérer au lieu d’attendre le délai d’expiration de l’exécution externe.
- Lorsque les diagnostics sont activés, les sessions qui restent en
processingau-delà dediagnostics.stuckSessionWarnMssans réponse, outil, statut, bloc ou progression ACP observé sont classées selon l’activité actuelle. Le travail actif est journalisé commesession.long_running; le travail actif sans progression récente est journalisé commesession.stalled;session.stuckest réservé à la gestion obsolète de session sans travail actif, et seul ce chemin peut libérer la voie de session affectée afin de vider le travail en file. Les diagnosticssession.stuckrépétés appliquent un délai exponentiel tant que la session reste inchangée.