GustavoandClaude Sonnet 5 ea105d525c fix(v2): three real bugs found by an actual end-to-end run against production GLPI data
Ran the deployed workflow for real (temporary webhook trigger, briefly
activated, immediately deactivated and removed after each attempt) against
the real GLPI MySQL database and a real OpenAI credential. Found and fixed:

1. $env access is blocked on this n8n instance (N8N_BLOCK_ENV_ACCESS_IN_NODE).
   parseConfig($env) threw "access to env vars denied" on the very first
   Code node. Config now comes from the "Config - Coordenador GLPI v2" Set
   node instead (same pattern the V1 workflow already used) -- expanded
   that node with all 13 tunable parameters, and pointed the 3 affected
   node drivers (build-sql-candidatos, decide-needs-ai, select-top10) at
   it instead of $env.

2. Data Table "upsert" operation requires both `columns` (values) and a
   separate `filters` (match condition) -- I had only set columns with
   matchingColumns, which isn't enough; n8n refused to activate the
   workflow ("Missing or invalid required parameters: filters"). Added
   filters.conditions matching on ticket_id to both memory-writing Data
   Table nodes.

3. Real architecture bug: "Data Table - Buscar Memoria" sat inline in the
   41-candidate chain (Mesclar Contexto -> Buscar Memoria -> Decidir
   Necessidade de IA). A bulk "get all rows" Data Table node run with 41
   input items produced 41 identical fetches and its OWN output (the empty
   memory table on a first run) replaced the 41 candidates entirely --
   "Decidir Necessidade de IA" received 0 items and the whole main branch
   silently skipped. Moved the memory fetch to a parallel branch off
   Config (fires once) and added a real Merge node ("Merge - Aguardar
   Memoria") to guarantee both the candidates and the memory rows have
   executed before "Decidir Necessidade de IA" runs -- same synchronization
   pattern already used for context and for the shadow comparison.

Also fixed a cosmetic bug found in the real message output: buildTopMessage
produced a quadruple newline between the header and the first ticket block
([header, '', ...blocks].join('\n\n') double-counts the blank line already
inserted by the '\n\n' join). Added a regression test.

Verified with a real execution (id 13599, 24/08/2026 19:25 UTC) against the
live GLPI database: 41 real candidates, 30 sent to OpenAI (capped), 11
fallback-capped, memory table populated with 41 real rows including
genuine WAITING_VENDOR/WAITING_REQUESTER classifications with real
blocker_type/waiting_for fields extracted from real ticket task content,
and a real shadow_runs row comparing Legacy x V2 (4 tickets removed by V2:
2 for INSUFFICIENT_CONTEXT, 1 WAITING_REQUESTER, 1 WAITING_VENDOR; 4 added).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 16:30:13 -03:00

Coordenador GLPI - Chamados Abertos

Projeto n8n para atuar como coordenador diario de Suporte de TI, analisando chamados abertos no GLPI e enviando no Slack os 10 chamados que precisam de acao imediata.

Objetivo

Todos os dias uteis, o workflow consulta o banco do GLPI, calcula um score operacional para cada chamado aberto e envia uma lista priorizada no Slack.

O foco nao e apenas listar chamados antigos. O ranking considera:

  • SLA vencido ou proximo de vencer
  • tempo sem interacao humana
  • prioridade, urgencia e impacto
  • idade do chamado
  • chamado sem tecnico atribuido
  • chamados em categorias e entidades reais do GLPI

Arquivos

  • Coordenador GLPI - Chamados Abertos Slack.n8n.json: workflow importavel no n8n
  • sql/top_10_chamados_abertos_glpi.sql: query base usada pelo workflow
  • .env.example: variaveis para subir n8n localmente
  • docker-compose.yml: n8n local via Docker

Como configurar

  1. Suba o n8n local, se necessario:
docker compose up -d
  1. Acesse:
http://localhost:5678
  1. Importe o workflow:
Coordenador GLPI - Chamados Abertos Slack.n8n.json
  1. Configure a credencial MySQL no node:
MySQL - Top 10 chamados abertos
  1. Abra o node Config - Coordenador GLPI e preencha:
  • slack_webhook_url: webhook do canal Slack
  • dias_sem_interacao_alerta: padrao 2
  • horas_sla_risco: padrao 8
  1. Execute pelo Manual Trigger para validar.

  2. Ative o workflow para rodar pelo Schedule Trigger - Dias uteis 08h.

Metodologia de priorizacao

Cada chamado aberto recebe um score_criticidade, mas a lista final nao e mais apenas o top 10 geral. O workflow monta a lista por blocos para evitar que chamados muito antigos monopolizem todos os dias.

Blocos do top 10:

  • 3 chamados com SLA vencido mais criticos
  • 3 chamados com maior tempo sem interacao
  • 2 chamados sem tecnico atribuido
  • 2 chamados de prioridade alta mais recentes

Se algum bloco nao tiver chamados suficientes, o complemento vem do ranking geral.

O mesmo chamado nao entra duas vezes. Se ele ja apareceu em um bloco anterior, e removido dos blocos seguintes.

Score

Pesos principais:

  • SLA vencido: +100
  • SLA vencendo nas proximas horas configuradas: +45
  • chamado sem interacao ha 7 dias ou mais: +35
  • chamado sem interacao ha 3 a 6 dias: +25
  • chamado sem interacao ha 1 a 2 dias: +10
  • prioridade GLPI: priority * 8
  • urgencia GLPI: urgency * 5
  • impacto GLPI: impact * 5
  • idade do chamado: ate +30
  • sem tecnico atribuido: +25

O resultado e ordenado por:

  1. score_criticidade desc
  2. chamados com SLA vencido primeiro
  3. maior tempo sem interacao
  4. chamados mais antigos

Reincidencia

O workflow controla reincidencia usando staticData global do n8n, sem gravar nada no banco do GLPI.

Regra:

  • apareceu 1 vez: normal
  • apareceu 2 dias seguidos: marcado como reincidente
  • apareceu 3 dias seguidos ou mais: escalar para coordenacao

Campos salvos no staticData:

  • ultima_data_disparo
  • ultimos_chamados_enviados
  • reincidencia_chamados

Se o workflow for duplicado, recriado ou importado como novo workflow, esse historico pode ser perdido porque pertence ao workflow no n8n.

Tempo sem interacao

O campo dias_sem_interacao considera a maior data encontrada entre:

  • followups publicos do chamado: date, date_mod, date_creation
  • tarefas do chamado: date, date_mod, date_creation
  • modificacao do chamado: glpi_tickets.date_mod
  • abertura do chamado: glpi_tickets.date

Isso evita marcar um chamado como parado quando alguem acabou de adicionar ou alterar uma tarefa no GLPI, mesmo que a tarefa esteja planejada para outro dia.

Se a maior data encontrada estiver no futuro por causa de uma tarefa planejada, o contador fica em 0 dias sem interacao, evitando valores negativos no relatorio.

Regra de chamados abertos

O SQL considera abertos todos os chamados com:

is_deleted = false
AND status NOT IN (5, 6)

Este gatilho principal ignora chamados das categorias:

  • ADMINISTRATIVO
  • DESENVOLVIMENTO
  • INFRA

O filtro usa o nome completo da categoria (completename) ou o nome simples (name) iniciando com esses termos, entao tambem remove subcategorias dessas filas.

No GLPI, normalmente:

  • 5: solucionado
  • 6: fechado

Campos usados

A query usa tabelas comuns do GLPI:

  • glpi_tickets
  • glpi_itilcategories
  • glpi_entities
  • glpi_itilfollowups
  • glpi_tickettasks
  • glpi_tickets_users
  • glpi_users

Se sua versao do GLPI tiver customizacoes, valide primeiro a query sql/top_10_chamados_abertos_glpi.sql diretamente no banco.

Saida no Slack

O Slack recebe uma mensagem curta com:

  • top 10 chamados para atacar hoje
  • tecnico atribuido, quando existir
  • SLA
  • dias sem interacao
  • dias aberto
  • reincidencia
  • link do chamado, se glpi_base_url estiver configurado no workflow

Campos removidos da mensagem para reduzir ruido:

  • motivo
  • acao
  • prazo

Se o agente de IA falhar, o workflow envia a mensagem curta gerada por codigo, sem depender da IA.

Agente de IA do n8n com Z IA

O workflow usa o node:

AI Agent - Revisar mensagem

Por padrao, ele esta conectado ao node:

Z IA Chat Model

Esse node usa o chat model compativel com OpenAI do n8n, mas a credencial deve ser configurada para a Z IA.

A IA nao monta mais a mensagem do zero. O node Code - Reincidencia e mensagem curta monta a mensagem final de forma deterministica, e a IA apenas revisa clareza e reduz texto.

Regras do prompt:

  • nao adicionar fatos
  • nao criar motivo
  • nao criar acao
  • nao criar prazo
  • nao alterar IDs, tecnicos, datas, SLA, dias, reincidencia ou links
  • nao usar tom agressivo

No n8n, abra o node:

Z IA Chat Model

Configure:

  • credencial Z IA
  • endpoint/base URL da Z IA, se a credencial permitir
  • modelo correto disponibilizado pela Z IA, por exemplo glm-4.5-flash

No arquivo importavel deixei o modelo como glm-4.5-flash. Se sua conta Z IA usar outro nome de modelo, troque pelo nome exato exibido na plataforma.

Se aparecer The resource you are requesting could not be found, revise principalmente:

  • Base URL da credencial: normalmente https://api.z.ai/api/paas/v4
  • Modelo: precisa existir na sua conta, por exemplo glm-4.5-flash
  • Chave API: precisa ser da Z IA, nao da OpenAI
  • Node usado: mantenha Z IA Chat Model conectado ao AI Agent - Revisar mensagem

Se a Z IA aparecer no seu n8n como node proprio, mantenha o AI Agent - Revisar mensagem e substitua somente o subnode Z IA Chat Model pelo modelo oficial da Z IA.

Recomendacao direta

Nao trate isso como relatorio bonito. Trate como fila diaria de comando.

Minha sugestao operacional:

  • rodar as 08h no canal da lideranca de suporte
  • exigir responsavel e prazo para cada um dos 10 chamados ate 10h
  • repetir apenas os chamados que continuarem parados no dia seguinte
  • se um chamado aparecer 3 dias seguidos, escalar para coordenacao/gestao
  • separar um segundo workflow para chamados sem tecnico atribuido, porque isso e falha de triagem, nao backlog comum
  • criar outro alerta intradiario para SLA vencendo nas proximas 2 horas

Se quiser resultado real, nao basta notificar. Tem que transformar a mensagem do Slack em ritual diario de cobranca.

S
Description
No description provided
Readme
353 KiB
Languages
JavaScript 99.3%
Python 0.7%