EvoluAI Docs
Integrações & Coleta

Coleta — Google Meet

Como a EvoluAI coleta reuniões do Google Meet detalhe por detalhe — app OAuth único de plataforma, conexão por usuário, data de corte, polling, transcrição com locutor, contatos e atribuição.

Coleta — Google Meet

Esta página descreve, detalhe por detalhe, como a EvoluAI coleta reuniões do Google Meet: desde o app OAuth até a análise atribuída ao vendedor certo. Para a matriz de quem-pode-o-quê, veja Permissionamento.

Visão geral do modelo

No Google Meet há um único app OAuth de plataforma, cadastrado apenas pelo super_admin, compartilhado por todos os tenants e usuários. Cada usuário apenas autentica a própria conta contra esse app (no perfil) para liberar a transcrição. Admin da empresa e vendedor não cadastram OAuth.

O fluxo tem dois níveis, propositalmente separados:

  1. App OAuth (uma vez, pelo super_admin). Define o client_id/client_secret do Google e o Redirect URI. É o "aplicativo" que o Google reconhece.
  2. Conexão por usuário (self-service). Cada pessoa conecta a própria conta Google contra esse app — é isso que libera a leitura das transcrições das reuniões dela e faz a coleta atribuir as reuniões a ela.

O app OAuth de plataforma

  • Único e compartilhado. Existe um app OAuth para toda a plataforma. Ele mora num tenant de sistema fixo com o nome do produto ("EvoluAI") — uma empresa reservada usada só como espaço de configuração. O super_admin autentica o app global selecionando esse tenant na mesma tela de Integrações → Google Meet.
  • Quem cadastra: só o super_admin, pelo menu/UI (compliance). A variável de ambiente GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET fica como fallback opcional.
  • Precedência de resolução do app: app próprio do tenant → app global (tenant de produto) → env. Ou seja, se um tenant tiver um app próprio cadastrado, ele usa o dele; senão, herda o global.
  • Redirect URI: o Google exige registrar a URL de callback exata do EvoluAI no Google Cloud Console. Ela aparece no próprio diálogo de credenciais (botão Copiar) e muda por ambiente. Sem isso, a conexão falha com redirect_uri_mismatch.

A configuração de OAuth (global ou própria de um tenant) nunca aparece para admin_company, supervisor ou vendedor — é exclusiva do super_admin. Para os demais, a única superfície é o botão de autoconexão no próprio perfil. A tela global de configuração do Google Meet mostra apenas o Google (o Yeastar não é global — é por-PABX/empresa e só aparece ao selecionar uma empresa).

Pré-requisitos do app no Google Cloud (consentimento, publicação, verificação)

Antes de os usuários conseguirem conectar a própria conta, o app OAuth no Google Cloud Console precisa estar configurado corretamente. É o passo que costuma travar a primeira conexão (ex.: um usuário externo recebendo 403: access_denied).

  • Tela de consentimento = "Externo" (External). O tipo "Interno" só funciona para contas do mesmo Google Workspace da empresa dona do app. Como os usuários reais (clientes/parceiros, ex.: @omniassessoria.com.br) são de fora desse Workspace, o app precisa ser Externo — senão essas contas nem aparecem para autorizar.
  • App em "Testing" (teste): só os e-mails adicionados como Usuários de teste (máx. 100) conseguem autorizar; qualquer outro recebe 403: access_denied. Além disso, em Testing com escopo sensível o refresh token expira a cada 7 dias → a coleta em background para toda semana e o usuário precisa reconectar na mão (não há como renovar um refresh vencido — nenhum ajuste no EvoluAI resolve isso).
  • Para uso real, publique o app "Em produção" e envie-o para verificação. O escopo do Meet (meetings.space.readonly) é sensível, então a verificação exige marca/logo, política de privacidade, homepage e o domínio verificado. Em produção o refresh é perene e some o limite de 100 contas. (É possível publicar antes de a verificação concluir — funciona com o aviso "app não verificado", até 100 usuários.)

O EvoluAI renova sozinho o access token (~1 h) usando o refresh token; ele não conserta o 403 (test users) nem a expiração de 7 dias — isso é 100% configuração no Google Cloud Console.

