Pular para o conteúdo
Samuel Mattos
Voltar

Engenharia de contexto: transformando incidentes de produção em regras para agentes de IA

Atualizado em:

Um agente de IA com acesso ao repositório inteiro ainda escreve código errado. Não por falta de capacidade: ele lê melhor e mais rápido do que eu. Erra porque a parte cara do conhecimento de um sistema com mais de uma década não está no código — está na memória de quem já derrubou a produção.

O sistema em que trabalho todo dia tem mais de dez anos de produção ininterrupta: dezenas de módulos, um data warehouse com procedures agendadas, filas com topologia própria e um front-end acoplado a decisões antigas de API. Quando comecei a usar agentes de código nele, o padrão dos erros ficou óbvio: eram exatamente os mesmos erros que um desenvolvedor novo comete no primeiro mês. Código plausível, convenção correta, e ainda assim uma consequência invisível três camadas adiante.

O que resolveu foi tratar o contexto como artefato de engenharia: versionado no repositório, revisado em pull request e mantido com o mesmo critério de um teste.

A pergunta que decide o que entra

O erro mais comum é transformar o arquivo de contexto em documentação. Descrição de pastas, lista de endpoints, explicação de padrão de projeto. Tudo isso é ruído: o agente já lê o código e deduz melhor do que a sua descrição desatualizada. Pior, cada linha inútil compete por atenção com as linhas que importam. Arquivo grande é arquivo ignorado.

O filtro que uso tem dois critérios, e a regra só entra se passar nos dois:

O filtro de entrada
  1. Não é derivável do código. Se dá para descobrir lendo o repositório ou o histórico do git, fora.
  2. Já custou caro. Incidente, retrabalho, hotfix ou bug que chegou no cliente.

O segundo critério é o que dá disciplina ao documento. Ele não cresce por opinião, cresce por post-mortem.

Três regras que existem porque doeu

Um campo de relatório mora em quatro lugares. O dado que o cliente vê num relatório passa por uma view SQL, por uma stored procedure de ETL que roda a cada quinze minutos, por variantes dessa procedure e pelas rotinas noturnas. Alterar a view e esquecer a procedure não quebra nada no deploy — quebra o número do relatório dois dias depois, silenciosamente. Nenhum agente descobre esse acoplamento lendo a view: os quatro arquivos não se referenciam. A regra é uma lista de quatro caminhos e uma frase: mexeu em um, mexa nos quatro.

Um campo de relatório mora em quatro lugares Um campo do relatório se ramifica em quatro artefatos: a view SQL, a stored procedure de ETL que roda a cada quinze minutos, as variantes dessa procedure e as rotinas noturnas. Alterar um sem alterar os outros três quebra o número do relatório.Um campodo relatórioo que o cliente vêView SQLleitura do relatórioStored procedure de ETLroda a cada 15 minutosVariantes dessa procedureRotinas noturnas
Os quatro arquivos não se referenciam entre si. Mexer em um e esquecer os outros não quebra o deploy — quebra o número do relatório dois dias depois.

Migration nova pode precisar de data no passado. Aquela view é reconstruída a partir do arquivo .sql vivo dentro de uma migration antiga. Ou seja: se a view passa a referenciar uma coluna nova, a migration que cria essa coluna precisa rodar antes daquela migration antiga — o que só acontece se ela for datada retroativamente. Sem isso, tudo funciona no banco que já existe e um migrate do zero morre.

O deploy que subiu do zero

Foi o que aconteceu comigo. A alteração passou limpa em todos os ambientes que já tinham a coluna, e derrubou o primeiro que subiu do zero: 502 em produção, com a causa numa migration antiga que ninguém tinha motivo para abrir. Os deploys anteriores não tinham sido sortudos — eles nunca chegaram a executar aquele trecho.

Nunca repasse um 4xx de integração para o cliente. O tratador de erro do front-end trata qualquer 400 como 401 e desloga o usuário. O certo seria consertar o front-end — e é o que vai acontecer, no dia em que der para mexer nele sem coordenar release com todos os clientes que consomem a API. Enquanto isso, a regra é operacional: falha de integração vira 502. Um agente lendo apenas o back-end propaga o status original — e a consequência aparece num sistema que ele nem abriu.

As três regras têm em comum o que importa: são curtas, imperativas e impossíveis de inferir do arquivo que está sendo editado.

Tabela ensina melhor que parágrafo

Contexto útil se parece mais com uma tabela de decisão do que com um texto. Para filas, por exemplo, o agente não precisa entender a topologia — precisa acertar o destino:

FilaConexãoUso
defaultredisJobs curtos. Padrão para o que não está abaixo
mediaredis-long-runningProcessamento de mídia (timeout 1800)
report-exportredisExportações — pod dedicado com autoescalonamento

Três linhas resolvem uma classe inteira de erro: job pesado despachado na fila padrão, que o worker mata por timeout. A versão em prosa da mesma informação ocuparia um parágrafo e seria seguida com menos precisão.

O mesmo vale para as armadilhas de teste. Elas viram uma lista seca:

Cada item desses custou uma tarde a alguém.

Memória separada do contexto permanente

