lixum.labs / field notes / adele-crm
← voltar
Product 04 de novembro de 2025 8 min de leitura

Como construímos um CRM jurídico com WhatsApp como canal principal

Um escritório de advocacia com 15 advogados, cada um com o próprio celular, cada um atendendo clientes pelo WhatsApp pessoal. Contratos em pasta compartilhada no Drive. Status de processos em planilha que ninguém atualizava. Esse era o estado da Adele antes de começarmos.

[ o problema real ]

O cliente ligava para o escritório perguntando sobre o processo. Ninguém sabia responder sem ligar para o advogado responsável. O advogado responsável estava em audiência. O cliente ficava sem resposta por horas.

O problema não era tecnologia. Era que cada advogado operava como uma ilha. O CRM ia ter que mudar esse comportamento sem exigir que ninguém mudasse de ferramenta — porque ninguém ia mudar de ferramenta.

[ a decisão central ]

WhatsApp Cloud API não como integração — como canal principal. Isso muda tudo.

Integração significa que você tem um sistema e o WhatsApp é uma saída. Canal principal significa que o WhatsApp é onde o atendimento acontece de verdade, e o sistema é o que organiza o que está chegando lá.

Escolhemos FastAPI + SQLModel no backend porque precisávamos de validação de schema rigorosa nos dados de processo. Cada mensagem recebida passa por um parser que tenta classificá-la: é sobre qual processo? É de qual cliente? É uma dúvida ou uma atualização?

O frontend em React ficou para o escritório — painel de casos, histórico de conversa por cliente, atribuição de responsável. O advogado continua respondendo pelo WhatsApp. O sistema apenas organiza o que está acontecendo.

python
# Classifier simplificado — versão de produção tem 3x mais regras
async def classify_message(msg: IncomingMessage) -> Classification:
    client = await db.get_client_by_phone(msg.from_number)
    if not client:
        return Classification(type="unknown_sender")

    open_cases = await db.get_open_cases(client.id)
    if len(open_cases) == 1:
        return Classification(
            type="case_update",
            case_id=open_cases[0].id,
            confidence=0.91
        )

    # múltiplos casos abertos — precisa de contexto adicional
    return Classification(type="ambiguous", client_id=client.id)

Classificação de mensagem — determina qual processo a mensagem pertence

[ o que ninguém documenta ]

Webhook reliability. A documentação do WhatsApp Cloud API é clara sobre o formato. O que ela não conta é que o mesmo webhook pode chegar duas vezes. Ou não chegar.

Implementamos idempotency por message ID antes de qualquer outra coisa. Cada mensagem processada é registrada. Duplicata descartada silenciosamente. Sem isso, um cliente receberia duas respostas automáticas e um caso seria registrado em duplicidade.

O segundo problema: múltiplos advogados no mesmo caso. Se dois advogados respondem ao cliente com 30 segundos de diferença, qual resposta o cliente vê primeiro? Qual a ordem no histórico? Adicionamos timestamp de envio real (não de recebimento pelo nosso server) e ordenação explícita na query.

15Advogados ativos
< 2hTempo médio de resposta
0Treinamentos formais
2 semPara adoção completa

"A lição central: quando o canal de comunicação já é o WhatsApp, o sistema precisa ir até lá — não o contrário. Qualquer CRM que exige que o advogado mude de ferramenta vai falhar na adoção. O que funciona é o sistema que se adapta ao comportamento existente."

lixum.labs

Tem um problema parecido na sua operação?

falar com a equipe
plugins premium WordPress