Phase 14 - Lesson 34

Memória do Repositório e Estado Durável

O histórico do chat é volátil. O repositório é durável. A workbench armazena o estado do agente em arquivos versionados para que a próxima sessão, o próximo agente e o próximo revisor leiam todos da mesma fonte da verdade.

Tipo: Build Linguagens: Python (stdlib + jsonschema opcional) Pré-requisitos: Fase 14 · 32 (Minimal Workbench) Tempo: ~60 minutos

Objetivos de Aprendizagem

  • Definir o que pertence à memória do repositório e o que pertence ao histórico do chat.
  • Criar JSON Schemas para agent_state.json e task_board.json.
  • Construir um gerenciador de estado que carrega, valida, modifica e persiste o estado de forma atômica.
  • Usar o schema para rejeitar gravações inválidas antes que corrompam a workbench.

O Problema

O agente finaliza uma sessão. O chat é fechado. A próxima sessão é aberta e pergunta por onde começar. O modelo diz "deixe-me verificar os arquivos", lê notas desatualizadas e refaz o trabalho que já estava concluído. Ou pior, ele reescreve um arquivo finalizado porque ninguém lhe disse que o arquivo estava pronto.

A solução da workbench é a memória do repositório: o estado reside em arquivos JSON no repositório, escritos sob um schema, persistidos de forma atômica e fáceis de visualizar diferenças (diff-friendly) em revisões de código. O chat é um fluxo transitório; o repositório é o sistema de registro.

O Conceito

flowchart LR
  Agent[Loop do Agente] --> Manager[StateManager]
  Manager --> Schema[agent_state.schema.json]
  Schema --> Validate{válido?}
  Validate -- sim --> Write[agent_state.json]
  Validate -- não --> Reject[rejeitar + lançar erro]
  Write --> Manager

O que pertence à memória do repositório

Pertence Não pertence
ID da tarefa ativa Transcrições brutas de chat
Arquivos modificados nesta sessão Rastreamento de raciocínio a nível de token
Suposições que o agente fez "O usuário parecia frustrado"
Bloqueios em aberto Amostras de conclusões (completions)
Próxima ação IDs de modelos específicos do provedor

O teste é a durabilidade: isso seria útil daqui a três meses em uma execução de CI? Se sim, vai para o repositório. Se não, é telemetria.

Estado schema-first

O JSON Schema é o contrato. Sem ele, cada agente inventa novos campos, cada revisor precisa aprender um novo formato e cada script de CI tem que tratar versões anteriores como casos especiais. Com ele, uma gravação ruim é uma gravação recusada.

O schema cobre:

  • Chaves obrigatórias.
  • Valores de status permitidos.
  • Valores proibidos (por exemplo, null para arrays).
  • Restrições de padrão (IDs de tarefas correspondendo a T-\d{3,}).
  • Campo de versão para migrações.

Gravações atômicas

As gravações de estado precisam sobreviver a falhas parciais: gravar em um arquivo temporário, realizar fsync e renomear substituindo o destino. O arquivo de estado é a fonte da verdade; um arquivo gravado pela metade é pior do que nenhum arquivo.

Migrações

Quando o schema mudar, envie um script de migração junto com a atualização do schema. O arquivo de estado carrega um campo schema_version; o gerenciador se recusa a carregar um arquivo de uma versão que não pode migrar.

Construa

code/main.py implementa:

  • agent_state.schema.json e task_board.schema.json.
  • Um validador que usa apenas a stdlib (subconjunto do JSON Schema: required, type, enum, pattern, items).
  • StateManager.load, StateManager.update, StateManager.commit com gravações atômicas do tipo cria-temporário-e-renomeia (temp-and-rename).
  • Uma demonstração que modifica o estado, persiste, recarrega e prova o ciclo completo (round-trip).

Execute:

python3 code/main.py

O script grava workdir/agent_state.json e workdir/task_board.json, modifica-os ao longo de dois turnos e imprime o estado validado em cada etapa.

Padrões de produção na prática

Quatro padrões transformam o mínimo desta lição em algo que um monorepo multiagente consegue suportar.

Gravação atômica com temporário e renomeação não é opcional. Um relatório de bug do projeto Hive de março de 2026 documenta claramente o modo de falha: state.json era gravado via write_text() e as exceções eram capturadas e silenciadas. Gravações parciais faziam com que as sessões fossem retomadas com estados corrompidos sem qualquer sinal de alerta. A correção é sempre: tempfile.mkstemp no mesmo diretório do destino, escrever, fsync, os.replace (renomeação atômica em POSIX e Windows). O atomic_write desta lição faz exatamente isso.

