Planejamento2026-08 – atualDesenvolvedor full-stack, único

Associado

A comissão de uma indicação depende de um aperto de mão fora do sistema, e um lado lucra negando que aconteceu.

  • fastapi
  • postgresql
  • pgvector
  • claude
  • sqlalchemy

O problema e as restrições

O Associado existe para formalizar algo que associações de classe já fazem informalmente e de forma inconsistente: um associado pergunta por aí por um encanador, um contador, um fotógrafo, alguém do grupo indica outro associado específico, os dois se conectam, um negócio acontece e, em tese, a associação era devedora de uma pequena comissão por ter feito a apresentação em primeiro lugar. Na prática, essa última parte quase nunca acontece, porque ninguém acompanha quem indicou quem, se deu em algo, ou quanto valeu.

A primeira restrição é que o único fato do qual o modelo de negócio inteiro depende (o negócio de fato fechou, e por quanto) acontece inteiramente fora do software, numa conversa e num aperto de mão entre duas pessoas. A plataforma pode perguntar sobre isso, mas não pode observar diretamente, e está perguntando a duas pessoas sem incentivo simétrico para responder com honestidade: quem teria que pagar uma comissão tem todo motivo para dizer menos que a verdade, enquanto quem não pagaria nada não tem motivo particular para corrigir.

A segunda restrição é a forma do próprio pedido. Associado não digita nome de categoria. Digita “quem conserta um vazamento”, e um sistema que só entende um termo exato de catálogo como “encanador” vai falhar em silêncio no momento em que o vocabulário de alguém não bater com o que foi digitado na lista de categorias. Mas um sistema que responde só por similaridade semântica vaga produz um resultado que ninguém consegue auditar, e a reclamação mais previsível que essa plataforma jamais vai receber é um prestador perguntando por que ele, especificamente, não foi o indicado. O que quer que resolva um pedido precisa ser flexível o bastante para entender linguagem real e preciso o bastante para se explicar numa frase.

A terceira restrição é lidar com dinheiro num sistema cujo mecanismo central é um agente de IA lendo mensagem de WhatsApp sem estrutura. Texto de um associado é exatamente o tipo de entrada que consegue manobrar um modelo de linguagem, de propósito ou não, e a única parte desse sistema que absolutamente não pode ser manobrada é o que é cobrado de quem. A arquitetura construída precisava tornar estruturalmente impossível qualquer coisa que o modelo toque decidir diretamente uma comissão, uma garantia que nenhuma política sozinha entregaria.

A quarta restrição foi evitar um erro específico já vivido de verdade. Uma plataforma irmã (um CRM de WhatsApp já em produção) resolve um problema de forma parecida com uma ferramenta visual de workflow orquestrando dezenas de passos de integração, e essa ferramenta tem um custo real e contínuo: credencial que não transfere entre ambientes, ordem de execução que depende de onde uma caixa está posicionada no canvas em vez de qualquer coisa versionada, e um arquivo de workflow salvo que diverge do que de fato roda. O volume esperado deste projeto é algumas centenas de solicitações por mês para uma associação, bem aquém da escala de SaaS multi-tenant que justificou a complexidade daquele outro sistema. Trazer a mesma arquitetura para cá significaria pagar custo operacional que o tamanho real deste projeto não pede.

A última restrição foi o tempo em si. Uma indicação que nunca expira vira uma comissão devida sobre uma relação comercial da qual a associação parou de fato de fazer parte no momento em que a apresentação virou um arranjo contínuo entre duas pessoas. Um encanador indicado uma vez que passa a fazer a manutenção mensal de um cliente por anos é um resultado real que essa plataforma precisa não interpretar como trinta e seis eventos separados merecedores de comissão.

Arquitetura

Um associado manda uma mensagem de WhatsApp descrevendo o que precisa. Um agente de IA (Claude, usando tool use em vez de geração livre) lê e tenta resolver para uma categoria no catálogo de serviços, primeiro por correspondência exata e trigram contra termos e sinônimos conhecidos, depois, só se isso não resolver com confiança, por busca semântica por vetor sobre os embeddings das categorias. Se nenhum dos dois caminhos resolve de forma limpa, o agente faz uma pergunta de esclarecimento em vez de chutar: uma solicitação não resolvida é registrada como lacuna no catálogo em vez de descartada em silêncio, o que eventualmente é o que diz à associação onde falta um sinônimo ou uma categoria inteira.

Depois que uma categoria resolve, o mesmo agente consulta prestadores que oferecem aquele serviço (filtrado, estruturalmente, só para quem ligou o consentimento de indicação) e devolve uma lista curta ao associado, avisando cada prestador indicado de que foi indicado. Tudo até aqui é trabalho do agente: entender linguagem, casar intenção com um item de catálogo, formatar uma resposta útil. Nada disso toca dinheiro.

