EVOPE AI Agent

Documentação completa de integração do Agente de Insights EVOPE.
Integre análise de dados com IA diretamente no front-end da plataforma.

Endpoint de Produção:
https://webhook.digital-ai.tech/webhook/evope/chat

O que é

O agente recebe os dados já renderizados em tela (JSON do nightly job: Mapa de Processos, Burnout, Grupos), processa com IA, armazena a sessão e retorna um diagnóstico inicial provocativo. A partir daí, o usuário pode fazer perguntas livres sobre os dados analisados.

Casos de uso

PáginaTipo de análiseDados enviados
Mapa de ProcessosEficiência operacional, automaçãoNodes (apps + horas) + Edges (caminhos)
Relatório de BurnoutRisco de burnout por colaboradorEmployeeList + BurnoutEmployeeList
GruposAproveitamento e entretenimento por grupoGruposDetalhes + Colaboradores

Quick Start #

Integração básica em 4 passos:

PASSO 01
Gerar IDSessao
UUID único por sessão de usuário. Recomendado: UsuarioID-EmpresaID-GrupoID
PASSO 02
Montar o payload
Incluir dados já em memória (JSON da tela atual) + metadados do usuário/grupo
PASSO 03
POST para o webhook
Content-Type: application/json. Aguardar resposta (20–40s na 1ª mensagem)
PASSO 04
Exibir diagnóstico + abrir chat
Resposta vem em output. Usar mesmo IDSessao para follow-ups
javascript — exemplo mínimo
// 1. Gerar sessão única por usuário/tela
const sessionId = `${usuarioId}-${empresaId}-${grupoId}`;

// 2. Montar payload com dados da tela
const payload = {
  UsuarioNome: currentUser.nome,
  UsuarioEmail: currentUser.email,
  UsuarioID: currentUser.id,
  EmpresaID: currentCompany.id,
  GrupoID: currentGroup.id,
  Grupo: currentGroup.nome,
  DataInicio: "01/05/2026",
  DataFim: "31/05/2026",
  IDSessao: sessionId,
  PaginaOrigem: "Mapa",
  data: {
    Nodes: mapaFuncoesJson,   // array já em memória
    Edges: mapaCaminhosJson    // array já em memória
  }
};

// 3. Chamar o webhook
const res = await fetch("https://webhook.digital-ai.tech/webhook/evope/chat", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(payload)
});

const { output } = await res.json();
// 4. "output" = diagnóstico inicial da IA
showChatMessage(output);

Arquitetura #

Front-end EVOPE
POST /webhook/evope/chat
n8n (orquestrador)
GPT-4.1-mini (análise)
GPT-4o-nano (chat)
Resposta JSON
PostgreSQL (memória)

Na 1ª mensagem (envio de dados), o n8n processa, analisa com IA e armazena a sessão. Nas mensagens seguintes (texto livre), recupera o histórico automaticamente via PostgreSQL.

Tempo de resposta estimado

Tipo de requisiçãoTempo típico
1ª mensagem — análise de dados (Mapa/Burnout)20 – 45 segundos
Follow-up — pergunta de texto5 – 15 segundos

Endpoint #

POST https://webhook.digital-ai.tech/webhook/evope/chat

Headers obrigatórios

HeaderValor
Content-Typeapplication/jsonobrigatório

O endpoint não requer autenticação por header — a sessão é controlada pelo IDSessao no body. Em produção, o acesso é restrito por IP/origin do servidor EVOPE.

Sessão — IDSessao #

O IDSessao é o identificador da conversa. Deve ser único por usuário + relatório. Toda mensagem (análise inicial + follow-ups) deve usar o mesmo IDSessao para manter o contexto.

Formato recomendado

javascript
// Padrão recomendado: UsuarioID-EmpresaID-GrupoID
const sessionId = `${usuarioId}-${empresaId}-${grupoId}`;
// Exemplo: "711-80-22889"

// Alternativa: UUID aleatório por sessão de navegação
const sessionId = crypto.randomUUID(); // "sess_3ae8d061-7f0d-..."

