· 14 min de leitura · ...

Alucinação vem do código, não do modelo: como engenharia de restrições acelera time-to-market com agentes

Alucinação vem do código, não do modelo: como engenharia de restrições acelera time-to-market com agentes

Em times que usam agentes autônomos, o maior gerador de alucinação não é o LLM. É a ausência de contratos, gates e rastreabilidade no código.

IAagentesengenhariaalucinaçãoMCParquiteturamcp-graph
Indice

A culpa não é do modelo

Toda vez que um agente autônomo inventa um estado que não existe, conclui uma tarefa sem evidência ou sobrescreve o trabalho de outro agente, a reação instintiva é a mesma: “o modelo alucinou”. E sim, modelos de linguagem alucinam. Isso é uma propriedade estatística intrínseca de qualquer sistema que gera texto token por token a partir de distribuições de probabilidade.

Mas aqui está a tese que eu defendo depois de meses construindo sistemas multi-agente em produção: em times de desenvolvimento com agentes, o maior gerador de alucinação operacional não é o LLM em si. É a ausência de engenharia de restrições no código e no processo. Quando a engenharia cria contratos, gates, contexto rastreável e controle de concorrência, a taxa de alucinação operacional cai drasticamente e o time-to-market sobe.

Este artigo vai provar isso com código real, teoremas práticos e uma metodologia que você pode aplicar amanhã no seu time.

O que significa “alucinação” neste contexto

Antes de qualquer coisa, preciso definir o que estou chamando de alucinação. Não estou falando de erro gramatical ou de o modelo confundir uma data. Estou falando de falha sistêmica que ocorre quando um agente autônomo opera dentro de um pipeline de desenvolvimento. Especificamente, cinco tipos de falha:

  1. Inventar estado do projeto. O agente afirma que uma task está em andamento quando ela nem foi iniciada. Ou que um arquivo existe quando ele foi deletado três commits atrás. Isso acontece quando não existe uma fonte de verdade consultável e o agente preenche lacunas com inferência.

  2. Concluir task sem critérios reais. O agente marca algo como “done” sem que nenhum teste tenha passado, nenhum critério de aceitação tenha sido verificado, nenhuma evidência tenha sido produzida. É o equivalente a um desenvolvedor fazendo merge de um PR sem review.

  3. Usar contexto irrelevante. O agente recebe um contexto enorme, não filtrado, e acaba usando trechos que não têm relação com a tarefa. A resposta parece coerente superficialmente, mas está fundamentada em informação errada.

  4. Sobrescrever trabalho de outro agente. Em cenários multi-agente, dois agentes editam o mesmo arquivo ou modificam o mesmo estado sem coordenação. Ambos estão “certos” localmente, mas o resultado global é inconsistente.

  5. Passar algo para “done” sem qualidade mínima. A task é movida para o status final, mas o código não compila, os testes não passam, ou a funcionalidade não atende ao requisito original.

Perceba o padrão: nenhuma dessas falhas é culpa exclusiva do modelo. Todas são falhas de sistema que ocorrem porque o código ao redor do modelo não impõe restrições suficientes. O modelo faz o que modelos fazem (gerar a continuação mais provável). O problema é que ninguém definiu o que “provável” deveria significar naquele contexto.

Prova prática: o código do mcp-graph

Para tornar essa discussão concreta, vou usar o código do mcp-graph, uma ferramenta open-source que implementa grafo de tarefas com pipeline de execução para agentes autônomos via MCP. A implementação foi desenhada especificamente para reduzir alucinação pela engenharia. Cada mecanismo abaixo é uma evidência de que o sistema força o agente a operar dentro de limites verificáveis.

