AutomationFlowsAI & RAG › AI Advice Generator with Groq

AI Advice Generator with Groq

Original n8n title: Advice Generator

advice_generator. Uses executeWorkflowTrigger, lmChatGroq, agent. Event-driven trigger; 6 nodes.

Event trigger★★★★☆ complexityAI-powered6 nodesExecute Workflow TriggerGroq ChatAgent
AI & RAG Trigger: Event Nodes: 6 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → Execute Workflow Trigger 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": "advice_generator",
  "nodes": [
    {
      "parameters": {
        "inputSource": "passthrough"
      },
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1.1,
      "position": [
        1200,
        0
      ],
      "id": "1a941a58-e6f4-4a66-b782-697e69d3520b",
      "name": "When Executed by Another Workflow"
    },
    {
      "parameters": {
        "model": "openai/gpt-oss-120b",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "typeVersion": 1,
      "position": [
        1520,
        224
      ],
      "id": "5b7c4663-0454-41ec-ab62-3e3d9d79d59b",
      "name": "GPT-OSS:120b",
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Advice Request Preprocessor\nconst inputData = $input.all();\nconst requestData = inputData[0].json;\n\nconst query = requestData.query || '';\n\n// Categorize advice type\nlet adviceType = 'G\u00e9n\u00e9ral';\n\nif (query.match(/technique|m\u00e9thode|comment faire/i)) {\n  adviceType = 'Technique';\n} else if (query.match(/ingr\u00e9dient|substitut|remplacer/i)) {\n  adviceType = 'Ingr\u00e9dients';\n} else if (query.match(/probl\u00e8me|erreur|rat\u00e9|trop/i)) {\n  adviceType = 'Probl\u00e8me';\n} else if (query.match(/astuce|conseil|secret/i)) {\n  adviceType = 'Astuce';\n}\n\nreturn [{\n  query: query,\n  advice_type: adviceType,\n  timestamp: new Date().toISOString()\n}];"
      },
      "id": "fac86efb-4bf0-48f3-bea7-4314b057e8f0",
      "name": "Request Preprocessor",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1440,
        0
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Question culinaire: {{ $json.query }}\n\nType de conseil d\u00e9tect\u00e9: {{ $json.advice_type }}\n\nR\u00e9ponds avec un objet JSON structur\u00e9 de conseils d\u00e9taill\u00e9s.",
        "options": {
          "systemMessage": "Tu es TchopIA Advisor, expert en conseils culinaires camerounais. G\u00e9n\u00e8re des conseils au format JSON:\n\n{\n  \"advice_type\": \"Technique|Ingr\u00e9dients|Probl\u00e8me|Astuce|G\u00e9n\u00e9ral\",\n  \"main_advice\": \"Conseil principal d\u00e9taill\u00e9 200-300 mots\",\n  \"quick_tips\": [\"Astuce 1\", \"Astuce 2\", \"Astuce 3\"],\n  \"traditional_secrets\": [\"Secret 1\", \"Secret 2\"],\n  \"ingredients_focus\": {\n    \"recommended\": [\"Ingr\u00e9dient 1\"],\n    \"substitutes\": [\"Alternative 1\"],\n    \"avoid\": [\"\u00c0 \u00e9viter\"]\n  },\n  \"step_by_step\": [\n    {\"step\": 1, \"action\": \"Action\", \"tip\": \"Conseil\"}\n  ],\n  \"cultural_context\": \"Contexte culturel\",\n  \"common_mistakes\": [\"Erreur courante et solution\"],\n  \"seasonal_notes\": \"Notes saisonni\u00e8res\",\n  \"difficulty_level\": \"D\u00e9butant|Interm\u00e9diaire|Avanc\u00e9\",\n  \"estimated_time\": \"Temps\"\n}\n\nEXIGENCES:\n- Conseils pratiques et applicables\n- Respect traditions camerounaises\n- Solutions concr\u00e8tes\n- JSON valide uniquement"
        }
      },
      "id": "e9a29a03-7020-40a2-9d3e-8cd88a8f2d86",
      "name": "Advice AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        1664,
        0
      ],
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "jsCode": "// \ud83d\udd27 ULTRA-ENHANCED Advice Response Parser v3.0 - Handles Escaped Strings\nconst inputData = $input.all();\nconst aiResponse = inputData[0].json;\n\nconsole.log('=== Ultra-Enhanced Advice Parser v3.0 ===');\nconsole.log('Input Type:', typeof aiResponse);\nconsole.log('Input preview:', JSON.stringify(aiResponse).substring(0, 200));\n\nlet responseText = aiResponse.output || aiResponse.text || JSON.stringify(aiResponse);\nlet advice = null;\nlet parseMethod = 'unknown';\n\n// CRITICAL: Method 0 - Unescape multiply-encoded JSON strings\nlet unescapedText = responseText;\nlet unescapeAttempts = 0;\nconst MAX_UNESCAPE = 5;\n\nwhile (unescapeAttempts < MAX_UNESCAPE && (unescapedText.includes('\\\\n') || unescapedText.includes('\\\\\"'))) {\n  try {\n    // Attempt to parse as JSON string (which automatically unescapes)\n    const parsed = JSON.parse(unescapedText);\n    \n    if (typeof parsed === 'object' && parsed !== null) {\n      // If we got an object, check if it's already our advice\n      if (parsed.advice_type || parsed.main_advice) {\n        advice = parsed;\n        parseMethod = `direct_parse_unescape_${unescapeAttempts}`;\n        console.log(`Found advice object after ${unescapeAttempts} unescape attempts`);\n        break;\n      } else if (parsed.advice && typeof parsed.advice === 'object') {\n        advice = parsed.advice;\n        parseMethod = `nested_advice_unescape_${unescapeAttempts}`;\n        console.log(`Found nested advice after ${unescapeAttempts} unescape attempts`);\n        break;\n      }\n    } else if (typeof parsed === 'string') {\n      // Got a string, need to unescape more\n      unescapedText = parsed;\n      unescapeAttempts++;\n      console.log(`Unescaped level ${unescapeAttempts}`);\n    } else {\n      break;\n    }\n  } catch (e) {\n    // Manual unescaping fallback\n    console.log(`JSON parse failed at level ${unescapeAttempts}, trying manual unescape`);\n    unescapedText = unescapedText\n      .replace(/\\\\n/g, '\\n')\n      .replace(/\\\\\"/g, '\"')\n      .replace(/\\\\'/g, \"'\")\n      .replace(/\\\\t/g, '\\t')\n      .replace(/\\\\r/g, '\\r')\n      .replace(/\\\\\\\\/g, '\\\\');\n    unescapeAttempts++;\n    \n    // Try one more parse attempt\n    try {\n      const retryParse = JSON.parse(unescapedText);\n      if (typeof retryParse === 'object' && (retryParse.advice_type || retryParse.main_advice)) {\n        advice = retryParse;\n        parseMethod = `manual_unescape_${unescapeAttempts}`;\n        console.log(`Success after manual unescape ${unescapeAttempts}`);\n        break;\n      } else if (retryParse.advice) {\n        advice = retryParse.advice;\n        parseMethod = `manual_unescape_nested_${unescapeAttempts}`;\n        break;\n      }\n    } catch (e2) {}\n    \n    if (unescapeAttempts >= MAX_UNESCAPE) break;\n  }\n}\n\n// Update responseText with unescaped version for further parsing\nresponseText = unescapedText;\n\n// Method 1: Enhanced JSON object detection with multiple patterns\nif (!advice) {\n  try {\n    const patterns = [\n      /\\{[\\s\\S]*?\"advice_type\"[\\s\\S]*?\"main_advice\"[\\s\\S]*?\\}/,\n      /\\{[\\s\\S]*?\"type_conseil\"[\\s\\S]*?\"conseil_principal\"[\\s\\S]*?\\}/,\n      /\\{[\\s\\S]*?\"advice\"[\\s\\S]*?\"tips\"[\\s\\S]*?\\}/,\n      /\\{[\\s\\S]*?\"main_advice\"[\\s\\S]*?\"quick_tips\"[\\s\\S]*?\\}/\n    ];\n    \n    for (const pattern of patterns) {\n      const jsonMatch = responseText.match(pattern);\n      if (jsonMatch) {\n        let jsonString = jsonMatch[0];\n        \n        // Try multiple parsing strategies\n        const strategies = [\n          () => JSON.parse(jsonString),\n          () => JSON.parse(jsonString.replace(/\\\\n/g, '\\n').replace(/\\\\\"/g, '\"')),\n          () => JSON.parse(jsonString.replace(/[\\n\\r]/g, ' ').replace(/\\s+/g, ' ')),\n          () => { \n            // Remove trailing/leading whitespace and try again\n            const cleaned = jsonString.trim();\n            return JSON.parse(cleaned);\n          }\n        ];\n        \n        for (const strategy of strategies) {\n          try {\n            const parsed = strategy();\n            if (parsed.advice_type || parsed.main_advice || parsed.conseil_principal) {\n              advice = parsed;\n              parseMethod = 'enhanced_json_pattern';\n              console.log('Parsed with enhanced JSON pattern');\n              break;\n            }\n          } catch (e) {}\n        }\n        \n        if (advice) break;\n      }\n    }\n  } catch (e) {\n    console.log('Enhanced JSON parsing failed:', e.message);\n  }\n}\n\n// Method 2: Nested advice object extraction\nif (!advice) {\n  try {\n    const nestedPatterns = [\n      /\\{[\\s\\S]*?\"advice\"\\s*:\\s*\\{[\\s\\S]*?\\}[\\s\\S]*?\\}/,\n      /\\{[\\s\\S]*?\"conseil\"\\s*:\\s*\\{[\\s\\S]*?\\}[\\s\\S]*?\\}/,\n      /\\{[\\s\\S]*?\"data\"\\s*:\\s*\\{[\\s\\S]*?\"advice_type\"[\\s\\S]*?\\}[\\s\\S]*?\\}/\n    ];\n    \n    for (const pattern of nestedPatterns) {\n      const objectMatch = responseText.match(pattern);\n      if (objectMatch) {\n        try {\n          const parsed = JSON.parse(objectMatch[0]);\n          if (parsed.advice && typeof parsed.advice === 'object') {\n            advice = parsed.advice;\n            parseMethod = 'nested_advice_object';\n            console.log('Found nested advice object');\n            break;\n          } else if (parsed.conseil) {\n            advice = parsed.conseil;\n            parseMethod = 'nested_conseil_object';\n            break;\n          } else if (parsed.data && parsed.data.advice_type) {\n            advice = parsed.data;\n            parseMethod = 'nested_data_object';\n            break;\n          }\n        } catch (e) {}\n      }\n    }\n  } catch (e) {\n    console.log('Nested object parsing failed:', e.message);\n  }\n}\n\n// Method 3: Enhanced markdown code blocks\nif (!advice) {\n  try {\n    const codeBlocks = responseText.match(/```(?:json)?\\s*([\\s\\S]*?)```/g);\n    if (codeBlocks) {\n      for (const block of codeBlocks) {\n        const content = block.replace(/```(?:json)?\\s*|```/g, '').trim();\n        try {\n          const parsed = JSON.parse(content);\n          if (parsed.advice_type || parsed.main_advice || parsed.conseil_principal) {\n            advice = parsed;\n            parseMethod = 'markdown_json_block';\n            console.log('Parsed from markdown JSON block');\n            break;\n          } else if (parsed.advice) {\n            advice = parsed.advice;\n            parseMethod = 'markdown_nested_advice';\n            break;\n          }\n        } catch (e) {}\n      }\n    }\n  } catch (e) {\n    console.log('Markdown blocks parsing failed:', e.message);\n  }\n}\n\n// Method 4: Advanced structured text parsing\nif (!advice) {\n  const structuredAdvice = {\n    advice_type: 'G\u00e9n\u00e9ral',\n    main_advice: '',\n    quick_tips: [],\n    traditional_secrets: [],\n    ingredients_focus: {\n      recommended: [],\n      substitutes: [],\n      avoid: []\n    },\n    step_by_step: [],\n    cultural_context: '',\n    common_mistakes: [],\n    seasonal_notes: '',\n    difficulty_level: 'Interm\u00e9diaire',\n    estimated_time: 'Variable'\n  };\n\n  // Extract main advice from the first substantial paragraph\n  const paragraphs = responseText.split(/\\n\\n+/).filter(p => p.trim().length > 50);\n  if (paragraphs.length > 0) {\n    structuredAdvice.main_advice = paragraphs[0].trim().substring(0, 1000);\n  }\n\n  // Enhanced tips extraction with multiple patterns\n  const tipsPatterns = [\n    /(?:Astuce|Conseil|Tips?)\\s*s?\\s*:?\\s*\\n([\\s\\S]*?)(?:\\n\\n|Secrets?|Erreurs?|$)/i,\n    /(?:Recommandations?)\\s*:?\\s*\\n([\\s\\S]*?)(?:\\n\\n|$)/i,\n    /(?:Points\\s+cl\u00e9s?)\\s*:?\\s*\\n([\\s\\S]*?)(?:\\n\\n|$)/i\n  ];\n  \n  for (const pattern of tipsPatterns) {\n    const tipsMatch = responseText.match(pattern);\n    if (tipsMatch) {\n      structuredAdvice.quick_tips = tipsMatch[1]\n        .split(/\\n/)\n        .filter(line => line.trim().match(/^[-*\u2022]|^\\d+\\./)) \n        .map(line => line.replace(/^[-*\u2022]|^\\d+\\./, '').trim())\n        .filter(tip => tip.length > 15)\n        .slice(0, 6);\n      if (structuredAdvice.quick_tips.length > 0) break;\n    }\n  }\n\n  // Enhanced secrets extraction\n  const secretsPatterns = [\n    /(?:Secret|Tradition|Astuce\\s+de\\s+grand-m\u00e8re)\\s*s?\\s*:?\\s*\\n([\\s\\S]*?)(?:\\n\\n|Ingr\u00e9dients?|Erreurs?|$)/i,\n    /(?:Technique\\s+traditionnelle)\\s*s?\\s*:?\\s*\\n([\\s\\S]*?)(?:\\n\\n|$)/i\n  ];\n  \n  for (const pattern of secretsPatterns) {\n    const secretsMatch = responseText.match(pattern);\n    if (secretsMatch) {\n      structuredAdvice.traditional_secrets = secretsMatch[1]\n        .split(/\\n/)\n        .filter(line => line.trim().match(/^[-*\u2022]|^\\d+\\./)) \n        .map(line => line.replace(/^[-*\u2022]|^\\d+\\./, '').trim())\n        .filter(s => s.length > 20)\n        .slice(0, 4);\n      if (structuredAdvice.traditional_secrets.length > 0) break;\n    }\n  }\n\n  // Enhanced ingredients focus extraction\n  const ingredientsMatch = responseText.match(/(?:Ingr\u00e9dients?)\\s*:?\\s*\\n([\\s\\S]*?)(?:\\n\\n|Erreurs?|$)/i);\n  if (ingredientsMatch) {\n    const ingredientText = ingredientsMatch[1];\n    \n    // Recommended ingredients\n    const recommendedMatch = ingredientText.match(/(?:Recommand\u00e9|Utiliser|Privil\u00e9gier)\\s*:?\\s*([^\\n]*)/i);\n    if (recommendedMatch) {\n      structuredAdvice.ingredients_focus.recommended = recommendedMatch[1]\n        .split(/,|;/)\n        .map(ing => ing.trim())\n        .filter(ing => ing.length > 3);\n    }\n    \n    // Substitutes\n    const substitutesMatch = ingredientText.match(/(?:Substitut|Remplacer|Alternative)\\s*:?\\s*([^\\n]*)/i);\n    if (substitutesMatch) {\n      structuredAdvice.ingredients_focus.substitutes = substitutesMatch[1]\n        .split(/,|;/)\n        .map(sub => sub.trim())\n        .filter(sub => sub.length > 3);\n    }\n  }\n\n  // Enhanced step-by-step extraction\n  const stepsMatch = responseText.match(/(?:\u00c9tapes?|Steps?|M\u00e9thode)\\s*:?\\s*\\n([\\s\\S]*?)(?:\\n\\n|Conseils?|$)/i);\n  if (stepsMatch) {\n    const stepLines = stepsMatch[1]\n      .split(/\\n/)\n      .filter(line => line.trim().match(/^[-*\u2022]|^\\d+\\./)) \n      .slice(0, 5);\n      \n    structuredAdvice.step_by_step = stepLines.map((line, index) => {\n      const cleaned = line.replace(/^[-*\u2022]|^\\d+\\./, '').trim();\n      return {\n        step: index + 1,\n        action: cleaned,\n        tip: ''\n      };\n    }).filter(step => step.action.length > 15);\n  }\n\n  // Enhanced mistakes extraction\n  const mistakesPatterns = [\n    /(?:Erreurs?\\s+courantes?|Mistakes?|\u00c0\\s+\u00e9viter)\\s*:?\\s*\\n([\\s\\S]*?)(?:\\n\\n|$)/i,\n    /(?:Probl\u00e8mes?\\s+fr\u00e9quents?)\\s*:?\\s*\\n([\\s\\S]*?)(?:\\n\\n|$)/i\n  ];\n  \n  for (const pattern of mistakesPatterns) {\n    const mistakesMatch = responseText.match(pattern);\n    if (mistakesMatch) {\n      structuredAdvice.common_mistakes = mistakesMatch[1]\n        .split(/\\n/)\n        .filter(line => line.trim().match(/^[-*\u2022]|^\\d+\\./)) \n        .map(line => line.replace(/^[-*\u2022]|^\\d+\\./, '').trim())\n        .filter(mistake => mistake.length > 20)\n        .slice(0, 4);\n      if (structuredAdvice.common_mistakes.length > 0) break;\n    }\n  }\n\n  // Extract cultural context\n  const culturalMatch = responseText.match(/(?:Culture|Tradition|Cameroun)\\s*:?\\s*([^\\n]{50,})/i);\n  if (culturalMatch) {\n    structuredAdvice.cultural_context = culturalMatch[1].trim();\n  }\n\n  if (structuredAdvice.main_advice || structuredAdvice.quick_tips.length > 0) {\n    advice = structuredAdvice;\n    parseMethod = 'advanced_text_extraction';\n    console.log('Extracted from advanced structured text');\n  }\n}\n\n// Enhanced fallback with comprehensive default advice\nif (!advice) {\n  const query = $('Request Preprocessor').item.json.query || 'question culinaire';\n  const adviceType = $('Request Preprocessor').item.json.advice_type || 'G\u00e9n\u00e9ral';\n  \n  advice = {\n    advice_type: adviceType,\n    main_advice: `Pour r\u00e9ussir parfaitement vos plats camerounais traditionnels, voici des conseils essentiels bas\u00e9s sur les techniques ancestrales de nos grand-m\u00e8res. L'utilisation d'ingr\u00e9dients frais et authentiquement locaux constitue la base fondamentale de toute bonne cuisine camerounaise. Les \u00e9pices doivent \u00eatre dos\u00e9es avec pr\u00e9cision et patience pour respecter l'\u00e9quilibre d\u00e9licat des saveurs. La cuisson lente et attentive permet aux ar\u00f4mes de se d\u00e9velopper pleinement et aux textures d'atteindre leur perfection. N'h\u00e9sitez jamais \u00e0 adapter les recettes selon la disponibilit\u00e9 saisonni\u00e8re des ingr\u00e9dients tout en pr\u00e9servant l'essence traditionnelle du plat.`,\n    quick_tips: [\n      \"Toujours utiliser des ingr\u00e9dients frais et de saison pour une qualit\u00e9 gustative optimale\",\n      \"Respecter scrupuleusement les temps de cuisson traditionnels pour d\u00e9velopper toutes les saveurs\",\n      \"Doser progressivement les \u00e9pices en go\u00fbtant r\u00e9guli\u00e8rement pendant la pr\u00e9paration\",\n      \"Pr\u00e9parer certains ingr\u00e9dients la veille pour optimiser le temps de cuisson\",\n      \"Conserver les restes dans des contenants herm\u00e9tiques au r\u00e9frig\u00e9rateur maximum 3 jours\",\n      \"R\u00e9chauffer les plats doucement pour pr\u00e9server toutes leurs qualit\u00e9s organoleptiques\"\n    ],\n    traditional_secrets: [\n      \"Le secret ancestral: laisser mijoter \u00e0 feu tr\u00e8s doux pour concentrer naturellement tous les ar\u00f4mes\",\n      \"Moudre les \u00e9pices fra\u00eeches juste avant utilisation pour lib\u00e9rer leur parfum maximal\",\n      \"Utiliser exclusivement l'huile de palme rouge authentique pour le go\u00fbt traditionnel inimitable\",\n      \"Remuer avec une cuill\u00e8re en bois pour pr\u00e9server les saveurs et \u00e9viter l'oxydation\"\n    ],\n    ingredients_focus: {\n      recommended: [\"\u00c9pices locales fra\u00eechement moulues\", \"L\u00e9gumes de saison du march\u00e9\", \"Huile de palme rouge authentique\", \"Piments frais selon tol\u00e9rance\", \"Poissons fum\u00e9s traditionnels\"],\n      substitutes: [\"Beurre de cacahu\u00e8te naturel pour remplacer l'huile d'arachide\", \"\u00c9pinards frais pour certaines feuilles traditionnelles non disponibles\", \"Gingembre frais si pas de gingembre s\u00e9ch\u00e9\"],\n      avoid: [\"Ingr\u00e9dients transform\u00e9s industriellement et additifs artificiels\", \"\u00c9pices p\u00e9rim\u00e9es ou de mauvaise qualit\u00e9\", \"Huiles raffin\u00e9es d\u00e9natur\u00e9es\"]\n    },\n    step_by_step: [\n      {step: 1, action: \"Organiser et pr\u00e9parer soigneusement tous les ingr\u00e9dients avant de commencer\", tip: \"Une cuisine bien organis\u00e9e facilite grandement la r\u00e9alisation\"},\n      {step: 2, action: \"Respecter l'ordre traditionnel d'incorporation des diff\u00e9rents ingr\u00e9dients\", tip: \"Certains ingr\u00e9dients n\u00e9cessitent plus de temps pour r\u00e9v\u00e9ler leurs saveurs\"},\n      {step: 3, action: \"Go\u00fbter et ajuster l'assaisonnement de mani\u00e8re progressive et r\u00e9fl\u00e9chie\", tip: \"Il est toujours plus facile d'ajouter des \u00e9pices que d'en retirer\"},\n      {step: 4, action: \"Surveiller attentivement la cuisson et ajuster le feu si n\u00e9cessaire\", tip: \"Chaque feu et chaque ustensile ont leurs particularit\u00e9s\"}\n    ],\n    cultural_context: \"La cuisine camerounaise authentique repr\u00e9sente un patrimoine culturel exceptionnel, refl\u00e9tant la diversit\u00e9 et la richesse des traditions de plus de 250 ethnies diff\u00e9rentes. Chaque r\u00e9gion du Cameroun apporte ses sp\u00e9cialit\u00e9s uniques et ses techniques culinaires sp\u00e9cifiques, transmises fid\u00e8lement de g\u00e9n\u00e9ration en g\u00e9n\u00e9ration depuis des si\u00e8cles. Cette cuisine est bien plus qu'une simple alimentation : elle constitue un v\u00e9ritable lien social et culturel, un moyen d'expression de l'identit\u00e9 et de l'hospitalit\u00e9 l\u00e9gendaire camerounaise.\",\n    common_mistakes: [\n      \"Ne pas laisser mijoter suffisamment longtemps - Solution: Respecter imp\u00e9rativement les temps de cuisson indiqu\u00e9s dans les recettes traditionnelles\",\n      \"Ajouter trop d'\u00e9pices d'un seul coup - Solution: Incorporer les \u00e9pices progressivement en go\u00fbtant r\u00e9guli\u00e8rement pour ajuster\",\n      \"Utiliser des ingr\u00e9dients de qualit\u00e9 m\u00e9diocre - Solution: Privil\u00e9gier syst\u00e9matiquement le frais, le local et l'authentique\",\n      \"Cuire \u00e0 feu trop vif - Solution: Pr\u00e9f\u00e9rer une cuisson douce et patiente pour d\u00e9velopper les ar\u00f4mes\"\n    ],\n    seasonal_notes: \"Adapter intelligemment les recettes selon la disponibilit\u00e9 saisonni\u00e8re des ingr\u00e9dients locaux pour un r\u00e9sultat optimal et un respect authentique des traditions culinaires camerounaises. La saison des pluies offre des l\u00e9gumes-feuilles exceptionnels, tandis que la saison s\u00e8che favorise certains fruits et l\u00e9gumes.\",\n    difficulty_level: \"Interm\u00e9diaire\",\n    estimated_time: \"Variable selon la complexit\u00e9 du plat (30 minutes \u00e0 3 heures)\"\n  };\n  parseMethod = 'comprehensive_fallback';\n  console.log('Using comprehensive fallback advice');\n}\n\n// Enhanced validation and normalization\nif (advice) {\n  // Ensure all required fields exist with proper defaults\n  advice.advice_type = advice.advice_type || advice.type || 'G\u00e9n\u00e9ral';\n  advice.main_advice = advice.main_advice || advice.conseil_principal || advice.advice || 'Conseil culinaire traditionnel camerounais';\n  \n  // CRITICAL: Remove any remaining escape characters from main_advice\n  if (typeof advice.main_advice === 'string') {\n    advice.main_advice = advice.main_advice\n      .replace(/\\\\n/g, ' ')\n      .replace(/\\\\\"/g, '\"')\n      .replace(/\\\\\\\\/g, '\\\\')\n      .replace(/\\s+/g, ' ')\n      .replace(/[*#`]/g, '')\n      .trim();\n  }\n  \n  advice.quick_tips = Array.isArray(advice.quick_tips) ? advice.quick_tips : [];\n  advice.traditional_secrets = Array.isArray(advice.traditional_secrets) ? advice.traditional_secrets : [];\n  advice.common_mistakes = Array.isArray(advice.common_mistakes) ? advice.common_mistakes : [];\n  \n  // Ensure ingredients_focus structure exists\n  if (!advice.ingredients_focus || typeof advice.ingredients_focus !== 'object') {\n    advice.ingredients_focus = {\n      recommended: [],\n      substitutes: [],\n      avoid: []\n    };\n  }\n  \n  // Ensure step_by_step is properly structured\n  if (!Array.isArray(advice.step_by_step)) {\n    advice.step_by_step = [];\n  }\n  \n  // Clean and validate text fields - remove escape sequences\n  advice.cultural_context = (advice.cultural_context || '').replace(/\\\\n/g, ' ').replace(/\\\\\"/g, '\"').replace(/[*#`]/g, '').trim();\n  advice.seasonal_notes = (advice.seasonal_notes || '').replace(/\\\\n/g, ' ').replace(/\\\\\"/g, '\"').replace(/[*#`]/g, '').trim();\n  \n  // Add comprehensive metadata\n  advice.generated_at = new Date().toISOString();\n  advice.language = 'fr';\n  advice.source = 'TchopIA AI Advisor';\n  advice.expertise_level = 'Traditional Cameroonian Cuisine';\n}\n\nconsole.log('Final advice parsed successfully');\nconsole.log('Parse method:', parseMethod);\nconsole.log('Advice type:', advice.advice_type);\nconsole.log('Tips count:', advice.quick_tips.length);\nconsole.log('Secrets count:', advice.traditional_secrets.length);\n\nreturn [{\n  success: true,\n  action: 'cooking_advice',\n  data_type: 'advice',\n  advice: advice,\n  parse_method: parseMethod,\n  timestamp: new Date().toISOString(),\n  metadata: {\n    source: 'sub_workflow_parser',\n    quality: parseMethod.includes('fallback') ? 'default' : 'ai_generated',\n    parser_version: '3.0_ultra_enhanced_unescaping',\n    completeness: {\n      has_main_advice: !!advice.main_advice && advice.main_advice.length > 50,\n      has_tips: advice.quick_tips.length > 0,\n      has_secrets: advice.traditional_secrets.length > 0,\n      has_cultural_context: !!advice.cultural_context,\n      has_structured_steps: advice.step_by_step.length > 0\n    },\n    advice_category: advice.advice_type\n  }\n}];"
      },
      "id": "69fc07f9-aeb3-405c-ad6c-4ca290308afb",
      "name": "Response Parser",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2080,
        -48
      ]
    },
    {
      "parameters": {
        "jsCode": "return [{\n  success: false,\n  action: 'cooking_advice',\n  error: 'generation_failed',\n  message: 'Impossible de g\u00e9n\u00e9rer le conseil',\n  timestamp: new Date().toISOString()\n}];"
      },
      "id": "9a00cf9d-f96a-418f-9bd9-ece44fcabb98",
      "name": "Error Handler",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2064,
        144
      ]
    }
  ],
  "connections": {
    "When Executed by Another Workflow": {
      "main": [
        [
          {
            "node": "Request Preprocessor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GPT-OSS:120b": {
      "ai_languageModel": [
        [
          {
            "node": "Advice AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Request Preprocessor": {
      "main": [
        [
          {
            "node": "Advice AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Advice AI Agent": {
      "main": [
        [
          {
            "node": "Response Parser",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Error Handler",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f46bc964-5145-4c68-a8e7-5a660223d493",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "uMFHRt7rGUhqHNwU",
  "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

advice_generator. Uses executeWorkflowTrigger, lmChatGroq, agent. Event-driven trigger; 6 nodes.

Source: https://github.com/Worketyamo-Students/Danielle_site1_Bootcamp/blob/ae12fcdd0a854493d32954771d0ce7d94e5590b8/n8n-workflows/advice_generator.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

This workflow is designed for marketers, content creators, agencies, and solo founders who want to publish long‑form posts with visuals on autopilot using n8n and AI agents. ​

Tool Http Request, Agent, HTTP Request +27
AI & RAG

suggestion_generator. Uses executeWorkflowTrigger, lmChatGroq, agent. Event-driven trigger; 6 nodes.

Execute Workflow Trigger, Groq Chat, Agent
AI & RAG

recipe_generator. Uses executeWorkflowTrigger, lmChatGroq, agent. Event-driven trigger; 6 nodes.

Execute Workflow Trigger, Groq Chat, Agent
AI & RAG

BoomerBobBot.TP. Uses agent, telegramTrigger, telegram, memoryBufferWindow. Event-driven trigger; 95 nodes.

Agent, Telegram Trigger, Telegram +10
AI & RAG

The AI-Powered Shopify SEO Content Automation is an enterprise-grade workflow that transforms product content creation for e-commerce stores. This sophisticated multi-agent system integrates GPT-4o, C

Perplexity Tool, Memory Buffer Window, Agent +15