--- title: Como criar um agente de IA sem escrever o boilerplate description: Você instala duas coisas e depois descreve o agente que quer. Seu coding agent escreve, deploya e testa. Seu trabalho é entender os conceitos o suficiente para pedir a coisa certa. date: 2026-08-11 author: Victor Villalobos locale: pt source: https://www.zavu.dev/pt/blog/how-to-build-an-ai-agent tags: AI Agents, Tutorial, CLI, WhatsApp --- # Como criar um agente de IA sem escrever o boilerplate Quase todo guia sobre como criar um agente de IA entrega cem linhas para você digitar. Um loop, um dispatcher de tools, um handler de webhook, um store de conversas. Você digita, funciona no seu notebook, e o tutorial se declara concluído. Esse era o formato certo de guia dois anos atrás. Não é mais, porque você já tem um agente que escreve código dentro do seu editor, e boilerplate é exatamente aquilo em que ele é bom. Então este guia tem outro formato. Você instala duas coisas. Depois descreve o que quer em linguagem natural, e o seu coding agent faz o scaffolding, deploya, testa e lê os logs. O que você precisa trazer é o que ele não consegue: saber do que um agente é feito, o suficiente para pedir o agente certo e para identificar uma resposta ruim. ## O que faz de algo um agente Vale ser preciso, porque a palavra foi esticada até não significar mais nada, e porque um modelo mental vago produz um prompt vago. Um **prompt** é uma chamada. Texto entra, texto sai. Um **agente** é um loop. O modelo recebe um objetivo e um conjunto de tools. Ele decide qual tool chamar, vê o resultado e decide de novo. Continua até cumprir o objetivo ou até desistir. ``` while not done: decision = model(conversation, tools) if decision.is_final_answer: done = True else: result = run_tool(decision.tool, decision.args) conversation.append(result) ``` Esse loop é a ideia inteira. Os frameworks acrescentam memória, retries, tracing e handoff entre agentes, mas se você desmontar qualquer um deles encontra isso. Você não vai escrever esse loop. O runtime cuida dele. Você precisa entender porque toda falha que vai debugar é uma falha desse loop: rodou vezes demais, chamou a tool errada, ou nunca chamou nenhuma. A consequência prática: **um agente vale o que valem as tools dele.** Um modelo sem tools consegue falar sobre a sua política de trocas. Um modelo com uma tool `lookup_order` consegue dizer ao cliente onde está o pacote. Quase todo o valor mora nas tools, o que significa que quase todo o seu prompt deveria ser sobre elas. ## As cinco decisões antes de pedir qualquer coisa Essas são as que um coding agent não pode tomar por você, porque são decisões de negócio vestidas de decisões técnicas. Dez minutos aqui economizam uma semana. **1. O que o agente tem permissão de fazer?** Escreva a lista de tools primeiro. `lookup_order`, `book_slot`, `transfer_to_human`. Se a lista ficar vazia, você quer um chatbot, não um agente, e vale [ler a comparação](/pt/blog/ai-agent-vs-chatbot) antes de construir qualquer um dos dois. **2. O que acontece quando ele não tem certeza?** Todo agente esbarra numa pergunta que não sabe responder. As duas opções honestas são: dizer isso e parar, ou passar para um humano. Escolha uma agora. A falha que você está evitando é o agente que inventa uma resposta com toda a confiança, e isso é decisão de design, não problema do modelo. **3. Qual canal?** Isso define a sua arquitetura, e é a pergunta mais pulada de todas. Está mais abaixo. **4. O que ele nunca pode fazer?** Prometer uma data de entrega. Aprovar um reembolso acima de um valor. Dar orientação médica. Isso vira linha do prompt, e se você não disser em voz alta agora, não vai estar lá. **5. Como você vai saber que quebrou?** Se a resposta for "algum cliente vai avisar", você não tem plano de observabilidade. Tem fila de reclamação. Escritas, essas cinco respostas são quase todo o seu prompt. É esse o motivo de escrevê-las. ## Escolher o canal Seus clientes já têm um lugar onde leem mensagens. A pergunta é em qual deles você aparece. | Canal | Bom para | O detalhe | |---|---|---| | WhatsApp | Suporte, agendamento, qualquer coisa conversacional no Brasil, LATAM, Índia, sudeste asiático | Verificação de negócio, e você só escreve livremente por 24 horas depois que o cliente escrever | | SMS | Alcançar qualquer um com celular, alertas, verificação | Nos Estados Unidos você precisa de registro A2P 10DLC antes de as operadoras entregarem | | Email | Contexto longo, anexos, threads, B2B | Deliverability é uma disciplina à parte: DKIM, SPF e uma reputação de domínio que dá para queimar | | Voz | Quem não vai digitar, público mais velho, mãos ocupadas | O orçamento de latência não perdoa. Dois segundos de silêncio soam como ligação caída | | Telegram, Instagram, Messenger | Comunidades e marcas de consumo cujo público já mora ali | Cada um tem seu modelo de identidade e seus rate limits | O widget de chat no site ficou fora da tabela de propósito. Um widget só alcança quem já está no seu site. Todos os canais acima alcançam a pessoa onde ela já está, e é por isso que um agente no WhatsApp é usado e o mesmo agente atrás de um widget não é. ## O setup: dois comandos ```bash npx skills add zavudev/zavu-skills npx zavudev@latest login ``` Eles fazem dois trabalhos diferentes, e vale saber qual é qual. **As skills dão conhecimento ao seu coding agent.** Peça a qualquer coding agent "adiciona WhatsApp no meu app" sem elas e você recebe código que parece certo. Parecer certo é o problema: ele inventa nomes de endpoint, ignora a janela de 24 horas e aí o primeiro envio em produção falha enquanto em dev nunca falhou, e escreve um handler de webhook sem verificação de assinatura. Isso não é o modelo ser fraco. Ele simplesmente nunca viu essa API, e não vai te avisar. As skills são markdown puro que se carrega sozinho quando a tarefa combina, e o instalador pergunta em quais coding agents instalar. São mais de quarenta suportados, incluindo Claude Code, Cursor, Copilot, Codex, Cline, Gemini CLI, Amp e Warp. **O CLI dá as mãos.** Scaffolding, secrets, deploy, teste, logs. O `login` abre o navegador, você entra, escolhe o projeto e clica em Authorize. A chave fica em `~/.zavu/credentials.json` e o seu agente usa dali em diante. Numa máquina sem navegador, defina `ZAVUDEV_API_KEY`. Isso é tudo o que você digita. Daqui em diante, você conversa. ## O prompt Agora use as cinco respostas. Um bom prompt para isso não é esperto, é específico: > Construa um agente de suporte para a minha loja online no WhatsApp. > > Ele deve responder perguntas sobre pedidos. Dê a ele uma tool que busque um pedido por ID em `https://api.example.com/orders/{id}`, usando `STORE_API_KEY` dos secrets. Dê uma segunda tool que passe a conversa para um humano, fazendo POST no nosso webhook de plantão. > > Regras: responder em duas frases ou menos, nunca inventar data de entrega, e se não achar um pedido dizer isso e oferecer uma pessoa. Para reembolsos acima de USD 200 sempre usar a tool de handoff em vez de decidir. > > Deploye e teste com "onde está o pedido 4471?" Seu coding agent vai fazer o scaffolding da function, escrever o agente e as duas tools, definir os secrets, deployar e rodar o teste. Repare no que fez esse prompt funcionar: eram as decisões 1, 2 e 4 da lista acima, ditas em voz alta. Nada ali é sintaxe. ## O que ele escreveu, e o que você confere Isso você não digita. Você lê, porque revisar o diff é a parte que continua sendo sua: ```ts import { defineAgent, defineTool } from "@zavudev/functions" defineAgent({ senderId: process.env.SENDER_ID!, name: "Nora", provider: "zavu", model: "openai/gpt-4o-mini", prompt: `Você é a Nora, suporte de uma loja online. Responda em duas frases ou menos. Se não encontrar um pedido, diga isso e ofereça passar o cliente para uma pessoa. Nunca invente uma data de entrega.`, }) defineTool({ name: "lookup_order", description: "Get the current status of a customer order. Use when the customer mentions an order number or asks where their package is.", parameters: { type: "object", properties: { orderId: { type: "string" } }, required: ["orderId"], }, handler: async ({ orderId }) => { const res = await fetch(`https://api.example.com/orders/${orderId}`, { headers: { Authorization: `Bearer ${process.env.STORE_API_KEY}` }, }) return res.json() }, }) ``` Três coisas para olhar, nesta ordem: **As descrições das tools.** `"Use when the customer mentions an order number or asks where their package is"` é o que o modelo lê ao decidir se chama aquilo. Essa é a linha de maior alavancagem do arquivo, e é a que um coding agent escreve de qualquer jeito com mais frequência. Se diz só "busca um pedido", faça dizer quando, e quando não. **Suas regras, de fato presentes.** Todo "nunca" que você pediu deveria aparecer na string do prompt. Se faltar um, boa intenção não vai fazer ele valer. **A regra de escalada em dois lugares.** A política vai no prompt para o modelo conhecer. O gatilho vai na descrição da tool para o modelo reconhecer o momento. Um agente que "sabe" que deveria escalar mas nunca escala quase sempre está sem o segundo. O que você não está revisando: o loop, o limite de turnos, o histórico por contato, a verificação de assinatura do webhook, a janela de 24 horas do WhatsApp. O runtime cuida de tudo isso, que é a razão de não haver boilerplate nesse arquivo. ## Testar antes que um cliente teste ```bash npx zavudev agents test --agent --message "onde está o pedido 4471?" ``` Roda o agente real com o prompt real e o knowledge base real, devolve o que ele diria, não entrega nada a ninguém e não cobra nada. Seu coding agent pode rodar isso em loop enquanto itera. Use `--json` para fazer assert no CI. Dois detalhes tornam isso mais honesto que a maioria dos previews. Ele devolve `warnings` com coisas que são verdade sobre o seu agente mas que um dry run não consegue provar: o agente desabilitado, ou tools que existem mas não foram oferecidas ao modelo naquela rodada. E por padrão ele **não** executa as tools, porque um ensaio que passa o cartão de um cliente não é ensaio. Quando quiser o loop completo, passe `executeTools` e olhe `executedToolCalls` para ver o que rodou. Um teste verde não prova que o agente funciona ao vivo. Prova que o prompt faz o que você acha, que era justamente a sua dúvida. ## Iterar é prompar mais Você não volta para o editor. Você diz o que ficou errado: > Ele respondeu "seu pedido está a caminho" sem chamar a tool. Aperte a descrição da tool para ela disparar sempre que um pedido for mencionado, redeploye e teste de novo com a mesma mensagem. Isso funciona porque o resumo do deploy é legível por máquina e o teste é um comando, então o seu coding agent fecha o ciclo sozinho: muda, deploya, testa, lê, muda de novo. Uma coisa para saber sobre esse resumo. `+` é criado, `~` é que existia e foi reescrito, `= (unchanged)` é que nada diferia. Os marcadores descrevem o que o deploy **escreveu**, não o que o agente agora **diz**. Para verificar que uma mudança chegou ao modelo, ponha uma palavra distintiva no prompt que você editou e veja se ela volta do `agents test`. E leia as linhas acima do ✓: os warnings aparecem antes da linha de sucesso, e cobrem os casos em que um deploy verde não fez o que parece. ## Partir de algo que já funciona Costuma ser mais rápido que descrever um agente do nada: ```bash npx zavudev agents catalog npx zavudev agents pull fermi --sender ``` O `catalog` lista agentes prontos para suporte, captação de leads e agendamento, com a contagem de tools e se atendem ligação. O `pull` coloca um deles no seu repositório como código real e editável que é seu, com o prompt e todas as tools já escritas. Depois você aponta o seu coding agent para lá: "mude isso para funcionar numa clínica odontológica e use a nossa API de agendamento". O `npx zavudev agents init` roda o processo inteiro como um comando guiado, incluindo a criação do sender. ## O que dá errado em produção Cinco falhas, na ordem em que você vai conhecer cada uma. Cada uma também é um bom prompt para o seu coding agent, porque ele consegue ler os mesmos registros que você. **Responde com confiança e erra.** Quase sempre é um prompt que nunca deu a ele permissão de falhar. Adicione a frase explícita: "Se você não sabe, diga que não sabe." Depois confira `knowledgeChunksUsed` no registro de execução. Zero, num agente com documentos anexados, significa que a resposta não veio do seu conteúdo. **Diz que vai consultar algo e nunca consulta.** A resposta parece que chamou uma tool. Nada chegou ao seu endpoint. Confira `toolCalls` na execução: zero num agente com tools configuradas significa que o modelo respondeu sem chamar nenhuma. Quase sempre a descrição da tool não bate com as palavras que os clientes usam. **Responde duas vezes.** Chegam duas mensagens em um segundo, rodam dois loops, os dois respondem. Trate o caso de uma conversa que já está sendo processada. **É lento.** Cada tool call é um round trip, e o modelo espera. No WhatsApp você tem alguns segundos antes do silêncio soar como quebrado, então marque a mensagem como lida e mostre o indicador de digitação. Na voz você tem cerca de um segundo, e é por isso que as tools de um voice agent precisam ser rápidas ou parecer rápidas. **Funciona e ninguém sabe explicar por quê.** O `npx zavudev agents executions` dá os tool calls, os argumentos, os resultados e os erros de um agente deployado. Passe essa saída para o seu coding agent e pergunte o que mudou. ## Limites honestos Algumas coisas para as quais um agente não deveria ser a resposta. Se a tarefa é determinística, peça uma função. Um agente que sempre chama a mesma tool na mesma ordem é um workflow com um imposto de modelo de linguagem em cima. Se uma resposta errada sai cara, o agente precisa de um humano no caminho de aprovação, não de prompting melhor. Reembolso, orientação médica e qualquer coisa juridicamente vinculante entram nessa categoria. Se você não tem tools, você tem uma interface de busca sobre os seus documentos. Isso pode ser genuinamente útil. Não é um agente, e chamar de agente cria uma expectativa que você não vai cumprir. E o limite deste fluxo em específico: o seu coding agent faz tudo o que está na coluna da direita, mas você continua criando a conta, autorizando o login, aprovando a compra de um número, conectando o WhatsApp Business pelo signup da Meta, e lendo o diff antes de ir para produção. Esses são os passos que legal, financeira ou fisicamente precisam de uma pessoa. ## Para continuar - [Agente de IA vs chatbot](/pt/blog/ai-agent-vs-chatbot): o que muda de verdade ao adicionar tools, e quando um flow com script ainda é o certo. - [Frameworks de agentes de IA comparados](/pt/blog/ai-agent-frameworks): LangGraph, CrewAI e os outros, e qual camada cada um resolve. - [Crie agentes de IA com o seu coding agent](/pt/blog/build-ai-agents-with-your-coding-agent): o mesmo fluxo com mais profundidade, incluindo quem faz o quê. - [Agentes de IA no WhatsApp com Next.js](/pt/blog/whatsapp-ai-agents-nextjs), [FastAPI](/pt/blog/whatsapp-ai-agents-fastapi) ou [Django](/pt/blog/whatsapp-ai-agents-django): quando você está ligando um app que já existe. - [Troque a sua URA por um voice agent](/pt/blog/replace-your-ivr-with-a-voice-agent): a mesma ideia, no telefone.