DEV Community

Cover image for Por que os assistentes de IA ainda erram tanto (e o que fazer sobre isso)
Giovana Armani for AWS

Posted on

Por que os assistentes de IA ainda erram tanto (e o que fazer sobre isso)

Em janeiro desse ano, perguntei para meu assistente de IA sobre AWS Lambda Durable Functions. Ele muito gentilmente me falou que eu estava ficando maluca, a AWS não tinha uma feature com esse nome...

Acontece que essa feature foi lançada em dezembro do ano passado e quando fiz a pergunta, estava usando um modelo de IA que tinha sido treinado vários meses antes. Meu assistente não tinha ferramentas que conectasse ele à documentação da AWS ou nenhuma instrução de quando ela deveria ser consultada.

Os desafios de trabalhar com IA

Conto essa história de frustração pessoal para dizer que trabalhar com IA não é um mar de rosas. Se você é desenvolvedor nos dias de hoje, você já sabe disso, mas quando tudo ao seu redor fala sobre como a IA vai dominar o mundo, é difícil entender porque ainda tem tantos problemas.

Para entender isso, é legal olhar para como os modelos de IA são construídos e como funcionam. Para começo de conversa, a maioria dos assistentes de IA atuais são construídos com LLMs (Large Language Models, ou em português, Grandes Modelos de Linguagem). Esses modelos são treinados com um volume gigante de dados que ajudam eles a entender, interpretar e produzir texto. Isso vale para linguagem humana e também para código.

Quando mandamos um prompt a um assistente de IA, o modelo por trás faz um cálculo probabilístico para nos dar uma resposta. Em outras palavras, o modelo produz o texto da resposta prevendo parte por parte qual é a próxima palavra mais provável de se encaixar no que o usuário espera. Isso nos traz resultados que parecem coerentes, mas não são necessariamente o que queremos ou a melhor solução para nosso problema.

Esse funcionamento traz vários desafios que vamos ver ao longo do artigo (e também como lidar com eles), mas também traz uma boa notícia para os desenvolvedores que vira e mexe me perguntam se a IA vai roubar o trabalho deles. Escrever código é diferente de construir software, assim como escrever texto é diferente de produzir conteúdo.

Quando falamos sobre escrever código, queremos dizer transformar instruções em implementação. Já quando falamos em software, nos referimos a transformar ideias abstratas em um sistema confiável. Ou seja, por mais poderosa que a IA fique, alguém ainda precisa entender o problema antes de ele virar código, acompanhar enquanto o sistema é desenvolvido e ser dono do software depois que ele existe. É aí que mora o perigo dos resultados que parecem certos, estão quase certos, mas não exatamente. Se a gente aceita tudo de olhos fechados, herdamos esses "quase" como se fossem nossos.

Como trabalhar melhor com IA

Vamos então falar mais especificamente sobre desafios do uso de IA no desenvolvimento e criação e o que podemos fazer sobre eles. Os assistentes de IA trazem várias features que podem nos ajudar a administrar esses desafios e trabalhar melhor com a ferramenta.

Vou usar o Kiro e suas features como base da discussão, mas a maioria das dicas aqui podem ser aplicadas com qualquer assistente.

O que fazer quando a IA te chama de maluca

Como vimos, os modelos de IA têm como base o conhecimento que receberam através de seus dados de treinamento. Se não conectamos eles a ferramentas ou fontes de informação externas, eles acabam ficando "presos no tempo", com o conhecimento limitado a esses dados. É isso que gera situações como a que eu descrevi no começo do artigo em que o Kiro me falou que não existia uma feature chamada AWS Lambda Durable Functions.

A forma mais comum de conectar seu assistente a ferramentas externas é o MCP, ou Model Context Protocol. Ele é um protocolo aberto que conecta assistentes de IA a ferramentas externas.

