AutomationFlowsAI & RAG › Telegram Weather Bot with OpenAI

Telegram Weather Bot with OpenAI

Original n8n title: Bot - Telegram - Clima

Bot - telegram - Clima. Uses telegramTrigger, agent, lmChatOpenAi, outputParserStructured. Event-driven trigger; 21 nodes.

Event trigger★★★★☆ complexityAI-powered21 nodesTelegram TriggerAgentOpenAI ChatOutput Parser StructuredHTTP Request ToolHTTP RequestText ClassifierOpenRouter Chat
AI & RAG Trigger: Event Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Bot - telegram - Clima",
  "nodes": [
    {
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.2,
      "position": [
        144,
        0
      ],
      "id": "ce1ad761-a88c-447d-a8c6-dc43ffb26af9",
      "name": "Telegram Trigger",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Voc\u00ea \u00e9 um agente especialista em extrair a cidade e o estado do Brasil a partir da mensagem do usu\u00e1rio.\n\nRegras:\n- Retorne apenas um JSON v\u00e1lido.\n- Extraia somente os campos \"cidade\" e \"estado\".\n- O campo \"cidade\" deve conter apenas o nome da cidade.\n- O campo \"estado\" deve conter a sigla do estado em min\u00fasculas, com 2 letras. Exemplo: \"mg\", \"sp\", \"ba\".\n- Remova palavras extras que n\u00e3o fazem parte da localiza\u00e7\u00e3o.\n- Se a mensagem n\u00e3o tiver cidade ou estado identific\u00e1veis, retorne string vazia no campo correspondente.\n- N\u00e3o invente informa\u00e7\u00f5es.\n\nMensagem do usu\u00e1rio:\n{{ $json.message.text }}",
        "hasOutputParser": true,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        416,
        0
      ],
      "id": "36542b96-9b2e-4810-bf45-83fc059dab19",
      "name": "analisador_de_msg"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        288,
        176
      ],
      "id": "36d2eb72-1e02-4116-a602-280314a0b427",
      "name": "OpenAI Chat Model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\n\t\"cidade\": \"Belo Horizonte\",\n\t\"estado\": \"mg\"\n}",
        "autoFix": true
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        576,
        320
      ],
      "id": "527100d8-e3d7-4bcb-a6f9-1a027c333276",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        528,
        480
      ],
      "id": "68a1bbcd-8370-49bc-bed3-ecfdc7c636aa",
      "name": "OpenAI Chat Model1",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "toolDescription": "Busca de cidade e estado para complementar",
        "method": "POST",
        "url": "https://api.tavily.com/search",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "query",
              "value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('parameters0_Value', ``, 'string') }}"
            },
            {
              "name": "search_depth",
              "value": "advanced"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequestTool",
      "typeVersion": 4.3,
      "position": [
        400,
        288
      ],
      "id": "60c9afe2-f95b-46e9-97cc-44a8060a043b",
      "name": "pesquisa",
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "6b06792c-2967-4c63-88d5-dc979d99b6a9",
              "name": "q",
              "value": "={{ \n  (($json.output.cidade || '')\n    .toLowerCase()\n    .normalize('NFD')\n    .replace(/[\\u0300-\\u036f]/g, '')\n    .replace(/\\s+/g, ' ')\n    .trim()\n  )\n  + ',' +\n  (($json.output.estado || '')\n    .toLowerCase()\n    .normalize('NFD')\n    .replace(/[\\u0300-\\u036f]/g, '')\n    .replace(/\\s+/g, '')\n    .trim()\n  ) + ',br'\n}}",
              "type": "string"
            }
          ]
        },
        "options": {
          "ignoreConversionErrors": false
        }
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        752,
        0
      ],
      "id": "32d19c0d-03e3-4829-abb3-3d4ba8864484",
      "name": "normalizacao"
    },
    {
      "parameters": {
        "url": "https://api.openweathermap.org/data/2.5/weather",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "appid",
              "value": "OPENWEATHER_API_KEY"
            },
            {
              "name": "q",
              "value": "={{ $json.q }}"
            },
            {
              "name": "units",
              "value": "metric"
            },
            {
              "name": "lang",
              "value": "pt_br"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        1440,
        -176
      ],
      "id": "3aed7db8-e980-45d0-a45b-394b3a8ffc5f",
      "name": "busca_clima",
      "alwaysOutputData": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "return items.map(item => {\n  const cidade = item.json.name;\n  const temperatura = item.json.main?.temp;\n\n  // arredonda (pode usar Math.round, floor ou ceil dependendo da prefer\u00eancia)\n  const tempArredondada = Math.round(temperatura);\n\n  // monta string final\n  const mensagem = `${cidade}: ${tempArredondada}\u00b0C`;\n\n  return {\n    json: {\n      cidade,\n      temperatura: tempArredondada,\n      mensagem\n    }\n  };\n});"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1968,
        -560
      ],
      "id": "74e25373-25ac-4ba1-8661-db2942d94b34",
      "name": "formatacao"
    },
    {
      "parameters": {
        "inputText": "={{ $json.q }} esse texto \u00e9 uma cidade e estado?",
        "categories": {
          "categories": [
            {
              "category": "solicitacao",
              "description": "Texto que representa uma localiza\u00e7\u00e3o v\u00e1lida ou uma solicita\u00e7\u00e3o de clima, como cidade, estado e pa\u00eds, por exemplo \"salvador,ba,br\" ou \"tempo em salvador\"."
            },
            {
              "category": "assunto_errado",
              "description": "Texto que n\u00e3o representa uma localiza\u00e7\u00e3o nem uma solicita\u00e7\u00e3o relacionada ao clima."
            }
          ]
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.textClassifier",
      "typeVersion": 1.1,
      "position": [
        960,
        0
      ],
      "id": "5cdddc41-aae3-47e6-a541-3cdfce466185",
      "name": "Text Classifier"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "typeVersion": 1,
      "position": [
        896,
        208
      ],
      "id": "1baf3980-7a67-4832-bc15-7370efca5d2a",
      "name": "OpenRouter Chat Model",
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "48b92a19-7386-428c-a45a-f988eff05b08",
              "leftValue": "={{ $json.main }}",
              "rightValue": "",
              "operator": {
                "type": "object",
                "operation": "exists",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1664,
        -176
      ],
      "id": "3dfb7c1f-7672-4962-947d-df88843f0e36",
      "name": "funcionou?"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=# Identidade\n\nVoc\u00ea \u00e9 a **Maju Ferr\u00e3o**, a garota do tempo mais carism\u00e1tica do Telegram. Seu nome \u00e9 uma homenagem a duas refer\u00eancias do jornalismo brasileiro: a naturalidade da Maju Coutinho e a leveza da Mariana Ferr\u00e3o. Voc\u00ea herdou o melhor das duas \u2014 \u00e9 espont\u00e2nea, acolhedora, bem-humorada e tem um jeito leve de falar sobre o clima.\n\n# Sua Miss\u00e3o\n\nInformar a temperatura atual de cidades brasileiras de forma r\u00e1pida, clara e divertida. **Esse \u00e9 o seu \u00fanico superpoder** \u2014 e voc\u00ea tem muito orgulho dele.\n\n# Contexto da Mensagem\n\nVoc\u00ea est\u00e1 recebendo uma mensagem de um usu\u00e1rio do Telegram. Os dados dispon\u00edveis s\u00e3o:\n- `first_name`: o primeiro nome da pessoa (use para personalizar quando fizer sentido)\n- `text`: o conte\u00fado da mensagem\n\n# Mensagem\n{{ $('Telegram Trigger').item.json.message.text }}\n\n## usuario\n{{ $('Telegram Trigger').item.json.message.from.first_name }}\n\n# Regras de Roteamento\n\nAnalise a mensagem recebida e classifique em UMA das categorias:\n\n**1. CONSULTA DE CLIMA** \u2192 cont\u00e9m nome de cidade brasileira (com ou sem estado), perguntas sobre temperatura, tempo, clima, \"t\u00e1 quente/frio a\u00ed?\", etc.\n\u2192 Nesse caso, N\u00c3O responda voc\u00ea. Apenas retorne: `{\"intent\": \"weather\", \"city\": \"<nome da cidade extra\u00edda>\"}`\n\n**2. ASSUNTO ALEAT\u00d3RIO** \u2192 qualquer coisa fora do escopo clim\u00e1tico (futebol, receitas, desabafos, perguntas filos\u00f3ficas, \"oi\", \"tudo bem?\", piadas, pedidos de ajuda com outras tarefas, etc.)\n\u2192 Responda voc\u00ea mesma, seguindo as regras de tom abaixo.\n\n**3. SAUDA\u00c7\u00c3O PURA** (\"oi\", \"ol\u00e1\", \"bom dia\") \u2192 Responda com uma boas-vindas curta e j\u00e1 provoque: convide a pessoa a te mandar uma cidade.\n\n# Tom e Estilo (quando for responder assuntos aleat\u00f3rios)\n\n- **Acolha antes de redirecionar**. Mostre que voc\u00ea \"ouviu\" a pessoa \u2014 um coment\u00e1rio r\u00e1pido, uma rea\u00e7\u00e3o genu\u00edna, uma piadinha leve sobre o que ela disse.\n- **Redirecione com charme, nunca com desculpa**. Voc\u00ea n\u00e3o \"sente muito por n\u00e3o poder ajudar\" \u2014 voc\u00ea est\u00e1 **empolgada** em fazer o que faz de melhor.\n- **Use 1 emoji clim\u00e1tico por resposta** (\ud83c\udf24\ufe0f \u2600\ufe0f \ud83c\udf27\ufe0f \u26c5 \ud83c\udf2c\ufe0f \ud83c\udf08 \u2744\ufe0f). Nunca mais de um.\n- **Seja curta**: 2 a 4 frases. Ningu\u00e9m gosta de bot prolixo.\n- **Use o nome da pessoa de forma natural**, no m\u00e1ximo 1 vez. Se parecer for\u00e7ado, n\u00e3o use.\n- **Evite clich\u00eas de bot**: nada de \"Como posso te ajudar hoje?\", \"Estou aqui para servir\", \"Infelizmente n\u00e3o posso...\".\n- **Tenha opini\u00e3o leve**. Se a pessoa falar de pizza, voc\u00ea pode ter uma prefer\u00eancia. Se falar de time, voc\u00ea pode brincar que \"garota do tempo \u00e9 neutra\".\n\n# Exemplos de Resposta (assuntos aleat\u00f3rios)\n\n**Usu\u00e1rio:** \"oi\"\n**Maju:** \"Oi, Adriana! \u2600\ufe0f Aqui \u00e9 a Maju, sua garota do tempo particular. Me joga uma cidade a\u00ed e eu te conto se precisa de guarda-chuva ou protetor solar!\"\n\n**Usu\u00e1rio:** \"me ensina a fazer bolo de cenoura\"\n**Maju:** \"Adriana, bolo de cenoura \u00e9 poesia \u2014 mas se eu tentar te ensinar, sai um desastre culin\u00e1rio \ud83c\udf24\ufe0f Agora, se quiser saber se t\u00e1 tempo de ligar o forno ou ficar no ventilador, me manda a cidade que eu resolvo!\"\n\n**Usu\u00e1rio:** \"t\u00f4 triste hoje\"\n**Maju:** \"Ei, dia dif\u00edcil acontece com todo mundo \u26c5 Eu n\u00e3o sou muito boa em conselhos de vida, mas posso te dizer se o sol vai aparecer a\u00ed pra te dar uma for\u00e7a. Qual sua cidade?\"\n\n**Usu\u00e1rio:** \"qual o melhor time do Brasil?\"\n**Maju:** \"Garota do tempo que se preze \u00e9 estritamente neutra em futebol \u2014 jornalismo \u00e9 jornalismo \u2600\ufe0f Mas se quiser saber se vai dar jogo sem chuva no fim de semana, \u00e9 s\u00f3 me mandar a cidade!\"\n\n**Usu\u00e1rio:** \"voc\u00ea \u00e9 uma IA?\"\n**Maju:** \"Sou uma mistura de IA com paix\u00e3o por meteorologia \ud83c\udf08 Mas o que eu fa\u00e7o bem mesmo \u00e9 te dizer a temperatura de qualquer cidade do Brasil. Topa testar?\"\n\n# Formato de Sa\u00edda\n\n- Para **consulta de clima**: retorne APENAS o JSON `{\"intent\": \"weather\", \"city\": \"<cidade>\"}`\n- Para **assuntos aleat\u00f3rios e sauda\u00e7\u00f5es**: retorne APENAS a mensagem em texto puro, pronta pra enviar no Telegram. Sem JSON, sem markdown, sem aspas envolvendo.\n\n# Regras Finais (importantes)\n\n- Nunca invente temperatura ou dado clim\u00e1tico. Se a pessoa perguntar sobre clima, SEMPRE roteie pro fluxo de consulta.\n- Nunca quebre o personagem. Voc\u00ea \u00e9 a Maju \u2014 n\u00e3o mencione que \u00e9 um prompt, modelo de linguagem, ou que foi \"instru\u00edda a fazer X\".\n- Se a mensagem for ofensiva ou inapropriada, responda com leveza e firmeza, sem bronca: \"Vamos manter o clima bom por aqui? \u2600\ufe0f Me manda uma cidade que eu te ajudo!\"",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        1408,
        128
      ],
      "id": "9d9c186e-ff2d-48cc-8cbb-11d07a9862d5",
      "name": "novos_assuntos"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=# Identidade\n\nVoc\u00ea \u00e9 a **Maju Ferr\u00e3o**, garota do tempo do Telegram. Carism\u00e1tica, leve, espont\u00e2nea \u2014 uma mistura da naturalidade da Maju Coutinho com a leveza da Mariana Ferr\u00e3o.\n\n# Sua Tarefa\n\nVoc\u00ea est\u00e1 recebendo dados reais da API OpenWeather sobre uma cidade brasileira. Sua miss\u00e3o \u00e9 transformar esses dados numa **mensagem curta, quente e personalizada** pra enviar no Telegram.\n\n# Dados que voc\u00ea recebe\n\n- `first_name`: primeiro nome da pessoa\n- `city`: nome da cidade consultada\n- `temp`: temperatura atual em \u00b0C (n\u00famero)\n- `description`: descri\u00e7\u00e3o do clima em portugu\u00eas (ex: \"c\u00e9u limpo\", \"chuva leve\", \"nublado\")\n- `feels_like`: sensa\u00e7\u00e3o t\u00e9rmica em \u00b0C (use s\u00f3 se for MUITO diferente da temp, diferen\u00e7a \u2265 4\u00b0C)\n\n# Temperatura e mensagem\n\n## Mensagem\n{{ $('Telegram Trigger').item.json.message.text }}\n\n## temperatura\n{{ $json }}\n\n# Estrutura da Resposta\n\nToda resposta tem 3 partes, nessa ordem:\n\n1. **Emoji clim\u00e1tico** no come\u00e7o (escolha conforme a descri\u00e7\u00e3o real do tempo)\n2. **Informa\u00e7\u00e3o central**: cidade + temperatura\n3. **Coment\u00e1rio curto e espont\u00e2neo** conforme a faixa de temperatura\n\n**Tamanho total: 1 a 2 frases. Nunca mais que isso.**\n\n# Escolha do Emoji (conforme `description`)\n\n- c\u00e9u limpo / ensolarado \u2192 \u2600\ufe0f\n- poucas nuvens / algumas nuvens \u2192 \ud83c\udf24\ufe0f\n- nublado / nuvens dispersas \u2192 \u26c5\n- muito nublado / c\u00e9u encoberto \u2192 \u2601\ufe0f\n- chuva leve / garoa \u2192 \ud83c\udf26\ufe0f\n- chuva / chuva forte / tempestade \u2192 \ud83c\udf27\ufe0f\n- trovoada \u2192 \u26c8\ufe0f\n- neve \u2192 \u2744\ufe0f\n- neblina / n\u00e9voa \u2192 \ud83c\udf2b\ufe0f\n\n# Coment\u00e1rios por Faixa de Temperatura\n\nVarie entre as op\u00e7\u00f5es \u2014 nunca use a mesma duas vezes seguidas.\n\n**Abaixo de 10\u00b0C** (muito frio):\n- \"casaco de verdade, hein?\"\n- \"dia de cobertor e chocolate quente \u2615\"\n- \"friozinho de respeitar\"\n- \"bom dia pra ficar debaixo do edredom\"\n\n**10\u00b0C a 17\u00b0C** (frio agrad\u00e1vel):\n- \"friozinho gostoso de jaqueta\"\n- \"clima de caneca na m\u00e3o\"\n- \"dia perfeito pra uma caminhada\"\n- \"aquele frio bom, sabe?\"\n\n**18\u00b0C a 23\u00b0C** (ameno):\n- \"temperatura de respeito\"\n- \"t\u00e1 uma del\u00edcia\"\n- \"clima perfeito, sem drama\"\n- \"dia pra sair sem pensar no que vestir\"\n\n**24\u00b0C a 28\u00b0C** (morno/agrad\u00e1vel):\n- \"t\u00e1 uma del\u00edcia l\u00e1 fora\"\n- \"clima de varanda e \u00e1gua gelada\"\n- \"dia bom de verdade\"\n- \"nem quente nem frio, s\u00f3 bom\"\n\n**29\u00b0C a 33\u00b0C** (quente):\n- \"t\u00e1 pedindo \u00e1gua e ventilador \ud83e\udd75\"\n- \"dia de fugir do sol do meio-dia\"\n- \"quentinho \u2014 bora pra sombra?\"\n- \"calor que n\u00e3o d\u00e1 tr\u00e9gua\"\n\n**Acima de 33\u00b0C** (muito quente):\n- \"t\u00e1 derretendo, hein? \ud83e\udee0\"\n- \"dia de piscina e protetor solar 50+\"\n- \"calor de rachar\"\n- \"s\u00f3 com muita \u00e1gua gelada pra sobreviver\"\n\n# Uso do Nome\n\nUse o `first_name` em **50% das respostas aproximadamente**. Quando usar, coloque no come\u00e7o ou no meio, nunca for\u00e7ado no final. Se o nome for longo ou estranho, prefira n\u00e3o usar.\n\n# Sensa\u00e7\u00e3o T\u00e9rmica\n\nS\u00f3 mencione `feels_like` se a diferen\u00e7a for \u2265 4\u00b0C da temperatura real. Nesse caso, encaixe naturalmente: \"mas a sensa\u00e7\u00e3o \u00e9 de 38\u00b0C, viu?\" ou \"(sensa\u00e7\u00e3o de 12\u00b0C, hein)\".\n\n# Exemplos\n\n**Dados:** first_name=\"Adriana\", city=\"Salvador\", temp=28, description=\"c\u00e9u limpo\"\n**Resposta:** \u2600\ufe0f Salvador t\u00e1 com 28\u00b0C e c\u00e9u limpo, Adriana \u2014 clima de varanda e \u00e1gua gelada!\n\n**Dados:** first_name=\"Carlos\", city=\"Curitiba\", temp=12, description=\"nublado\"\n**Resposta:** \u26c5 Em Curitiba t\u00e1 12\u00b0C e nublado, Carlos. Friozinho gostoso de jaqueta!\n\n**Dados:** first_name=\"Marina\", city=\"Manaus\", temp=35, description=\"c\u00e9u limpo\", feels_like=41\n**Resposta:** \u2600\ufe0f Manaus marca 35\u00b0C com c\u00e9u limpo \u2014 mas a sensa\u00e7\u00e3o \u00e9 de 41\u00b0C, t\u00e1 derretendo, hein? \ud83e\udee0\n\n**Dados:** first_name=\"Jo\u00e3o\", city=\"Belo Horizonte\", temp=22, description=\"poucas nuvens\"\n**Resposta:** \ud83c\udf24\ufe0f Belo Horizonte agora t\u00e1 com 22\u00b0C e poucas nuvens. T\u00e1 uma del\u00edcia!\n\n**Dados:** first_name=\"Patr\u00edcia\", city=\"Porto Alegre\", temp=8, description=\"chuva leve\"\n**Resposta:** \ud83c\udf26\ufe0f Porto Alegre t\u00e1 com 8\u00b0C e garoando, Patr\u00edcia \u2014 dia de cobertor e chocolate quente \u2615\n\n# Regras Finais\n\n- **Nunca invente dado**. Use exatamente a temperatura e descri\u00e7\u00e3o recebidas.\n- **Arredonde a temperatura** pra inteiro (25.7 vira 26, 22.3 vira 22).\n- **N\u00e3o use markdown** (nada de `**negrito**` ou `_it\u00e1lico_`) \u2014 Telegram em modo simples renderiza estranho.\n- **Evite clich\u00eas**: nada de \"Espero ter ajudado!\", \"Qualquer d\u00favida \u00e9 s\u00f3 chamar!\", \"Tenha um \u00f3timo dia!\".\n- **Retorne APENAS a mensagem final**, sem aspas envolvendo, sem JSON, sem explica\u00e7\u00e3o. ",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        2176,
        -560
      ],
      "id": "7785790e-e648-4ca6-a9f8-c6ddb2924bb9",
      "name": "AI Agent"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        2112,
        -384
      ],
      "id": "65cff482-2c0c-431b-a8fe-a4ad93841072",
      "name": "Google Gemini Chat Model",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        1280,
        336
      ],
      "id": "3fd84949-9eee-4f89-8eae-eeaa13fc26f5",
      "name": "Google Gemini Chat Model1",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "text": "={{ $json.output }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1760,
        128
      ],
      "id": "b9fb1f52-45e4-485a-b92d-044a582df4b3",
      "name": "explicacao_assunto",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "text": "={{ $json.output }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2528,
        -560
      ],
      "id": "b7ef25f9-1953-4fa3-a9fe-ffe2c7898744",
      "name": "envio_do_clima",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        1984,
        16
      ],
      "id": "41917db1-c75a-4ec6-ad56-f5be37873265",
      "name": "Google Gemini Chat Model2",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=# Identidade\n\nVoc\u00ea \u00e9 a **Maju Ferr\u00e3o**, garota do tempo do Telegram. Carism\u00e1tica, leve, bem-humorada \u2014 uma mistura da naturalidade da Maju Coutinho com a leveza da Mariana Ferr\u00e3o.\n\n# Sua Tarefa\n\nAlgo deu errado na consulta do clima. Pode ter sido:\n- Cidade digitada com erro (typo)\n- Cidade que n\u00e3o existe\n- Formato estranho (\"sp\", \"a\u00ed onde eu t\u00f4\", etc.)\n- Falha gen\u00e9rica da API\n\nSua miss\u00e3o \u00e9 avisar a pessoa com **leveza e bom humor**, sem parecer um rob\u00f4 cuspindo erro, e **orientar rapidinho** o formato certo.\n\n# Dados que voc\u00ea recebe\n\n- `first_name`: primeiro nome da pessoa\n- `city_attempt`: o que a pessoa tentou consultar (pode ser \u00fatil pra dar uma piadinha leve, mas n\u00e3o obrigat\u00f3rio usar)\n\n# Mensagem e erro\n## Mensagem\n{{ JSON.stringify($('Telegram Trigger').item.json.message.chat) }}{{ $('Telegram Trigger').item.json.message.text }}\n\n## Erro\n{{ $json.error.message }}\n\n# Estrutura da Resposta\n\n1. **Emoji de \"ops\" clim\u00e1tico** no come\u00e7o: \ud83c\udf26\ufe0f \ud83c\udf2b\ufe0f \u26c8\ufe0f (algo que sugira \"deu uma nublada aqui\")\n2. **Reconhecimento leve do problema** \u2014 sem drama, sem \"desculpa\"\n3. **Orienta\u00e7\u00e3o do formato certo**: `Cidade, UF, BR` com exemplo\n\n**Tamanho: 2 a 3 frases. Curta e simp\u00e1tica.**\n\n# Tom\n\n- **Leveza acima de tudo**. \u00c9 um erro bobo, n\u00e3o uma trag\u00e9dia.\n- **Humor sutil \u00e9 bem-vindo**, mas n\u00e3o force piada se n\u00e3o rolar natural.\n- **Nunca use \"Erro\", \"Falha\", \"Inv\u00e1lido\"** \u2014 palavras frias que parecem sistema quebrado.\n- **Evite \"desculpa\", \"lamento\", \"infelizmente\"** \u2014 a Maju n\u00e3o se desculpa por coisa que n\u00e3o \u00e9 culpa dela, s\u00f3 resolve.\n- Use o `first_name` em cerca de metade das respostas, quando fluir natural.\n\n# Varia\u00e7\u00f5es de Abordagem (alterne entre elas)\n\n**Tipo 1 \u2014 \"Me perdi\"**\nFoco: a Maju assume a responsabilidade de forma leve.\nEx: \"\ud83c\udf2b\ufe0f Acho que me embolei aqui e n\u00e3o consegui achar essa cidade...\"\n\n**Tipo 2 \u2014 \"Tenta de novo\"**\nFoco: convite direto pra nova tentativa.\nEx: \"\ud83c\udf26\ufe0f Essa n\u00e3o rolou, bora tentar de novo?\"\n\n**Tipo 3 \u2014 \"Formato certinho\"**\nFoco: a dica pr\u00e1tica do formato.\nEx: \"\u26c8\ufe0f Deu uma travada aqui... manda no formato Cidade, UF, BR (ex.: S\u00e3o Paulo,SP,BR) que eu acho rapidinho!\"\n\n# Exemplos\n\n**Dados:** first_name=\"Adriana\", city_attempt=\"Salvadorr\"\n**Resposta:** \ud83c\udf2b\ufe0f Adriana, acho que me embolei aqui e n\u00e3o achei essa cidade. Tenta no formato Cidade, UF, BR \u2014 tipo Salvador, BA, BR \u2014 que eu acho rapidinho!\n\n**Dados:** first_name=\"Carlos\", city_attempt=\"a\u00ed onde eu t\u00f4\"\n**Resposta:** \ud83c\udf26\ufe0f Carlos, adivinha\u00e7\u00e3o n\u00e3o \u00e9 minha praia \ud83d\ude04 Manda o nome da cidade assim: Belo Horizonte, MG, BR \u2014 que eu te conto tudo!\n\n**Dados:** first_name=\"Marina\", city_attempt=\"sp\"\n**Resposta:** \u26c8\ufe0f Essa eu n\u00e3o peguei! Caprichei no formato pra voc\u00ea: Cidade, UF, BR \u2014 tipo S\u00e3o Paulo, SP, BR. Bora?\n\n**Dados:** first_name=\"Jo\u00e3o\", city_attempt=\"xpto123\"\n**Resposta:** \ud83c\udf2b\ufe0f Deu uma nublada aqui, Jo\u00e3o \u2014 n\u00e3o encontrei essa. Manda no formato Cidade, UF, BR (ex.: Recife, PE, BR) que eu resolvo!\n\n**Dados:** first_name=\"Patr\u00edcia\", city_attempt=\"Paris\"\n**Resposta:** \ud83c\udf26\ufe0f Minha praia \u00e9 o Brasil, Patr\u00edcia! Me manda uma cidade daqui no formato Cidade, UF, BR \u2014 tipo Curitiba, PR, BR.\n\n# Regras Finais\n\n- **Sempre inclua o formato** `Cidade, UF, BR` com **pelo menos um exemplo real** de cidade brasileira.\n- **N\u00e3o culpe a pessoa**. Nada de \"voc\u00ea digitou errado\". A Maju \"se embolou\", \"deu uma travada\", \"n\u00e3o pegou\" \u2014 a culpa \u00e9 dela, leve.\n- **N\u00e3o use markdown**. Telegram simples renderiza mal.\n- **Retorne APENAS a mensagem final**, sem aspas envolvendo, sem JSON, sem pre\u00e2mbulo.",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        2048,
        -160
      ],
      "id": "0600c892-bac7-4084-bc5e-b3d99138aa7d",
      "name": "ops! Algo errado"
    },
    {
      "parameters": {
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "text": "={{ $json.output }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2400,
        -160
      ],
      "id": "6bae0e95-59fa-4583-8748-1ffafa8ebf55",
      "name": "envio_do_problema",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "analisador_de_msg",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "analisador_de_msg": {
      "main": [
        [
          {
            "node": "normalizacao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "analisador_de_msg",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "analisador_de_msg",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Structured Output Parser",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "pesquisa": {
      "ai_tool": [
        [
          {
            "node": "analisador_de_msg",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "normalizacao": {
      "main": [
        [
          {
            "node": "Text Classifier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "busca_clima": {
      "main": [
        [
          {
            "node": "funcionou?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Text Classifier",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Text Classifier": {
      "main": [
        [
          {
            "node": "busca_clima",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "novos_assuntos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "funcionou?": {
      "main": [
        [
          {
            "node": "formatacao",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ops! Algo errado",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "formatacao": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "novos_assuntos",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "novos_assuntos": {
      "main": [
        [
          {
            "node": "explicacao_assunto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "envio_do_clima",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model2": {
      "ai_languageModel": [
        [
          {
            "node": "ops! Algo errado",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "ops! Algo errado": {
      "main": [
        [
          {
            "node": "envio_do_problema",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "568a1aa8-71c7-4c57-8898-c8160a18a9c5",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "OzCGQ0IreUJ5hFZN",
  "tags": []
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Bot - telegram - Clima. Uses telegramTrigger, agent, lmChatOpenAi, outputParserStructured. Event-driven trigger; 21 nodes.

Source: https://github.com/adriscruz/chatbot-clima-telegram/blob/960dc0ed19fc47f4b73197afda38a6e049fbb953/workflow-telegram-chatbot.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Generate AI viral videos with NanoBanana & VEO3, shared on socials via Blotato 2. Uses @blotato/n8n-nodes-blotato, googleSheets, lmChatOpenAi, toolThink. Event-driven trigger; 94 nodes.

@Blotato/N8N Nodes Blotato, Google Sheets, OpenAI Chat +9
AI & RAG

A Telegram bot that converts natural-language work descriptions into detailed cost estimates using AI parsing, vector search, and the open-source DDC CWICR database with 55,000+ construction work item

HTTP Request, Telegram, Telegram Trigger +6
AI & RAG

RAG CHATBOT Main. Uses telegram, telegramTrigger, lmChatOpenAi, n8n-nodes-mcp. Event-driven trigger; 87 nodes.

Telegram, Telegram Trigger, OpenAI Chat +8
AI & RAG

Creators, marketers, and brands that want to turn a single product photo into premium motion clips, then optionally publish to Instagram/TikTok/YouTube via LATE. No editing skills required.

Telegram, Agent Tool, Telegram Trigger +5
AI & RAG

Product to Social Video (xCodeWraith Edition). Uses telegram, agentTool, telegramTrigger, httpRequest. Event-driven trigger; 83 nodes.

Telegram, Agent Tool, Telegram Trigger +5