Conexão por usuário (self-service)

Cada usuário conecta a própria conta em Configurações → "Conectar meu Google Meet":

  • Quem conecta: admin_company e vendedor SIM; supervisor NÃO. (O super_admin não tem reuniões próprias — não se aplica.)
  • O que acontece: ao autorizar, o token OAuth é gravado cifrado por usuário (user_integration_config). A partir daí as reuniões daquela conta passam a ser coletadas e atribuídas àquele usuário.
  • Auto-correção (sem depender do suporte): no mesmo card, quem já está conectado pode Desconectar e Conectar de novo a qualquer momento — por exemplo, para corrigir uma conta errada. Ambas as ações são escopadas à sessão do próprio usuário.
  • Apagar a conexão de outro usuário (ação de suporte) é exclusiva do super_admin.

Data de corte da coleta (collectSince)

Nada anterior à conexão é coletado. Ao conectar, a EvoluAI grava a data/hora como marco de corte; reuniões anteriores a esse marco não entram.

  • Guardado em integration_config.credentials.collectSince (ISO, cifrado).
  • Inicializado na conexão (collectSince = agora, se ainda não houver valor).
  • Editável depois: campo "Coletar a partir de" no card conectado.
  • Na coleta, o limite inferior usado é o maior entre lastPolledAt (última varredura) e collectSince.

Polling automático (a cada ~5 min)

  • A coleta é automática por polling: o sistema busca automaticamente, a cada ~5 minutos, reuniões/transcrições novas a partir do corte.
  • Para cada transcrição encontrada: baixa o texto, monta os participantes, cria a análise e a atribui (ver abaixo).

Espaços monitorados (opcional)

  • Além do polling automático das conexões, é possível registrar espaços monitorados (salas específicas do Meet) — recurso opcional/manual.
  • A lista mostra o link meet.google.com (resolvido via spaces.get) em vez do id spaces/..., com paginação, e um botão para carregar o endereço e as transcrições.

Transcrição com locutor por frase

No Google Meet, "quem falou" aparece frase a frase — a diarização é nativa da API do Meet (transcripts.entries traz o participante de cada trecho). A EvoluAI grava Locutor: frase por linha.

  • Coleta: o transcript é salvo no formato displayName: frase (nome de exibição do participante via participants.list; id curto quando não há nome).
  • Exibição correlacionada: na leitura da análise, se houver correlação identificador↔usuário, o rótulo do locutor é trocado pelo nome oficial do usuário do EvoluAI. A troca é só na visão do leitor — o texto original permanece intacto.
  • O nome do Google é sempre trazido e persistido, mesmo sem correspondência com um usuário cadastrado. A correlação apenas substitui o nome na exibição quando existe.

Contatos reutilizáveis

Para mapear uma vez e valer para todas as reuniões, os participantes vistos nas coletas viram contatos persistentes:

  • Tabela integration_contact por (company_id, provider, external_id) — o external_id é o People-id do Meet. Guarda display_name, o user_id mapeado, seen_count e first/last_seen_at.
  • A cada coleta, os contatos têm a recorrência incrementada e o nome atualizado, sem sobrescrever o mapeamento já feito.
  • Na tela de Integrações há a seção "Contatos do Google Meet": lista com "visto Nx"
    • um seletor de usuário por contato (mapear/desmapear).

Atribuição (de quem é a reunião)

Ao registrar a análise, a EvoluAI resolve o dono nesta ordem:

  1. Mapeamento de vendedor (salesperson_mapping / contato mapeado).
  2. Identidade externa do usuário — o e-mail do Google cadastrado no usuário (googleMeetEmail).
  3. Supervisor padrão do tenant (mais antigo) — quando nada casa, a análise é auto-correlacionada ao supervisor já no registro (status auto_supervisor). Sem supervisor no tenant → pending.

Limites da API do Meet

A API do Meet expõe displayName + People-id do participante, mas NÃO o e-mail. Por isso a correlação automática por e-mail não é garantida no Meet.

  • A correlação robusta por e-mail depende do mapeamento manual (campo "E-mail/login do Meet" no cadastro do usuário) ou do salesperson_mapping/contato mapeado.

On this page