AG
Projetos
Ativo2026 — em produção

Automação de Reservas Hoteleiras

Um recepcionista que trabalha 24h no WhatsApp, com o banco de dados como fiador de cada reserva.

Meu papel

Projeto e implementação, do schema do banco ao agente

01

O problema

Pousada pequena atende reserva no WhatsApp, na mão. As perguntas são sempre as mesmas — tem vaga nesse feriado, quanto fica, como eu pago — e chegam a qualquer hora, inclusive quando não tem ninguém pra responder. Uma resposta que demora duas horas é uma reserva que foi pro concorrente.

O outro problema é mais caro: sem um lugar único que mande na disponibilidade, dá pra vender o mesmo quarto duas vezes. Planilha e caderno não seguram isso, e sistema de gestão hoteleira pronto resolve o cadastro mas não resolve o atendimento — que é justamente onde a reserva se ganha ou se perde.

02

A solução

Montei um agente de IA no n8n que conversa pelo WhatsApp da pousada via Evolution API. Ele entende a intenção da mensagem e executa de verdade: cadastra o hóspede, consulta disponibilidade, cria a reserva, gera a cobrança e confirma o pagamento — tudo sem sair da conversa.

Cada capacidade do agente é um sub-workflow isolado que fala direto com o PostgreSQL por SQL parametrizado. O modelo não inventa dado nem escreve query: ele escolhe a ferramenta, o banco faz o resto. Isso mantém o comportamento previsível e auditável execução por execução.

Em paralelo roda um painel web (NestJS + React) que lê o mesmo banco, pra equipe humana ver o que o bot fez e assumir a conversa quando precisa. O banco é o contrato entre os dois — não existe estado escondido em nenhum dos lados.

03

Como funciona

  1. 01

    Mensagem chega

    A Evolution API recebe o WhatsApp do hóspede e dispara o evento MESSAGES_UPSERT no webhook do n8n.

  2. 02

    Rajada vira uma mensagem só

    Mensagem picada em quatro linhas seguidas não vira quatro respostas: um buffer com debounce acumula e só aciona o agente se ninguém escreveu por cima, com compare-and-swap por timestamp.

  3. 03

    O agente decide a intenção

    O AI Agent (gpt-4o-mini) lê a mensagem já com o número do remetente embutido e escolhe qual ferramenta chamar. A memória por número de WhatsApp mantém o contexto entre mensagens.

  4. 04

    A ferramenta executa no banco

    cadastrar_cliente, consultar_disponibilidade, criar_reserva, consultar_reservas, gerar_cobranca ou escalar_humano — cada uma é um sub-workflow com a query já parametrizada.

  5. 05

    Cobrança e confirmação

    gerar_cobranca cria o link no InfinitePay (Pix ou cartão) e o webhook de pagamento, exposto por túnel Cloudflare, confirma e atualiza a reserva sozinho.

  6. 06

    Equipe acompanha ao vivo

    O painel refaz a consulta em intervalo curto nas telas que refletem escrita do bot, então reserva criada no WhatsApp aparece pra recepção quase na hora.

04

Decisões técnicas

O banco barra o overbooking, não o código

Uma constraint EXCLUDE USING gist em reservas torna fisicamente impossível gravar duas reservas sobrepostas no mesmo quarto. Como o bot e a equipe escrevem ao mesmo tempo, checar disponibilidade na aplicação abriria uma corrida clássica: dois "tem vaga" simultâneos viram duas reservas. Deixando a garantia no banco, o agente recebe o erro e já oferece outro quarto na mesma conversa.

Webhook no lugar de polling

A confirmação de pagamento nasceu consultando o InfinitePay a cada 2 minutos. Depois que o túnel Cloudflare fixo deixou um endpoint público estável, virou webhook: confirmação na hora e zero requisição desperdiçada. O fluxo antigo ficou desativado no banco, documentado como fallback — não apagado.

Erro de Postgres vira português

Um filtro global no NestJS traduz o código do banco pra HTTP e mensagem legível — overbooking (23P01) e duplicidade (23505) viram 409, violação de check (23514) vira 400. A regra mora num lugar só, em vez de espalhada por cada controller.

A aplicação não é dona do schema

TypeORM roda com synchronize:false. O schema é compartilhado com o n8n, então nenhuma mudança pode vir do ORM: tudo passa por migration versionada, aditiva e idempotente. Isso evita que um deploy do painel derrube a automação.

Idempotência em duas camadas

O workflow deduplica por cliente + quarto + período antes de inserir e reaproveita reserva pendente existente. Por baixo, um índice único no banco é a rede de segurança contra corrida — porque o WhatsApp reentrega mensagem e a mesma intenção pode chegar duas vezes.

Escalar pra humano é estado no banco

Quando o assunto sai do script, o agente vira o status do cliente de Bot pra Humano e para de responder. A equipe assume pelo painel, no mesmo número — sem transferir o hóspede pra outro canal e sem perder o histórico.

Dashboard sai de SQL, não de ferramenta de BI

As métricas de operação vivem em views versionadas no próprio Postgres. Sem BI no stack: uma dependência a menos pra manter, e o mesmo número serve pro painel e pro psql.

05

O que o sistema faz

  • Cadastra o hóspede na primeira mensagem, sem formulário
  • Consulta disponibilidade por período e tipo de quarto
  • Cria a reserva e devolve o link de pagamento na conversa
  • Aceita Pix e cartão de crédito via InfinitePay
  • Confirma o pagamento por webhook e atualiza a reserva sozinho
  • Expira automaticamente reserva pendente que não foi paga
  • Passa o atendimento pra equipe quando o assunto sai do script
  • Painel com reservas, quartos, clientes, produtos e consumos extras
06

Stack

n8nOpenAI gpt-4o-miniEvolution APIPostgreSQL 15NestJS 11TypeORMReact 19ViteTailwind 4TanStack QueryDocker ComposenginxCloudflare TunnelInfinitePay API