64 pontos por GN⁺ 2026-03-17 | 9 comentários | Compartilhar no WhatsApp
  • Compartilha uma metodologia concreta para manter projetos com dezenas de milhares de linhas com baixa taxa de defeitos por meio de um fluxo de trabalho multiagente de arquiteto-desenvolvedor-revisor no desenvolvimento de software com LLMs
  • Eu achava que me interessava mais por programar, mas na verdade eu me interessava mais por construir coisas, e agora que os LLMs ficaram bons em codar posso me concentrar nisso
  • Mais do que a habilidade de escrever código, as skills de engenharia de projetar a arquitetura do sistema e tomar as decisões certas ficaram muito mais importantes
  • Misturar modelos diferentes aumenta a qualidade do code review, separando por papel os pontos fortes e fracos de cada modelo
  • O autor publica a sessão completa real de adição de uma funcionalidade de e-mail e registra em detalhes o processo de colaboração com LLMs liderado por humanos, das decisões de arquitetura ao QA

Vantagens de construir com LLMs

  • Eu achava que gostava de programação, mas na prática gostava mesmo era de construir coisas; agora que os LLMs programam bem, estou criando sem parar
  • Por volta do lançamento do Codex 5.2, e mais recentemente com o Opus 4.6, passou a ser possível escrever software com taxa de defeitos muito baixa. Ela pode ser significativamente menor do que quando eu programo tudo manualmente
  • Antes, depois de 2 ou 3 dias de trabalho, o código entrava num estado impossível de manter; hoje consigo trabalhar por semanas seguidas e fazer crescer com estabilidade dezenas de milhares de linhas de código úteis
  • As skills de engenharia não ficaram inúteis, elas mudaram de lugar: em vez da capacidade de escrever o código corretamente, o que importa é o julgamento para arquitetar o sistema do jeito certo e torná-lo utilizável
  • Em projetos cujo stack eu conheço bem (por exemplo, backend), dezenas de milhares de SLoC não são um problema; mas em tecnologias que conheço menos (por exemplo, app mobile), o código ainda vira bagunça por causa do acúmulo de escolhas erradas
  • No começo dos LLMs (depois do davinci), era preciso revisar cada linha de código; nas gerações seguintes, bastava revisar por função; hoje, a tendência é só verificar no nível da arquitetura inteira. No ano que vem, talvez nem isso seja necessário

Projetos feitos desse jeito

  • Stavrobot: um assistente pessoal com LLM focado em segurança. Faz gerenciamento de calendário, decide disponibilidade, pesquisa, escreve código para se expandir, envia lembretes, gerencia tarefas domésticas de forma autônoma etc. O valor principal não está em uma única killer feature, mas em eliminar milhares de pequenos incômodos
  • Middle: um pequeno dispositivo em forma de pingente que grava memos de voz, converte em texto e envia por webhook. O essencial é estar sempre à mão e poder ser usado sem fricção
  • Sleight of Hand: um projeto artístico de relógio de parede que tic-taqueia de forma irregular em segundos, mas continua sempre exato em minutos. Oferece vários modos, como ticks variáveis de 500ms a 1500ms, mudanças de velocidade difíceis de perceber seguidas de paradas aleatórias, corrida em velocidade dupla e espera de 30 segundos, entre outros
  • Pine Town: um canvas multiplayer infinito, um projeto interativo de pradaria em que cada pessoa recebe um pequeno terreno para desenhar
  • Todos esses projetos foram feitos com LLMs, e eu nunca li a maior parte do código, mas conheço bem a arquitetura e o funcionamento interno de cada projeto

Ferramenta de harness

  • Estou usando o OpenCode como harness, e também tive uma boa experiência com o Pi
  • Dois requisitos essenciais para um harness:
    • Poder usar vários modelos de diferentes empresas: a maioria dos harnesses first-party (Claude Code, Codex CLI, Gemini CLI) só suporta os próprios modelos, então não atende a esse requisito
    • Permitir que agentes customizados chamem uns aos outros de forma autônoma

Por que usar vários modelos

  • Dá para pensar em um modelo específico como se fosse uma pessoa; mesmo reiniciando o contexto, ele tende a manter as mesmas opiniões, pontos fortes e fracos
  • Pedir a um modelo para revisar o código que ele mesmo escreveu é quase inútil, porque ele tende a concordar consigo próprio; mas quando o review é feito por outro modelo, a qualidade melhora muito
  • No momento, o Codex 5.4 é minucioso e exigente, então é bom para review; o Opus 4.6 costuma bater bem com as decisões que eu tomaria; e o Gemini 3 Flash às vezes propõe soluções que os outros modelos deixaram passar
  • Para obter o melhor resultado, é preciso misturar todos os modelos

