Messages and delivery
Fila de comandos
Serializamos execuções de resposta automática de entrada (todos os canais) por meio de uma pequena fila em processo para impedir que várias execuções de agente colidam, ainda permitindo paralelismo seguro entre sessões.
Por quê
- Execuções de resposta automática podem ser caras (chamadas de LLM) e podem colidir quando várias mensagens de entrada chegam muito próximas.
- A serialização evita disputa por recursos compartilhados (arquivos de sessão, logs, stdin da CLI) e reduz a chance de limites de taxa upstream.
Como funciona
- Uma fila FIFO ciente de lanes esvazia cada lane com um limite de concorrência configurável (padrão 1 para lanes não configuradas; main usa 4 por padrão, subagent usa 8).
runEmbeddedAgentenfileira por chave de sessão (lanesession:<key>) para garantir apenas uma execução ativa por sessão.- Cada execução de sessão é então enfileirada em uma lane global (
mainpor padrão), de modo que o paralelismo geral seja limitado poragents.defaults.maxConcurrent. - Quando o logging verboso está ativado, execuções enfileiradas emitem um aviso curto se esperarem mais de ~2s antes de iniciar.
- Indicadores de digitação ainda disparam imediatamente ao enfileirar (quando compatíveis com o canal), portanto a experiência do usuário permanece inalterada enquanto aguardamos nossa vez.
Padrões
Quando não definido, todas as superfícies de canal de entrada usam:
mode: "steer"debounceMs: 500cap: 20drop: "summarize"
O direcionamento no mesmo turno é o padrão. Um prompt que chega no meio da execução é injetado no runtime ativo quando a execução pode aceitar direcionamento, então nenhuma segunda execução de sessão é iniciada. Se a execução ativa não puder aceitar direcionamento, o OpenClaw espera a execução ativa terminar antes de iniciar o prompt.
Modos de fila
/queue controla o que mensagens de entrada normais fazem enquanto uma sessão já tem
uma execução ativa:
steer: injeta mensagens no runtime ativo. O OpenClaw entrega todas as mensagens de direcionamento pendentes depois que o turno atual do assistente termina de executar suas chamadas de ferramenta, antes da próxima chamada de LLM; o app-server do Codex recebe umturn/steerem lote. Se a execução não estiver transmitindo ativamente ou se o direcionamento estiver indisponível, o OpenClaw espera até que a execução ativa termine antes de iniciar o prompt.followup: não direciona. Enfileira cada mensagem para um turno posterior do agente depois que a execução atual termina.collect: não direciona. Agrupa mensagens enfileiradas em um único turno de acompanhamento após a janela de silêncio. Se as mensagens apontarem para canais/threads diferentes, elas são esvaziadas individualmente para preservar o roteamento.interrupt: aborta a execução ativa dessa sessão e então executa a mensagem mais recente.
Para comportamento de timing e dependência específico do runtime, consulte
Fila de direcionamento. Para o comando explícito /steer <message>,
consulte Direcionar.
Configure globalmente ou por canal via messages.queue:
{ messages: { queue: { mode: "steer", debounceMs: 500, cap: 20, drop: "summarize", byChannel: { discord: "collect" }, }, },}Opções de fila
As opções se aplicam à entrega enfileirada. debounceMs também define a
janela de silêncio de direcionamento do Codex no modo steer:
debounceMs: janela de silêncio antes de esvaziar acompanhamentos enfileirados ou lotes collect; no modosteerdo Codex, janela de silêncio antes de enviarturn/steerem lote. Números simples são milissegundos; as unidadesms,s,m,hedsão aceitas por opções de/queue.cap: máximo de mensagens enfileiradas por sessão. Valores abaixo de1são ignorados.drop: "summarize": padrão. Descarta as entradas enfileiradas mais antigas conforme necessário, mantém resumos compactos e os injeta como um prompt sintético de acompanhamento.drop: "old": descarta as entradas enfileiradas mais antigas conforme necessário, sem preservar resumos.drop: "new": rejeita a mensagem mais recente quando a fila já está cheia.
Padrões: debounceMs: 500, cap: 20, drop: summarize.
Direcionamento e streaming
Quando o streaming do canal é partial ou block, o direcionamento pode parecer várias
respostas visíveis curtas enquanto a execução ativa alcança limites do runtime:
partial: a prévia pode finalizar cedo e então uma nova prévia começa depois que o direcionamento é aceito.block: blocos do tamanho de rascunho podem criar a mesma aparência sequencial.- Sem streaming, o direcionamento recai para um acompanhamento após a execução ativa quando o runtime não consegue aceitar direcionamento no mesmo turno.
steer não aborta ferramentas em andamento. Use /queue interrupt quando a mensagem
mais recente deve abortar a execução atual.
Precedência
Para seleção de modo, o OpenClaw resolve:
- Sobrescrita de
/queueinline ou armazenada por sessão. messages.queue.byChannel.<channel>.messages.queue.mode.steerpadrão.
Para opções, opções inline ou armazenadas de /queue têm precedência sobre a configuração. Em seguida,
são aplicados debounce específico por canal (messages.queue.debounceMsByChannel), padrões de
debounce do Plugin, opções globais de messages.queue e padrões integrados.
cap e drop são opções globais/de sessão, não chaves de configuração por canal.
Sobrescritas por sessão
- Envie
/queue <steer|followup|collect|interrupt>como um comando independente para armazenar o modo de fila da sessão atual. - Opções podem ser combinadas:
/queue collect debounce:0.5s cap:25 drop:summarize /queue defaultou/queue resetlimpa a sobrescrita da sessão.
Escopo e garantias
- Aplica-se a execuções de agente de resposta automática em todos os canais de entrada que usam o pipeline de resposta do Gateway (WhatsApp web, Telegram, Slack, Discord, Signal, iMessage, webchat, etc.).
- A lane padrão (
main) é ampla ao processo para entradas + heartbeats principais; definaagents.defaults.maxConcurrentpara permitir várias sessões em paralelo. - Lanes adicionais podem existir (por exemplo,
cron,cron-nested,nested,subagent) para que trabalhos em segundo plano possam executar em paralelo sem bloquear respostas de entrada. Turnos isolados de agente cron seguram um slotcronenquanto sua execução interna de agente usacron-nested; ambos usamcron.maxConcurrentRuns. Fluxos compartilhados não cronnestedmantêm seu próprio comportamento de lane. Essas execuções desvinculadas são rastreadas como tarefas em segundo plano. - Lanes por sessão garantem que apenas uma execução de agente toque uma determinada sessão por vez.
- Sem dependências externas ou threads de worker em segundo plano; TypeScript puro + promises.
Solução de problemas
- Se os comandos parecerem travados, ative logs verbosos e procure linhas "queued for ...ms" para confirmar que a fila está sendo esvaziada.
- Se você precisar da profundidade da fila, ative logs verbosos e observe as linhas de timing da fila.
- Execuções do app-server do Codex que aceitam um turno e então param de emitir progresso são interrompidas pelo adaptador do Codex para que a lane de sessão ativa possa ser liberada em vez de esperar pelo timeout da execução externa.
- Quando diagnósticos estão ativados, sessões que permanecem em
processingalém dediagnostics.stuckSessionWarnMssem resposta, ferramenta, status, bloco ou progresso ACP observado são classificadas pela atividade atual. Trabalho ativo é registrado comosession.long_running; chamadas de modelo silenciosas com proprietário também permanecemsession.long_runningatédiagnostics.stuckSessionAbortMs, para que provedores lentos ou sem streaming não sejam reportados como parados cedo demais. Trabalho ativo sem progresso recente é registrado comosession.stalled; chamadas de modelo com proprietário mudam parasession.stalledno ou após o limite de abort, e atividade antiga de modelo/ferramenta sem proprietário não é ocultada como longa execução.session.stucké reservado para bookkeeping recuperável de sessão antiga, incluindo sessões enfileiradas ociosas com atividade antiga de modelo/ferramenta sem proprietário, e somente esse caminho pode liberar a lane da sessão afetada para que o trabalho enfileirado seja esvaziado. Diagnósticossession.stuckrepetidos fazem backoff enquanto a sessão permanece inalterada.