AI AgentsE-commerceNuvemshopWhatsAppTelegramTutorialAPI v2

Chatbot com IA para loja virtual: responde com as suas políticas e diz onde está o pedido

Como criar um chatbot com IA para loja virtual com a API da Zavu: responde com as políticas de frete e trocas, consulta pedidos e passa para uma pessoa.

Escrito por: Zavu TeamRevisado por: Jennifer Villalobos19 de outubro de 202613 min de leitura
Ver como Markdown

TL;DR

  • As respostas saem das suas políticas. O agente busca numa base de conhecimento com os seus documentos de frete, trocas e perguntas frequentes antes de responder.
  • O status do pedido vem da sua loja. Uma tool get_order_status chama o seu endpoint HTTPS, que verifica a assinatura e devolve o status real.
  • Você testa sem mandar mensagem para clientes. POST /v2/agents/{agentId}/test devolve a resposta e a tool que o modelo escolheu; com o provider zavu o teste é cobrado como uma resposta real.
  • Comece no Telegram e troque de canal depois. O Telegram conecta com uma chamada à API; WhatsApp e Instagram, em Canais no dashboard, com o mesmo agente.
  • Responder pela caixa de entrada não pausa o agente. Só o passo transfer de um fluxo pausa, até alguém da sua equipe responder.

Uma loja virtual recebe quase sempre as mesmas cinco perguntas: cadê meu pedido, quanto é o frete, posso trocar, tem em outro tamanho, quantos dias para chegar. Um chatbot com IA para loja virtual vale a pena quando responde isso com as suas políticas reais e os seus pedidos reais, e não com o que o modelo imagina.

Este tutorial monta isso sobre a API da Zavu, de ponta a ponta, com HTTP simples. Funciona igual se você vende na Nuvemshop, na Shopify ou no seu próprio site. No final você tem:

  • Um canal de chat conectado (Telegram para começar, WhatsApp ou Instagram quando for para produção).
  • Um agente com IA que responde a partir de uma base de conhecimento com a sua política de frete, de trocas e devoluções e as perguntas frequentes.
  • Uma tool get_order_status: o agente chama o seu endpoint, você verifica a assinatura e responde com o status do pedido direto da sua loja.
  • Um jeito de testar tudo sem mandar mensagem para nenhum cliente.
  • Uma palavra-chave que passa a conversa para uma pessoa, e o agente quieto até essa pessoa responder.

Se você prefere fazer pelo painel, o passo a passo do agente de suporte monta a versão do Telegram sem código. Este post é a versão pela API, com os seus pedidos dentro do loop.

O que você precisa

  • Uma conta na Zavu e uma API key. Todas as chamadas abaixo enviam Authorization: Bearer $ZAVUDEV_API_KEY.
  • Um canal onde os seus clientes escrevem. Cada um tem um custo diferente para colocar no ar:

- Telegram: um token de bot do @BotFather. Uma chamada à API, sem revisão, sem conta na Meta. O jeito mais rápido de ter algo real para testar. - WhatsApp: uma conta do WhatsApp Business pelo cadastro da Meta, conectada em Canais no painel. É o canal com mais atrito para conectar, e no Brasil quase sempre é o que o seu cliente realmente usa. - Instagram: também passa pela Meta, em Canais no painel.

  • Um endpoint HTTPS do seu lado que saiba buscar um pedido. Ele precisa ser público: a Zavu recusa uma tool cuja URL não é um endereço HTTPS público.
  • As suas políticas em texto. Frete, trocas e devoluções, formas de pagamento, o que você responde toda semana no direct.

Os SDKs (@zavudev/sdk, zavudev) chamam a API v1. A API v2 é chamada por HTTP, então os exemplos usam curl e fetch. Duas peças desta montagem ainda não têm endpoint na v2, a base de conhecimento e as tools, e ficam na v1 em /v1/agents/{agentId}/..., com a mesma key e o mesmo id de agente. O guia de migração lista o que continua na v1. Cada passo diz qual versão usa.

1. Conectar um canal (v2)

Comece pelo Telegram. Crie um bot com o @BotFather, copie o token e conecte:

terminal
curl -X POST https://api.zavu.dev/v2/channels \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{"type": "telegram", "botToken": "123456789:AA..."}'

O 201 lista as entradas do endereço que você conectou. O endereço de um bot do Telegram é @nomedobot:

JSON
{ "items": [ { "address": "@loja_aurora_bot", "type": "telegram", "active": true, "v1SenderId": "kd7..." } ] }