Fluxo de trabalho: arquiteto → desenvolvedor → revisor

  • O fluxo é composto por arquiteto, desenvolvedor e 1 a 3 revisores. Eles são configurados como agentes do OpenCode (arquivos de skill)
  • Três razões para usar múltiplos agentes:
    • Modelos caros (Opus) ficam com o planejamento, e modelos baratos (Sonnet) com a escrita de código, economizando tokens
    • Fazer reviews com modelos diferentes permite capturar problemas diferentes
    • Dá para fazer separação de permissões por papel (por exemplo, somente leitura vs. permissão de escrita)
  • Usar dois agentes com o mesmo modelo e as mesmas permissões não muda muita coisa; é como uma pessoa usando chapéus diferentes
  • Os arquivos de skill são escritos manualmente. Se você pedir para um LLM escrever as skills, é como pedir para alguém escrever “como se tornar um ótimo engenheiro”, devolver esse texto e dizer “agora seja ótimo”

Papel do arquiteto

  • O arquiteto (hoje, Claude Opus 4.6) é o único agente com quem eu converso diretamente e deve ser o modelo mais forte
  • Eu apresento um objetivo de funcionalidade ou correção de bug bem específico e passo até 30 minutos conversando até fechar objetivos, restrições e trade-offs
  • O resultado é um plano bem de baixo nível, no nível de arquivos individuais e funções
  • Não é só prompting; é um processo de formar o plano com ajuda do LLM. Quando ele está errado ou propõe algo diferente do que eu faria, eu corrijo bastante, e essa é a principal contribuição para tornar o projeto “meu”
  • Ele é configurado para não começar a implementar até eu dizer explicitamente a palavra "approved". Alguns modelos tendem a sair implementando cedo demais quando acham que já entenderam
  • Depois da aprovação, o arquiteto divide o trabalho em tarefas, registra tudo em detalhes em um arquivo de plano e chama o desenvolvedor

Papel do desenvolvedor

  • O desenvolvedor pode usar um modelo mais fraco e mais eficiente em tokens (Sonnet 4.6)
  • Como o plano deixa pouco espaço para discricionariedade, o papel é estritamente implementar as mudanças previstas no plano
  • Quando termina a implementação, ele chama os revisores

Papel do revisor

  • Cada revisor analisa e critica de forma independente o plano e o diff
  • O Codex é sempre usado no mínimo; às vezes entra o Gemini, e em projetos importantes entra também o Opus
  • O feedback volta para o desenvolvedor e, quando há divergência entre revisores, o caso é escalado para o arquiteto
  • O Opus é ótimo em escolher o feedback certo e às vezes ignora comentários excessivamente exigentes cuja chance de virarem problema real é baixa em relação ao custo de implementação

Abordagem geral e modos de falha

  • Com esse método, eu entendo todas as escolhas acima do nível de função e uso esse conhecimento no trabalho posterior
  • Quando o LLM tem um ponto cego e deixa passar algum elemento do codebase, se eu disser “você deve usar Y”, ele passa a perceber a existência de Y e muda para uma abordagem melhor
  • Quando não conheço bem uma tecnologia, posso deixar passar decisões erradas do LLM, e então decisões erradas se acumulam até o projeto chegar a um estado sem solução
  • Um padrão clássico de falha é repetir “o código não está funcionando”; o LLM responde “entendido! vou corrigir” e acaba piorando ainda mais
  • Por isso, mesmo quando não domino uma tecnologia, tento entender o máximo possível já na fase de planejamento

