O que logs-de-sessão faz?
Pesquise seu histórico completo de conversas armazenado em arquivos JSONL de sessão. Use esta habilidade quando um usuário fizer referência a conversas mais antigas, conversas pai ou contexto histórico que não está em arquivos de memória.
Gatilho
Use esta habilidade quando o usuário perguntar sobre conversas anteriores, conversas pai ou contexto histórico que não está em arquivos de memória.
Localização
Os logs de sessão estão localizados no diretório de estado ativo:
$OPENCLAW_STATE_DIR/agents/<agentId>/sessions/ (padrão: ~/.openclaw/agents/<agentId>/sessions/).
Use o valor agent=<id> da linha Runtime do prompt do sistema.
sessions.json- Índice mapeando chaves de sessão para IDs de sessão<session-id>.jsonl- Transcrição completa da conversa por sessão<session-id>.jsonl.reset.<timestamp>Z- Transcrição arquivada por/newou/reset<session-id>.jsonl.deleted.<timestamp>Z- Transcrição arquivada quando uma sessão foi deletada
Ao pesquisar o histórico, inclua também as variantes arquivadas (.reset.*, .deleted.*) — elas
ainda contêm conteúdo real de conversa. Os exemplos de glob simples abaixo capturam apenas os
arquivos *.jsonl ativos; use o trecho "Incluir transcrições arquivadas" quando precisar de
recuperação completa.
Estrutura
Cada arquivo .jsonl contém mensagens com:
type: "session" (metadados) ou "message" (mensagem)timestamp: timestamp ISOmessage.role: "user" (usuário), "assistant" (assistente) ou "toolResult" (resultado de ferramenta)message.content[]: Texto, pensamentos ou chamadas de ferramenta (filtretype=="text"para conteúdo legível por humanos)message.usage.cost.total: Custo por resposta
Consultas Comuns
Incluir transcrições arquivadas (.reset.*, .deleted.*)
# Auxiliar Bash que emite cada caminho de transcrição pesquisável — ativa e arquivada.
# Salva e restaura `nullglob` localmente para que as opções do shell do chamador
# não sejam perturbadas.
AGENT_ID="<agentId>"
SESSION_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/agents/$AGENT_ID/sessions"
list_session_transcripts() {
local _nullglob_state
_nullglob_state=$(shopt -p nullglob 2>/dev/null)
shopt -s nullglob
for f in "$SESSION_DIR"/*.jsonl \
"$SESSION_DIR"/*.jsonl.reset.*Z \
"$SESSION_DIR"/*.jsonl.deleted.*Z; do
[ -f "$f" ] && printf '%s\n' "$f"
done
eval "$_nullglob_state"
}
Use list_session_transcripts (ou uma invocação find equivalente) sempre que o
glob simples *.jsonl for mostrado abaixo, se você precisar incluir sessões arquivadas:
find "$SESSION_DIR" -maxdepth 1 -type f \
\( -name '*.jsonl' -o -name '*.jsonl.reset.*Z' -o -name '*.jsonl.deleted.*Z' \) -print
Listar todas as sessões por data e tamanho
AGENT_ID="<agentId>"
SESSION_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/agents/$AGENT_ID/sessions"
for f in "$SESSION_DIR"/*.jsonl; do
date=$(head -1 "$f" | jq -r '.timestamp' | cut -dT -f1)
size=$(ls -lh "$f" | awk '{print $5}')
echo "$date $size $(basename $f)"
done | sort -r
Dica: troque a linha for f in ... por um while-read sobre
list_session_transcripts (veja trecho acima) quando você também quiser arquivos
.reset / .deleted arquivados na listagem. O padrão while-read é seguro
para caminhos com espaços ou outros caracteres IFS:
while IFS= read -r f; do
date=$(head -1 "$f" | jq -r '.timestamp' | cut -dT -f1)
size=$(ls -lh "$f" | awk '{print $5}')
echo "$date $size $(basename "$f")"
done < <(list_session_transcripts) | sort -r
Encontrar sessões de um dia específico
AGENT_ID="<agentId>"
SESSION_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/agents/$AGENT_ID/sessions"
for f in "$SESSION_DIR"/*.jsonl; do
head -1 "$f" | jq -r '.timestamp' | grep -q "2026-01-06" && echo "$f"
done
Extrair mensagens do usuário de uma sessão
jq -r 'select(.message.role == "user") | .message.content[]? | select(.type == "text") | .text' <session>.jsonl
Pesquisar palavra-chave nas respostas do assistente
jq -r 'select(.message.role == "assistant") | .message.content[]? | select(.type == "text") | .text' <session>.jsonl | rg -i "keyword"
Obter custo total de uma sessão
jq -s '[.[] | .message.usage.cost.total // 0] | add' <session>.jsonl
Resumo de custo diário
AGENT_ID="<agentId>"
SESSION_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/agents/$AGENT_ID/sessions"
for f in "$SESSION_DIR"/*.jsonl; do
date=$(head -1 "$f" | jq -r '.timestamp' | cut -dT -f1)
cost=$(jq -s '[.[] | .message.usage.cost.total // 0] | add' "$f")
echo "$date $cost"
done | awk '{a[$1]+=$2} END {for(d in a) print d, "$"a[d]}' | sort -r
Contar mensagens e tokens em uma sessão
jq -s '{
messages: length,
user: [.[] | select(.message.role == "user")] | length,
assistant: [.[] | select(.message.role == "assistant")] | length,
first: .[0].timestamp,
last: .[-1].timestamp
}' <session>.jsonl
Detalhamento de uso de ferramentas
jq -r '.message.content[]? | select(.type == "toolCall") | .name' <session>.jsonl | sort | uniq -c | sort -rn
Pesquisar em TODAS as sessões por uma frase
AGENT_ID="<agentId>"
SESSION_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/agents/$AGENT_ID/sessions"
# Apenas sessões ativas:
rg -l "phrase" "$SESSION_DIR"/*.jsonl
# Sessões ativas + arquivadas (`.reset.*`, `.deleted.*`) — use isso ao verificar
# conteúdo que pode ter sido compactado/resetado/deletado:
rg -l "phrase" "$SESSION_DIR"/*.jsonl \
"$SESSION_DIR"/*.jsonl.reset.*Z \
"$SESSION_DIR"/*.jsonl.deleted.*Z 2>/dev/null
Dicas
- As sessões são JSONL somente anexo (um objeto JSON por linha)
- Sessões grandes podem ter vários MB - use
head/tailpara amostragem - O índice
sessions.jsonmapeia provedores de chat (discord, whatsapp, etc.) para IDs de sessão - Sessões resetadas/compactadas têm sufixo
.jsonl.reset.<timestamp>Z— ainda contêm transcrições completas e são pesquisáveis. - Sessões deletadas têm sufixo
.jsonl.deleted.<timestamp>Z— também ainda pesquisáveis. - Um glob simples
*.jsonlvai perder ambas as formas arquivadas. Inclua-as explicitamente (veja o trecho "Incluir transcrições arquivadas" acima) quando precisar do histórico completo.
Dica rápida somente texto (baixo ruído)
AGENT_ID="<agentId>"
SESSION_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/agents/$AGENT_ID/sessions"
jq -r 'select(.type=="message") | .message.content[]? | select(.type=="text") | .text' "$SESSION_DIR"/<id>.jsonl | rg 'keyword'