Se o Telegram recusar o token, nada é criado e você recebe 400 invalid_bot_token, com as palavras do Telegram em details.telegramSaid. Copie o token de novo no @BotFather.

Confira active. Uma conexão que no seu plano custa dinheiro nasce desligada; você liga com POST /v2/channels/{address}/{type}/activate, e a resposta diz quanto cobrou em chargedCents e monthlyCents. Detalhes em Endereços e canais.

WhatsApp e Instagram não se conectam por este endpoint. Eles se conectam em Canais no painel; depois de conectados aparecem em GET /v2/channels e o resto do tutorial funciona igual, com o número (por exemplo +5511987654321) ou o @usuario como endereço.

2. Criar o agente (v2)

terminal
curl -X POST https://api.zavu.dev/v2/agents \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Assistente Loja Aurora", "provider": "zavu", "model": "openai/gpt-4o-mini", "systemPrompt": "Você atende clientes da Loja Aurora, uma loja virtual brasileira. Responda só com a base de conhecimento e a tool get_order_status. Se a resposta não estiver lá, diga que não sabe e ofereça falar com uma pessoa. Para consultar um pedido, peça o número do pedido e o e-mail da compra. Nunca invente prazo de entrega. Respostas curtas: isto é um chat." }'

name, provider, model e systemPrompt são obrigatórios, e a v2 aponta todos os que faltam num único 400. provider é openai, anthropic, google, mistral ou zavu.

zavu é o provedor gerenciado: você não precisa de API key própria e cada resposta é cobrada do seu saldo na Zavu por token. Com qualquer outro provedor você envia apiKey e os tokens são cobrados na sua conta desse provedor. Com zavu, model é escrito como provedor/modelo, por exemplo openai/gpt-4o-mini; o seletor de modelos do painel lista o catálogo em vigor.

Duas coisas da resposta importam. O agente é criado desativado, e o channels vem vazio: ainda não responde ninguém. Guarde o id.

JavaScript
const res = await fetch("https://api.zavu.dev/v2/agents", { method: "POST", headers: { Authorization: Bearer ${process.env.ZAVUDEV_API_KEY}, "Content-Type": "application/json", }, body: JSON.stringify({ name: "Assistente Loja Aurora", provider: "zavu", model: "openai/gpt-4o-mini", systemPrompt: SYSTEM_PROMPT, }), }); const { agent } = await res.json(); console.log(agent.id, agent.enabled); // "kh7...", false

O prompt de sistema é onde a maioria dos chatbots erra. "Responda só com a base de conhecimento" e "nunca invente prazo de entrega" são as duas linhas que impedem um bot de e-commerce de prometer o que o seu estoque não consegue cumprir.

3. Carregar as suas políticas numa base de conhecimento (v1)

Uma base de conhecimento é um conjunto de documentos que o agente consulta antes de responder. Crie uma no agente e adicione um documento por assunto:

terminal
curl -X POST https://api.zavu.dev/v1/agents/$AGENT_ID/knowledge-bases \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "Políticas da loja", "description": "Frete, trocas, pagamentos e perguntas frequentes"}'
terminal
curl -X POST https://api.zavu.dev/v1/agents/$AGENT_ID/knowledge-bases/$KB_ID/documents \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Política de frete", "content": "# Frete\n\nPedidos pagos até as 14h (horário de Brasília) são despachados no mesmo dia útil.\nFrete padrão para todo o Brasil: 3 a 8 dias úteis, grátis em compras acima de R$ 199.\nFrete expresso para capitais do Sudeste: 1 a 2 dias úteis, R$ 29,90.\nPedidos pagos por boleto são despachados após a compensação." }'

Repita para trocas e devoluções, formas de pagamento (Pix, cartão, boleto, o que você aceita) e perguntas frequentes. Um documento por assunto é recuperado melhor do que um documento longo com tudo. Cada documento é processado depois de criado; o isProcessed vira true quando ele já está dividido e pode ser buscado.

Se você vende na Nuvemshop ou na Shopify, esse texto você já tem: está nas páginas de política da sua loja. Cole como está e corrija o que estiver desatualizado. O agente vai repetir para os seus clientes exatamente o que estiver escrito.

4. Dar a ele uma tool get_order_status (v1)

A base de conhecimento responde "quantos dias leva o frete". Ela não responde "cadê o pedido 1042". Para isso o agente chama uma tool: um endpoint HTTPS seu que a Zavu chama com os argumentos que o modelo preenche.

