DEV Community

Cover image for Meu Processo de Agentic Engineering: Do Vibe Code ao BD
Antoniel Magalhães
Antoniel Magalhães

Posted on

Meu Processo de Agentic Engineering: Do Vibe Code ao BD

TL;DR Uso BDD para transformar especificação em código validado. Os cenários definem o comportamento; os testes cobrem; a mutação confere se os testes são de fato úteis. Depois de validado, consigo refatorar a implementação sem medo de regressão.

Introdução

Este post trata de como eu atualmente lido com agentic engineering e de como tento criar features usando agentes de IA (Cursor, Claude Code, ou qualquer outro) por meio de uma metodologia definida, especificamente BDD (Behavior Driven Design) para guiar a produção de código e garantir a corretude.

Vibe Code vs Agent Engineering

A primeira vez que vi o termo agentic engineering aparecer foi no artigo do Simon Willison sobre padrões de agentic engineering. Eu já praticava isso, mas continuava chamando de vibe coding e eu gostei da nomenclatura, parece algo mais sério e bem definido.

Vibe coding

Quando você não presta atenção no código de forma geral

Não presta atenção em como as coisas estão sendo feitas. O foco está em entregar, não em estabelecer padrões ou validar a qualidade do que o agente produz.

Agentic engineering

Quando você cria e estabelece normas

Cria normas, guidelines e define as formas como quer que o código seja escrito pela IA. Você ainda não digita; mas influencia ativamente como o código é produzido.

Explorando novos padrões de agentic engineering

No dia a dia, é difícil abrir mão de produtividade ou qualidade em relação à baseline só para experimentar padrões de agentic engineering. Então o que faço normalmente é criar pequenos side projects que quero fazer e usá-los para explorar essas capacidades com o agente.

Comecei o projeto com meu workflow já estabelecido de agentic engineering que é: eu tenho uma intenção, crio uma especificação usando SpecKit ou OpenSpec, a partir da especificação eu crio um plano, e desse plano eu crio a implementação.

Intenção → Especificação → Plano → Implementação
Enter fullscreen mode Exit fullscreen mode

Um pipeline simples, mas que funciona bem para mim. O "problema" é que preciso estar atento em todas as etapas: a intenção está na minha mente; tenho que confirmar que a especificação reflete o que imaginei; verificar se o plano de implementação segue como eu imaginei; e no final fazer code review da implementação. Esse é um processo que exige bastante da minha atenção e minha vontade era explorar diferentes padrões que pudessem reduzir o meu tempo de atenção por tarefa mas mantendo a mesma qualidade.

TDD

Já tinha visto o padrão de usar testes automatizados para validar a implementação e criar essa contrapressão no agente para que ele valide o próprio trabalho. Acho válido. O problema, na minha experiência, é que quando deixo o agente criar os testes sozinho, sem supervisão adequada, ele acaba pegando atalhos: testes que cobrem coisas triviais e detalhes de implementação. Coisas como expect(1).toBe(1) e afins.

O Simon documenta o padrão de TDD com red/green em seu guia: fazer o teste falhar e depois fazê-lo passar, garantindo que o teste é realmente útil. Dada a minha experiência, ainda não me sentia à vontade confiando na boa vontade do agente de não editar o teste só para fazê-lo passar (@effectfully). Meu pior cenário: implemento TDD, levo n minutos, vou revisar o código, especificamente os testes e os testes não fazem sentido ou faço um teste manual e descubro que a feature não funciona, e os testes passam.

Antes: Just Go

Fluxo anterior sem especificação formal

Abrir o agente, explicar a tarefa, refinar ao longo das iterações. Sem spec, sem validação formal. O risco: testes triviais, implementação que passa mas não entrega o esperado.

Explicar tarefa → Agente implementa → Revisar → OK? → (Não → Agente implementa) | (Sim → Pronto)
Enter fullscreen mode Exit fullscreen mode

Depois: BDD

Especificação para ação

Spec → .feature → tony-bdd-test → mutação. Cenários aprovados viram fonte de verdade; testes validam comportamento; mutação garante que os testes não passam por acaso.

Spec → .feature → tony-bdd-test → Mutação
Enter fullscreen mode Exit fullscreen mode

BDD

Há um tempo atrás, em tempos pré-llms, me deparei com um requisito: como garantir a qualidade do código através de testes que conversam com o produto? Havia um descompasso entre o que era pedido no ticket e o que o time entregava. A solução: BDD (Behavior Driven Design), documentado pela Cucumber. Uma vez aprovados os arquivos .feature e os cenários, o time teria de garantir que os testes de cada cenário estivessem passando.