Evidência no códigoO que isso forçaEfeito na alucinação
start_task junta next + contexto + RAG + TDD + status (src/mcp/tools/start-task.ts, src/core/pipeline/start-task.ts)Entrada padronizada para execuçãoMenos improviso de contexto
finish_task executa DoD + bloqueia done se checks required falham (src/mcp/tools/finish-task.ts, src/core/pipeline/finish-task.ts)Saída controladaMenos “done falso”
DoD com 9 checks e score/grade (src/core/implementer/definition-of-done.ts)Critério objetivo de términoMenos conclusão sem evidência
Validação de AC via INVEST + parser testável/mensurável (src/core/analyzer/ac-validator.ts, src/core/analyzer/ac-parser.ts)Requisitos viram contrato testávelMenos ambiguidade
Contexto RAG com cache, dedup, rerank, citações (src/mcp/tools/context.ts, src/core/rag/post-retrieval.ts, src/core/rag/citation-mapper.ts)Evidência rastreável e orçamento de tokenMenos “chute textual”
Gate unificado bloqueando chamadas com erro de fase/pré-requisito (src/mcp/unified-gate.ts)Fluxo obrigatórioMenos desvio de processo
Lock por lease + conflito explícito (src/core/store/lock-manager.ts)Exclusão mútua entre agentesMenos conflito de estado
Optimistic locking por versão (src/core/store/sqlite-store.ts)Detecta escrita em estado staleMenos overwrite silencioso
Harness com 7 dimensões e alerta de risco de alucinação (src/core/harness/harnessability-score.ts, src/core/harness/harness-preflight.ts)Qualidade estrutural mensurávelMenos erro sistêmico recorrente

Cada linha dessa tabela é uma parede do labirinto. E cada parede existe porque, sem ela, o agente encontrava um atalho que produzia resultado incorreto.

O pipeline de entrada e saída

O mecanismo mais importante é o par start_task / finish_task. Quando o agente chama start_task, o sistema não entrega apenas o texto da tarefa. Ele monta um pacote completo: a próxima task na fila (respeitando dependências), o contexto relevante filtrado por RAG, os critérios de aceitação parseados, o estado atual do grafo e os testes esperados. O agente recebe tudo que precisa para executar, e nada que possa confundir.

Na saída, finish_task não aceita um “done” sem verificação. O sistema executa a Definition of Done (DoD), que inclui 9 checks obrigatórios: existência de testes, passagem de testes, cobertura mínima, conformidade com os critérios de aceitação, qualidade de código, ausência de regressões, entre outros. Se os checks required não passam, a task não avança. O agente é forçado a corrigir antes de prosseguir.

Isso elimina a alucinação de conclusão. O agente pode “achar” que terminou, mas o sistema só confirma com evidência.

Contexto com citação obrigatória

O módulo de RAG do mcp-graph não é um retrieval ingênuo que joga texto no prompt. Ele implementa cache para evitar reprocessamento, deduplicação para remover redundância, reranking para priorizar relevância e, crucialmente, mapeamento de citações. Cada trecho de contexto usado pelo agente precisa apontar para sua fonte original.

Isso é importante porque transforma o modelo de “gerador de texto” em “sintetizador de evidência”. Quando o agente precisa citar a fonte de cada afirmação, o espaço para invenção cai drasticamente. É como a diferença entre escrever uma redação opinativa e escrever um artigo acadêmico com referências.

Concorrência segura

Em cenários multi-agente, o lock-manager implementa exclusão mútua por lease: quando um agente está trabalhando em uma task, outros agentes não podem modificar o mesmo recurso. Se o lease expira (porque o agente travou ou foi interrompido), outro agente pode assumir. E o optimistic locking por versão no SQLite garante que, mesmo em cenários de race condition, uma escrita em estado stale é detectada e rejeitada explicitamente, em vez de sobrescrever silenciosamente.

Sem esses mecanismos, dois agentes podem estar simultaneamente “certos” em suas visões locais do estado, mas produzir um resultado global inconsistente. É alucinação por design de sistema, não por falha de modelo.

Quatro teoremas práticos

Com base nas evidências acima, proponho quatro teoremas que formalizam a relação entre engenharia de restrições e alucinação operacional. Chamo de “teoremas” não no sentido matemático formal, mas no sentido de proposições que emergem da prática e que você pode verificar empiricamente.

Teorema 1: Densidade de Restrições

Enunciado: quanto maior a densidade de restrições executáveis (schema + gate + DoD), menor a alucinação operacional.

Intuição: o agente pode “imaginar” qualquer coisa, mas não consegue persistir imaginação quando o sistema exige passagem por checks required. Cada restrição é um filtro que separa output válido de output alucinado. Uma única restrição pode ser contornada; uma rede densa de restrições cria um campo de força que converge o agente para o comportamento correto.

Exemplo prático: no mcp-graph, mesmo que o modelo gere um status inválido, o unified-gate bloqueia a transição. Mesmo que o modelo afirme que os testes passaram, a DoD executa os testes de verdade. A alucinação é gerada, mas nunca persiste.