Importante: Use o mesmo IDSessao em TODAS as mensagens da conversa. Se mudar o IDSessao, o agente perde o contexto e responde como se fosse uma nova sessão.

Ciclo de vida da sessão

EventoAção no IDSessao
Usuário abre o chat pela 1ª vezGerar novo IDSessao
Usuário envia dados + perguntasManter o mesmo IDSessao
Usuário clica em "Nova análise" / "Recomeçar"Gerar novo IDSessao
Usuário muda de relatório (Mapa → Burnout)Gerar novo IDSessao ou manter (contexto diferente)

Requisição de Análise (1ª mensagem) #

Enviada quando o usuário abre o chat e envia os dados da tela atual. O agente analisa os dados, gera o diagnóstico inicial e armazena a sessão.

Campos do payload (raiz)

CampoTipoDescrição
PaginaOrigemstring"Mapa", "Burnout" ou "Grupos"obrigatório
IDSessaostringIdentificador único da sessãoobrigatório
EmpresaIDnumberID da empresa no sistema EVOPEobrigatório
GrupoIDstringID do grupo/filtro selecionadoobrigatório
GrupostringNome do grupo (ex: "Master > TI")obrigatório
DataIniciostringPeríodo início no formato "DD/MM/YYYY"obrigatório
DataFimstringPeríodo fim no formato "DD/MM/YYYY"obrigatório
UsuarioIDnumberID do usuário autenticadoopcional
UsuarioNomestringNome do usuárioopcional
UsuarioEmailstringE-mail do usuárioopcional
dataobjectDados da análise (ver seções abaixo)obrigatório

Requisição de Chat (follow-up) #

Enviada nas mensagens seguintes, quando o usuário faz perguntas livres. O agente recupera o histórico da sessão automaticamente.

Campos

CampoTipoDescrição
chatInputstringTexto da mensagem do usuárioobrigatório
IDSessaostringMesmo IDSessao da análise inicialobrigatório
javascript — follow-up
fetch("https://webhook.digital-ai.tech/webhook/evope/chat", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    chatInput: "Qual é o app com maior risco de automação?",
    IDSessao: sessionId  // mesmo IDSessao da análise inicial
  })
});

Resposta #

Formato

json
{
  "output": "## DIAGNÓSTICO\n**Teams concentra 54% das 47.343h mapeadas**..."
}

Campos da resposta

CampoTipoDescrição
outputstringTexto da resposta da IA em Markdown. Renderizar com marked.js ou similar.

Status HTTP

200Resposta gerada com sucesso
400Payload inválido ou dados ausentes
500Erro interno no servidor
504Timeout — análise levou mais de 90s

O campo output contém Markdown com **negrito**, *itálico*, ## cabeçalhos e listas. Renderize com uma biblioteca Markdown ou aplique CSS básico para exibição correta.

Payload — Mapa de Processos #

Usado na página Mapa de Processos. Os dados já estão em memória no front (carregados na renderização da tela).

Estrutura do campo data

SubcampoTipoDescrição
data.NodesarrayLista de aplicativos/funções mapeados (Funcoes.json)
data.EdgesarrayLista de caminhos entre apps (Caminhos.json)

Campos de cada item em Nodes

CampoTipoDescrição
AplicativostringCategoria do app ("Web", "Teams", "Excel")
FuncionalidadestringSub-app ou página específica ("Gmail", "meet.google.com")
HorasstringHoras no período em formato "HH:MM" (ex: "477:53")
TecladonumberTotal de teclas digitadas
MousenumberTotal de cliques de mouse
InteracoesnumberTotal de interações
ColaboradoresstringNº de colaboradores que usam este app (string)
CopiarnumberTotal de operações Ctrl+C
ColarnumberTotal de operações Ctrl+V
ProcessonumberIndicador de processo (0 ou 1)

Campos de cada item em Edges (opcional)

CampoTipoDescrição
OrigemstringApp de origem do caminho
DestinostringApp de destino do caminho
QuantidadenumberNúmero de vezes que o caminho foi percorrido

Payload completo — Mapa