terminal
curl -X POST https://api.zavu.dev/v1/agents/$AGENT_ID/tools \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "get_order_status", "description": "Consulta o status de um pedido. Use quando o cliente perguntar onde está o pedido ou quando chega. Precisa do número do pedido e do e-mail da compra.", "webhookUrl": "https://lojaaurora.com.br/zavu/tools/order-status", "parameters": { "type": "object", "properties": { "order_number": { "type": "string", "description": "Número do pedido, por exemplo 1042" }, "email": { "type": "string", "description": "E-mail usado na compra" } }, "required": ["order_number", "email"] } }'

O 201 traz tool.webhookSecret. Ele só é devolvido na criação, nunca numa leitura posterior. Guarde. Se perder, gere outro com POST /v1/agents/{agentId}/tools/{toolId}/webhook/secret.

O que o seu endpoint recebe

A Zavu envia um POST com este corpo JSON:

JSON
{ "tool": "get_order_status", "arguments": { "order_number": "1042", "email": "camila@example.com" }, "context": { "conversationId": "js72...", "channel": "telegram", "contactPhone": "...", "messageId": "jd7..." }, "timestamp": 1760889600000 }

e estes headers: X-Zavu-Tool (o nome da tool), X-Zavu-Timestamp, e X-Zavu-Signature, o HMAC-SHA256 em hexadecimal do corpo bruto com o segredo da tool. Sem prefixo e sem o timestamp misturado. contactPhone é o identificador de onde o cliente escreveu: o número no WhatsApp, o chat id no Telegram.

O endpoint

JavaScript
import express from "express"; import crypto from "node:crypto"; const app = express(); const SECRET = process.env.ZAVU_TOOL_SECRET; // Corpo bruto: a assinatura é sobre os bytes exatos que a Zavu enviou. app.post("/zavu/tools/order-status", express.raw({ type: "application/json" }), async (req, res) => { const expected = crypto.createHmac("sha256", SECRET).update(req.body).digest("hex"); const received = req.get("X-Zavu-Signature") ?? ""; const ok = received.length === expected.length && crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected)); if (!ok) return res.status(401).json({ error: "assinatura inválida" }); const { arguments: args } = JSON.parse(req.body.toString("utf8")); // A sua loja: a API da Nuvemshop, a da Shopify ou o seu próprio banco de dados. const order = await findOrder(args.order_number); // Não confirme um pedido para quem não consegue provar que ele é seu. if (!order || order.email.toLowerCase() !== String(args.email).toLowerCase()) { return res.json({ found: false }); } res.json({ found: true, status: order.status, // "pago" | "enviado" | "entregue" | ... carrier: order.carrier ?? null, // Correios, Jadlog, Loggi... trackingUrl: order.trackingUrl ?? null, estimatedDelivery: order.estimatedDelivery ?? null, }); }); app.listen(3000);

A mesma verificação em Python:

Python
import hmac, hashlib def valid(raw_body: bytes, signature: str, secret: str) -> bool: expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, signature or "")

O que você devolve é o que o agente lê, então devolva dados, não texto pronto: um status, uma transportadora, um link de rastreio, uma data quando houver. Uma resposta que não é 2xx chega ao agente como chamada com falha e ele responde contornando o erro, então um found: false com 200 gera uma resposta melhor do que um 404. Mantenha o endpoint rápido: o cliente está esperando a resposta enquanto ele roda.

Pedir o e-mail é uma escolha sua, não uma exigência da Zavu. No Telegram você não tem um número para comparar com o pedido, e um número de pedido sozinho é fácil de adivinhar. Como o endpoint lida com dados pessoais do cliente, trate o que ele devolve com o cuidado que a LGPD já exige da sua loja: só o necessário para responder.

5. Conectar o agente e ligar (v2)

terminal
curl -X POST https://api.zavu.dev/v2/agents/$AGENT_ID/channels \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{"address": "@loja_aurora_bot", "type": "telegram"}'

address e type são uma entrada de GET /v2/channels. Um endereço responde com um agente por vez: se outro agente já estiver nele, o 400 diz qual. Um endereço que o projeto não tem é 404 not_found. O SMS de mão única é recusado com 409 channel_cannot_receive, porque ninguém consegue responder a ele e o agente nunca responderia.

Depois ative:

terminal
curl -X PATCH https://api.zavu.dev/v2/agents/$AGENT_ID \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{"enabled": true}'