Teorema 2: Evidência com Citação

Enunciado: contexto com recuperação multi-estratégia + pós-processamento + citação reduz erro factual mais que contexto bruto.

Intuição: quando cada pedaço de resposta precisa apontar para uma fonte verificável, o espaço de invenção cai. O agente fica “preso” à evidência disponível. É a diferença entre dar a alguém uma biblioteca inteira sem índice (contexto bruto) e dar um conjunto curado de referências com número de página (contexto com citação).

Exemplo prático: o pipeline de RAG do mcp-graph faz retrieval, dedup, rerank e citation mapping. O agente não recebe “tudo que pode ser relevante”. Recebe o que é relevante, sem duplicação, ordenado por importância, com citação obrigatória. A taxa de “chute textual” cai porque o modelo tem menos espaço para inventar.

Teorema 3: Integridade de Fluxo

Enunciado: se status só avança por transições válidas e conclusão exige DoD, a taxa de retrabalho cai.

Intuição: bloquear “atalho para done” reduz dívida técnica escondida e acelera entrega líquida. Parece contraintuitivo (mais gates = mais lento?), mas na prática o oposto acontece. Sem gates, tasks são fechadas prematuramente, bugs aparecem depois, retrabalho consome o dobro do tempo. Com gates, tasks demoram um pouco mais para fechar, mas fecham de verdade.

Exemplo prático: o unified-gate do mcp-graph impede que um agente chame finish_task se a task não passou pelos pré-requisitos de fase. Isso elimina o cenário onde uma task “pronta” na verdade precisa de mais trabalho, o que economiza ciclos inteiros de reabertura e correção.

Teorema 4: Concorrência Segura

Enunciado: lock de recurso + versionamento otimista reduzem inconsistência entre agentes paralelos.

Intuição: sem controle de concorrência, dois agentes podem estar “certos” localmente (cada um vê um estado consistente) e errar globalmente (o resultado combinado é inconsistente). O lock por lease garante exclusão mútua. O versionamento otimista garante detecção de conflito. Juntos, eliminam a classe inteira de alucinações causadas por visão parcial de estado.

Exemplo prático: no mcp-graph, se o Agente A está editando a Task 5 e o Agente B tenta editar a mesma task, o lock-manager rejeita a segunda operação explicitamente. Se dois agentes leem a mesma versão e um escreve primeiro, o segundo recebe um erro de conflito de versão em vez de sobrescrever silenciosamente.

Metodologia M.A.P.A.: um framework para reduzir alucinação

Com base nos teoremas acima, proponho a metodologia M.A.P.A., um acrônimo para quatro práticas que, combinadas, criam a infraestrutura de contenção que transforma agentes de “geradores de texto” em executores confiáveis.

M: Modelar contratos

Defina schemas estritos para tudo que o agente manipula: nodes, edges, status, transições. Exija critérios de aceitação mensuráveis e testáveis. Não deixe o agente decidir o que é “suficiente”; codifique isso em validações.

Na prática, isso significa usar validação de schema (Zod, JSON Schema, ou equivalente) para cada entrada e saída do agente. Se o agente precisa criar uma task, o schema define quais campos são obrigatórios, quais valores são válidos e quais transições de estado são permitidas.

A: Amarrar fluxo com gates

Fase, pré-requisito e status não são “boas práticas” opcionais. São verificações de runtime que o código executa a cada transição. Um gate é uma função que recebe o estado atual, a ação proposta e retorna “permitido” ou “bloqueado com motivo”.

No mcp-graph, o unified-gate centraliza todas essas verificações em um único ponto. Isso garante que nenhuma chamada de ferramenta pule uma etapa obrigatória, independentemente de qual agente está operando ou qual prompt foi usado.

P: Provar com pipeline

Use pipelines de entrada (start_task) e saída (finish_task) para padronizar a execução. O pipeline de entrada monta o contexto completo e filtrado. O pipeline de saída valida o resultado contra critérios objetivos.

Isso transforma cada execução de task em um processo reproduzível: mesma entrada, mesma validação, resultados comparáveis. O pipeline é o contrato executável entre “o que o agente recebeu” e “o que o agente precisa entregar”.

A: Auditar qualidade continuamente