json
{
  "PaginaOrigem": "Mapa",
  "UsuarioNome": "João Silva",
  "UsuarioEmail": "joao@empresa.com.br",
  "UsuarioID": 711,
  "EmpresaID": 80,
  "GrupoID": "22889",
  "Grupo": "Master > CSC > HTR Latam",
  "DataInicio": "01/05/2026",
  "DataFim": "31/05/2026",
  "IDSessao": "711-80-22889",
  "data": {
    "Nodes": [
      {
        "Aplicativo": "Web",
        "Funcionalidade": "meet.google.com",
        "Horas": "477:53",
        "Teclado": 88505,
        "Mouse": 64657,
        "Interacoes": 26899,
        "Colaboradores": "43",
        "Copiar": 766,
        "Colar": 1143,
        "Processo": 0
      }
      // ... demais apps
    ],
    "Edges": [
      {
        "Origem": "[Teams]-Chat",
        "Destino": "[Web]-portal.evope.com.br",
        "Quantidade": 320
      }
    ]
  }
}

Payload — Burnout #

Campos de cada item em EmployeeList

CampoTipoDescrição
ColaboradorstringNome do colaborador
GrupostringGrupo ao qual pertence
Aproveitamentonumber% de aproveitamento (pode ser > 100)
Entretenimentonumber% de uso de apps de entretenimento
TotalHorasnumberTotal de horas ativas no período
HorasPrevistasnumberHoras previstas/esperadas no período
DiasPropensaoBurnoutnumberDias com risco de burnout calculado
json — payload Burnout
{
  "PaginaOrigem": "Burnout",
  "EmpresaID": 80,
  "GrupoID": "22889",
  "Grupo": "Master > CSC > Finanças",
  "DataInicio": "01/05/2026",
  "DataFim": "31/05/2026",
  "IDSessao": "711-80-22889-burnout",
  "data": {
    "EmployeeList": [
      {
        "Colaborador": "Roberta Reis",
        "Grupo": "Administrativo / Financeiro",
        "Aproveitamento": 111.0,
        "Entretenimento": 1.0,
        "TotalHoras": 179.0,
        "HorasPrevistas": 160.0,
        "DiasPropensaoBurnout": 2
      }
      // ... demais colaboradores
    ],
    "BurnoutEmployeeList": [
      // subset de EmployeeList onde Aproveitamento >= 100 e Entretenimento < 7
    ]
  }
}

Payload — Grupos #

json — payload Grupos
{
  "PaginaOrigem": "Grupos",
  "EmpresaID": 80,
  "GrupoID": "22889",
  "Grupo": "Master",
  "DataInicio": "01/05/2026",
  "DataFim": "31/05/2026",
  "IDSessao": "711-80-22889-grupos",
  "data": {
    "GruposDetalhes": [
      // Array de grupos com métricas agregadas
    ],
    "ColaboradoresBurnout": [
      // Colaboradores com Aproveitamento alto + Entretenimento baixo
    ],
    "ColaboradoresEntretenimento": [
      // Colaboradores com Entretenimento > 15%
    ]
  }
}

Integração — Botão / Widget #

O padrão mais comum: um botão "Pergunte ao Agente" na tela de relatório que abre o chat flutuante.

javascript — integração completa
class EvopeAIChat {
  constructor(config) {
    this.endpoint = "https://webhook.digital-ai.tech/webhook/evope/chat";
    this.sessionId = config.sessionId || `${config.usuarioId}-${config.empresaId}-${config.grupoId}`;
    this.analysisData = config.analysisData;
    this.onMessage = config.onMessage || console.log;
    this.onTyping = config.onTyping || (() => {});
    this.initialized = false;
  }

  // Chamado quando usuário abre o chat pela 1ª vez
  async initialize() {
    if (this.initialized) return;
    this.onTyping(true);
    const res = await this._post(this.analysisData);
    this.onTyping(false);
    this.initialized = true;
    this.onMessage({ role: "assistant", text: res.output });
  }

  // Chamado a cada mensagem do usuário
  async send(userMessage) {
    this.onTyping(true);
    const res = await this._post({
      chatInput: userMessage,
      IDSessao: this.sessionId
    });
    this.onTyping(false);
    this.onMessage({ role: "assistant", text: res.output });
  }

