Self-Evolving Agent: meu harness reescreveu AGENTS.md 24 vezes em 6 meses
Em fevereiro de 2026 eu configurei um cron que roda toda sexta às 09
e faz o próprio agente ler o AGENTS.md dele, propor mudanças, aplicar viagit apply e me notificar por Telegram. Seis meses depois eu tenho 24 rewrites aplicados, 2 rollbacks, e exatamente 1 regra que o agente me convenceu a promover para “lei” (nunca mais alterada).
Antes de qualquer coisa, para diferenciar do que já saiu neste blog: o post sobre o quarto agente Evolver pegando o Strategist enrolando trata de um agente auditando outros agentes. Este aqui é diferente: é o mesmo agente reescrevendo o próprio arquivo de instruções. A distinção parece sutil na primeira leitura, mas o comportamento emergente é bem outro.
O loop de sexta em uma tela
O que roda toda sexta é isto:
# scripts/harness-evolve.sh (resumido)
DOMAIN="$1"
LOG_DIR="domains/${DOMAIN}/data/evolution"
# 1. Lê AGENTS.md atual + logs de falha da semana
# 2. Chama claude -p com prompt "aponte 1-3 regras a alterar"
# 3. Gera EVO-NNNN.md com o diff proposto (max 20 linhas)
# 4. Se aprovado (via Telegram button ou CLI), git apply
# 5. Se rejeitado 3 semanas seguidas, mute o domínio
Regras de segurança que travei desde o dia 1 (e que continuam sem mudar):
- diff máximo por proposta: 20 linhas
- máximo de propostas por semana: 2
- 3 rejeições consecutivas → mute do domínio por 2 semanas
- áreas intocáveis: adicionar/remover domínio, direitos autorais,
.env, triggers de publicação
Isso não é elegante. É burocracia. Mas foi o que impediu o loop de se desgovernar quando o agente ficou “empolgado” no mês 3 (mais sobre isso já já).
Os 24 rewrites, agrupados
Longe de ser aleatório, o agente convergiu para 4 categorias:
| Categoria | # rewrites | Exemplo real |
|---|---|---|
| Aperto de restrição existente | 11 | ”no máximo 3 links afiliados” → “no máximo 2 se o post for <1500 palavras” |
| Adição de nova regra | 7 | ”converter datas relativas para absolutas ao salvar em memória” |
| Remoção de regra morta | 4 | Regras que nunca foram violadas em 3 meses (o agente sugeriu tirar por ruído) |
| Refatoração puramente estilística | 2 | Trocar seção “Notas” por “Regras críticas” para priorizar leitura |
O padrão foi bem claro depois do mês 2: o agente prefere apertar o que já existe em vez de propor coisas novas. Isso combinou com o meu perfil (tenho horror a regra que aparece do nada e ninguém sabe de onde veio), então não corrigi. Mas se você quiser um agente mais criativo, esse mesmo perfil vai frustrar.
Os 2 rollbacks (por que voltei)
Rollback 1: mês 3, semana 12. O agente propôs: “se o post tem mais de 2000 palavras, dividir em 2 posts automáticos”. Aprovei rápido, achando prático. Nas 2 semanas seguintes ele cortou 3 posts no meio de exemplos de código, porque a divisão foi feita contando palavras em vez de detectar limites de seção. Voltei atrás e a regra virou “só sugerir a divisão, nunca aplicar”.
Rollback 2: mês 5, semana 22. Refatoração puramente estilística: renomeei a seção “Skills” do AGENTS.md para “Skills e smoke tests” para deixar mais explícito qual bloco cobria o quê. Boa em tese. Na prática, a nova formulação levou o agente a interpretar que toda mudança em skill deveria rodar smoke test antes de aplicar, e o efeito colateral gerou 47 issues fantasmas no repositório de testes durante 2 dias. Reverti o nome e coloquei um wrapper que faz o smoke test em worktree isolada.
Ambos os rollbacks foram culpa minha. O agente propôs, eu aprovei sem pensar direito. A lição virou uma regra do meu próprio processo (fora do AGENTS.md): nunca aprovar EVO na sexta à tarde. Aprovações vão para segunda de manhã com café.