Rode harness e quality gates para detectar regressão antes que ela exploda em produção. O harness score do mcp-graph avalia 7 dimensões de qualidade estrutural e emite alertas de risco de alucinação quando uma dimensão cai abaixo do limiar.

A auditoria contínua fecha o ciclo: os contratos (M) definem as regras, os gates (A) as aplicam, o pipeline (P) padroniza a execução, e a auditoria (A) verifica que tudo continua funcionando ao longo do tempo.

Como provar isso no seu time: um experimento de duas semanas

Se você quer validar essa tese na prática, proponho um experimento A/B simples que pode ser executado em duas semanas:

Grupo A (controle): agente com fluxo livre, sem gates fortes, sem DoD obrigatória, sem controle de concorrência. O agente recebe a task e tem autonomia total para executar como quiser.

Grupo B (engenharia): mesmo agente, mas com schema estrito, start_task/finish_task, DoD com checks required, RAG com citação e lock/versionamento.

Métricas para comparar:

MétricaO que medeExpectativa
Lead timeTempo total do pedido à entregaB menor (menos retrabalho)
Cycle timeTempo de execução ativaB levemente maior (gates adicionam overhead)
Taxa de task reabertaTasks que voltaram de “done” para “in progress”B significativamente menor
Defeitos pós-mergeBugs encontrados depois que o código entrou na branch principalB menor
% de “done” bloqueado por DoDQuantas vezes a DoD impediu um done prematuroExclusivo de B (indicador de alucinações evitadas)
Regressão de harnessQueda na pontuação de qualidade estrutural ao longo do tempoB estável, A degradando

Critério de sucesso: se B entrega mais rápido (lead time menor), com menos reabertura e menos defeito escapado, sua tese está provada empiricamente. O gargalo era engenharia, não modelo.

Na minha experiência, B tende a ter um cycle time ligeiramente maior por task (porque os gates adicionam overhead), mas um lead time total significativamente menor (porque não há retrabalho). O resultado líquido é mais throughput real com menos custo total.

Por que isso importa para o time-to-market

O argumento de negócio é direto: retrabalho é o assassino silencioso do time-to-market. Quando um agente “entrega rápido” mas a entrega precisa ser refeita, corrigida ou completada manualmente, o tempo total é maior do que se a entrega tivesse sido mais lenta, porém correta.

A engenharia de restrições troca velocidade aparente por velocidade real. O agente demora um pouco mais por task (porque precisa passar por gates), mas cada task entregue é de fato entregue. Não há surpresas no review. Não há rollback inesperado. Não há sprint inteira consumida corrigindo o que um agente “entregou” na sprint anterior.

Empresas como Stripe, Datadog e Salesforce chegaram a essa mesma conclusão por caminhos diferentes. A Stripe com seus Minions e o “envelope de execução”. O Datadog com harness-first engineering e testes determinísticos. A Salesforce com o Agent Graph e máquinas de estado finito. O padrão é convergente: a inteligência do modelo só se converte em valor de negócio quando envolvida por engenharia determinística.

Conclusão

Modelos alucinam. Isso é fato. Mas em produção, o que define o impacto da alucinação é a arquitetura de contenção ao redor do modelo.

Quando o código impõe contrato, trilha de estado, evidência rastreável e concorrência segura, o agente deixa de ser “gerador de texto com sorte” e vira executor confiável. A alucinação pode até ser gerada internamente pelo modelo, mas nunca persiste no sistema porque cada gate, cada check, cada validação funciona como um filtro que separa output válido de output inventado.

O resultado de negócio é claro: menos retrabalho, menos rollback, mais throughput real. Ou seja, time-to-market menor com segurança maior.

A próxima vez que seu agente “alucinar” em produção, antes de trocar o modelo ou ajustar o prompt, olhe para o código ao redor. Pergunte: existe contrato de entrada? Existe validação de saída? Existe controle de concorrência? Existe rastreabilidade de contexto?

Se a resposta for “não” para qualquer uma dessas perguntas, o problema não é o modelo. É a engenharia.

E a boa notícia é que engenharia, diferente de modelos, está 100% sob o seu controle.

Comentários

Carregando comentários...

Deixe um comentário

Posts relacionados

Fique por dentro

Receba artigos sobre arquitetura de software, IA e projetos open source direto no seu e-mail.