CH 10 · Log de Sessão como Fonte da Verdade
Objetivo do Capítulo
O CH 09 cobriu o "livro-razão" (sessão); este capítulo o desdobra: por que ele é a fonte da verdade da máquina inteira — o que o modelo lembra, a trajectory que você vê, a transcrição que você pode exportar, o novo branch que você pode abrir em fork, todos derivados deste único log, que por si só apenas cresce, nunca edita.
Uma Frase: Log de Sessão = Razão, Memória e Arquivo do Agent
A definição oficial de Session é direta, dividida em três pontos:
- Append-only: apenas adicione registros na cauda, sem modificação, sem exclusão dos antigos.
- Eventos tipados: cada linha não é texto de forma livre, mas um tipo de "evento" —
turn/start,user/message,assistant/message,tool/result,turn/end... - Fonte única da verdade: o histórico inteiro de interação do agent, este é o único que é real; todo o resto é uma projeção dele.
Conectando ao CH 09 fica bem suave: o "fluxo de mensagem" que você viu no capítulo anterior, cada step na verdade está escrevendo um evento neste log — turn/start abre o turn, step/start inicia uma step, user/message registra o que você enviou, assistant/message registra o que o modelo respondeu, tool/result registra quais ferramentas rodaram, turn/end fecha o turn.
Mnemônica: o fluxo é "o que está acontecendo", o log é "o registro do que aconteceu", um-para-um entre eles.
Por Que é a "Fonte da Verdade"
Palavras oficiais:
O histórico de mensagens do modelo é derivado do log, nunca armazenado separadamente.
Significado: no dsh, não há segunda cópia do registro de conversa. Você pensa "o modelo lembra o que foi dito antes", mas o histórico que o modelo vê é projetado a partir do log; a visão de Trajectory que você vê, as transcrições que você pode exportar, os forks que você pode abrir — todos renderizados a partir deste mesmo log:
- Histórico de conversa do modelo:
deriveMessages()projeta oMessage[]que o modelo vê a partir do log — então "o que o modelo lembra" = "o que está no log"; - Visão de Trajectory: a timeline
ASSISTANT / TOOLque você viu no CH 04, é apenas uma visualização do log; - Transcrição / exportação: texto completo da conversa, reproduzido a partir do log;
- Branch de fork: cresce uma nova sessão em algum nó histórico;
- Telemetria / estatísticas: uso de tokens, tempo gasto, computado a partir do log;
- Arquivo de persistência: o
session.jsonl.zstdem$DSH_HOME/sessions.
Por que deve ser projetado assim? Porque apenas uma fonte da verdade significa que você nunca tem "o que é mostrado na UI, o que o modelo lembra, e o que é exportado — três cópias que não batem". Outras visões são todas projeções do mesmo log, com regras consistentes, sempre consistentes.
"O Que o Modelo Vê é o Que é Registrado": O Eixo do Design
Esta é uma regra rígida no dsh, mencionada no capítulo anterior, expandida aqui:
Qualquer coisa que chegue a uma requisição de modelo deve ser reconstruível a partir do log, e o runtime verifica isso com um invariante.
Isso leva a dois corolários diretos:
- Para adicionar algo novo para o modelo ver, você deve adicionar um novo tipo de evento. Por exemplo, se você quer que o Agent veja um pedaço injetado de contexto, você não pode contornar o log e enfiá-lo diretamente na requisição — em vez disso, defina um novo evento de sessão, escreva-o no log, e projete-o a partir do log. Isso torna cada step rastreável, e é a garantia subjacente daquela frase da homepage "cada execução é rastreável".
- O log é sem perdas. Até mesmo os chunks brutos de streaming retornados pelo modelo são preservados (
assistant/chunk), então a reprodução pode ser fiel token por token, e a UI pode restaurá-lo exatamente.
Uma frase: este design torna "rastreável" não um slogan, mas uma inevitabilidade arquitetural.
Uma referência cruzada rápida com o CH 04: o comando /compact que você usou para comprimir contexto, por baixo dos panos, apenas registra uma ação "eu comprimi" no log (evento compaction/*), e projeta uma forma mais refinada para o modelo a partir do log. Ele não reescreve o histórico — os eventos originais ainda estão no log, apenas a projeção que o modelo vê é rearranjada. É também por isso que o Agent "lembra" uma versão mais refinada após a compressão, mas o registro original ainda está completo.
Como é na Real: Logs de Sessão Locais
De volta à sua própria máquina — tome este computador como exemplo (depois que o CH 05 rodou headless, isto existe aqui):
C:\Users\mortal\.dsh\
├─ profiles\ ← lista de profiles (os "cards" do CH 08)
├─ sessions\ ← logs de sessão aqui
│ ├─ --E-software-workspace-DeepSeek~0020harness~0020demo--\
│ │ └─ session-307edce2-...\session.jsonl.zstd ← o registro do headless do CH 05
│ └─ --E-software-workspace-doubaowork-DeepSeekHarnessGuide--\
│ └─ session-f417b4dd-...\session.jsonl.zstd ← sessões usadas neste projeto
├─ storages\
├─ settings.yaml
└─ .credentials.yamlAlguns pontos:
- Diretórios por workspace: nomes de diretório são escapes de caminhos de workspace (espaços viram
~0020), então você pode ver de relance qual sessão foi produzida enquanto trabalhava onde; - Uma pasta por sessão, dentro está
session.jsonl.zstd— um arquivo de persistência JSONL linha por linha append + comprimido com zstd; - Ecoando o "Sem agrupamento" do CH 05: esses arquivos são armazenados por workspace, mas a lista de sessões da Web UI agrupa execuções headless em Sem agrupamento — não confunda as duas dimensões;
- Esses arquivos são o "arquivo de memória" da sessão, não os delete por aí. Delete-os, e a "memória" daquela sessão se foi de verdade.
fork: Crescendo uma Nova Sessão a partir do Log
Como o log pode ser reproduzido por inteiro, naturalmente você pode "regredir a partir de uma certa posição" — a equipe oficial chama isso de fork: clone todos os eventos antes de uma posição estável como a abertura de uma nova sessão, então siga caminhos separados. O uso é direto: quer tentar um novo caminho em algum nó histórico sem mexer na sessão original. Os detalhes de como usá-lo, vamos chegar nos capítulos práticos posteriores; por agora, apenas saiba "existe, e a razão de poder existir é precisamente que o log pode ser reproduzido por inteiro".
O que você aprendeu neste capítulo
- [ ] Afirmar as três características do log de sessão (append-only / eventos tipados / fonte única da verdade)
- [ ] Emparelhar o fluxo de mensagem do CH 09 com eventos do log um-para-um (turn/start, user/message, assistant/message, tool/result, turn/end)
- [ ] Explicar "o histórico do modelo é derivado do log, nunca armazenado separadamente", e por que isso evita três cópias que não batem
- [ ] Afirmar os dois corolários de "o que o modelo vê é o que é registrado" (adicionar coisas novas = adicionar novos tipos de evento; log sem perdas pode ser reproduzido token por token)
- [ ] Saber onde estão os logs de sessão locais ($DSH_HOME/sessions com diretórios por workspace, session.jsonl.zstd), e a diferença com o "Sem agrupamento" da Web UI