Um bom exemplo é o servidor MCP aws-knowledge, mantido pela própria AWS, que dá ao assistente acesso à documentação oficial sempre atualizada. Com ele conectado, o Kiro deixa de depender só do que aprendeu no treinamento e passa a consultar a fonte na hora de responder. Foi assim que resolvi meu problema lá no começo do ano enquanto estudava sobre Lambda Durable Functions. Com esse servidor configurado, em vez de me dizer que eu estava ficando maluca, o Kiro agora consulta a documentação, descobre que a feature existe sim, e me responde baseado nela.

{
  "mcpServers": {
    "aws-knowledge-mcp-server" : {
      "url" : "https://knowledge-mcp.global.api.aws",
      "disabled" : false
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

MCP - Melhores Práticas

É importante lembrar que além de leitura, um servidor MCP pode também ter acesso a ferramentas para criar, editar ou até apagar coisas por você. Por isso, vale tomar cuidado com o uso. Algumas melhores práticas que sugiro:

  1. Revise antes de aprovar: Toda vez que o assistente quiser usar uma ferramenta MCP, ele pede sua aprovação. Não aprove no automático, antes leia o que ele vai fazer, confira os parâmetros e entenda o efeito. Se parecer suspeito, negue. Deixe o auto-approve apenas para ações que você sabe que são seguras e repetitivas, como uma consulta de leitura.

  2. Bloqueie ações perigosas: Além do cuidado de revisar o que o assistente faz, você pode explicitamente configurar o que você jamais quer que ele faça. Por exemplo, se você conecta seu assistente com um MCP do GitHub, pode querer impedir que ele tome ações destrutivas como apagar repositórios ou forçar o merge de uma alteração. No Kiro, por exemplo, faríamos isso com disabledTools:

{
  "mcpServers": {
    "github": {
      "command": "uvx",
      "args": ["github-mcp-server@latest"],
      "disabledTools": ["delete_repository", "force_push"]
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

3 . Auto approve para ações seguras: Por outro lado, existem ações cotidianas que sabemos que são seguras e não queremos ficar clicando aprove o tempo todo, para isso podemos declarar as ferramentas que são automaticamente aprovadas.

{
  "mcpServers": {
    "github": {
      "command": "uvx",
      "args": ["github-mcp-server@latest"],
      "disabledTools": ["delete_repository", "force_push"],
      "autoApprove": ["search_repositories", "get_file_contents"]
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

4 . Proteja suas chaves e tokens: Muitos servidores MCP precisam de credenciais para funcionar. Nunca faça commit de uma config com segredos dentro, prefira variáveis de ambiente. E quando gerar um token, use o de menor permissão possível e rotacione de tempos em tempos.

Por que você recebe respostas genéricas mesmo com prompts gigantes

Outro problema que enfrentamos é de fazer a IA entender exatamente o que queremos. Costumamos achar que colocar o máximo de informação possível no prompt vai fazer com que as respostas sejam mais assertivas, o que muitas vezes até ajuda. Mas quando o assistente tem informação demais sem referência de prioridade, pode ter dificuldade de determinar o que é realmente importante. A verdade é que contexto irrelevante não é neutro, compete por atenção e piora a qualidade da resposta.

A solução para isso é direcionar o foco do seu assistente, e uma das formas mais práticas de fazer isso são os steering files. São arquivos markdown onde você registra as regras, padrões e preferências do seu projeto, e que o assistente passa a considerar na hora de responder. Em vez de repetir no prompt que você usa um certo padrão de nomes, que prefere uma biblioteca a outra ou que todo componente precisa ser acessível, você escreve isso uma vez em um steering file e o assistente lembra. No Kiro eles ficam na pasta .kiro/steering/.

Um detalhe importante é que você não precisa deixar todo esse contexto ligado o tempo todo, o que nos traria de volta o problema de contexto demais. Para isso existem os inclusion modes, que controlam quando cada arquivo entra na conversa. No Kiro, um steering file pode estar sempre ativo (always), ser carregado só quando você mexe em certos arquivos (fileMatch), entrar sob demanda quando você chama (manual), ou ser puxado por relevância com base na descrição (auto). Assim, o Kiro carrega cada regra no momento em que ela é realmente necessária.

Steering Files - Melhores Práticas

Para aproveitar bem os steering files, algumas boas práticas:

  1. Um domínio por arquivo: Separe API, testes, deploy, etc em arquivos distintos, em vez de amontoar tudo em um arquivão só. É o mesmo princípio de um bom código. Isso traz dois ganhos. Primeiro, os inclusion modes só funcionam bem se cada arquivo tem um escopo único, afinal não dá para carregar "só a parte de testes" de um arquivo que mistura dez assuntos diferentes. Segundo, facilita a manutenção, já que arquivos focados geram diffs pequenos e legíveis, o que facilita a revisão.

  2. Nomes claros e descritivos: Prefira nomes específicos como api-rest-conventions.md, testing-unit-patterns.md ou components-form-validation.md. A própria lista de arquivos vira um índice do que existe e de onde mexer, tanto para você quanto para o assistente.

  3. Inclua o "porquê": Não registre só o "o quê" da regra, explique a razão por trás dela. Uma regra sem justificativa só funciona nos casos que ela previu literalmente, enquanto uma regra com justificativa funciona também nos casos que ninguém antecipou. Se o steering diz "fazemos X porque já tentamos Y e deu o problema Z", o assistente não vai tentar "consertar" uma decisão que foi deliberada.

  4. Faça manutenção regular: Trate mudanças de steering como mudanças de código, com revisão. Revise os arquivos em momentos como planejamento de sprint ou mudanças de arquitetura, e confira as referências a arquivos depois de reestruturações, para não deixar o assistente seguindo uma regra que não vale mais.

Para quando não aguentar mais escrever os mesmos prompts

Já teve algum momento que você percebeu que vive sempre pedindo a mesma coisa para seu assistente de IA? E mesmo assim, a cada vez que pede tem que ir fazendo várias correçõezinhas no processo? Talvez esteja na hora de criar uma skill.

Skills são pacotes de conhecimento especializado e instruções que você empacota uma vez e reutiliza sempre que precisar. Em vez de reescrever o mesmo prompt detalhado e ir fazendo as mesmas correções toda vez, você formaliza aquele processo recorrente numa skill: o passo a passo, as regras principais e até scripts de apoio ou arquivos de referência. O resultado é mais assertividade, porque o assistente deixa de reinventar o processo a cada pedido e passa a seguir sempre o mesmo caminho que você já validou.

A diferença das skills para os steering files está em quando e como cada um atua. O steering é amplo e sempre lembra o assistente dos padrões do seu projeto. Já a skill é especializada e sob demanda. Dá para pensar assim: steering é "sempre tenha isso em mente", enquanto skill é "quando alguém pedir para fazer X, carregue todo esse conhecimento especializado e siga este workflow". No Kiro, as skills ficam em pastas (uma por skill, com um arquivo que descreve o que ela faz) e são ativadas automaticamente quando o pedido combina com a descrição que você escreveu, ou você pode chamá-las explicitamente.

Imagem ilustrando a diferença entre steerings (sempre tenha isso em mente durante as tarefas) e skills (quando te pedirem tarefa X, faça dessa maneira)

Skills - Melhores Práticas

Para criar skills que realmente ajudam, valem algumas boas práticas:

  1. Escreva descrições precisas: É a descrição que decide quando o assistente ativa a skill, então inclua palavras-chave e ações concretas. No início da conversa, só o nome e a descrição são carregados (um mecanismo chamado progressive disclosure, que evita encher o contexto do assistente), e o resto só entra quando a skill é acionada. Por isso quanto mais clara e precisa for sua descrição, mais fácil será para o assistente saber o momento de usá-la.

  2. Use scripts para tarefas determinísticas: Tarefas determinísticas como validação, geração de arquivos e chamadas de API são mais confiáveis como scripts do que como código gerado pelo LLM na hora. Se o passo sempre acontece do mesmo jeito, deixe-o num script dentro da skill, em vez de contar com o modelo para recriá-lo a cada vez.

  3. Escolha o escopo certo: Use o escopo global (~/.kiro/skills/) para workflows pessoais que você usa em qualquer projeto, e o escopo de workspace (.kiro/skills/) para procedimentos do time e convenções específicas daquele projeto. Nesse segundo caso, versione a pasta junto do código para que todo mundo compartilhe os mesmos workflows.

Como ser mais assertivo no vibe coding

Por último, vamos falar sobre o uso de IA quando desenvolvemos aplicações. Com o uso de IA para desenvolvimento de software, a produção de código está mais rápida do que nunca. Mas será que com tanta velocidade e volume, estamos sendo atentos à qualidade produzida? Temos clareza dos requisitos e certeza que o código os cumpre como esperado? Estamos seguindo os padrões de código que determinamos para facilitar revisão e manutenção?

Para nos ajudar com isso, o Kiro traz uma funcionalidade de spec-driven development, ou o Spec mode. Se trata de uma forma de desenvolvimento de features guiado por especificações. Você começa o desenvolvimento pela especificação de requisitos e documentação. Isso acontece no Kiro através da criação de 3 arquivos: um requirements.md com o que precisa ser feito, um design.md com as decisões técnicas e um tasks.md com o passo a passo da implementação. Só depois de alinhar esses documentos é que a IA parte para escrever o código, agora com um alvo claro em vez de um prompt solto. Se quiser saber mais sobre specs e o que eu construi usando esse modo, veja esse artigo sobre a aplicação que construí para acompanhar meus treinos.

Spec Driven Development - Melhores Práticas

Para tirar o melhor do spec-driven development, sugiro algumas boas práticas:

  1. Uma spec por feature, não uma spec gigante: O padrão recomendado é ter várias specs no repositório, cada uma para uma feature, em vez de uma única spec tentando descrever o codebase inteiro. Algo como .kiro/specs/user-authentication/, .kiro/specs/product-catalog/, .kiro/specs/shopping-cart/. Isso mantém cada documento gerenciável e ainda permite que pessoas diferentes trabalhem em features diferentes em paralelo.

  2. Itere nas specs: As specs não devem ser escritas em pedra no começo e esquecidas. Conforme o entendimento da feature evolui, atualize o requirements.md e o design.md, e mantenha o tasks.md sincronizado com o que realmente vai ser feito. A spec só continua útil enquanto reflete a realidade do que você está construindo.

  3. Versione e compartilhe: Guarde as specs no repositório, junto do código, para que elas sejam versionadas da mesma forma.

O que levar dessa leitura

Começamos esse artigo com um assistente me chamando de maluca, e ao longo dele vimos que boa parte das dores de trabalhar com IA tem explicação, e também solução. Quando o modelo está preso no tempo, conectamos ferramentas externas com MCP. Quando ele se perde em contexto demais, direcionamos o foco com steering files. Quando ele dá respostas genéricas ou nos faz repetir o mesmo pedido mil vezes, empacotamos conhecimento em skills. E quando a pressa de produzir código ameaça atropelar os requisitos, trazemos método com o spec-driven development.

Nenhuma dessas técnicas precisa andar sozinha. Na prática, o melhor resultado vem de combinar várias (ou todas) delas, e de nunca abrir mão da revisão humana, principalmente nas etapas de criação e nas ações mais críticas. Porque, no fim do dia, por mais que a IA faça o trabalho pesado, é a gente que entende o problema antes dele virar código e responde pelo software depois que ele existe.

E apesar de eu ter usado ferramentas de desenvolvimento como exemplo, esse raciocínio vale para qualquer pessoa que trabalha com IA, seja escrevendo código, texto ou qualquer outra coisa. A IA é uma ferramenta poderosa, talvez a mais poderosa que a gente já teve nas mãos, mas continua sendo uma ferramenta. E toda orquestra, por melhores que sejam os instrumentos, ainda precisa de um maestro.

Se se interessou pelo Kiro e gostaria de saber mais, assista à playlist sobre Kiro no canal do YouTube mantido pelo meu time da AWS e me siga para mais conteúdos sobre IA, desenvolvimento e cloud! 😉

Top comments (0)