Snapshot: gti-scheduling-mcp (Z-PRO + Klingo adapters) e workflow n8n de agendamento funcionando de ponta a ponta
- gti-scheduling-mcp: MCP server com ZProAdapter e KlingoAdapter (agendar() completo pros dois) - Workflow n8n 'Agendamento - GChat - Z-PRO': webhook -> AI Agent -> MCP -> Z-PRO, testado com sucesso real - Documentacao: specs, plano, runbook de problemas reais e export do workflow Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
# Design — Workflow n8n de Agendamento via GChat/Z-PRO + gti-scheduling-mcp
|
||||
|
||||
**Data:** 2026-08-10
|
||||
**Status:** Aprovado pelo usuário, aguardando plano de implementação.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Construir o primeiro workflow n8n que recebe mensagens de clientes via
|
||||
GChat (webhook do Z-PRO), conduz a conversa com um agente de IA para
|
||||
capturar os dados necessários e realiza o agendamento de fato, chamando a
|
||||
tool `agendar` do `gti-scheduling-mcp` (que por sua vez delega ao Adapter
|
||||
do sistema da clínica — Z-PRO neste MVP).
|
||||
|
||||
Escopo do MVP: **só agendamento** (`agendar`). Consulta de disponibilidade,
|
||||
cancelamento e remarcação ficam fora desta etapa.
|
||||
|
||||
## Contexto verificado (não inventado)
|
||||
|
||||
Estes fatos vêm de um workflow real já em produção no n8n de referência
|
||||
("Enforcer - GLPI"/fluxo de suporte via Z-PRO, código do node `1 - Decide`
|
||||
compartilhado pelo usuário) e de consultas diretas ao n8n
|
||||
(`devn8n.gtigrupo.com.br`) e ao registro de nodes via `n8n-mcp`:
|
||||
|
||||
- O Z-PRO chama o webhook do n8n **uma vez por mensagem do cliente** — não
|
||||
agrupa/enfileira mensagens.
|
||||
- O corpo da requisição (`req = $json.body`) tem os campos: `step`
|
||||
(esperado `"process"`), `entrada` (texto da mensagem do cliente),
|
||||
`number` (telefone), `contactName`, `protocol` (identificador único do
|
||||
**atendimento**, não do telefone — o mesmo cliente pode ter vários
|
||||
atendimentos/protocolos ao longo do tempo).
|
||||
- **Se o workflow segurar a resposta** (esperando mais mensagens antes de
|
||||
responder), o Z-PRO **descarta** as mensagens seguintes do cliente
|
||||
(confirmado em teste real: 5 mensagens em sequência → 1 execução no
|
||||
n8n). O workflow precisa responder a cada execução, sempre.
|
||||
- A resposta ao Z-PRO é **texto puro** (não JSON), via node `Respond to
|
||||
Webhook` em modo texto.
|
||||
- O node oficial `MCP Client Tool` (`@n8n/n8n-nodes-langchain`) só suporta
|
||||
transporte HTTP Streamable/SSE — **não** suporta rodar um comando local
|
||||
via stdio.
|
||||
- O node comunitário `n8n-nodes-mcp` (`mcpClient`/`mcpClientTool`) suporta
|
||||
conexão via linha de comando (stdio) — é o caminho escolhido para não
|
||||
precisar alterar o transporte do `gti-scheduling-mcp` (que hoje só
|
||||
implementa `StdioServerTransport`).
|
||||
- O `gti-scheduling-mcp` (`ZProAdapter`/`KlingoAdapter`) já está pronto e
|
||||
testado para `agendar()` — nenhuma mudança de arquitetura nele é
|
||||
necessária para este workflow.
|
||||
|
||||
## Arquitetura
|
||||
|
||||
```
|
||||
[Cliente WhatsApp]
|
||||
│
|
||||
▼
|
||||
[Z-PRO/GChat] ──webhook──▶ [n8n: Webhook] → [Normalizar entrada] → [AI Agent] → [Respond to Webhook]
|
||||
│ ▲
|
||||
(tool call) │ │ (memória de sessão)
|
||||
▼ │
|
||||
[MCP Client Tool] [Simple Memory]
|
||||
(stdio, agendar) (sessionId = protocol)
|
||||
│
|
||||
▼
|
||||
[gti-scheduling-mcp: tool "agendar"]
|
||||
│
|
||||
▼
|
||||
[AdapterFactory → ZProAdapter/KlingoAdapter]
|
||||
│
|
||||
▼
|
||||
[Sistema real da clínica: Z-PRO/Klingo]
|
||||
```
|
||||
|
||||
O `gti-scheduling-mcp` não sofre nenhuma alteração de arquitetura para
|
||||
este workflow — o n8n é só mais um cliente MCP, como qualquer outro.
|
||||
|
||||
## Componentes (nós do n8n)
|
||||
|
||||
1. **Webhook (Z-PRO)** — `POST`, recebe `{step, entrada, number,
|
||||
contactName, protocol}`.
|
||||
2. **Normalizar entrada** (`Set`/`Code`) —
|
||||
- Valida `step === "process"`; caso contrário, responde com um texto
|
||||
mínimo e encerra (mesma defesa do fluxo de referência).
|
||||
- Monta as variáveis usadas a seguir: `sessionId = protocol`,
|
||||
`mensagem = entrada`, `nomeContato = contactName`, `telefone =
|
||||
number`.
|
||||
- **Nó de configuração da clínica** (fixo por cópia do workflow, não
|
||||
dinâmico em runtime): `provider` (ex.: `"zpro"`), `clinicId`, e
|
||||
referência de qual Credential do n8n / config do MCP Client Tool
|
||||
usar para esta clínica. Cada clínica nova = uma cópia deste workflow
|
||||
com esses valores ajustados e seu próprio webhook cadastrado no
|
||||
Z-PRO — não há branching dinâmico de provider dentro de uma mesma
|
||||
execução.
|
||||
3. **AI Agent** (`@n8n/n8n-nodes-langchain.agent`) —
|
||||
- Chat Model: OpenAI (credencial a configurar no n8n).
|
||||
- System prompt cobre: confirmar o nome completo do paciente (mesmo já
|
||||
tendo `contactName`), perguntar data/horário desejado, motivo
|
||||
(opcional), nunca chamar `agendar` mais de uma vez por atendimento,
|
||||
responder sempre em português, tom cordial, nunca inventar dado que
|
||||
o cliente não informou.
|
||||
- **Memória**: `Simple Memory` (`memoryBufferWindow`), `sessionId =
|
||||
protocol`. Trade-off aceito para o MVP: essa memória vive na RAM do
|
||||
processo do n8n — um restart do n8n no meio de um atendimento perde
|
||||
o histórico da conversa. Evolução futura, se necessário: Postgres ou
|
||||
Redis Chat Memory (durável, mas exige infraestrutura adicional).
|
||||
- **Tool**: `MCP Client Tool` (via `n8n-nodes-mcp`, transporte stdio),
|
||||
expondo a tool `agendar` do `gti-scheduling-mcp` (comando: `node
|
||||
dist/index.js`, variáveis de ambiente = credenciais da clínica,
|
||||
vindas de uma Credential do n8n — nunca hardcoded no node/JSON do
|
||||
workflow).
|
||||
4. **Respond to Webhook** — modo texto simples; devolve só a resposta em
|
||||
linguagem natural produzida pelo AI Agent.
|
||||
|
||||
## Tratamento de erro
|
||||
|
||||
Quando `agendar` falha (`VALIDATION_ERROR`, `AUTHENTICATION_ERROR`,
|
||||
`NOT_FOUND`, `ZPRO_API_ERROR`/`KLINGO_API_ERROR`, timeout, etc.), o MCP já
|
||||
devolve uma resposta estruturada (`success:false` + código/mensagem) — o
|
||||
AI Agent recebe isso como resultado da tool e decide, em linguagem
|
||||
natural, como comunicar isso ao cliente (pedir os dados de novo, avisar
|
||||
que vai encaminhar para um atendente humano, etc.), dentro do que o
|
||||
system prompt permitir. Não há tratamento hard-coded por código de erro
|
||||
neste workflow — isso fica deliberadamente a cargo do agente, para manter
|
||||
o MVP simples.
|
||||
|
||||
## Risco de agendamento duplicado (mitigação no nível do workflow)
|
||||
|
||||
O `ZProAdapter`/`KlingoAdapter` já trata qualquer HTTP 2xx do provider
|
||||
como sucesso operacional (sem risco de duplicidade por reinterpretação de
|
||||
resposta ambígua — ver `docs/zpro-api-mapping.md`). O risco adicional
|
||||
neste workflow é de outra natureza: o **próprio agente** decidir chamar a
|
||||
tool `agendar` mais de uma vez na mesma conversa (ex.: o cliente confirma
|
||||
duas vezes, ou o agente se confunde). Mitigação adotada para o MVP:
|
||||
instrução explícita no system prompt para nunca chamar `agendar` mais de
|
||||
uma vez por atendimento (`protocol`). Isto é uma mitigação por prompt, não
|
||||
uma garantia determinística — se isso se mostrar insuficiente em uso real,
|
||||
a evolução natural é adicionar uma marcação de "já agendado" no estado da
|
||||
sessão, verificada por código antes de permitir uma nova chamada da tool.
|
||||
|
||||
## Fora de escopo (explicitamente adiado)
|
||||
|
||||
- Consulta de disponibilidade (`consultar_horarios`) — não implementada
|
||||
para nenhum provider neste MVP (Z-PRO não suporta; Klingo tem lacuna de
|
||||
mapeamento de resposta).
|
||||
- Cancelamento/remarcação de agendamento.
|
||||
- Transferência automática de fila/atendimento humano no Z-PRO após o
|
||||
agendamento (padrão existente no fluxo de referência via
|
||||
`updateticketinfo`) — pode ser adicionado depois, não é necessário para
|
||||
o MVP funcionar.
|
||||
- Suporte a múltiplas clínicas com providers diferentes atendidas por uma
|
||||
única execução/webhook compartilhado — cada clínica é uma cópia
|
||||
dedicada do workflow.
|
||||
- Memória de conversa durável entre restarts do n8n (Postgres/Redis Chat
|
||||
Memory).
|
||||
|
||||
## Testes
|
||||
|
||||
Este workflow vive no n8n, fora do repositório `gti-scheduling-mcp` — não
|
||||
há testes automatizados de código aqui. A validação é funcional/manual:
|
||||
|
||||
- Testar o fluxo completo com uma conversa real (ou simulada via chamada
|
||||
direta ao webhook) contra o Z-PRO, com dados fictícios, seguindo a mesma
|
||||
disciplina de segurança contra duplicidade já usada nos testes manuais
|
||||
do `ZProAdapter` (execução única, verificação visual no Z-PRO antes de
|
||||
qualquer nova tentativa).
|
||||
- Confirmar que o `Respond to Webhook` devolve texto puro, sem envelope
|
||||
JSON, compatível com o que o Z-PRO espera exibir ao cliente.
|
||||
Reference in New Issue
Block a user