A IA Não Pertence ao Core: Arquitetura Modular com Camada de IA na Threeger Platform
Quando comecei a desenhar a arquitetura da Threeger Platform, uma decisão me separava de um produto sustentável e de um conjunto de integrações frágeis disfarçadas de plataforma: onde exatamente a IA deveria entrar no sistema?

A resposta errada é simples e tentadora. Você adiciona um client do OpenAI dentro do ConversationService, chama o modelo quando uma mensagem chega, e em dois dias tem um protótipo funcionando que impressiona qualquer demo. O problema é que esse protótipo já nasce com dívida arquitetural. Não dívida técnica no sentido de código ruim. Dívida estrutural, no sentido de que a regra de negócio passou a depender de um detalhe de infraestrutura que vai mudar.
Provedores mudam. Modelos são descontinuados. Preços sobem. Rate limits aparecem. E quando o core do produto já está acoplado diretamente a esses detalhes, cada mudança exige cirurgia no coração da plataforma.
Esse artigo explica como desenhei a arquitetura da Threeger Platform para evitar exatamente isso.
O que o core precisa proteger
A Threeger Platform opera no espaço de CRM e automação de atendimento multicanal: WhatsApp, Instagram, Telegram, e-mail, widget web e API. O núcleo operacional do produto lida com conversas, contatos, inbox, times, pipelines, jornadas, automações, campanhas, relatórios, billing e auditoria.
Nenhum desses conceitos de negócio depende de qual modelo de linguagem está rodando em produção. Uma conversa não precisa saber se a resposta foi gerada pelo GPT-4o, pelo Claude Sonnet ou por um modelo fine-tunado interno. Um pipeline de automação não precisa conhecer o schema de resposta da API do Qdrant.
O core deve proteger essa separação.
Isso não é opinião de arquitetura. É uma consequência direta do princípio de inversão de dependência aplicado em nível de domínio. O domínio não depende de infraestrutura. A infraestrutura de IA é implementada para atender ao domínio, não o contrário.
Na prática, isso significa que o ConversationService nunca chama o OpenAI. Ele chama um LLMPort. Quem implementa esse port pode ser o OpenAI hoje, o Claude amanhã, ou um modelo local na semana que vem. A regra de negócio não precisa ser tocada nenhuma dessas vezes.
O mesmo vale para busca semântica. O core não conhece Qdrant nem Pinecone. Ele conhece VectorSearchPort. Embeddings? EmbeddingPort. Classificação de intenção? ClassificationPort. Moderação? ModerationPort. Resumo automático de conversa? SummarizationPort. Acesso ao gateway centralizado de IA? AIGatewayPort. Cada capacidade tem seu contrato. Nenhuma tem sua implementação vazando para dentro do domínio.
A Channel Adapter Layer como fronteira de normalização
Antes de qualquer evento de domínio existir, há um problema mais imediato: cada canal de entrada fala um idioma diferente.
Uma mensagem do WhatsApp chega via webhook com um payload específico da Meta. Uma mensagem do Instagram tem estrutura diferente, com campos próprios para stories, reações e DMs. O widget web envia eventos via WebSocket. A API pública recebe chamadas REST com contratos definidos pelo cliente. O e-mail tem headers, threading e multipart.
Colocar essa diversidade diretamente na Application Layer é um erro que acumula rápido. O código de entrada vira um labirinto de condicionais por canal, cada um com seu tratamento especial, suas exceções e sua lógica de normalização misturada com lógica de negócio.
A Channel Adapter Layer resolve isso antes que o problema chegue ao core. Cada canal tem seu adapter dedicado, responsável por uma única coisa: transformar a entrada específica do canal em um evento de domínio normalizado. O WhatsAppAdapter sabe o que é um wamid. O InstagramAdapter sabe o que é um mid. O EmailAdapter sabe parsear threading de MIME. O core não sabe nada disso e não precisa saber.
Quando um novo canal é adicionado à plataforma, o trabalho de integração fica contido no novo adapter. Nenhuma regra de negócio é alterada. Nenhum evento de domínio existente precisa mudar. O canal novo simplesmente aprende a falar a língua do core.
Acima da Channel Adapter Layer fica o BFF/API Gateway, responsável por autenticação, gestão de sessão, controle de permissões e rate limiting. Uma requisição que chega ao core já passou por normalização de canal e por controle de acesso. O domínio recebe contexto limpo, nunca payload bruto.
Por que eventos são a cola certa para esse tipo de sistema
A Threeger Platform lida com muitos fluxos simultâneos. Mensagem recebida pelo WhatsApp aciona uma sequência que pode envolver atualização de conversa, execução de automação, busca de contexto, geração de resposta, validação por guardrail, notificação para o atendente e registro de métricas. Isso sem contar campanhas ativas, webhooks externos e ações manuais do operador acontecendo ao mesmo tempo.
Um design linear e síncrono não escala nesse cenário. Mais do que isso, ele força um acoplamento artificial entre operações que são conceitualmente independentes.
A solução é modelar o sistema em torno de eventos de domínio. Quando uma mensagem chega, o core processa o que é sua responsabilidade e publica message.received. O que acontece depois é responsabilidade de quem assina esse evento. A camada de IA assina. O módulo de automações assina. O módulo de analytics assina. Cada um processa de forma independente, sem que o core precise orquestrar essa cadeia.
Eventos relevantes na plataforma incluem conversation.created, contact.updated, automation.triggered, campaign.started, ai.intent.detected e conversation.assigned. Cada um carrega contexto suficiente para que os consumers atuem sem precisar fazer queries adicionais ao core.
Essa separação tem um benefício concreto que vai além de escalabilidade: rastreabilidade. Cada evento é um registro auditável do que aconteceu no sistema. Quando algo dá errado em produção, não preciso reconstruir o estado a partir de logs de stack trace. O event log conta a história.
Como a camada de IA se encaixa fora do core
A camada de IA da plataforma não é um serviço monolítico. É um conjunto de capacidades que o core pode acessar via contracts bem definidos.
Dentro dessa camada existem componentes com responsabilidades distintas. O AIGatewayPort centraliza o roteamento para provedores externos e gerencia autenticação, retry e fallback entre modelos. Os agentes executam fluxos de raciocínio mais complexos quando necessário. O pipeline de RAG recupera contexto relevante da base de conhecimento do cliente antes que uma resposta seja gerada. A classificação de intenção categoriza mensagens recebidas para orientar o roteamento automático. O SummarizationPort gera resumos automáticos de conversas, útil tanto para handoff entre atendentes quanto para relatórios operacionais e contexto comprimido em conversas longas. O módulo de guardrails valida respostas antes que cheguem ao atendente ou ao cliente final. E a observabilidade de IA registra latência, custo por operação, qualidade de embedding e taxa de fallback.
O que une esses componentes é que nenhum deles conhece as regras de negócio da plataforma. Eles recebem contexto via evento ou chamada por port, executam sua função específica e retornam um resultado. A decisão sobre o que fazer com esse resultado é do core.
Isso importa mais do que parece. Quando o guardrail rejeita uma resposta gerada, quem decide se isso significa escalar para atendente humano, tentar novamente com prompt diferente ou registrar como falha é o core, aplicando a política configurada pelo cliente. A IA detecta. O domínio decide.
O fluxo completo em produção
Em ambiente de produção, uma mensagem recebida via qualquer canal percorre um caminho que deixa clara essa separação de responsabilidades.
O canal entrega a mensagem ao seu adapter dedicado na Channel Adapter Layer. O adapter normaliza o payload, converte o formato específico do canal em um evento de domínio padronizado e o encaminha pelo BFF, onde autenticação e rate limiting são aplicados. O evento message.received é publicado no barramento. O worker de conversas consome o evento, aplica as regras de negócio (existe conversa aberta para esse contato? o contato está em algum fluxo de automação? existe horário de atendimento configurado?), atualiza o estado e publica conversation.updated.
O worker de IA consome esse evento e inicia a pipeline de processamento inteligente. Primeiro, busca contexto no RAG usando o histórico da conversa e o perfil do contato como query. Se a conversa é longa, o SummarizationPort comprime o histórico antes que ele seja enviado ao modelo, reduzindo custo de tokens sem perder contexto relevante. Com contexto disponível, classifica a intenção da mensagem, aciona o agente responsável pela geração de resposta sugerida e passa pelo guardrail antes de retornar. Toda a operação é registrada com latência, modelo usado, custo estimado e resultado.
O atendente ou o fluxo de automação recebe a sugestão e decide o que fazer com ela. A IA não age. Ela apoia.
Esse modelo tem um custo de setup maior que um protótipo rápido. Mas em produção, com múltiplos clientes, fluxos simultâneos e necessidade de trocar provedores sem downtime, ele paga a conta com margem.
O que muda quando você precisa trocar de provedor
Esse é o teste real da arquitetura.
Suponha que o custo do OpenAI suba 40% e um modelo alternativo com desempenho equivalente fica disponível. Em um sistema acoplado diretamente, isso significa encontrar todas as chamadas ao SDK do OpenAI espalhadas pelo código, entender o contexto de cada uma, reescrever os clients, testar cada ponto de integração individualmente.
Na Threeger Platform, o processo é diferente. Crio um novo adapter que implementa LLMPort apontando para o novo provedor. Configuro o AI Gateway para rotear para o novo adapter. Rodo os testes de contrato do port. Se passarem, o deploy está pronto.
O ConversationService não foi tocado. O AutomationService não foi tocado. Nenhuma regra de negócio foi alterada. Porque nenhuma regra de negócio dependia do provedor.
O mesmo raciocínio vale para vector databases, modelos de embedding, serviços de moderação, ferramentas de classificação e modelos de sumarização. Cada um tem seu port. Cada port tem seus adapters. Os adapters são a única parte do sistema que conhece os detalhes externos. O AIGatewayPort em particular centraliza esse controle para os provedores de LLM, permitindo rotear diferentes tipos de tarefa para modelos diferentes sem que nenhuma camada acima do gateway precise ser alterada.
Observabilidade não é opcional em produção com IA
Um erro que vejo com frequência em produtos que incorporam IA é tratar a observabilidade como afterthought. Os logs de aplicação registram que a IA foi chamada. O resultado aparece na conversa. O que aconteceu no meio fica invisível.
Em produção real, invisibilidade tem custo. Quando a taxa de respostas inadequadas aumenta, preciso saber se o problema está no RAG recuperando contexto errado, no prompt gerando resposta fora do padrão, no guardrail com threshold mal calibrado ou no modelo apresentando degradação de qualidade.
A camada de IA da plataforma registra cada operação com contexto suficiente para esse tipo de diagnóstico. Latência por componente, documento recuperado pelo RAG e seu score de similaridade, versão do prompt usada, modelo e temperatura da chamada, resultado do guardrail com a razão de rejeição quando aplicável, e custo estimado da operação.
Esses dados alimentam dashboards operacionais que permitem identificar padrões de degradação antes que cheguem a reclamações de clientes. Não é monitoramento de aplicação convencional. É observabilidade de comportamento de sistema de IA em produção, que é uma disciplina diferente.
O princípio que orienta todas essas decisões
Provedores de IA, modelos, vector databases, frameworks de agentes e ferramentas de orquestração vão continuar evoluindo em ritmo acelerado. O que é estado da arte hoje tem probabilidade real de ser legado em dezoito meses.
A regra de negócio da Threeger Platform, o que define como uma conversa é gerenciada, como um contato é organizado, como uma automação é executada, como um time opera, essa parte precisa sobreviver a essas mudanças sem precisar ser reescrita toda vez.
A separação entre core e camada de IA não é uma preferência estética de arquitetura. É o que garante que o produto possa evoluir sua inteligência sem comprometer sua estabilidade operacional.
Construir com IA não é difícil. Construir um produto que usa IA e ainda assim é confiável, auditável, manutenível e capaz de evoluir, isso exige arquitetura.
Alexsander Valente é engenheiro e arquiteto de software com 15 anos de experiência em sistemas de produção. É fundador da Threeger e professor de desenvolvimento de agentes conversacionais no MBA do Ibmec.


