Skip to content

CH 10 · El log de sesión como fuente de verdad

Cantidad de texto~2.340 palabrasTiempo~12 minPrereqFlujo de mensaje de CH 09NivelConceptual

Objetivo del capítulo

CH 09 cubrió el "libro de cuentas" (session); este capítulo lo desempaca: por qué es la fuente de verdad de toda la máquina — lo que el modelo recuerda, la trajectory que ves, la transcripción que puedes exportar, la nueva rama que puedes bifurcar, todo se deriva de este único log, que él mismo solo crece, nunca se edita.

Una línea: el log de sesión = libro de cuentas, memoria y archivo del Agent

La definición oficial de Session es estricta, dividida en tres puntos:

  1. Append-only: solo se añaden registros al final, sin modificación, sin borrar los antiguos.
  2. Eventos tipados: cada línea no es texto libre, sino un tipo de "evento" — turn/start, user/message, assistant/message, tool/result, turn/end...
  3. Única fuente de verdad: todo el historial de interacción del agent, esta es la única cosa que es real; todo lo demás es una proyección suya.

Conectándolo con CH 09 queda muy fluido: el "flujo de mensajes" que viste en el capítulo anterior, cada paso en realidad está escribiendo un evento en este logturn/start abre el turn, step/start empieza un step, user/message registra lo que enviaste, assistant/message registra lo que respondió el modelo, tool/result registra qué herramientas corrieron, turn/end cierra el turn.

Regla nemotécnica: el flujo es "lo que está pasando", el log es "el registro de lo que pasó", uno a uno entre ellos.

Por qué es la "fuente de verdad"

Palabras oficiales:

El historial de mensajes del modelo se deriva del log, nunca se almacena por separado.

Significado: en dsh, no hay una segunda copia del registro de la conversación. Piensas "el modelo recuerda lo que se dijo antes", pero el historial que ve el modelo se proyecta desde el log; la vista de Trajectory que ves, las transcripciones que puedes exportar, los forks que puedes abrir — todo se renderiza desde este mismo log:

El log de sesión = fuente de verdad: todo se deriva de él (ilustración)

  • Historial de conversación del modelo: deriveMessages() proyecta el Message[] que ve el modelo desde el log — así que "lo que el modelo recuerda" = "lo que está en el log";
  • Vista de Trajectory: el timeline ASSISTANT / TOOL que viste en CH 04, no es más que una visualización del log;
  • Transcripción / exportación: texto completo de la conversación, reproducido desde el log;
  • Bifurcación fork: hacer crecer una nueva sesión en algún nodo histórico;
  • Telemetría / estadísticas: uso de tokens, tiempo invertido, calculado desde el log;
  • Archivo de persistencia: el session.jsonl.zstd en $DSH_HOME/sessions.

¿Por qué tiene que estar diseñado así? Porque una sola fuente de verdad significa que nunca tienes "lo que se muestra en la UI, lo que el modelo recuerda y lo que se exporta — tres copias que no coinciden". Las otras vistas son todas proyecciones del mismo log, con reglas consistentes, siempre consistentes.

"Lo que ve el modelo es lo que está registrado": el eje del diseño

Esta es una regla dura en dsh, mencionada en el capítulo anterior, ampliada aquí:

Cualquier cosa que llegue a una petición al modelo debe ser reconstruible desde el log, y el runtime lo comprueba con un invariante.

Conduce a dos corolarios directos:

  1. Para añadir algo nuevo que vea el modelo, debes añadir un nuevo tipo de evento. Por ejemplo, si quieres que el Agent vea un fragmento de contexto inyectado, no puedes saltarte el log y meterlo directamente en la petición — en su lugar, define un nuevo evento de sesión, escríbelo en el log y proyéctalo desde el log. Esto hace que cada paso sea trazable, y es la garantía subyacente de esa frase de la página de inicio "cada ejecución es trazable".
  2. El log no tiene pérdidas. Incluso los chunks crudos de streaming que devuelve el modelo se preservan (assistant/chunk), así que la reproducción puede ser fiel token por token, y la UI puede restaurarla exactamente.

Una línea: este diseño hace que "trazable" no sea un eslogan, sino una inevitabilidad arquitectónica.

Una referencia rápida con CH 04: el comando /compact que usaste para comprimir contexto, por debajo, solo registra una acción de "he comprimido" en el log (evento compaction/*), y proyecta una forma más depurada al modelo desde el log. No reescribe la historia — los eventos originales siguen en el log, solo se reordena la proyección que ve el modelo. Por eso el Agent "recuerda" una versión más depurada después de la compresión, pero el registro original sigue completo.

Cómo se ve realmente: logs de sesión locales

Volviendo a tu propia máquina — toma este ordenador como ejemplo (después de que CH 05 ejecutó headless, esto existe aquí):

C:\Users\mortal\.dsh\
├─ profiles\            ← lista de profiles (las "cartas" de CH 08)
├─ sessions\            ← logs de sesión aquí
│  ├─ --E-software-workspace-DeepSeek~0020harness~0020demo--\
│  │  └─ session-307edce2-...\session.jsonl.zstd   ← el registro de la ejecución headless de CH 05
│  └─ --E-software-workspace-doubaowork-DeepSeekHarnessGuide--\
│     └─ session-f417b4dd-...\session.jsonl.zstd   ← sesiones usadas en este proyecto
├─ storages\
├─ settings.yaml
└─ .credentials.yaml

Algunos puntos:

  • Directorios por workspace: los nombres de directorio son escapes de rutas de workspace (los espacios se convierten en ~0020), así puedes ver de un vistazo qué sesión se produjo mientras trabajabas dónde;
  • Una carpeta por sesión, dentro está session.jsonl.zstd — un archivo de persistencia JSONL línea por línea append + comprimido con zstd;
  • Haciendo eco del "Sin agrupar" de CH 05: estos archivos se almacenan por workspace, pero la lista de sesiones de la Web UI agrupa las ejecuciones headless en Sin agrupar — no confundas las dos dimensiones;
  • Estos archivos son el "archivo de memoria" de la sesión, no los borres a la ligera. Si los borras, la "memoria" de esa sesión se habrá ido de verdad.

fork: hacer crecer una nueva sesión desde el log

Como el log se puede reproducir de principio a fin, naturalmente puedes "volver a crecer desde cierta posición" — el equipo oficial lo llama fork: clona todos los eventos antes de una posición estable como la apertura de una nueva sesión, y luego toma caminos separados. El uso es directo: quieres probar un camino nuevo en algún nodo histórico sin tocar la sesión original. Los detalles de cómo usarlo los veremos en los capítulos prácticos posteriores; por ahora, quédate con "existe, y la razón de que pueda existir es precisamente que el log se puede reproducir de principio a fin".

Lo que aprendiste en este capítulo

  • [ ] Enunciar las tres características del log de sesión (append-only / eventos tipados / única fuente de verdad)
  • [ ] Emparejar uno a uno el flujo de mensajes de CH 09 con los eventos del log (turn/start, user/message, assistant/message, tool/result, turn/end)
  • [ ] Explicar "el historial del modelo se deriva del log, nunca se almacena por separado", y por qué esto evita tres copias que no coinciden
  • [ ] Enunciar los dos corolarios de "lo que ve el modelo es lo que está registrado" (añadir cosas nuevas = añadir nuevos tipos de evento; log sin pérdidas se puede reproducir token por token)
  • [ ] Saber dónde están los logs de sesión locales ($DSH_HOME/sessions con directorios por workspace, session.jsonl.zstd), y la diferencia con "Sin agrupar" de la Web UI

Open Source · MIT · Community Driven