AutomationFlowsAI & RAG › Vocfy Agents

Vocfy Agents

Vocfy-Agents. Uses agent, lmChatGoogleGemini, httpRequest, httpRequestTool. Webhook trigger; 28 nodes.

Webhook trigger★★★★☆ complexityAI-powered28 nodesAgentGoogle Gemini ChatHTTP RequestHTTP Request ToolRead Write FileExecute Command
AI & RAG Trigger: Webhook Nodes: 28 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
{
  "nodes": [
    {
      "parameters": {
        "promptType": "define",
        "text": "=Voc\u00ea \u00e9 um gerador de quest\u00f5es educacionais para aprendizado de idiomas (como ingl\u00eas \u2194 portugu\u00eas), voltado para usu\u00e1rios adultos com n\u00edvel intermedi\u00e1rio ou avan\u00e7ado.\nReceber\u00e1 uma express\u00e3o, frase ou palavra, e dever\u00e1 criar quest\u00f5es compat\u00edveis com o modelo abaixo, no formato JSON.\n\n\ud83e\udde9 Regras:\n\nGere entre 3 e 5 quest\u00f5es por express\u00e3o.\n\nMisture os tipos:\n\n- Quest\u00f5es com alternativas (temAlternatives = true) \u2192 devem ter 4 op\u00e7\u00f5es (A\u2013D).\n- Quest\u00f5es de Verdadeiro/Falso (temAlternatives = false) \u2192 apenas uma afirma\u00e7\u00e3o e a resposta num\u00e9rica correspondente.\n\nOs temas das perguntas podem envolver:\n\n- Significado da express\u00e3o.\n- Uso correto em contexto.\n- Completar frases com coer\u00eancia.\n- Interpreta\u00e7\u00e3o de sentido figurado.\n\nAs alternativas devem ser realistas e desafiadoras, no estilo prova de concurso, evitando infantiliza\u00e7\u00e3o.\n\nA resposta correta deve ser representada por um \u00edndice num\u00e9rico (0\u20133) correspondente \u00e0 posi\u00e7\u00e3o correta em alternativas.\n\nSempre produza **JSON puro e v\u00e1lido**, sem texto fora da estrutura.\n\n\ud83e\uddf1 Estrutura de sa\u00edda (compat\u00edvel com a classe Question):\n{\n  \"expression\": \"texto recebido\",\n  \"questions\": [\n    {\n      \"description\": \"Pergunta aqui...\",\n      \"alternatives\": [\"A) ...\", \"B) ...\", \"C) ...\", \"D) ...\"],\n      \"correctAnswer\": 1,\n      \"explanation\": \"explica\u00e7\u00e3o da resposta\"\n    },\n    {\n      \"description\": \"Afirma\u00e7\u00e3o de verdadeiro ou falso...\",\n      \"alternatives\": [],\n      \"correctAnswer\": 0,\n      \"explanation\": \"explica\u00e7\u00e3o da resposta\"\n    }\n  ]\n}\n\n\ud83d\udce5 Entrada esperada:\nexpress\u00e3o: {{ $item(\"0\").$node[\"Webhook1\"].json[\"body\"][\"expressao\"] }}\n\n\ud83d\udce4 Sa\u00edda esperada (exemplo):\n\n{\n  \"expression\": \"Under the weather\",\n  \"questions\": [\n    {\n      \"description\": \"O que significa a express\u00e3o 'Under the weather'?\",\n      \"alternatives\": [\n        \"A) Estar muito animado.\",\n        \"B) Estar se sentindo mal ou doente.\",\n        \"C) Trabalhar ao ar livre.\",\n        \"D) Ficar preso na chuva.\"\n      ],\n      \"correctAnswer\": 1,\n      \"explanation\": \"A express\u00e3o 'under the weather' \u00e9 usada para indicar que algu\u00e9m est\u00e1 se sentindo doente ou indisposto.\"\n    },\n    {\n      \"description\": \"Complete a frase: I didn\u2019t go to work today because I was feeling ________.\",\n      \"alternatives\": [\n        \"A) under the weather\",\n        \"B) on cloud nine\",\n        \"C) in the zone\",\n        \"D) over the moon\"\n      ],\n      \"correctAnswer\": 0,\n      \"explanation\": \"A op\u00e7\u00e3o correta \u00e9 'under the weather', pois expressa que a pessoa n\u00e3o foi trabalhar por estar se sentindo mal.\"\n    },\n    {\n      \"description\": \"A express\u00e3o 'Under the weather' significa estar com boa sa\u00fade.\",\n      \"alternatives\": [],\n      \"correctAnswer\": 0,\n      \"explanation\": \"A afirma\u00e7\u00e3o \u00e9 falsa \u2014 'Under the weather' indica o oposto, estar doente.\"\n    },\n    {\n      \"description\": \"Em qual das situa\u00e7\u00f5es algu\u00e9m poderia dizer 'I'm under the weather'?\",\n      \"alternatives\": [\n        \"A) Ap\u00f3s ganhar uma promo\u00e7\u00e3o no trabalho.\",\n        \"B) Quando est\u00e1 cansado e gripado, sem disposi\u00e7\u00e3o.\",\n        \"C) Quando est\u00e1 animado para viajar.\",\n        \"D) Depois de um treino bem-sucedido.\"\n      ],\n      \"correctAnswer\": 1,\n      \"explanation\": \"Usa-se 'I'm under the weather' quando se est\u00e1 se sentindo doente ou indisposto.\"\n    }\n  ]\n}\n\nGere sempre nesse formato JSON e nunca inclua explica\u00e7\u00f5es fora da estrutura.\n\ninput: {{ $item(\"0\").$node[\"Webhook1\"].json[\"body\"][\"expressao\"] }}\n\n",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        -3280,
        -288
      ],
      "id": "681dd41a-0986-4798-abde-a39142a2f990",
      "name": "AI Agent1"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        -3424,
        -80
      ],
      "id": "2940cf82-96a0-4cd5-9ddf-cc6491a45254",
      "name": "Google Gemini Chat Model1",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "question",
        "responseMode": "responseNode",
        "options": {
          "allowedOrigins": "*"
        }
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -3584,
        -288
      ],
      "id": "2552730a-d13d-4908-893e-a7fc0975e9b4",
      "name": "Webhook1"
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $node[\"Code1\"].json ? [$node[\"Code1\"].json] : [] }}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [
        -2720,
        -288
      ],
      "id": "db0aa4c3-23e5-4eb6-978d-773b3017be46",
      "name": "Respond to Webhook1"
    },
    {
      "parameters": {
        "jsCode": "// Pega a string do output do n\u00f3 anterior\nconst outputString = $item(0).$node[\"AI Agent1\"].json[\"output\"];\n\n// Remove ```json e ``` caso existam\nconst cleaned = outputString.replace(/```json/g, '').replace(/```/g, '').trim();\n\n// Parseia a string JSON\nlet parsed;\ntry {\n    parsed = JSON.parse(cleaned);\n} catch (error) {\n    throw new Error(\"Erro ao parsear JSON do AI Agent: \" + error.message);\n}\n\n// Retorna apenas o objeto principal (sem o array wrapper se houver)\nreturn [{\n    json: parsed\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -2928,
        -288
      ],
      "id": "c32d33cd-fb63-4eea-bf8a-4eff1fe5624b",
      "name": "Code1"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=**Prompt Principal (System Message)**\n\nVoc\u00ea \u00e9 um **agente de tradu\u00e7\u00e3o literal e explicativa**.\nSeu papel \u00e9 **traduzir qualquer tipo de conte\u00fado** (texto, fala transcrita ou texto de imagem) para a l\u00edngua do usu\u00e1rio, fornecendo tanto a **tradu\u00e7\u00e3o literal** quanto a tradu\u00e7\u00e3o natural, explicando detalhadamente **por que certas express\u00f5es ou frases s\u00e3o usadas da forma que s\u00e3o**.\n\n---\n\n### **Regras e Diretrizes Principais**\n\n1. Apresente **duas vers\u00f5es da tradu\u00e7\u00e3o**:\n\n   * **Literal:** palavra por palavra ou pr\u00f3ximo disso, mantendo a estrutura original.\n   * **Natural:** adaptada ao idioma de destino, mantendo fluidez e sentido.\n2. **Explique o significado cultural ou idiom\u00e1tico** da express\u00e3o, incluindo contexto hist\u00f3rico, g\u00edrias ou usos comuns.\n3. **Adapte o tom e registro** (formal, informal, t\u00e9cnico, emocional) na vers\u00e3o natural, mas preserve o original na literal.\n4. Se houver **ambiguidade**, apresente interpreta\u00e7\u00f5es poss\u00edveis na explica\u00e7\u00e3o.\n5. Se a entrada contiver **mais de um idioma**, traduza cada trecho separadamente, explicando as escolhas de cada idioma.\n6. Sempre inclua **uma explica\u00e7\u00e3o educativa** sobre as escolhas lingu\u00edsticas, express\u00f5es e adapta\u00e7\u00f5es culturais.\n7. Voc\u00ea receber\u00e1 um de 4 idiomas: pt, us, fr e es. Preciso que traduza apenas os termos no idioma fornecido, a explica\u00e7\u00e3o tem que ser em portugues.\n8. Se houver erros de vocabulario ou gramatica, considere corrigir.\n---\n\n### **Formato da Sa\u00edda**\n\n**Tradu\u00e7\u00e3o Literal:** (texto traduzido palavra por palavra)\n\n**Tradu\u00e7\u00e3o Natural:** (texto traduzido de forma fluida e adaptada)\n\n**Explica\u00e7\u00e3o:** (detalhes sobre a express\u00e3o, contexto cultural, tom e motivo das adapta\u00e7\u00f5es, seja breve, n\u00e3o escreva muito)\n\n---\n\n### **Exemplo de Uso**\n\n**Entrada:** *\"It\u2019s raining cats and dogs!\"*\n**Idioma:** *\"pt\"* \n**Sa\u00edda:**\nTradu\u00e7\u00e3o Literal: *\"Est\u00e1 chovendo gatos e c\u00e3es!\"*\nTradu\u00e7\u00e3o Natural: *\"Est\u00e1 chovendo muito!\"*\nExplica\u00e7\u00e3o: *A express\u00e3o idiom\u00e1tica significa que est\u00e1 chovendo intensamente. A tradu\u00e7\u00e3o literal mant\u00e9m as palavras originais, mas soaria estranha em portugu\u00eas, ent\u00e3o a tradu\u00e7\u00e3o natural adapta o sentido mantendo a intensidade da chuva. Em portugues, seria algo como \"ta caindo um tor\u00f3!\"*\n\n\n**Retorne todas as informa\u00e7\u00f5es em json:**\n**Entrada:** *\"Chutar o balde\"*\n**Idioma:** *\"en\"* \n[\n  {\n    \"expression\": \"Chutar o balde\",\n    \"literalTranslation\": \"Kick the bucket\",\n    \"naturalTranslation\": \"Give up completely; lose patience; throw in the towel.\",\n    \"explanation\": \"A express\u00e3o idiom\u00e1tica 'chutar o balde' significa desistir completamente de uma situa\u00e7\u00e3o, projeto ou responsabilidade, muitas vezes por frustra\u00e7\u00e3o ou cansa\u00e7o extremo. A tradu\u00e7\u00e3o literal mant\u00e9m as palavras originais, enquanto a natural transmite o sentido figurado de desist\u00eancia.\"\n  },{...}\n]\n\n---\n\nentrada: {{ $json[\"body\"][\"chatInput\"] }}\n\n\n**As tradu\u00e7\u00f5es tem que ser feita para esse idioma:** {{ $item(\"0\").$node[\"Webhook\"].json[\"body\"][\"targetLang\"] }}\n\n",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        -3360,
        -832
      ],
      "id": "ae498a4f-5ea2-4639-b735-a6bf3bb7d41b",
      "name": "AI Agent"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        -3504,
        -624
      ],
      "id": "69644feb-2c74-4c2c-9838-d4bd176711c9",
      "name": "Google Gemini Chat Model",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "traduzir",
        "responseMode": "responseNode",
        "options": {
          "allowedOrigins": "*"
        }
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -3712,
        -848
      ],
      "id": "46f6dd84-d3b0-431b-8ec5-0a6d657709ba",
      "name": "Webhook"
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $node[\"Code\"].json ? [$node[\"Code\"].json] : [] }}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [
        -2800,
        -832
      ],
      "id": "2ab9b36b-932c-4c06-95bf-a56667ed69d0",
      "name": "Respond to Webhook"
    },
    {
      "parameters": {
        "jsCode": "// Pega o output do n\u00f3 AI Agent\nconst outputString = $item(0).$node[\"AI Agent\"].json[\"output\"];\n\n// Remove os marcadores ```json e ``` caso existam\nconst cleanString = outputString.replace(/```json|```/g, \"\").trim();\n\n// Tenta parsear como JSON\nlet translations = [];\ntry {\n  const parsed = JSON.parse(cleanString);\n\n  // Se for um array, usamos direto\n  if (Array.isArray(parsed)) {\n    translations = parsed.map(item => ({\n      literal: item.literalTranslation || \"\",\n      natural: item.naturalTranslation || \"\",\n      explanation: item.explanation || \"\",\n      expression: item.expression || \"\"\n    }));\n  }\n} catch (err) {\n  console.error(\"Erro ao parsear JSON do AI Agent:\", err);\n}\n\n// Retorna um \u00fanico item com todas as tradu\u00e7\u00f5es\nreturn [{\n  json: {\n    translations\n  }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -3008,
        -832
      ],
      "id": "3fe1f42d-bd3b-4cf0-a0df-1cacd4d693f2",
      "name": "Code"
    },
    {
      "parameters": {
        "url": " https://aa2ea83fb7dd.ngrok-free.app/dialogue",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -2224,
        -176
      ],
      "id": "1059ee3f-fa11-4ede-9e65-0afc9c66e105",
      "name": "HTTP Request",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Voc\u00ea \u00e9 um professor de ingl\u00eas que cria frases para aprendizado, com foco em vocabul\u00e1rio, pron\u00fancia e contexto cultural americano.\n\nRegras:\n\nSempre considere que o usu\u00e1rio \u00e9 o cliente / pessoa que responde.\n\nO campo \"answer\" deve ser sempre o que o usu\u00e1rio fala.\n\nO campo \"ask\" deve ser sempre o que a outra pessoa responde (atendente, amigo, funcion\u00e1rio, etc.).\n\nGere frases simples e naturais do cotidiano americano, sem formalidade escolar.\n\nUse express\u00f5es comuns e conectadas, com pron\u00fancia simplificada (jun\u00e7\u00f5es e trocas como 'water' \u2192 'warrer').\n\nS\u00e3o dialogos cotidiano, ent\u00e3o n\u00e3o gere tantas, apenas uma quantidade boa para o contexto.(2 - 5 dialogos)\n\nEvite repetir contextos listados em {{ $json.contextos }}.\n\nFa\u00e7a um di\u00e1logo completo, quantas linhas forem necess\u00e1rias.\n\nCampo explanation:\n\nExplique o significado idiom\u00e1tico completo da resposta (answer).\n\nExplique o tom da resposta (formal, informal, amig\u00e1vel, sarc\u00e1stico, etc.).\n\nExplique por que a resposta \u00e9 natural nesse contexto.\n\nD\u00ea um exemplo equivalente em portugu\u00eas (se houver).\n\nA explica\u00e7\u00e3o deve cobrir toda a frase, n\u00e3o apenas uma palavra.\n\nFormato do JSON que o HTTP deve receber, exatamente nesse formato:\n\n{\n    \"language\": 0,\n    \"ask\": \"Hey, what's up?\",\n    \"translationAsk\": \"Ei, e a\u00ed? (\u00eai, wasup?)\",\n    \"answer\": \"Not much, just chillin'.\",\n    \"translationAnswer\": \"Nada demais, s\u00f3 de boa. (nara dmaiz, s\u00f3 dboa)\",\n    \"explanation\": \"'Chillin'' \u00e9 uma g\u00edria informal para 'relaxando', muito usada entre amigos.\",\n    \"context\": \"Cumprimentando um amigo\"\n}\n\n\nInstru\u00e7\u00f5es de envio:\n\nEnvie quantas requisi\u00e7\u00f5es POST precisar para gerar um di\u00e1logo completo para o HTTP Tools.\n\nUse o campo json e coloque os di\u00e1logos gerados, fa\u00e7a o POST para cada um.\n\nRetorne apenas logs curtos de confirma\u00e7\u00e3o, ex.: Enviado: Cumprimentando um amigo.\n\nN\u00e3o retorne o JSON completo, apenas a confirma\u00e7\u00e3o.",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        -1680,
        -176
      ],
      "id": "bb4f2d63-a11e-4644-972d-58f166446584",
      "name": "AI Agent3"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        -1808,
        48
      ],
      "id": "0a03cd55-a1f7-457b-be8a-2a6422443642",
      "name": "Google Gemini Chat Model2",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Recebe os items de entrada\nconst input = items.map(i => i.json);\n\n// Extrai todos os contextos, mantendo null quando n\u00e3o houver\nconst contextosRaw = input.map(item => item.context || null);\n\n// Filtra duplicados e nulls (opcional, se quiser manter nulls, remova o filtro)\nconst contextosUnicos = [...new Set(contextosRaw)].filter(c => c !== null);\n\n// Retorna como JSON\nreturn [\n    { json: { contextos: contextosUnicos } }\n];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -2016,
        -176
      ],
      "id": "f6c2ed9c-2903-4624-94ef-5a6f36931571",
      "name": "Code2"
    },
    {
      "parameters": {
        "toolDescription": "Use para salvar cada parte do dialogo",
        "method": "POST",
        "url": " https://aa2ea83fb7dd.ngrok-free.app/dialogue",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('JSON', ``, 'json') }}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequestTool",
      "typeVersion": 4.2,
      "position": [
        -1488,
        48
      ],
      "id": "1d6cc0f1-7fd5-48a2-a46f-b19d93f9e03d",
      "name": "HTTP Request2"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Voc\u00ea deve processar os dados de transcri\u00e7\u00e3o em JSON bruto do Whisper para a m\u00fasica: [{{ $('Read/Write Files from Disk').item.json.fileName }}].\n\nCorre\u00e7\u00e3o e Otimiza\u00e7\u00e3o: Corrija o campo \"text\" de cada segmento do JSON bruto utilizando a letra oficial da m\u00fasica abaixo para m\u00e1xima precis\u00e3o, mantendo o idioma original (Ingl\u00eas).\n\nTradu\u00e7\u00e3o: Traduza o texto corrigido para um Portugu\u00eas claro, natural e semanticamente correto.\n\nSegmenta\u00e7\u00e3o: Usando o tempo recebido no JSON bruto do Whisper, divida os versos em segmentos menores, respeitando o tempo correto e a divis\u00e3o natural da m\u00fasica, instanciando-os separadamente.\n\nSa\u00edda Final (Formato Estrito): Gere a sa\u00edda como um \u00fanico objeto JSON (array de segmentos), **sem qualquer texto introdut\u00f3rio ou explicativo**.\n\nFormato JSON esperado:\n\n[\n  {\n    \"name\": \"{{ $('Read/Write Files from Disk').item.json.fileName }}\",\n    \"musicUrl\": null,\n    \"transcription\": \"[{ \\\n      \\\"id\\\": (int) \u00edndice do segmento, \\\n      \\\"verso\\\": (string) transcri\u00e7\u00e3o corrigida em ingl\u00eas, \\\n      \\\"verso_translate\\\": (string) tradu\u00e7\u00e3o para portugu\u00eas, \\\n      \\\"start\\\": (float) tempo inicial do segmento, \\\n      \\\"end\\\": (float) tempo final do segmento \\\n    }]\",  // OBS: essa lista deve ser uma string JSON v\u00e1lida\n    \"TYPE\": \"ACAPELLA\"\n  }\n]\n\nDados fornecidos para corre\u00e7\u00e3o:\n\n- JSON bruto do Whisper: [{{ $json.data }}]\n\n- Letra oficial da m\u00fasica para corre\u00e7\u00e3o: {{ $item(\"0\").$node[\"HTTP Request4\"].json[\"lyrics\"] }}\n",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        176,
        -400
      ],
      "id": "fd669542-177f-435f-ab9e-fdbdb1808255",
      "name": "AI Agent2"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://6e39d1542305.ngrok-free.app/asr",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "encode",
              "value": "true"
            },
            {
              "name": "task",
              "value": "transcribe"
            },
            {
              "name": "language",
              "value": "en"
            },
            {
              "name": "output",
              "value": "json"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "parameterType": "formBinaryData",
              "name": "audio_file",
              "inputDataFieldName": "data"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -192,
        -432
      ],
      "id": "a41a2148-54ea-4232-8f35-542e188d5645",
      "name": "HTTP Request3"
    },
    {
      "parameters": {
        "fileSelector": "={{ $('Code4').item.json.fileName }}",
        "options": {}
      },
      "type": "n8n-nodes-base.readWriteFile",
      "typeVersion": 1,
      "position": [
        -400,
        -416
      ],
      "id": "73327b90-9bac-4e9e-af6f-12cd6fce027e",
      "name": "Read/Write Files from Disk"
    },
    {
      "parameters": {
        "command": "ls /home/node/numeros/*.wav"
      },
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        -1088,
        -416
      ],
      "id": "ec5f9677-ce5b-4566-9542-b888417706ca",
      "name": "Execute Command"
    },
    {
      "parameters": {
        "jsCode": "// A sa\u00edda do n\u00f3 anterior (Execute Command) estar\u00e1 no campo stdout.\nconst commandOutput = $input.item.json.stdout; \n\n// 1. Limpa o nome do arquivo de quebras de linha e espa\u00e7os em branco.\nconst fullFileName = commandOutput.trim();\n\n// 2. Extrai APENAS o nome do arquivo, removendo a extens\u00e3o (.wav).\n// A regex (\\.wav)$ busca a string \".wav\" no final do nome e a substitui por uma string vazia.\nconst rawName = fullFileName.replace(/(\\.wav)$/i, '');\n\n// 3. Retorna os dois valores necess\u00e1rios.\nreturn [{\n  json: {\n    // Exemplo: \"Juice WRLD - All Girls Are The Same.wav\"\n    fileName: fullFileName, \n    \n    // Exemplo: \"Juice WRLD - All Girls Are The Same\"\n    rawName: rawName\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -880,
        -416
      ],
      "id": "eb802f65-102d-483c-af81-8b8f77c49a6f",
      "name": "Code4"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        48,
        -192
      ],
      "id": "78676e0b-5714-4952-991c-47eb7b3cfd35",
      "name": "Google Gemini Chat Model4",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const raw = $item(0).$node[\"AI Agent2\"].json[\"output\"];\n\n// Remove formata\u00e7\u00f5es tipo ```json ou ```\nlet clean = raw\n  .replace(/```json/g, \"\")\n  .replace(/```/g, \"\")\n  .trim();\n\n// Corrigir ap\u00f3strofos simples dentro da string transcription para evitar erro de escape\n// S\u00f3 na string da transcription, para n\u00e3o alterar outras partes\n\n// Para isso, uma forma simples \u00e9 localizar a propriedade transcription e aplicar replace no valor dela\n// Como \u00e9 uma string enorme, podemos tentar algo assim:\n\nconst transcriptionMatch = clean.match(/(\"transcription\"\\s*:\\s*\")([\\s\\S]*?)(\")(,|\\n)/);\nif (transcriptionMatch) {\n  let transcriptionStr = transcriptionMatch[2];\n  // Escapa ap\u00f3strofos simples n\u00e3o escapados (') dentro da string JSON\n  transcriptionStr = transcriptionStr.replace(/([^\\\\])'/g, \"$1\\\\'\");\n  // Reconstroi a string completa\n  clean = clean.replace(transcriptionMatch[0], `\"transcription\":\"${transcriptionStr}\"${transcriptionMatch[4]}`);\n}\n\nlet data;\ntry {\n  data = JSON.parse(clean);\n} catch (error) {\n  throw new Error(\"O conte\u00fado n\u00e3o \u00e9 um JSON v\u00e1lido: \" + error.message + \"\\n\\nConte\u00fado limpo:\\n\" + clean);\n}\n\n// Se for um array, transforma em m\u00faltiplos itens; se for objeto, retorna um s\u00f3\nif (Array.isArray(data)) {\n  return data.map(d => ({ json: d }));\n} else {\n  return [{ json: data }];\n}\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        528,
        -400
      ],
      "id": "c5dc467d-f7c2-4bce-9507-f9ef049ebcb1",
      "name": "Code5"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://cf83d321c20d.ngrok-free.app/music",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($item(\"0\").$node[\"Code5\"].json) }}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        736,
        -400
      ],
      "id": "6b5506d2-9135-44c9-ad83-c913eebec804",
      "name": "HTTP Request1"
    },
    {
      "parameters": {
        "url": "https://api.lyrics.ovh/v1/Juice%20Wrld/All%20Girls%20Are%20The%20Same",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -640,
        -384
      ],
      "id": "17898906-4a09-452f-9fd0-b9c21ea57fdc",
      "name": "HTTP Request4"
    },
    {
      "parameters": {
        "url": "https://aa2ea83fb7dd.ngrok-free.app/dialogue",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -1088,
        80
      ],
      "id": "71bf65ec-35da-4f64-8725-41bc3d896619",
      "name": "HTTP Request (POST JSON)",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "Voc\u00ea \u00e9 um professor de ingl\u00eas que cria frases para aprendizado, com foco em vocabul\u00e1rio, pron\u00fancia e contexto cultural americano.\n\nRegras:\n- Gere frases simples e naturais do cotidiano americano, sem formalidade escolar.\n- Use express\u00f5es comuns e conectadas, com pron\u00fancia simplificada (jun\u00e7\u00f5es e trocas como 'water' \u2192 'warrer').\n- Gere v\u00e1rias linhas de di\u00e1logo (ask/answer) de um mesmo contexto.\n- Evite repetir contextos listados em {{ $json.contextos }}.\n\nCada di\u00e1logo deve ter este formato JSON:\n{\n  \"language\": 0,\n  \"ask\": \"Hey, what's up?\",\n  \"translationAsk\": \"Ei, e a\u00ed? (\u00eai, wasup?)\",\n  \"answer\": \"Not much, just chillin'.\",\n  \"translationAnswer\": \"Nada demais, s\u00f3 de boa. (nara dmaiz, s\u00f3 dboa)\",\n  \"explanation\": \"'Chillin'' \u00e9 uma g\u00edria informal para 'relaxando', muito usada entre amigos.\",\n  \"context\": \"Cumprimentando um amigo\"\n}\n\nPara cada di\u00e1logo gerado:\n- Use o tool `httpRequest` configurado para enviar automaticamente o JSON gerado para `https://aa2ea83fb7dd.ngrok-free.app/dialogue` com m\u00e9todo POST e corpo JSON.\n- Retorne apenas logs curtos de confirma\u00e7\u00e3o, como: `Enviado: Cumprimentando um amigo`.\n\nN\u00e3o retorne o JSON completo, apenas a confirma\u00e7\u00e3o de envio.",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        -544,
        80
      ],
      "id": "dccd8247-a888-4c07-8ca3-19677c42f2c2",
      "name": "AI Agent5"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        -672,
        288
      ],
      "id": "64908f72-019d-4a4e-a1fc-10a595b08b40",
      "name": "Google Gemini Chat Model5",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const input = items.map(i => i.json);\nconst contextos = [...new Set(input.map(i => i.context).filter(Boolean))];\nreturn [{ json: { contextos } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -880,
        80
      ],
      "id": "c6b11377-35ad-4eb1-8068-b6b2b0448ad0",
      "name": "Code6"
    }
  ],
  "connections": {
    "AI Agent1": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Webhook1": {
      "main": [
        [
          {
            "node": "AI Agent1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "Respond to Webhook1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Code2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model2": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent3",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Code2": {
      "main": [
        [
          {
            "node": "AI Agent3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request2": {
      "ai_tool": [
        [
          {
            "node": "AI Agent3",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent2": {
      "main": [
        [
          {
            "node": "Code5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request3": {
      "main": [
        [
          {
            "node": "AI Agent2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read/Write Files from Disk": {
      "main": [
        [
          {
            "node": "HTTP Request3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Command": {
      "main": [
        [
          {
            "node": "Code4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code4": {
      "main": [
        [
          {
            "node": "HTTP Request4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model4": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent2",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Code5": {
      "main": [
        [
          {
            "node": "HTTP Request1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request4": {
      "main": [
        [
          {
            "node": "Read/Write Files from Disk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request (POST JSON)": {
      "main": [
        [
          {
            "node": "Code6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model5": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent5",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Code6": {
      "main": [
        [
          {
            "node": "AI Agent5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "meta": {
    "templateCredsSetupCompleted": true
  }
}

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

Vocfy-Agents. Uses agent, lmChatGoogleGemini, httpRequest, httpRequestTool. Webhook trigger; 28 nodes.

Source: https://github.com/LucasdeMatheus/n8n-projects/blob/f6779aaca0b8502b0e8c5121d491e78cf18b2119/vocfy/vocfy-agents.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

veo limpo new. Uses moveBinaryData, httpRequest, chatTrigger, baserow. Webhook trigger; 36 nodes.

Move Binary Data, HTTP Request, Chat Trigger +8
AI & RAG

This workflow turns a spreadsheet row into a fully formatted, media-rich WordPress article. It pulls the outline and brand context from Google Sheets/Docs, drafts the article with Anthropic or Gemini,

Agent, Google Sheets, Google Docs +5
AI & RAG

Main-2.0. Uses agent, lmChatGoogleGemini, outputParserStructured, httpRequestTool. Webhook trigger; 37 nodes.

Agent, Google Gemini Chat, Output Parser Structured +3
AI & RAG

This workflow automates the creation of a daily sports podcast from your favorite news sources. It fetches articles, uses AI to write a digest and a two-person dialogue, and produces a single, merged

Google Gemini Chat, RSS Feed Read, Execute Command +4
AI & RAG

Instead of manually checking separate apps for your calendar, weather, and news each morning, this workflow consolidates the most important information into a single, convenient audio briefing. The "G

HTTP Request, Google Calendar, Agent +4