6. Testar sem mandar mensagem para ninguém (v2)

POST /v2/agents/{agentId}/test roda o prompt, o modelo e a base de conhecimento do agente contra uma mensagem e devolve a resposta em vez de enviá-la. Nenhuma mensagem sai e nenhuma execução é registrada.

terminal
curl -X POST https://api.zavu.dev/v2/agents/$AGENT_ID/test \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "message": "o e-mail é camila@example.com", "history": [ { "role": "user", "content": "oi, cadê meu pedido 1042?" }, { "role": "assistant", "content": "Vou verificar. Qual e-mail você usou na compra?" } ] }'

A resposta:

JSON
{ "success": true, "text": "...", "knowledgeChunksUsed": 0, "plannedToolCalls": [ { "name": "get_order_status", "arguments": "{\"order_number\":\"1042\",\"email\":\"camila@example.com\"}" } ], "executedToolCalls": [], "warnings": [ "The model was offered 1 tool (get_order_status) but none ran, since running them would reach your real handlers. ..." ], "inputTokens": 812, "outputTokens": 41, "latencyMs": 1430, "cost": 0.000146 }

Olhe três campos:

  • plannedToolCalls: a tool que o modelo escolheu e os argumentos que preencheu. Por padrão nada roda, então a resposta para nessa escolha.
  • knowledgeChunksUsed: pergunte "vocês despacham pedido pago no boleto na hora?" e deve vir acima de zero. Zero quer dizer que a resposta não veio dos seus documentos.
  • warnings (em inglês): o que um teste a seco não consegue provar. Um agente desativado, um agente sem canal conectado, tools oferecidas mas não executadas, fluxos que não foram avaliados, metadados de contato que não existem num teste.

Para rodar o loop completo, o modelo chamando o seu endpoint real e respondendo com o resultado, adicione "executeTools": true. O seu endpoint é chamado de verdade, e executedToolCalls lista o que rodou com ok e o error, se houver. Use um pedido de teste.

Um teste num agente zavu é cobrado como uma resposta real, pelo mesmo preço por token, e o cost da resposta diz quanto. Com saldo zerado ele é recusado com 402 insufficient_balance; num agente com a sua própria key quem cobra é o seu provedor.

Depois mande uma mensagem para o bot da sua própria conta do Telegram. Essa é a primeira conversa real.

7. Acompanhar as conversas e assumir

No painel, cada chat que o agente atende aparece em Conversas, junto com as mensagens de todos os outros canais. Você pode abrir uma conversa e responder.

Vale ser preciso sobre o que essa resposta faz. Responder em Conversas não pausa o agente. A próxima mensagem do cliente é respondida pelo agente de novo. O agente só fica quieto enquanto há uma transferência aberta, e uma transferência abre quando um fluxo chega a um passo transfer.

Então dê ao cliente um jeito de pedir uma pessoa. Fluxos são v1:

terminal
curl -X POST https://api.zavu.dev/v1/agents/$AGENT_ID/flows \ -H "Authorization: Bearer $ZAVUDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Falar com uma pessoa", "trigger": { "type": "keyword", "keywords": ["atendente", "humano", "falar com alguém"] }, "steps": [ { "id": "transferencia", "type": "transfer", "config": { "message": "Alguém da nossa equipe vai te responder por aqui em breve." } } ], "enabled": true, "priority": 10 }'

Um trigger keyword procura a palavra dentro da mensagem, sem diferenciar maiúsculas. Quando dispara, o cliente recebe a mensagem, a sessão fica transferred e o agente para de responder aquele contato. As próximas mensagens continuam chegando em Conversas. Assim que alguém da sua equipe responde, por Conversas ou pela API, a transferência termina e o agente retoma a conversa.

Ninguém é avisado por você: não há fila nem atribuição. Se a sua equipe não acompanha Conversas, coloque um passo tool antes do transfer que avise o seu Slack ou o seu sistema de atendimento. Para a diferença entre isso e um bot de menu, leia agente de IA vs chatbot.

O que pode dar errado