Dinheiro vive inteiramente num caminho separado e determinístico ao qual o agente não tem acesso. Dias depois de uma indicação sair, um worker de agendamento (rodando como parte do mesmo processo, sobre uma tabela de banco comum em vez de uma fila de tarefas) manda um acompanhamento ao solicitante e ao prestador, de forma independente, perguntando se o negócio fechou e por quanto. Só quando as duas respostas descrevem o mesmo negócio, dentro de uma pequena tolerância para arredondamento, o backend gera uma comissão automaticamente. Divergência de valor, silêncio de um lado só, ou qualquer ambiguidade não é resolvida com mais automação: vira um item na fila do painel administrativo para uma pessoa olhar, na teoria de que uma cobrança gerada indevidamente custa mais confiança à associação do que uma perdida custa dinheiro.

Essa comissão, uma vez gerada, é limitada no tempo nas duas pontas. Uma solicitação que passa 30 dias sem um fechamento confirmado simplesmente expira. Não existe indicação aberta para sempre. E se o mesmo solicitante e prestador fecham outro negócio na mesma categoria dentro de 90 dias do último, o sistema ainda registra a nova indicação e ainda avisa todo mundo, mas grava o negócio resultante como isento em vez de gerador de comissão, visivelmente, como um registro de valor zero e explicitamente isento, em vez de uma entrada que simplesmente não existe. As duas janelas são valores de configuração em vez de constante fixada na lógica, e as duas são deliberadamente números de primeiro chute que o desenho espera revisar assim que existir dado real de conversão para revisar com ele.

Arquitetura

Associado: referral and commission flow A member asks for a service on WhatsApp. An AI agent resolves the request to a catalog category, first by taxonomy, then by semantic search only if taxonomy is not confident. The agent returns a list of matching providers and notifies them, but every write to the commission table happens only in deterministic backend code the AI cannot reach. Days later, both the requester and the provider are asked independently whether the deal closed; a commission is generated only when both answers agree. Member asks on WhatsApp AI agent (Claude) taxonomy, then semantic fallback Providers matched notified of the referral Backend (deterministic) asks both sides later, only writer of commissions the AI never writes to the commission table

Decisões

DECISION 01/04 · Casar um pedido em texto livre

EscolhidoResolver toda solicitação para uma categoria do catálogo primeiro por correspondência exata e aproximada contra termos conhecidos, e só cair para busca semântica por vetor quando isso não resolve com confiança, ambiguidade vira pergunta ao associado em vez de um chute

DescartadoBusca semântica pura sobre a descrição livre, ou deixar o próprio modelo escolher quais prestadores sugerir

A primeira reclamação previsível desse sistema é um prestador perguntando por que ele não foi indicado; casar por categoria primeiro mantém toda indicação explicável numa frase, e dá à regra de comissão uma chave estável para se ligar. Deixar o modelo escolher prestadores direto colocaria a lista inteira de associados no contexto dele e tornaria o resultado inauditável

Custo aceitoExistem dois caminhos de código para responder a mesma pergunta, com limiares de confiança que começam como um chute informado em vez de um resultado medido, e um provedor externo de embeddings entra na stack só para cobrir o vocabulário que a taxonomia sozinha não cobre

DECISION 02/04 · Confirmar um negócio fechado

EscolhidoPerguntar ao solicitante e ao prestador de forma independente se o negócio indicado fechou, e gerar comissão automaticamente só quando as duas respostas concordam: qualquer divergência, silêncio ou confirmação unilateral vira caso para um humano resolver em vez de decisão automática

DescartadoConfiar no relato do próprio prestador e a associação conferir depois por amostragem, ou só perguntar ao solicitante

O lado que paga a comissão é também o único lado com incentivo para subdeclarar o valor ou negar que o negócio aconteceu: um relato de um lado só transforma o cálculo de comissão em autodeclaração de quem menos tem motivo para ser preciso sobre isso

Custo aceitoDobra as mensagens enviadas por indicação, o que aumenta tanto o incômodo percebido quanto o risco de conta junto ao provedor de WhatsApp, e silêncio sem resposta, o resultado mais comum na prática, vira trabalho humano recorrente em vez de um fechamento automatizado

DECISION 03/04 · Por quanto tempo uma indicação vale

EscolhidoUm negócio fechado só gera comissão se confirmado em até 30 dias da indicação; o mesmo par fechando de novo na mesma categoria em até 90 dias fica isento de uma segunda comissão

DescartadoSem limite de tempo: qualquer negócio futuro entre duas pessoas apresentadas pela plataforma deveria comissão para sempre

Sem janela, uma indicação de janeiro deveria em tese comissão sobre um negócio fechado em novembro, e uma relação recorrente (um contador contratado todo mês) deveria comissão todo mês a partir de uma única apresentação original, as duas são relações comerciais que a associação parou de fato de intermediar