Chaves de idempotência em cada chamada de ferramenta não idempotente. Se um agente falhar após chamar uma ferramenta, mas antes de salvar o ponto de verificação (checkpoint) do resultado, a recuperação repetirá a chamada da ferramenta. Isso é seguro para leituras, mas perigoso para e-mails, inserções no banco de dados e uploads de arquivos. O padrão: registrar cada ID de chamada de ferramenta em um pending_calls.jsonl antes da execução. Na tentativa de repetição, verificar o ID; se estiver presente, pular a chamada e usar o resultado em cache. A Anthropic e o LangChain destacam isso em suas diretrizes de 2026; o checkpointer do LangGraph persiste as gravações pendentes pelo mesmo motivo.

Separe artefatos grandes do estado. Não armazene arquivos CSV, transcrições longas ou arquivos gerados em agent_state.json. Salve o artefato como um arquivo separado (ou faça o upload para um armazenamento de objetos) e mantenha apenas o caminho no estado. Os checkpoints continuam pequenos e rápidos; os artefatos crescem de forma independente.

Event sourcing para auditoria, snapshots para retomar. Adicione a um log de eventos (state.events.jsonl) a cada modificação; faça snapshots periódicos para state.json. A retomada lê o snapshot e, em seguida, reproduz todos os eventos após o carimbo de data/hora (timestamp) do snapshot. Isso custa mais espaço em disco, mas permite reproduzir as decisões do agente exatamente como ocorreram — essencial ao depurar execuções de longo prazo (long-horizon). É o mesmo formato que o Postgres usa internamente para WAL.

Migrações de schema ou recusa de carregamento. O número inteiro schema_version é o contrato. Quando o gerenciador carrega um arquivo com uma versão desconhecida, ele se recusa a ler. Envie um script de migração junto com a atualização do schema; o tools/migrate_state.py é executado de forma idempotente a cada inicialização.

Uso

Em produção:

  • Checkpointers do LangGraph. Mesma ideia, armazenamento diferente. O checkpointer persiste o estado do grafo no SQLite, Postgres ou em um backend customizado. O schema ensinado nesta lição é o que você usará quando o checkpointer falhar e você precisar ler o estado manualmente.
  • Blocos de memória do Letta. Blocos persistentes com schemas estruturados (Fase 14 · 08). A mesma disciplina voltada para personas de longa execução.
  • OpenAI Agents SDK session store. Backends plugáveis, cientes do schema. O arquivo de estado nesta lição é o backend de arquivo local.

Implementação

outputs/skill-state-schema.md gera um par de JSON Schema específico para o projeto (estado + painel/board), um StateManager em Python conectado a gravações atômicas e uma estrutura de migração para que a próxima atualização de schema não quebre a workbench.

Exercícios

  1. Adicione um carimbo de data/hora (timestamp) last_human_touch. Recuse qualquer gravação do agente dentro de cinco segundos após uma edição humana.
  2. Estenda o validador para suportar oneOf para que uma tarefa possa ser uma tarefa de build ou uma tarefa de revisão com diferentes campos obrigatórios.
  3. Adicione um campo schema_version e escreva a migração de v1 para v2 (renomeie blockers para risks).
  4. Mova o backend de armazenamento de um arquivo local para o SQLite. Mantenha a API do StateManager idêntica.
  5. Execute dois agentes contra o mesmo arquivo de estado com uma corrida de gravação (write race) de 50 ms. O que dá errado e como a renomeação atômica protege você?

Termos-Chave

Termo O que as pessoas dizem O que realmente significa
Memória do repositório (Repo memory) "Arquivo de notas" Estado armazenado em arquivos rastreados no repositório, sob um schema
Schema-first "Validar entradas" Definir o contrato antes de quem escreve, rejeitando desvios
Gravação atômica "Apenas renomeie" Gravar em arquivo temporário, realizar fsync e renomear, para que falhas parciais não corrompam os dados
Migração "Atualização de schema" Um script que transforma o estado vN em estado v(N+1)
Sistema de registro (System of record) "Fonte da verdade" O artefato que a workbench trata como autoritativo

Leituras Adicionais

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).