Files
INDENTIFICAR-TEXTO-EM-IMAGEM/n8n/orcamento-exames-imagem.workflow.json
T
EricandClaude Sonnet 5 095a80edc5 feat(n8n): consulta ticket via API do Z-PRO para tentar obter midia (fase diagnostica)
O ChatFlow do Z-PRO nao expoe nenhuma variavel de imagem/anexo no seletor
(confirmado pelo usuario) -- so metadados de contato/sessao. Adiciona
chamada a showticketchatbot logo apos extrair os campos do webhook, guardando
a resposta crua em 'ticketApiRaw' para inspecionar o formato real antes de
extrair a URL da midia definitivamente.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-21 09:55:01 -03:00

469 lines
14 KiB
JSON

{
"id": "6FU0jjPwEKDBrFSW",
"name": "Orçamento de Exames - GChat - Z-PRO (IA Visão)",
"active": true,
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "orcamento-exames-zpro",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-orcamento",
"name": "Webhook - Foto Exame",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-608,
0
],
"webhookId": "5ea5f89e-7351-4d45-a881-0055009423a0",
"onError": "continueRegularOutput"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "campo-sessionid",
"name": "sessionId",
"type": "string",
"value": "={{ $json.body.protocol }}"
},
{
"id": "campo-telefone",
"name": "telefone",
"type": "string",
"value": "={{ $json.body.number }}"
},
{
"id": "campo-nomecontato",
"name": "nomeContato",
"type": "string",
"value": "={{ $json.body.contactName }}"
},
{
"id": "campo-entrada",
"name": "entrada",
"type": "string",
"value": "={{ String($json.body.entrada || $json.body.text || '').trim() }}"
},
{
"id": "campo-imagemurl",
"name": "imagemUrl",
"type": "string",
"value": "={{ $json.body.mediaUrl || $json.body.fileUrl || $json.body.file || '' }}"
},
{
"id": "campo-tipomidia",
"name": "tipoMidia",
"type": "string",
"value": "={{ $json.body.mediaType || $json.body.type || '' }}"
}
]
},
"options": {}
},
"id": "extrair-campos",
"name": "Extrair campos do webhook",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-368,
0
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"combinator": "and",
"conditions": [
{
"id": "cond-tem-imagem",
"leftValue": "={{ $json.imagemUrl }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
}
}
]
},
"options": {}
},
"id": "if-e-imagem",
"name": "É mensagem de imagem?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
-128,
0
]
},
{
"parameters": {
"url": "={{ $json.imagemUrl }}",
"options": {
"response": {
"response": {
"responseFormat": "file"
}
},
"timeout": 20000
}
},
"id": "baixar-imagem",
"name": "Baixar imagem",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
64,
-288
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"model": {
"__rl": true,
"mode": "id",
"value": "gpt-5.6-luna"
},
"builtInTools": {},
"options": {}
},
"id": "openai-chat-model-orcamento",
"name": "OpenAI Chat Model - Orçamento",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.3,
"position": [
96,
128
],
"credentials": {
"openAiApi": {
"id": "h16jFm10cTU15k6M",
"name": "OpenAI - Orçamento de Exames"
}
}
},
{
"parameters": {
"promptType": "define",
"text": "={{ $('Extrair campos do webhook').item.json.entrada || 'O cliente enviou uma imagem (sem texto). Veja a imagem anexada, que é o pedido médico dele.' }}",
"options": {
"systemMessage": "Você é o assistente de orçamentos de exames de uma clínica, atendendo automaticamente pelo WhatsApp, numa conversa com várias mensagens (não só uma).\n\nTABELA DE EXAMES E VALORES (lista de exemplo — será substituída pela lista real depois):\n- Hemograma completo — R$ 35,00\n- Glicemia de jejum — R$ 20,00\n- Colesterol total e frações — R$ 45,00\n- Triglicérideos — R$ 25,00\n- TSH (hormônio tireoidiano) — R$ 40,00\n- Exame de urina (EAS) — R$ 30,00\n- Ultrassonografia abdominal — R$ 150,00\n- Raio-X de tórax — R$ 90,00\n- Eletrocardiograma (ECG) — R$ 80,00\n- Papanicolau — R$ 60,00\n\nCOMO CONVERSAR:\n1. O cliente pode mandar uma foto do pedido médico (com ou sem legenda), digitar os nomes dos exames, ou fazer as duas coisas em mensagens separadas, em qualquer ordem — use também o histórico da conversa (mensagens anteriores) pra juntar as informações, não só a mensagem atual. Uma imagem anexada a esta mensagem (quando houver) é o pedido médico do cliente.\n2. Se o cliente ainda não mandou, nem agora nem antes nesta conversa, nenhuma foto de pedido nem nomes de exames, NÃO invente orçamento — cumprimente rapidamente e peça pra ele mandar a foto do pedido médico ou digitar os nomes dos exames.\n3. Assim que tiver pelo menos um exame identificável (considerando a imagem atual, o texto atual E o histórico da conversa), identifique cada exame pedido.\n4. Para cada exame identificado que corresponde (mesmo com sinônimo, abreviação comum ou pequena diferença de grafia) a um item da tabela acima, inclua na resposta o nome do exame e o valor.\n5. Para exames identificados que NÃO correspondem a nenhum item da tabela, ou que você não conseguiu ler/entender com confiança, liste-os separadamente avisando que um atendente vai confirmar o valor.\n6. Nunca deixe de orçar por causa de um item não reconhecido — sempre orçe o que for possível reconhecer.\n7. Calcule e mostre o valor total somando apenas os itens com preço confirmado na tabela.\n8. Responda sempre em português, tom cordial e objetivo, formatado para WhatsApp: texto simples, sem markdown (nada de ** ou #), pode usar emojis com moderação e quebras de linha para organizar.\n9. Sua resposta deve conter SOMENTE o texto a ser enviado ao cliente nesta mensagem — nada de comentários extras, explicações do seu raciocínio, ou texto fora da conversa com o cliente.",
"passthroughBinaryImages": true
}
},
"id": "ai-agent-orcamento",
"name": "AI Agent - Orçamento",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 3.1,
"position": [
160,
-96
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "resp-output",
"name": "output",
"type": "string",
"value": "={{ $json.output ? $json.output : 'Recebemos sua solicitação de exames! Nossa equipe vai confirmar os valores e te retornar em breve.' }}"
}
]
},
"options": {}
},
"id": "montar-corpo-resposta",
"name": "Montar corpo da resposta",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
640,
-128
]
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "={{ 'orcamento-' + ($('Extrair campos do webhook').item.json.sessionId || $('Extrair campos do webhook').item.json.telefone) }}",
"contextWindowLength": 20
},
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"typeVersion": 1.4,
"position": [
240,
112
],
"id": "aa58f6fd-5d98-43ed-b645-eeb7e3494564",
"name": "Simple Memory"
},
{
"parameters": {
"respondWith": "text",
"responseBody": "={{ $json.output }}",
"options": {}
},
"id": "responder-webhook",
"name": "Responder Webhook (texto)",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
912,
-128
]
},
{
"id": "buscar-ticket-zpro",
"name": "Buscar ticket (Z-PRO)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
-240,
160
],
"parameters": {
"method": "POST",
"url": "https://apigchat.gtigrupo.com.br/v2/api/external/ab2d51db-54e3-48c2-8b97-114a20340809/showticketchatbot",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"contentType": "json",
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ number: $json.telefone }) }}",
"options": {
"timeout": 15000
}
},
"credentials": {
"httpHeaderAuth": {
"id": "8XHGuA4cg9z1jUq8",
"name": "ZPRO API Token - Canal QR - MC AGENDAMENTO"
}
},
"onError": "continueErrorOutput"
},
{
"id": "mesclar-dados-ticket",
"name": "Mesclar dados do ticket",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-100,
160
],
"parameters": {
"assignments": {
"assignments": [
{
"id": "merge-sessionid",
"name": "sessionId",
"type": "string",
"value": "={{ $('Extrair campos do webhook').item.json.sessionId }}"
},
{
"id": "merge-telefone",
"name": "telefone",
"type": "string",
"value": "={{ $('Extrair campos do webhook').item.json.telefone }}"
},
{
"id": "merge-nomecontato",
"name": "nomeContato",
"type": "string",
"value": "={{ $('Extrair campos do webhook').item.json.nomeContato }}"
},
{
"id": "merge-entrada",
"name": "entrada",
"type": "string",
"value": "={{ $('Extrair campos do webhook').item.json.entrada }}"
},
{
"id": "merge-imagemurl",
"name": "imagemUrl",
"type": "string",
"value": "={{ $('Extrair campos do webhook').item.json.imagemUrl }}"
},
{
"id": "merge-tipomidia",
"name": "tipoMidia",
"type": "string",
"value": "={{ $('Extrair campos do webhook').item.json.tipoMidia }}"
},
{
"id": "merge-ticketapiraw",
"name": "ticketApiRaw",
"type": "string",
"value": "={{ JSON.stringify($json) }}"
}
]
},
"options": {}
}
}
],
"connections": {
"Webhook - Foto Exame": {
"main": [
[
{
"node": "Extrair campos do webhook",
"type": "main",
"index": 0
}
]
]
},
"É mensagem de imagem?": {
"main": [
[
{
"node": "Baixar imagem",
"type": "main",
"index": 0
}
],
[
{
"node": "AI Agent - Orçamento",
"type": "main",
"index": 0
}
]
]
},
"Baixar imagem": {
"main": [
[
{
"node": "AI Agent - Orçamento",
"type": "main",
"index": 0
}
],
[
{
"node": "Montar corpo da resposta",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model - Orçamento": {
"ai_languageModel": [
[
{
"node": "AI Agent - Orçamento",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"AI Agent - Orçamento": {
"main": [
[
{
"node": "Montar corpo da resposta",
"type": "main",
"index": 0
}
],
[
{
"node": "Montar corpo da resposta",
"type": "main",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent - Orçamento",
"type": "ai_memory",
"index": 0
}
]
]
},
"Montar corpo da resposta": {
"main": [
[
{
"node": "Responder Webhook (texto)",
"type": "main",
"index": 0
}
]
]
},
"Extrair campos do webhook": {
"main": [
[
{
"node": "Buscar ticket (Z-PRO)",
"type": "main",
"index": 0
}
]
]
},
"Buscar ticket (Z-PRO)": {
"main": [
[
{
"node": "Mesclar dados do ticket",
"type": "main",
"index": 0
}
],
[
{
"node": "Mesclar dados do ticket",
"type": "main",
"index": 0
}
]
]
},
"Mesclar dados do ticket": {
"main": [
[
{
"node": "É mensagem de imagem?",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"saveDataErrorExecution": "all",
"saveDataSuccessExecution": "all",
"saveManualExecutions": true,
"saveExecutionProgress": true,
"binaryMode": "separate"
}
}