Contexto permanente e histórico de trabalho são coisas diferentes, e misturar os dois estraga os dois. A regra da fila vale para sempre; o diagnóstico do card da semana passada só importa quando aquele assunto volta.

Por isso o que é permanente fica no arquivo de contexto do repositório, e o que é histórico fica numa memória à parte: um arquivo por fato, com um índice de uma linha por entrada. O agente lê o índice sempre e abre o arquivo inteiro só quando o assunto aparece.

O índice é a peça que faz funcionar. Uma linha por fato, escrita para ser descartada na leitura se o assunto não for aquele:

- [Ordenação de migration da view de relatório](view-migration.md) — coluna nova
  referenciada pela view exige migration retroativa, senão o migrate do zero morre
- [Truncate no banco errado](config-cache-testes.md) — config em cache sobrepõe
  o phpunit.xmlMEMORY.md

Mesmo princípio de índice de banco: carregar tudo é caro, carregar o ponteiro é barato. E quando o card volta seis meses depois, a investigação já está escrita.

Restringir a capacidade também é design

Peguei do sistema de skills do Matt Pocock a ideia de empacotar fluxos de trabalho como skills: arquivos versionados junto com o código, cada um com escopo declarado, carregados só quando o assunto aparece. O que adaptei foi o recorte. As dele são fluxos genéricos de desenvolvimento; os meus são amarrados ao processo do time, ao board e às regras do próprio sistema. A parte reaproveitável é o formato — o valor está no que só existe aqui dentro.

E a skill que mais mudou meu resultado não ensina o agente a escrever código. Ela cria um fluxo em que ele não escreve.

Lê o card no Jira, investiga o código, faz uma rodada de perguntas sobre as decisões de design e publica um plano de ação como comentário no próprio card. Não edita um único arquivo. O resultado é um plano revisável por humano, com os arquivos afetados e o porquê de cada um, antes de existir qualquer diff para revisar.

Planejar antes de editar não tem nada de novo — as ferramentas já trazem um modo de planejamento embutido. O que muda aqui é onde o plano para: num comentário do card, no fluxo que o time já lê, revisável por quem conhece o domínio e não está com o agente aberto. Plano que vive na sessão morre com a sessão.

E é isso que ataca o gargalo real de usar IA em base legada: a decisão que antecede o código. Revisar um plano de dez linhas custa cinco minutos. Revisar um pull request de trinta arquivos construído sobre a premissa errada custa a tarde inteira — e normalmente termina em “refaz”.

O efeito colateral

As armadilhas que eu explicava de boca para cada pessoa nova — o campo que mora em quatro lugares, a coluna que não é auto-increment, o 400 que desloga o usuário — estavam todas na minha cabeça, e só saíam de lá depois que alguém já tinha tropeçado. Agora estão num arquivo que qualquer um abre antes.

Escrever para a máquina me obrigou a escrever com precisão. Não dá para instruir um agente com “cuidado com os relatórios”: ou são os quatro caminhos, na ordem, ou a regra não existe. É o rigor que a gente cobra de uma mensagem de erro, aplicado ao conhecimento tácito do time.

Como isso se mantém vivo

Documentação de arquitetura morre porque ninguém tem motivo para atualizá-la. Essa não morre, porque o custo de estar desatualizada é imediato: o agente erra hoje, na sua frente, e você corrige a regra em vez de corrigir o mesmo código pela terceira vez.

O ciclo é curto:

O ciclo de manutenção do arquivo de contexto Um incidente entra no ciclo. Se a causa era derivável do código, o problema é outro: falta de teste, nome ruim ou abstração vazando. Se não era, vira uma regra curta e imperativa no pull request da própria correção. Regra que vale para o sistema inteiro vai para o arquivo de contexto na raiz; regra de um módulo só vai para o README daquele módulo. O próximo erro do agente realimenta o ciclo.Incidente, retrabalho ou bugque chegou no clienteA causa era deriváveldo código?simO problema é outro:falta de teste,nome ruim,abstração vazandonãoVira regra curta e imperativano pull request da própria correçãoVale além deum módulo?nãoREADME daquelemódulosimArquivo de contexto na raizsó o que é transversalo próximo erro corrige a regra
O custo de estar desatualizado é imediato: o agente erra na sua frente, e a regra é corrigida em vez do mesmo código pela terceira vez.

Esse último ponto é o que segura o crescimento. Sem ele, todo aprendizado quer morar no arquivo principal, e em seis meses você tem um documento de mil linhas que ninguém — nem o agente — lê até o fim.

O que eu levaria para qualquer projeto

Contexto não é prompt. É artefato versionado, com critério de entrada, dono e manutenção:

O limite honesto

Isso funciona porque quem escreve as regras é quem viveu os incidentes. Num time que rodou inteiro, ou num sistema que ninguém acompanhou desde o começo, esse arquivo não tem de onde nascer — e nenhuma quantidade de agente resolve isso.

Contexto não é o que você configura na ferramenta. É o que sobrou de dez anos prestando atenção no que quebrou.

Se você acha que isso é só documentação com nome novo, eu quero ouvir o argumento. O contato está aberto.


Compartilhe este artigo:

Artigo anterior
Bem-vindo ao meu blog