Phase 14 - Lesson 37
Loops de Feedback em Tempo de Execução
Agentes que não veem a saída real do comando adivinham. Um executor de feedback captura stdout, stderr, código de saída e tempo em um registro estruturado que a próxima iteração pode ler. Assim, o agente reage a fatos em vez de reagir à sua própria previsão dos fatos.
Tipo: Build Idiomas: Python (stdlib) Pré-requisitos: Phase 14 · 32 (Minimal Workbench), Phase 14 · 35 (Init Script) Tempo: ~50 minutos
Objetivos de Aprendizado
- Distinguir o feedback em tempo de execução da telemetria de observabilidade.
- Construir um executor de feedback que envolve comandos do shell e persiste registros estruturados.
- Truncar saídas grandes de forma determinística para que o loop permaneça dentro do limite de tokens.
- Recusar o avanço do loop quando o feedback estiver ausente.
O Problema
O agente diz "executando testes agora." A mensagem seguinte diz "todos os testes passaram." A realidade é que nenhum teste foi executado. O agente imaginou a saída, ou executou o comando e nunca leu o resultado, ou leu o resultado e truncou silenciosamente a linha de falha.
Um executor de feedback elimina essa lacuna. Cada comando passa pelo executor. Cada registro contém o comando, o stdout e stderr capturados, o código de saída, a duração de tempo real e uma nota de uma linha do agente. O agente lê o registro na iteração seguinte. O portão de verificação lê os registros no final da tarefa.
O Conceito
flowchart LR
Agent[Loop do Agente] --> Runner[run_with_feedback.py]
Runner --> Shell[subprocess]
Shell --> Capture[stdout / stderr / exit / duration]
Capture --> Record[feedback_record.jsonl]
Record --> Agent
Record --> Gate[Portão de Verificação]
O que vai em um registro de feedback
| Campo | Por que isso importa |
|---|---|
command |
Argv exato, sem surpresas de expansão do shell |
stdout_tail |
Últimas N linhas, truncamento determinístico |
stderr_tail |
Últimas N linhas, separado do stdout |
exit_code |
O sinal inequívoco de sucesso |
duration_ms |
Revela sondagens lentas e processos fora de controle |
started_at |
Carimbo de data/hora para reprodução |
agent_note |
Uma linha que o agente escreve sobre o que ele esperava |
O truncamento é determinístico
Um log de 50 MB destrói o loop. O executor trunca o início e o fim com um marcador ...truncated N lines..., de forma determinística para que a mesma saída sempre produza o mesmo registro. Sem amostragem; as partes que o agente precisa ver (erro final, resumo final) ficam no fim (tail).
Feedback versus telemetria
A telemetria (Phase 14 · 23, convenções do OTel GenAI) é para operadores humanos que revisam execuções ao longo do tempo. O feedback é para a próxima iteração desta execução. Eles compartilham campos, mas vivem em arquivos diferentes com tempos de retenção diferentes.
Recusar avanço sem feedback
Se o executor falhar antes de capturar a saída, o registro conterá exit_code: null e error: <reason>. O loop do agente deve se recusar a declarar sucesso com um código de saída null. Sem saída, sem progresso.
Construa
code/main.py implementa:
run_with_feedback(command, agent_note)que envolvesubprocess.run, captura stdout/stderr/exit/duration, trunca deterministicamente e anexa afeedback_record.jsonl.- Um pequeno carregador que transmite o JSONL para uma lista Python.
- Uma demonstração que executa três comandos (sucesso, falha, lento) e imprime o último registro de cada comando.
Execute:
python3 code/main.py
Saída: três registros de feedback anexados a feedback_record.jsonl, o último de cada impresso em linha. Monitore o final do arquivo (tail) ao longo das reexecuções para ver o loop se acumular.
Padrões de produção no mundo real
Três padrões tornam o executor robusto o suficiente para ser implantado.
Ocultar na escrita, não na leitura. Qualquer registro que toque em stdout ou stderr pode vazar segredos. O executor realiza uma etapa de ocultação antes de anexar ao JSONL: remove linhas correspondentes a ^Bearer , password=, api[_-]?key=, AKIA[0-9A-Z]{16} (AWS), xox[baprs]- (Slack). A ocultação no momento da leitura é perigosa; o arquivo em disco é o que um invasor acessa. Realize auditorias nos padrões de ocultação trimestralmente em relação aos formatos de segredos observados no ambiente de execução de produção.
Política de rotação, não um único arquivo. Limite o feedback_record.jsonl a 1 MB por arquivo; no estouro, rotacione para .1, .2, descarte .5. O loop do agente lê apenas o arquivo atual, mantendo o custo de execução limitado. O armazenamento de artefatos de CI recebe o conjunto rotacionado completo. Sem rotação, o arquivo se torna o gargalo em cada chamada de carregamento.
ID de comando pai para cadeias de tentativa. Cada registro recebe um command_id; as tentativas carregam um parent_command_id apontando para a tentativa anterior. A lista de "tentativas fracassadas" do revisor (Phase 14 · 40) e a auditoria do portão de verificação seguem a cadeia. Sem esse vínculo, as tentativas parecem sucessos independentes e a auditoria esconde o histórico de falhas.
Use
Padrões de produção:
- Ferramenta Bash do Claude Code. A ferramenta já captura stdout, stderr, exit e duration. O executor nesta lição é o equivalente agnóstico de framework para qualquer produto de agente.
- Nós do LangGraph. Envolva qualquer nó de shell no executor para que o registro persista fora do estado do grafo.
- Logs de CI. Transmita o JSONL para o armazenamento de artefatos de CI; revisores podem reproduzir qualquer comando sem reexecutar a sessão.
O executor é um invólucro fino que sobrevive a qualquer migração de framework porque ele é o dono do formato do registro.
Envie
outputs/skill-feedback-runner.md gera um run_with_feedback.py específico do projeto com o limite de truncamento adequado, um gravador JSONL conectado à bancada de trabalho (workbench) e um carregador que o agente lê a cada iteração.
Exercícios
- Adicione um campo
cwdpor registro para que o mesmo comando executado a partir de diretórios diferentes possa ser distinguido. - Adicione uma etapa de ocultação que remova linhas correspondentes a
^Beareroupassword=. Teste em um registro de teste (fixture). - Limite o tamanho total do
feedback_record.jsonlem 1 MB rotacionando para os arquivos.1e.2. Defenda a política de rotação. - Adicione um
parent_command_idpara que as cadeias de tentativas sejam visíveis: qual comando produziu a entrada que o comando seguinte consumiu. - Direcione o JSONL para uma pequena TUI que destaque o último código de saída diferente de zero. Liste oito recursos principais que a TUI deve mostrar para ser útil em uma revisão.
Termos-Chave
| Termo | O que as pessoas dizem | O que realmente significa |
|---|---|---|
| Registro de feedback | "Log de execução" | Entrada estruturada em JSONL com comando, saída (stdout/stderr), código de saída, duração |
| Truncamento de cauda | "Cortar o log" | Captura determinística de início + fim para que os registros caibam no orçamento de tokens |
| Recusa em caso de nulo | "Bloquear com dados ausentes" | O loop não deve avançar quando exit_code for nulo |
| Nota do agente | "Tag de expectativa" | A previsão de uma linha que o agente escreve antes de ler o resultado |
| Divisão de telemetria | "Dois arquivos de log" | Feedback para a próxima iteração, telemetria para o operador |
Leituras Adicionales
- OpenTelemetry GenAI semantic conventions
- Anthropic, Effective harnesses for long-running agents
- Guardrails AI x MLflow — segurança determinística, PII, validadores de qualidade — padrões de ocultação como testes de regressão
- Aport.io, Melhores Guardrails para Agentes de IA em 2026: Comparação de Autorização Pré-Ação — captura pré/pós-ferramenta
- Andrii Furmanets, Agentes de IA em 2026: Arquitetura Prática para Ferramentas, Memória, Avaliações, Guardrails — superfícies de observabilidade
- Phase 14 · 23 — convenções do OTel GenAI para a parte de telemetria
- Phase 14 · 24 — plataformas de observabilidade de agentes (Langfuse, Phoenix, Opik)
- Phase 14 · 33 — a regra que exige feedback antes de declarar a tarefa concluída
- Phase 14 · 38 — o portão de verificação que lê o JSONL