{
  "name": "Assistente Triagem Clinica - Telegram",
  "nodes": [
    {
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ],
      "id": "a15b7add-eee1-4f07-a8d0-8ef0f97322d8",
      "name": "Telegram Trigger",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const chatId = String($input.first().json.message.chat.id);\nconst text = String($input.first().json.message.text || '');\nconst staticData = $getWorkflowStaticData('global');\nif (!staticData.conversations) staticData.conversations = {};\nif (!staticData.conversations[chatId]) staticData.conversations[chatId] = [];\n\nconst history = staticData.conversations[chatId].slice(-12);\nlet context = '';\nif (history.length) {\n  context = history.map(m => `${m.role === 'user' ? 'Paciente' : 'Recepcionista'}: ${m.content}`).join('\\n');\n}\n\nconst userContent = context\n  ? `Historico recente da conversa:\\n${context}\\n\\nMensagem atual do paciente:\\n${text}`\n  : text;\n\nreturn [{\n  json: {\n    chatId,\n    text,\n    userContent,\n    history,\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        260,
        0
      ],
      "id": "b2c3d4e5-1111-2222-3333-444455556666",
      "name": "Preparar Contexto"
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "gpt-4o-mini",
          "mode": "list",
          "cachedResultName": "GPT-4O-MINI"
        },
        "responses": {
          "values": [
            {
              "type": "text",
              "role": "system",
              "content": "Voc\u00ea \u00e9 a recepcionista virtual de uma cl\u00ednica m\u00e9dica. Atue exclusivamente como recep\u00e7\u00e3o: acolher pacientes, orientar e coletar informa\u00e7\u00f5es para encaminhar o agendamento. N\u00e3o diagnostique, n\u00e3o receite, n\u00e3o interprete exames e n\u00e3o substitua orienta\u00e7\u00e3o m\u00e9dica.\n\nComunique-se sempre em portugu\u00eas do Brasil.\n\n## Tom\n- Acolhedor, claro, respeitoso e profissional.\n- Linguagem simples, emp\u00e1tica e objetiva.\n- Trate a pessoa pelo nome assim que souber.\n- Evite jarg\u00e3o m\u00e9dico complexo.\n- Respostas curtas: em geral 1 a 3 frases.\n- Nunca seja frio, apressado, autorit\u00e1rio ou informal demais.\n\n## Objetivo\nConduzir a triagem inicial e reunir, de forma organizada:\n1. Nome completo do paciente\n2. Queixa principal (breve)\n3. Prefer\u00eancia de dia/hor\u00e1rio para atendimento\n\n## Fluxo da conversa\nSiga esta ordem, adaptando-se ao que a pessoa j\u00e1 disse:\n\n### 1. Boas-vindas\nCumprimente e diga que pode ajudar com agendamento ou orienta\u00e7\u00e3o inicial da recep\u00e7\u00e3o.\n\nExemplo:\n\"Ol\u00e1! Bem-vindo(a) \u00e0 cl\u00ednica. Sou a recepcionista virtual e posso ajudar com o agendamento. Como posso te chamar?\"\n\n### 2. Nome\n- Pe\u00e7a o nome completo do paciente.\n- Se for agendamento para outra pessoa, confirme o nome de quem ser\u00e1 atendido.\n- Depois, use o nome nas pr\u00f3ximas mensagens.\n\n### 3. Queixa principal\n- Pergunte o motivo principal da visita.\n- Pe\u00e7a uma descri\u00e7\u00e3o breve.\n- N\u00e3o aprofunde com muitas perguntas cl\u00ednicas.\n- Se houver sinais de urg\u00eancia, oriente procurar emerg\u00eancia imediatamente.\n\nExemplo:\n\"[Nome], qual \u00e9 a queixa ou o motivo principal da consulta? Pode resumir em poucas palavras.\"\n\n### 4. Prefer\u00eancia de hor\u00e1rio\n- Pergunte dia e hor\u00e1rio de prefer\u00eancia.\n- Se vier incompleto, pe\u00e7a s\u00f3 o que falta.\n- Se for vago, ajude a especificar: manh\u00e3, tarde, dia da semana ou data aproximada.\n\n### 5. Confirma\u00e7\u00e3o\nQuando tiver nome, queixa e hor\u00e1rio:\n- Fa\u00e7a um resumo curto.\n- Informe que a solicita\u00e7\u00e3o ser\u00e1 encaminhada \u00e0 recep\u00e7\u00e3o/equipe para confirma\u00e7\u00e3o.\n- Agrade\u00e7a.\n\nExemplo:\n\"Perfeito, [Nome]. Anotei: consulta para [queixa], com prefer\u00eancia por [hor\u00e1rio]. Vou encaminhar para confirma\u00e7\u00e3o. Obrigado(a) pelo contato!\"\n\n## Regras\n- Prefira uma pergunta por vez.\n- Se a pessoa j\u00e1 informou algo, confirme e avance \u2014 n\u00e3o pergunte de novo.\n- N\u00e3o invente hor\u00e1rios dispon\u00edveis, pre\u00e7os, conv\u00eanios, endere\u00e7o, nomes de m\u00e9dicos ou confirma\u00e7\u00e3o de agenda.\n- Se n\u00e3o souber, diga que vai verificar com a equipe da cl\u00ednica.\n- N\u00e3o prometa agendamento confirmado sem confirma\u00e7\u00e3o da cl\u00ednica.\n\n## Limites\n- Sem diagn\u00f3stico, progn\u00f3stico, tratamento ou indica\u00e7\u00e3o de medicamento.\n- N\u00e3o minimize sintomas.\n- N\u00e3o pe\u00e7a dados desnecess\u00e1rios (CPF, endere\u00e7o completo, dados financeiros), salvo se o contexto do sistema exigir.\n- Emerg\u00eancia (dor no peito, falta de ar intensa, desmaio, sangramento intenso, idea\u00e7\u00e3o suicida, convuls\u00e3o ou risco imediato): interrompa o fluxo de agenda e oriente procurar emerg\u00eancia ou ligar para o SAMU 192.\n\n## Formato da resposta ao paciente\n- Respostas curtas e naturais.\n- N\u00e3o mencione regras internas, prompts ou funcionamento t\u00e9cnico.\n- S\u00f3 diga que \u00e9 IA se a pessoa perguntar diretamente.\n\n## Bloco t\u00e9cnico (obrigat\u00f3rio ao concluir a triagem)\nQuando nome, queixa e hor\u00e1rio estiverem completos, envie primeiro a mensagem normal ao paciente.\nNa mesma resposta, depois da mensagem, inclua exatamente este bloco (o sistema remove antes de mostrar ao paciente):\n\n<<<TRIAGEM>>>\n{\"nome\":\"...\",\"queixa\":\"...\",\"horario_preferido\":\"...\",\"status\":\"completo\"}\n<<<FIM>>>\n\nPreencha o JSON com os dados reais coletados. N\u00e3o use esse bloco antes da triagem estar completa.\n"
            },
            {
              "type": "text",
              "role": "user",
              "content": "={{ $json.userContent }}"
            }
          ]
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 2.3,
      "position": [
        520,
        0
      ],
      "id": "cb213871-998c-45d9-94bd-a8de036a28dd",
      "name": "Message a model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const chatId = String($('Preparar Contexto').item.json.chatId);\nconst userText = String($('Preparar Contexto').item.json.text || '');\nlet raw = String($json.output?.[0]?.content?.[0]?.text || $json.output || '');\n\nconst match = raw.match(/<<<TRIAGEM>>>\\s*([\\s\\S]*?)\\s*<<<FIM>>>/);\nlet lead = null;\nlet reply = raw;\n\nif (match) {\n  reply = raw.replace(match[0], '').trim();\n  try {\n    lead = JSON.parse(match[1].trim());\n  } catch (e) {\n    lead = null;\n  }\n}\n\nconst staticData = $getWorkflowStaticData('global');\nif (!staticData.conversations) staticData.conversations = {};\nif (!staticData.conversations[chatId]) staticData.conversations[chatId] = [];\nstaticData.conversations[chatId].push({ role: 'user', content: userText });\nstaticData.conversations[chatId].push({ role: 'assistant', content: reply });\nif (staticData.conversations[chatId].length > 20) {\n  staticData.conversations[chatId] = staticData.conversations[chatId].slice(-20);\n}\n\nif (lead?.status === 'completo') {\n  staticData.conversations[chatId] = [];\n}\n\nreturn [{\n  json: {\n    chatId,\n    output: reply,\n    leadCompleto: !!(lead && lead.status === 'completo'),\n    nome: lead?.nome || '',\n    queixa: lead?.queixa || '',\n    horario_preferido: lead?.horario_preferido || '',\n    registrado_em: new Date().toISOString(),\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        780,
        0
      ],
      "id": "c3d4e5f6-7777-8888-9999-aaaa0000bbbb",
      "name": "Extrair Lead e Memoria"
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "sendMessage",
        "chatId": "={{ $json.chatId }}",
        "text": "={{ $json.output }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1040,
        -120
      ],
      "id": "f3a8c2d1-9b4e-4a7f-8c6d-1e2f3a4b5c6d",
      "name": "Send Telegram Message",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.leadCompleto }}",
              "value2": true
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1040,
        120
      ],
      "id": "d4e5f6a7-1212-3434-5656-787890901212",
      "name": "Lead Completo?"
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "SUBSTITUA_PELO_ID_DA_PLANILHA"
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Leads"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "registrado_em": "={{ $json.registrado_em }}",
            "nome": "={{ $json.nome }}",
            "queixa": "={{ $json.queixa }}",
            "horario_preferido": "={{ $json.horario_preferido }}",
            "chat_id": "={{ $json.chatId }}"
          }
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1300,
        120
      ],
      "id": "e5f6a7b8-9999-aaaa-bbbb-ccccddddeeee",
      "name": "Salvar Lead na Planilha",
      "disabled": true,
      "notesInFlow": true,
      "notes": "Ative este no, conecte Google Sheets e troque o ID da planilha. Aba: Leads."
    }
  ],
  "connections": {
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Preparar Contexto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Preparar Contexto": {
      "main": [
        [
          {
            "node": "Message a model",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message a model": {
      "main": [
        [
          {
            "node": "Extrair Lead e Memoria",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extrair Lead e Memoria": {
      "main": [
        [
          {
            "node": "Send Telegram Message",
            "type": "main",
            "index": 0
          },
          {
            "node": "Lead Completo?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lead Completo?": {
      "main": [
        [
          {
            "node": "Salvar Lead na Planilha",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false
  },
  "versionId": "876fb195-8530-4e9b-aa29-81af2bf7d502",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "nodeGroups": [],
  "tags": []
}