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 →
{
"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.
googlePalmApi
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 →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
veo limpo new. Uses moveBinaryData, httpRequest, chatTrigger, baserow. Webhook trigger; 36 nodes.
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,
Main-2.0. Uses agent, lmChatGoogleGemini, outputParserStructured, httpRequestTool. Webhook trigger; 37 nodes.
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
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