Essa ideia voltou à medida que o meu side project ia crescendo. O tempo de validar todas as features aumentava na mesma medida em que eu adicionava funcionalidades. A pergunta reapareceu: como consolidar o que tenho agora e garantir que eu possa adicionar coisas novas de forma estruturada, com testes que de fato validem o comportamento?

BDD. Meu approach foi criar dois /commands no Cursor: um para gerar o .feature e outro para implementar a feature e seus testes.

/tony-bdd

O comando pega um arquivo (um componente, uma rota, um handler) e extrai dele os cenários que importam. Em vez de organizar por página ou tela, organiza por domínio: auth, checkout, layout, o que fizer sentido pro vocabulário do código. Começa com poucos cenários de alto impacto, os journeys que provam que a coisa funciona ponta a ponta. Só depois, se precisar, desdobra em regras e variações. Cada cenário ganha um @id estável. Um script varre os .feature e verifica se há teste correspondente a cada cenário declarado. Não usa Cucumber; os .feature são só a fonte de comportamento. O comando não toca em código nem em testes, só escreve specs.

/tony-bdd-test

Já esse comando pega os cenários Gherkin e implementa os testes. Coloca os testes ao lado do código sob teste, com mocks mínimos (MSW quando for web). Para cada teste que escreve, exige um sanity-check por mutação: quebra a implementação de propósito, roda o teste, confirma que falha, reverte. O objetivo é garantir que os testes não passem por acaso.

tony-bdd (.feature) → tony-bdd-test (Testes) → Mutação → Teste falha? → (Sim → Reverte → Pronto) | (Não → Reforça → Mutação)
Enter fullscreen mode Exit fullscreen mode

/tony-workflow

Os comandos base permitem criar .features e implementá-las. Como encadear os dois? É aí que entra o /tony-workflow. O workflow roda o /tony-bdd e depois o /tony-bdd-test, mas se aproveita da engenharia de contexto e subagents. Uma das instruções é paralelizar sempre que possível. Para features que lidam com partes diferentes do sistema ou que podem ser divididas em unidades de trabalho menores, uma vez gerados os .feature, cada um pode ser lançado em um subagent em paralelo, em background. Não bloqueia a thread principal nem polui o contexto principal.

Thread principal: tony-bdd → .feature
                         ↓
    ┌────────────────────┼────────────────────┐
    ↓                    ↓                    ↓
Subagent 1          Subagent 2          Subagent N
    ↓                    ↓                    ↓
tony-bdd-test       tony-bdd-test       tony-bdd-test
    └────────────────────┼────────────────────┘
                         ↓
                    background
Enter fullscreen mode Exit fullscreen mode

Specs First vs BDD

Então BDD é melhor que o spec first? Não. Na prática eles podem ser usados juntos. Você pode gerar a especificação (SpecKit, OpenSpec) e definir o que deve ser construído. Depois, esse spec vira insumo pro tony-bdd. Os cenários .feature nascem desse material. O spec diz o quê; o BDD extrai o comportamento testável.

Conclusão

Essa metodologia não lida com ensinar ao agente como você quer que o código seja escrito. Ela cria ferramentas para garantir que, uma vez que o código está certo e validado, você não terá regressões ao longo do tempo. Esse workflow deve ser usado junto com outras técnicas: skills, rules, guardrails, agents.md.

Meu resultado: uma vez que o resultado está pronto e validado manualmente, revisar as interfaces criadas, os testes e a implementação leva menos tempo do que se eu tivesse que revisar tudo no Spec First. Por quê? Porque com tudo validado, testes prontos e implementação correta, posso trocar a implementação livremente. O que testo é a interface, não os detalhes internos. Isso me dá flexibilidade para refatorar sem medo pois está tudo coberto por testes. Se chegar ao ponto em que eu olho a implementação e percebo que não ficou tão boa quanto poderia ser; posso alterá-la completamente sabendo que os testes garantem o comportamento.

Resultados

Esses números vêm do projeto em que apliquei o workflow BDD. O coverage do Vitest cruza os cenários dos .feature com os relatórios de cobertura; o valor 0 em Uncovered indica que todos os cenários têm ao menos algum teste associado; nenhum ficou sem cobertura.

Métrica Valor
Arquivos de feature 19
Cenários BDD 94
Arquivos de teste 15
Testes 176
Coverage (Vitest) 42%

Apesar de 42% ser uma cobertura baixa, a ideia não é ser exaustivo nos testes, mas preciso no que testar: garantir o comportamento que importa, não cobrir cada linha.

Referências

Top comments (0)