Capítulo 7 de 13
Sem isto, cada mensagem começa do zero e o cliente repete tudo. Com isto, a conta pode disparar. O meio-termo, com código.
Manual gratuito de Certu · Atualizado em 30 de agosto de 2026 · ver o manual inteiro
Resposta curta
Você guarda as últimas mensagens da conversa em um banco simples, com o telefone como chave, e manda esse histórico junto na próxima chamada ao modelo. Guardar as últimas dez trocas resolve quase todo atendimento sem encarecer a resposta.
Cada chamada ao modelo é independente. Ele não guarda nada entre uma mensagem e outra: quem guarda é você.
Sem memória, o cliente diz "quero marcar pra sexta" e a próxima resposta pergunta de novo o que ele quer. É o defeito que mais entrega que tem robô do outro lado.
Guarda as últimas dez trocas por telefone e apaga sozinho depois de 24 horas.
CONVERSAS é um espaço de chave e valor. No Cloudflare, você cria com npx wrangler kv namespace create CONVERSAS e cola a linha que ele imprime no wrangler.jsonc.
Qualquer banco serve. O que importa é a chave ser o telefone e o valor ser a lista das últimas mensagens.
const MAX_TROCAS = 10; // 10 do cliente + 10 do atendente
const VALIDADE = 60 * 60 * 24; // 24 horas, em segundos
async function lerHistorico(env, telefone) {
const bruto = await env.CONVERSAS.get('hist:' + telefone);
return bruto ? JSON.parse(bruto) : [];
}
async function salvarHistorico(env, telefone, historico) {
const cortado = historico.slice(-MAX_TROCAS * 2);
await env.CONVERSAS.put('hist:' + telefone, JSON.stringify(cortado), {
expirationTtl: VALIDADE,
});
}
// A chamada do capitulo 5, agora com historico
async function pensarResposta(env, cerebro, historico, mensagemDoCliente) {
const contents = [
...historico.map((m) => ({ role: m.papel, parts: [{ text: m.texto }] })),
{ role: 'user', parts: [{ text: mensagemDoCliente }] },
];
const resposta = await fetch(
'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent',
{
method: 'POST',
headers: {
'x-goog-api-key': env.GEMINI_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
system_instruction: { parts: [{ text: cerebro }] },
contents,
generationConfig: { temperature: 0.4, maxOutputTokens: 300 },
}),
},
);
if (!resposta.ok) return null;
const dados = await resposta.json();
return dados?.candidates?.[0]?.content?.parts?.[0]?.text?.trim() ?? null;
}
// No webhook, depois de responder:
// const historico = await lerHistorico(env, de);
// const resposta = await pensarResposta(env, CEREBRO, historico, texto);
// if (resposta) {
// await enviarWhatsApp(env, de, resposta);
// historico.push({ papel: 'user', texto });
// historico.push({ papel: 'model', texto: resposta });
// await salvarHistorico(env, de, historico);
// }Dez trocas é o ponto em que quase todo atendimento cabe e o custo ainda é de centavos. Acima disso você paga para o modelo reler o que não vai usar.
| Tamanho | Efeito na conversa | Efeito no custo |
|---|---|---|
| Nenhum | O cliente repete tudo a cada mensagem | O mais barato |
| 5 trocas | Resolve pergunta e resposta curtas | Quase o mesmo |
| 10 trocas | Aguenta um agendamento inteiro | Cerca de duas vezes a entrada |
| Conversa inteira | Lembra de tudo, inclusive do que não importa | Cresce sem parar e fica caro |
Arraste a tabela para o lado para ver todas as colunas.
O nível gratuito do armazenamento de chave e valor da Cloudflare permite 100 mil leituras por dia, mas só mil escritas por dia.
Como o código acima escreve uma vez por mensagem respondida, mil respostas por dia é o teto do plano gratuito. É bastante para começar e é a primeira coisa que estoura quando o volume sobe.
Onde as pessoas se queimam
Guardar conversa é guardar dado de cliente. Coloque prazo de validade desde o primeiro dia, como o expirationTtl acima, em vez de deixar tudo para sempre. O capítulo 11 explica a parte legal disso.
Um espaço simples de chave e valor resolve. Banco relacional só passa a valer quando você quiser relatório, busca por cliente ou histórico ligado a um cadastro.
O suficiente para o atendimento fazer sentido. Vinte e quatro horas cobre a maioria dos casos; se você quiser retomar depois, guarde um resumo curto em vez do histórico inteiro.
Dá, e é o caminho quando as conversas ficam longas: a cada dez trocas, peça ao modelo um resumo de três linhas e guarde só o resumo mais as últimas mensagens.
Um pode sobrescrever o outro, porque os dois leem e escrevem a mesma chave. Em volume baixo isso quase não aparece; em volume alto, use um banco com escrita atômica.
E onde entra Certu
Em Certu cada conversa vira contato, negócio e tarefa num lugar só, e o histórico é o que o dono lê quando assume a conversa no meio. É a mesma memória deste capítulo, com uma tela em cima e prazo de guarda decidido no lugar certo.
Ver o que Certu faz e quanto custa