O que você vêPor quêO que fazer
400 invalid_bot_tokenO Telegram recusou o tokenCopie de novo no @BotFather
400 citando name, provider, model, systemPromptFaltam campos na criaçãoEnvie os quatro
400 "already answered by the agent ..."O endereço já tem outro agenteDesconecte lá ou use outro endereço
409 channel_cannot_receiveVocê conectou SMS de mão únicaUse um canal em que o cliente consiga responder
402 insufficient_balance no testeModelo da Zavu, saldo zeradoAdicione saldo ou use a sua própria key
O agente responde mas inventa prazosEle não está chamando a toolConfira plannedToolCalls; melhore a description da tool
knowledgeChunksUsed: 0Documentos não processados ou pouco relevantesConfira isProcessed; divida documentos longos por assunto

Os erros da v2 são planos, {code, message, details}. A referência de erros lista todos.

Indo para produção com o seu chatbot com IA para loja virtual

  • Vá para o canal que os seus clientes usam. Conecte WhatsApp ou Instagram em Canais e depois POST /v2/agents/{agentId}/channels com esse endereço. Mesmo agente, mesma base de conhecimento, mesma tool: o bot de teste no Telegram vira o chatbot de WhatsApp da sua loja sem reescrever nada.
  • Custos do WhatsApp. A Meta cobra as mensagens de serviço que passam das 1.000 gratuitas por número por mês, e deixa de entregá-las se a conta do WhatsApp Business não tiver forma de pagamento. Veja como funciona.
  • Custo do agente. Com zavu, cada resposta é cobrada do seu saldo por token. Você acompanha nas execuções e estatísticas do agente (v1: GET /v1/agents/{agentId}/executions e /stats, ou a página do agente no painel).
  • Limites. Os limites diários e mensais de envio dependem do seu plano e da sua verificação. A página de limites de envio tem os números.
  • Mantenha as políticas em dia. Se o prazo de troca mudar, atualize o documento (um PATCH no documento processa de novo). O bot repete o que a base de conhecimento diz, inclusive o que está desatualizado.

Se você quer começar um chatbot de WhatsApp do zero, como criar um chatbot de WhatsApp cobre esse caminho. Para ver onde isto se encaixa na nova API, leia o anúncio da Zavu 2.0 e a visão geral da v2.

Perguntas frequentes

Um chatbot com IA para loja virtual consegue dizer onde está o pedido?
Sim, se você der a ele uma tool que leia os seus pedidos. Na Zavu você cria uma tool get_order_status com uma URL de webhook; o agente chama o seu endpoint com o número do pedido, você verifica o header X-Zavu-Signature e devolve o status da Nuvemshop, da Shopify ou do seu banco. O modelo nunca adivinha o status.
Preciso de uma API key da OpenAI para montar o chatbot?
Não. Com o provedor zavu o agente usa um modelo gerenciado e cada resposta é cobrada do seu saldo na Zavu por token. Se preferir a sua própria conta, use openai, anthropic, google ou mistral como provider e envie apiKey; nesse caso os tokens são cobrados por esse provedor, e não pela Zavu.
Se eu responder em Conversas o agente para de responder?
Não. Uma pessoa respondendo em Conversas não pausa o agente: a próxima mensagem do cliente é respondida pelo agente de novo. O agente só fica quieto depois que um fluxo chega a um passo transfer, e retoma a conversa assim que alguém da sua equipe responde.
Como testo o chatbot sem mandar mensagem para clientes reais?
Chame POST /v2/agents/{agentId}/test com uma mensagem e, se quiser, um histórico. Ele roda o prompt, o modelo e a base de conhecimento e devolve a resposta, a tool escolhida e avisos, sem enviar nada. As tools só rodam com executeTools em true. Com o provedor zavu o teste é cobrado como uma resposta real.
Posso usar o mesmo chatbot no WhatsApp e no Telegram?
Sim. Um agente responde em cada endereço que você conecta com POST /v2/agents/{agentId}/channels. O Telegram se conecta com um token de bot pela API; WhatsApp e Instagram se conectam pela Meta em Canais no painel. A base de conhecimento e as tools não mudam, então o bot testado no Telegram vai para o WhatsApp igual.
A base de conhecimento e as tools fazem parte da API v2 da Zavu?
Ainda não. Agentes, canais e testes estão na v2, mas base de conhecimento, tools e fluxos continuam na v1 em /v1/agents/{agentId}/. As duas versões usam a mesma API key e compartilham os dados, então um agente criado na v2 é gerenciado na v1 com o mesmo id.

Precisa de ajuda? Contate-nos ou junte-se à nossa comunidade Discord para suporte.

Get started

Pronto para começar?

Comece a construir gratuitamente ou agende uma chamada para discutir seu caso de uso específico.

Chatbot com IA para loja virtual | Zavu Blog