Custo aceitoA associação perde comissão de negócios que fecham devagar de verdade (obra grande, ciclo longo de orçamento), e a regra de antiduplicidade pode ser explorada simplesmente esperando 90 dias entre contratações, os dois aceitos porque a alternativa, cobrar para sempre, causa muito mais atrito com os associados do que a receita que protegeria

DECISION 04/04 · Um serviço só

EscolhidoUm único serviço em FastAPI faz tudo (webhook, agente de IA, matching, conciliação, comissão, painel administrativo e o worker de agendamento) sem n8n, sem Redis e sem frontend construído separado

DescartadoO mesmo padrão de uma plataforma irmã já em produção: FastAPI mais n8n para orquestração, Redis para estado, um frontend construído à parte

Essa plataforma irmã funciona, mas o custo operacional dela se concentra em lugares específicos e recorrentes: um workflow visual de 99 nós cujas credenciais não transferem entre ambientes e cuja ordem de execução real depende da posição do nó no canvas em vez de qualquer coisa versionada. No volume esperado deste projeto (centenas de solicitações por mês, lógica majoritariamente determinística), esse custo não tem benefício correspondente

Custo aceitoNão existe editor visual para ajustar o fluxo sem deploy: qualquer mudança de comportamento é commit e rebuild. O worker de agendamento roda no mesmo processo da API, então um pico de tráfego HTTP pode atrasar uma mensagem de acompanhamento; separar isso é a primeira mudança a fazer se o volume crescer o suficiente para importar

Invariantes

  • Um associado sem consentimento de indicação ativo nunca aparece num resultado de busca, em nenhuma circunstância

    Garantido pora consulta que resolve uma categoria para prestadores candidatos filtra por consentimento_indicacao = true antes de qualquer outra coisa rodar

  • O agente de IA nunca escreve na tabela de comissões nem muda o status de um negócio

    Garantido pornenhuma tool exposta ao modelo tem acesso de escrita a essas tabelas; toda escrita em dinheiro ou status de negócio acontece exclusivamente em código determinístico de backend que o modelo não alcança

  • Um valor monetário nunca é representado como float

    Garantido portodo valor é um BIGINT em centavos, só em BRL, uma restrição no nível do schema em vez de uma convenção de código que alguém precisa lembrar

  • A mesma mensagem de WhatsApp recebida nunca é processada duas vezes, mesmo se o provedor entregar mais de uma vez

    Garantido portoda mensagem recebida é gravada com o ID de mensagem do próprio provedor sob índice UNIQUE; conflito na inserção é tratado como duplicata e descartado

  • O identificador estável de uma categoria nunca muda depois de criado

    Garantido porcategorias_servico.slug é imutável por convenção e pelo fato do histórico de comissão e dos relatórios usarem ele como chave; só o rótulo de exibição é editável

Risco identificado

Risco identificado · mitigado no desenho

Este projeto ainda não tem incidente real porque nunca rodou em produção. Este é um risco que o desenho já contempla.

Sintoma
Se a comissão fosse gerada pela palavra de um lado só, o lado que paga tem incentivo direto para subdeclarar o valor do negócio ou negar que ele fechou, transformando o cálculo de comissão em autodeclaração de quem menos tem motivo para ser honesto sobre isso
Causa raiz
O fato de um negócio ter acontecido vive inteiramente fora do sistema, numa conversa de WhatsApp e num aperto de mão entre duas pessoas; o único sinal da plataforma é o que qualquer um dos lados escolher digitar de volta, dias depois, quando perguntado
Correção
Perguntar aos dois lados de forma independente, e gerar comissão automaticamente só quando a resposta do solicitante e do prestador concordam sobre o mesmo negócio, com tolerância de 20% no valor, para arredondamento comum não virar trabalho manual. Qualquer coisa fora isso, inclusive silêncio de um dos lados, vira caso pendente na fila para um humano resolver
Prevenção
O desenho assume rodar conservador por padrão: uma comissão perdida custa menos à associação do que uma cobrança indevida custaria, e toda divergência é tratada como um dado para revisar em vez de um limiar para ajustar em silêncio até as reclamações pararem

Resultados

8specs funcionais escritas antes de qualquer códigocontagem de arquivos em docs/specs/, 2026-08-29
11decisões de arquitetura registradascontagem de arquivos em docs/decisions/, 2026-08-29
30 diasjanela para uma indicação ainda gerar comissãoADR-007
90 diasjanela de antiduplicidade para o mesmo par e categoriaADR-007
20%divergência de valor tolerada antes de precisar de humanoADR-006

Stack completa

Backend

  • FastAPI (Python 3.12)
  • SQLAlchemy 2 + Alembic
  • Jinja2 + HTMX (painel admin)

Dados

  • PostgreSQL 16 + pgvector

Infra

  • Evolution API (WhatsApp self-hosted)
  • EasyPanel

IA

  • Claude (Anthropic, tool use)
  • provedor externo de embeddings

Tem interesse em um projeto como esse? Entre em contato.

Entrar em contato