Sessão real: adicionando suporte a e-mail no Stavrobot

  • O autor publica a transcrição real comentada da sessão; as chamadas de ferramenta e as partes prolixas foram omitidas, mas a conversa e o processo de decisão foram mantidos como são
  • Conversa inicial: apresentação do objetivo em alto nível ("quero adicionar suporte a e-mail a este bot") → o LLM lê o código, entende o padrão atual (webhook de entrada → enqueueMessage → processamento por LLM → resposta) e faz perguntas de design
    • Método de entrada (polling IMAP, webhook, servidor SMTP), método de saída, se deve ser bidirecional, arquitetura (container separado vs. in-process), tratamento de e-mail HTML, rastreamento de threads, anexos etc.
  • Decisões de design: entrada via webhook do Cloudflare Email Worker, saída via cliente SMTP, conversa totalmente bidirecional, processamento in-process, conversão para Markdown, tratamento como e-mails independentes e suporte a anexos
  • Proposta detalhada de design do LLM: apresenta 7 preocupações com soluções concretas, incluindo parsing MIME (usando mailparser), autenticação do webhook (segredo compartilhado), necessidade de assunto na saída, tratamento de e-mails apenas em HTML, identidade do endereço From, tratamento de e-mails encaminhados e anexos de saída
    • Propõe simplificar o payload do Worker para { from, to, raw } e fazer o parsing do lado do servidor
    • Organiza a estrutura de config, os fluxos de entrada/saída, a lista de arquivos a modificar e os itens explicitamente fora de escopo (YAGNI)
  • Refinamento do plano: o humano aponta itens que faltavam, como atualizar README.md e config.example.toml e remover a validação E.164 da página de allowlist de e-mail → o LLM incorpora tudo
  • Divisão em 6 tarefas: config/dependências, allowlist, UI/validação de backend da allowlist, e-mail de entrada, e-mail de saída, README/testes
  • Melhoria adicional: surge a ideia de tornar os campos SMTP opcionais, para que o e-mail de entrada funcione mesmo sem configuração SMTP → implementado
  • Bug encontrado no QA: as mensagens eram descartadas porque o e-mail do owner não estava registrado → a causa era que seedOwnerInterlocutor não incluía o canal de e-mail → corrigido
  • Sugestão de melhoria de código: refatorar os blocos if hardcoded por canal para iterar sobre uma lista compartilhada de canais. Depois de discutir o caso especial de conversão numérica do Telegram, decidiu-se aplicar o loop apenas em seedOwnerInterlocutor e manter getOwnerIdentities, já que a diferença de tipos ali é essencial
  • Allowlist de e-mail com wildcard: foi adicionado suporte a wildcards no nível de domínio, como *@example.com. Isso era necessário para um caso de uso real com endereços de e-mail descartáveis
    • Consideração de segurança: para evitar ataques como "me@mydomain.com"@evildomain.com, o * é convertido para [^@]*, de modo que não possa atravessar o limite do @
    • Também há suporte a wildcards parciais, como myusername+*@gmail.com
    • O humano aponta que, ao usar regex, é preciso escapar todos os outros caracteres do endereço de e-mail
  • Foi confirmado que os wildcards funcionam tanto no campo de owner quanto na allowlist, usando a mesma função helper matchesEmailEntry
  • A implementação da funcionalidade inteira levou cerca de 1 hora

Epílogo

  • Não é um setup absurdamente extravagante, mas funciona muito bem, e o autor está satisfeito com a confiabilidade do processo
  • O Stavrobot está rodando 24/7 há quase um mês e se mostrou muito estável

9 comentários

 
kurthong 2026-03-17

Assim como, há mais de 20 anos, a popularização dos editores web e dos blogs de produção em massa gerou uma enxurrada de páginas pessoais e posts que ninguém via, estamos vendo algo parecido na era da IA. Ainda assim, criar apps customizados e compartilhar esse processo ou rotina é, sem dúvida, um excelente e valioso patrimônio. Pessoalmente, acho que este não é um momento para fazer apps ou serviços lucrativos com IA, mas sim para criar com facilidade ferramentas customizadas de que eu preciso e, assim, aumentar a produtividade.

 
zetbouaka 2026-03-18
  • Se você pedir ao modelo para revisar o código que ele mesmo escreveu, há uma tendência de concordar consigo próprio, então isso é quase inútil; mas, se a revisão for feita por outro modelo, a qualidade melhora bastante.

Na verdade, acho que com humanos também deve ser assim. Não seria justamente por isso que os humanos precisam buscar diversidade...

 
newbie1004 2026-03-17

Como é um modelo de linguagem, faz sentido que um modelo caro fique responsável pelo planejamento.

 
tested 2026-03-17

> O modelo caro (Opus) é usado para planejamento, e o modelo barato (Sonnet) para escrever código, economizando tokens

Muita gente costuma fazer o contrário, usando o Sonnet para planejar e o Opus para implementar o código, mas aqui é o inverso.

 
wegaia 2026-03-18

Também estou colocando o opus e o codex para fazer esse vai e vem com o planejamento.
Deixo o opus cuidar da programação, e faço outra instância do opus e o codex cuidarem da revisão de código.
O que sinto fazendo isso é que, seja IA ou gente, parece que ambos são muito bons em apontar os erros dos outros...

 
pencil6962 2026-03-17

Na configuração padrão do Oh my opencode, o planejamento é feito pelo opus, enquanto a implementação fica a cargo de um modelo mais leve.

 
princox 2026-03-17

Ao meu redor, o pessoal costuma fazer o planejamento/arquitetura com o Sonnet e escrever o código com o GLM-5..

 
developerohn 2026-03-17

Eu também faço o planejamento com o Sonnet e a implementação do código com o Opus, mas talvez o método do autor seja mais eficiente.

 
bigseoul 2026-03-17

Eu também planejo com o Opus, faço as revisões no Codex high e rodo a codificação de fato no sonet ou no codex medium.