Gerenciamento de sessão e compactação (análise detalhada)
Este documento explica como o OpenClaw gerencia sessões de ponta a ponta:- Roteamento de sessão (como mensagens de entrada são mapeadas para uma
sessionKey) - Armazenamento de sessão (
sessions.json) e o que ele rastreia - Persistência de transcrição (
*.jsonl) e sua estrutura - Higiene de transcrição (ajustes específicos do provedor antes das execuções)
- Limites de contexto (janela de contexto vs tokens rastreados)
- Compactação (compactação manual + automática) e onde conectar trabalho de pré-compactação
- Manutenção silenciosa (por exemplo, gravações de memória que não devem produzir saída visível ao usuário)
- /concepts/session
- /concepts/compaction
- /concepts/memory
- /concepts/memory-search
- /concepts/session-pruning
- /reference/transcript-hygiene
Fonte da verdade: o Gateway
O OpenClaw foi projetado em torno de um único processo Gateway que detém o estado da sessão.- UIs (app macOS, UI web Control, TUI) devem consultar o Gateway para listas de sessões e contagens de tokens.
- No modo remoto, os arquivos de sessão estão no host remoto; “verificar os arquivos no seu Mac local” não refletirá o que o Gateway está usando.
Duas camadas de persistência
O OpenClaw persiste sessões em duas camadas:-
Armazenamento de sessão (
sessions.json)- Mapa chave/valor:
sessionKey -> SessionEntry - Pequeno, mutável, seguro para editar (ou excluir entradas)
- Rastreia metadados da sessão (id da sessão atual, última atividade, alternâncias, contadores de tokens etc.)
- Mapa chave/valor:
-
Transcrição (
<sessionId>.jsonl)- Transcrição append-only com estrutura em árvore (as entradas têm
id+parentId) - Armazena a conversa real + chamadas de ferramenta + resumos de compactação
- Usada para reconstruir o contexto do modelo para turnos futuros
- Transcrição append-only com estrutura em árvore (as entradas têm
Locais em disco
Por agente, no host do Gateway:- Armazenamento:
~/.openclaw/agents/<agentId>/sessions/sessions.json - Transcrições:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl- Sessões de tópico do Telegram:
.../<sessionId>-topic-<threadId>.jsonl
- Sessões de tópico do Telegram:
src/config/sessions.ts.
Manutenção do armazenamento e controles de disco
A persistência de sessão tem controles automáticos de manutenção (session.maintenance) para sessions.json e artefatos de transcrição:
mode:warn(padrão) ouenforcepruneAfter: limite de idade para entradas obsoletas (padrão30d)maxEntries: limite de entradas emsessions.json(padrão500)rotateBytes: faz rotação desessions.jsonquando fica grande demais (padrão10mb)resetArchiveRetention: retenção para arquivos de arquivamento de transcrição*.reset.<timestamp>(padrão: igual apruneAfter;falsedesabilita a limpeza)maxDiskBytes: orçamento opcional para o diretório de sessõeshighWaterBytes: alvo opcional após a limpeza (padrão80%demaxDiskBytes)
mode: "enforce"):
- Remova primeiro os artefatos de transcrição arquivados ou órfãos mais antigos.
- Se ainda estiver acima da meta, remova as entradas de sessão mais antigas e seus arquivos de transcrição.
- Continue até que o uso esteja em ou abaixo de
highWaterBytes.
mode: "warn", o OpenClaw informa possíveis remoções, mas não altera o armazenamento/arquivos.
Execute a manutenção sob demanda:
Sessões de cron e logs de execução
Execuções isoladas de cron também criam entradas/transcrições de sessão e têm controles de retenção dedicados:cron.sessionRetention(padrão24h) remove sessões antigas de execução isolada de cron do armazenamento de sessões (falsedesabilita).cron.runLog.maxBytes+cron.runLog.keepLinespodam arquivos~/.openclaw/cron/runs/<jobId>.jsonl(padrões:2_000_000bytes e2000linhas).
Chaves de sessão (sessionKey)
Uma sessionKey identifica em qual compartimento de conversa você está (roteamento + isolamento).
Padrões comuns:
- Chat principal/direto (por agente):
agent:<agentId>:<mainKey>(padrãomain) - Grupo:
agent:<agentId>:<channel>:group:<id> - Sala/canal (Discord/Slack):
agent:<agentId>:<channel>:channel:<id>ou...:room:<id> - Cron:
cron:<job.id> - Webhook:
hook:<uuid>(a menos que seja substituído)
IDs de sessão (sessionId)
Cada sessionKey aponta para um sessionId atual (o arquivo de transcrição que continua a conversa).
Regras gerais:
- Reset (
/new,/reset) cria um novosessionIdpara essasessionKey. - Reset diário (padrão 4:00 da manhã no horário local do host do gateway) cria um novo
sessionIdna próxima mensagem após o limite de reset. - Expiração por inatividade (
session.reset.idleMinutesou legadosession.idleMinutes) cria um novosessionIdquando uma mensagem chega após a janela de inatividade. Quando diário + inatividade estão ambos configurados, vale o que expirar primeiro. - Proteção de bifurcação de pai de thread (
session.parentForkMaxTokens, padrão100000) pula a bifurcação da transcrição pai quando a sessão pai já está grande demais; a nova thread começa do zero. Defina0para desabilitar.
initSessionState() em src/auto-reply/reply/session.ts.
Schema do armazenamento de sessão (sessions.json)
O tipo de valor do armazenamento é SessionEntry em src/config/sessions.ts.
Campos principais (não exaustivo):
sessionId: id da transcrição atual (o nome do arquivo é derivado disso, a menos quesessionFileesteja definido)updatedAt: timestamp da última atividadesessionFile: substituição opcional explícita do caminho da transcriçãochatType:direct | group | room(ajuda UIs e política de envio)provider,subject,room,space,displayName: metadados para rotulagem de grupo/canal- Alternâncias:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(substituição por sessão)
- Seleção de modelo:
providerOverride,modelOverride,authProfileOverride
- Contadores de tokens (best-effort / dependentes do provedor):
inputTokens,outputTokens,totalTokens,contextTokens
compactionCount: quantas vezes a compactação automática foi concluída para esta chave de sessãomemoryFlushAt: timestamp do último flush de memória pré-compactaçãomemoryFlushCompactionCount: contagem de compactação quando o último flush foi executado
Estrutura da transcrição (*.jsonl)
As transcrições são gerenciadas pelo SessionManager de @mariozechner/pi-coding-agent.
O arquivo é JSONL:
- Primeira linha: cabeçalho da sessão (
type: "session", incluiid,cwd,timestamp,parentSessionopcional) - Depois: entradas da sessão com
id+parentId(árvore)
message: mensagens de usuário/assistente/toolResultcustom_message: mensagens injetadas por extensão que entram no contexto do modelo (podem ser ocultadas da UI)custom: estado da extensão que não entra no contexto do modelocompaction: resumo persistido da compactação comfirstKeptEntryIdetokensBeforebranch_summary: resumo persistido ao navegar por um ramo da árvore
SessionManager para lê-las/escrevê-las.
Janelas de contexto vs tokens rastreados
Dois conceitos diferentes importam:- Janela de contexto do modelo: limite rígido por modelo (tokens visíveis para o modelo)
- Contadores do armazenamento de sessão: estatísticas acumuladas gravadas em
sessions.json(usadas em /status e dashboards)
- A janela de contexto vem do catálogo de modelos (e pode ser substituída via configuração).
contextTokensno armazenamento é um valor de estimativa/relato em runtime; não o trate como garantia estrita.
Compactação: o que é
A compactação resume a conversa mais antiga em uma entradacompaction persistida na transcrição e mantém as mensagens recentes intactas.
Após a compactação, turnos futuros veem:
- O resumo de compactação
- Mensagens após
firstKeptEntryId
Limites de chunk da compactação e pareamento de ferramentas
Quando o OpenClaw divide uma transcrição longa em chunks de compactação, ele mantém as chamadas de ferramenta do assistente pareadas com suas entradastoolResult correspondentes.
- Se a divisão por participação de tokens cair entre uma chamada de ferramenta e seu resultado, o OpenClaw desloca o limite para a mensagem da chamada de ferramenta do assistente em vez de separar o par.
- Se um bloco final de resultado de ferramenta de outra forma ultrapassaria a meta do chunk, o OpenClaw preserva esse bloco de ferramenta pendente e mantém intacta a cauda não resumida.
- Blocos de chamada de ferramenta abortados/com erro não mantêm uma divisão pendente aberta.
Quando a compactação automática acontece (runtime Pi)
No agente Pi incorporado, a compactação automática é acionada em dois casos:- Recuperação de overflow: o modelo retorna um erro de estouro de contexto
(
request_too_large,context length exceeded,input exceeds the maximum number of tokens,input token count exceeds the maximum number of input tokens,input is too long for the model,ollama error: context length exceedede variantes semelhantes moldadas pelo provedor) → compactar → tentar novamente. - Manutenção por limite: após um turno bem-sucedido, quando:
contextTokens > contextWindow - reserveTokens
Onde:
contextWindowé a janela de contexto do modeloreserveTokensé a folga reservada para prompts + a próxima saída do modelo
Configurações de compactação (reserveTokens, keepRecentTokens)
As configurações de compactação do Pi ficam nas configurações do Pi:
- Se
compaction.reserveTokens < reserveTokensFloor, o OpenClaw o aumenta. - O piso padrão é
20000tokens. - Defina
agents.defaults.compaction.reserveTokensFloor: 0para desabilitar o piso. - Se já estiver mais alto, o OpenClaw o deixa como está.
ensurePiCompactionReserveTokens() em src/agents/pi-settings.ts
(chamado por src/agents/pi-embedded-runner.ts).
Superfícies visíveis ao usuário
Você pode observar a compactação e o estado da sessão por meio de:/status(em qualquer sessão de chat)openclaw status(CLI)openclaw sessions/sessions --json- Modo verboso:
🧹 Auto-compaction complete+ contagem de compactação
Manutenção silenciosa (NO_REPLY)
O OpenClaw oferece suporte a turnos “silenciosos” para tarefas em segundo plano em que o usuário não deve ver saída intermediária.
Convenção:
- O assistente começa sua saída com o token silencioso exato
NO_REPLY/no_replypara indicar “não entregue uma resposta ao usuário”. - O OpenClaw remove/suprime isso na camada de entrega.
- A supressão exata do token silencioso não diferencia maiúsculas de minúsculas, então
NO_REPLYeno_replycontam quando a carga inteira é apenas o token silencioso. - Isso serve apenas para turnos realmente em segundo plano/sem entrega; não é um atalho para solicitações normais acionáveis do usuário.
2026.1.10, o OpenClaw também suprime streaming de rascunho/digitação quando um
chunk parcial começa com NO_REPLY, para que operações silenciosas não vazem saída parcial no meio do turno.
”Memory flush” pré-compactação (implementado)
Objetivo: antes que a compactação automática aconteça, executar um turno agêntico silencioso que grave estado durável em disco (por exemplo,memory/YYYY-MM-DD.md no workspace do agente) para que a compactação não possa
apagar contexto crítico.
O OpenClaw usa a abordagem de flush antes do limite:
- Monitorar o uso de contexto da sessão.
- Quando ele cruza um “limite suave” (abaixo do limite de compactação do Pi), executar uma diretiva silenciosa “gravar memória agora” para o agente.
- Usar o token silencioso exato
NO_REPLY/no_replypara que o usuário não veja nada.
agents.defaults.compaction.memoryFlush):
enabled(padrão:true)softThresholdTokens(padrão:4000)prompt(mensagem do usuário para o turno de flush)systemPrompt(prompt extra de sistema acrescentado ao turno de flush)
- O prompt/system prompt padrão inclui uma dica
NO_REPLYpara suprimir a entrega. - O flush é executado uma vez por ciclo de compactação (rastreado em
sessions.json). - O flush é executado apenas para sessões Pi incorporadas (backends de CLI o ignoram).
- O flush é ignorado quando o workspace da sessão é somente leitura (
workspaceAccess: "ro"ou"none"). - Veja Memória para o layout de arquivos do workspace e padrões de gravação.
session_before_compact na API de extensão, mas a lógica de
flush do OpenClaw vive hoje no lado do Gateway.
Checklist de solução de problemas
- Chave de sessão errada? Comece com /concepts/session e confirme a
sessionKeyem/status. - Incompatibilidade entre armazenamento e transcrição? Confirme o host do Gateway e o caminho do armazenamento em
openclaw status. - Spam de compactação? Verifique:
- janela de contexto do modelo (pequena demais)
- configurações de compactação (
reserveTokensalto demais para a janela do modelo pode causar compactação mais cedo) - inchaço de tool-result: habilite/ajuste a poda de sessão
- Turnos silenciosos vazando? Confirme que a resposta começa com
NO_REPLY(token exato sem diferenciação de maiúsculas/minúsculas) e que você está em uma build que inclui a correção de supressão de streaming.