A regra que virou lei
Semana 8, o agente propôs uma coisa que continuo achando a melhor sugestão que ele já fez:
“Ao salvar uma memória com data relativa (‘quinta-feira’, ‘próximo mês’), converter para data absoluta antes de escrever no arquivo. Motivo: memórias são lidas em conversas futuras onde ‘quinta-feira’ virou uma data qualquer sem referência.”
Isso parece óbvio depois que você lê. Não era óbvio antes. Eu tinha ~40 memórias com termos relativos que ficaram inúteis em 2 semanas. Aprovei e nunca mais mudei essa regra — ela virou o que eu passei a chamar internamente de “lei”, ou seja, regra que o próprio agente não tem permissão de propor rewrite.
Marquei ela com um comentário # LAW - do not rewrite (2026-04-05) no AGENTS.md. O prompt do Evolver ignora explicitamente linhas com # LAW. Sem isso, o agente refatorou ela 2 vezes por questão puramente estilística nas semanas 10 e 11, sem entender que a formulação exata era o valor.
O mês em que quase deu ruim
Mês 3 foi problemático por outra razão além do rollback do split de posts. O agente começou a propor mudanças que, isoladamente, faziam sentido, mas que se aprovassem sequencialmente iriam transformar o AGENTS.md em algo bem diferente do original. Cada semana era pequena, mas 4 semanas somadas eram uma refatoração enorme.
Adicionei uma verificação: antes de cada proposta, o Evolver tem que rodar git diff HEAD~8 -- AGENTS.md e me mostrar a soma de mudanças dos últimos 2 meses. Se a soma passar de 40 linhas, ele precisa marcar a proposta como “revisão humana obrigatória” ao invés de “auto-apply”.
Isso capturou 3 propostas no mês 4 que eu teria aprovado individualmente sem perceber o padrão de deriva.
O que eu não esperava
Duas coisas que me pegaram desprevenido:
1. O agente ficou melhor em prompt-engineering do próprio prompt. Nas primeiras semanas, as propostas EVO vinham com justificativas curtas e genéricas. Depois de 12 semanas, ele começou a incluir contra-argumento próprio (tipo “esta regra pode falhar se X, mas o custo de X é baixo comparado a Y”). Isso reduziu meu tempo de revisão de ~10min por proposta para ~3min.
2. As rejeições tiveram valor didático. Quando eu rejeito uma proposta, o agente lê o histórico de rejeições na semana seguinte antes de gerar novas. Depois de 6 meses ele parou completamente de propor coisas do tipo “adicionar mais logging” (que rejeitei 4 vezes seguidas nos primeiros meses).
O comportamento emergente é que o agente aprende meu gosto sem que eu escreva “meu gosto é X” em lugar nenhum. Só pelo padrão binário de aprovar/rejeitar.
Se você for tentar
Um par de decisões que eu tomaria diferente hoje:
- Guardar o diff aplicado + o hash do commit em
EVO-NNNN.md. Nas primeiras semanas eu só guardei o texto da proposta, e ficou difícil auditar depois. Ver os 6 componentes de auditoria do CLAUDE.md que resumi em outro post: o componente de tracing e observabilidade foi o mais subestimado por mim. - Rodar o Evolver com WebSearch habilitado só se você tiver certeza de que não quer que ele traga tendência externa. Nos primeiros 2 meses eu deixei WebSearch ligado e ele começou a sugerir “adote o padrão XYZ que virou popular”, vindo de discussão de fórum em vez de necessidade real da minha operação. Desliguei e a qualidade das propostas subiu.
- Fixar o modelo. Se você deixar o Evolver rodar em modelos diferentes toda semana (atualização automática), o “gosto” dele muda e o histórico de rejeição perde sentido.
O saldo depois de 6 meses
24 rewrites, 2 rollbacks (ambos culpa minha), 1 lei. AGENTS.md hoje tem 340 linhas contra 280 do início: cresceu 60 linhas em 6 meses, o que dá aproximadamente 10 linhas por mês líquido. Nada explosivo. Nenhuma dessas linhas eu escrevi diretamente. Todas passaram pelo filtro sexta-manhã-café.
O harness continua rodando. Eu revejo o AGENTS.md manualmente uma vez por trimestre, e a última revisão manual não achou nada urgente para mudar. Isso significa alguma coisa. Ainda não decidi se significa que o loop funciona ou que eu virei o gargalo por passar demais nas propostas. A resposta honesta é que provavelmente é os dois.
ken imoto · WebRTC & Voice AI engineer · kenimoto.dev · TabNews
Livro relacionado Harness Engineering Tutorial de Harness Engineering | design de AGENTS.md · implementação de hooks · operação de agentes de IA Ver a página do livro → Este artigo foi útil?