  async _post(payload) {
    const r = await fetch(this.endpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload)
    });
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    return r.json();
  }
}

// ── USO ──────────────────────────────────────────────────
const chat = new EvopeAIChat({
  usuarioId: currentUser.id,
  empresaId: currentCompany.id,
  grupoId: selectedGroup.id,
  analysisData: {
    PaginaOrigem: "Mapa",
    UsuarioID: currentUser.id,
    EmpresaID: currentCompany.id,
    GrupoID: selectedGroup.id,
    Grupo: selectedGroup.nome,
    DataInicio: periodoInicio,   // "01/05/2026"
    DataFim: periodoFim,         // "31/05/2026"
    IDSessao: `${currentUser.id}-${currentCompany.id}-${selectedGroup.id}`,
    data: {
      Nodes: mapaFuncoesData,    // já em memória
      Edges: mapaCaminhosData    // já em memória
    }
  },
  onMessage: (msg) => appendChatBubble(msg),
  onTyping: (show) => showTypingIndicator(show)
});

// Botão "Pergunte ao Agente"
document.getElementById("btn-ai-agent").addEventListener("click", () => {
  openChatPanel();
  chat.initialize();  // só analisa na 1ª vez
});

Integração — Embed (iframe) #

Use a interface pronta via iframe. Comunicação bidirecional via postMessage.

html — embed básico
<!-- Embed do chat EVOPE AI -->
<iframe
  id="evope-chat"
  src="https://reports.digital-ai.tech/evope/chat.html"
  width="420"
  height="680"
  style="border:none;border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,.4)"
></iframe>
javascript — postMessage API
const chatFrame = document.getElementById("evope-chat");

// Enviar análise para o iframe (dispara automaticamente)
chatFrame.contentWindow.postMessage({
  type: "evope:startAnalysis",
  payload: {
    sessionId: "711-80-22889",
    analysisData: { /* payload completo */ }
  }
}, "https://reports.digital-ai.tech");

// Resetar sessão no iframe
chatFrame.contentWindow.postMessage(
  { type: "evope:resetSession" },
  "https://reports.digital-ai.tech"
);

// Ouvir quando o iframe está pronto
window.addEventListener("message", (event) => {
  if (event.data.type === "evope:chatReady") {
    console.log("Chat EVOPE pronto!");
  }
});

Integração — API Direta #

Para quem quer construir o próprio componente de chat usando apenas a API.

javascript — implementação completa com estado
// Estado global da sessão
const session = {
  id: null,
  initialized: false
};

async function startAISession(pageData) {
  // Gerar sessão única
  session.id = `${pageData.usuarioId}-${pageData.empresaId}-${pageData.grupoId}`;

  showTypingDots();

  try {
    const response = await fetch(
      "https://webhook.digital-ai.tech/webhook/evope/chat",
      {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(buildPayload(pageData)),
        signal: AbortSignal.timeout(90000)  // 90s timeout
      }
    );

    if (!response.ok) throw new Error(`Erro ${response.status}`);
    const { output } = await response.json();

    hideTypingDots();
    session.initialized = true;
    renderAssistantMessage(output);

  } catch (err) {
    hideTypingDots();
    showError(err.message);
  }
}

async function sendChatMessage(userText) {
  if (!session.id) return;

  renderUserMessage(userText);
  showTypingDots();

  try {
    const response = await fetch(
      "https://webhook.digital-ai.tech/webhook/evope/chat",
      {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          chatInput: userText,
          IDSessao: session.id
        }),
        signal: AbortSignal.timeout(60000)
      }
    );

    const { output } = await response.json();
    hideTypingDots();
    renderAssistantMessage(output);

  } catch (err) {
    hideTypingDots();
    renderAssistantMessage("⚠️ Falha na comunicação. Tente novamente.");
  }
}

function buildPayload(pageData) {
  return {
    PaginaOrigem: pageData.pagina,      // "Mapa", "Burnout" ou "Grupos"
    UsuarioID:   pageData.usuarioId,
    EmpresaID:   pageData.empresaId,
    GrupoID:     pageData.grupoId,
    Grupo:       pageData.grupoNome,
    DataInicio:  pageData.dataInicio,   // "01/05/2026"
    DataFim:     pageData.dataFim,
    IDSessao:    session.id,
    data:        pageData.data          // { Nodes, Edges } ou { EmployeeList }
  };
}

function resetSession() {
  session.id = null;
  session.initialized = false;
  clearChatMessages();
}

Tratamento de Erros #

CenárioCausaAção recomendada
HTTP 500Erro interno no n8nExibir mensagem de erro, botão "Tentar novamente"
Timeout (>90s)IA demorou mais que o esperadoUsar AbortSignal.timeout(90000), retentar uma vez
output vazioResposta sem conteúdoTratar como erro, exibir fallback
Sem memória do contextoIDSessao diferente no follow-upGarantir que o IDSessao é idêntico em todas as requisições
Análise sem dadosArray Nodes ou EmployeeList vazioValidar no front antes de chamar a API
javascript — tratamento robusto de erros
async function callAgent(payload) {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), 90000);

  try {
    const res = await fetch(ENDPOINT, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
      signal: controller.signal
    });
    clearTimeout(timeout);

    if (!res.ok) {
      throw new Error(`Servidor retornou ${res.status}`);
    }

    let data;
    try {
      data = await res.json();
    } catch {
      throw new Error("Resposta inválida do servidor");
    }

    if (!data?.output) {
      throw new Error("Resposta vazia");
    }

    return data.output;

  } catch (err) {
    clearTimeout(timeout);
    if (err.name === "AbortError") {
      return "⏱ Tempo limite excedido. Tente novamente.";
    }
    return `⚠️ ${err.message}. Tente novamente.`;
  }
}

Exemplos Completos #

cURL — análise inicial

bash
curl -s -X POST \
  https://webhook.digital-ai.tech/webhook/evope/chat \
  -H "Content-Type: application/json" \
  -d '{
    "PaginaOrigem": "Burnout",
    "EmpresaID": 80,
    "GrupoID": "22889",
    "Grupo": "Master > CSC > Finanças",
    "DataInicio": "01/05/2026",
    "DataFim": "31/05/2026",
    "IDSessao": "711-80-22889-burnout",
    "data": {
      "EmployeeList": [
        {
          "Colaborador": "Roberta Reis",
          "Grupo": "Financeiro",
          "Aproveitamento": 111.0,
          "Entretenimento": 1.0,
          "TotalHoras": 179.0,
          "HorasPrevistas": 160.0,
          "DiasPropensaoBurnout": 2
        }
      ],
      "BurnoutEmployeeList": []
    }
  }' | jq '.output'

cURL — follow-up

bash
curl -s -X POST \
  https://webhook.digital-ai.tech/webhook/evope/chat \
  -H "Content-Type: application/json" \
  -d '{
    "chatInput": "Quais são os 3 maiores riscos identificados?",
    "IDSessao": "711-80-22889-burnout"
  }' | jq '.output'

Python — exemplo completo

python
import requests

ENDPOINT = "https://webhook.digital-ai.tech/webhook/evope/chat"
SESSION_ID = "711-80-22889"

# 1. Análise inicial
response = requests.post(ENDPOINT, json={
    "PaginaOrigem": "Mapa",
    "EmpresaID": 80,
    "GrupoID": "22889",
    "Grupo": "Master > TI",
    "DataInicio": "01/05/2026",
    "DataFim": "31/05/2026",
    "IDSessao": SESSION_ID,
    "data": {
        "Nodes": nodes_data,   # lista de apps
        "Edges": edges_data    # lista de caminhos
    }
}, timeout=90)

print(response.json()["output"])

# 2. Follow-up
followup = requests.post(ENDPOINT, json={
    "chatInput": "Qual app tem mais horas?",
    "IDSessao": SESSION_ID
}, timeout=60)

print(followup.json()["output"])

Pronto para integrar!
Interface de demo disponível em reports.digital-ai.tech/evope/chat.html