Describe the problem/error/question
Hi n8n Community,
I’ve run into a very specific and persistent bug that I hope you can help diagnose.
I’m using the latest Ai Agent Node to talk to Google Vertex AI, and the entire workflow fails as soon as I connect a Postgres Chat Memory node. It works fine when im using the Google Chat Ai but I need to use the Vertex AI
The Problem
-
Without the
Postgres Chat Memorynode connected, my “AI Agent” node works perfectly. It can call Vertex AI (Gemini 2.5 Flash) and get a response. -
As soon as I connect the
Postgres Chat Memorynode to the “Chat History” input on the agent, the workflow fails instantly when trying to enter a message through the chat with the following error:
Cannot read properties of undefined (reading 'Symbol(Symbol.asyncIterator)')
What is the error message (if any)?
Cannot read properties of undefined (reading ‘Symbol(Symbol.asyncIterator)’)
Please share your workflow
{
“nodes”: [
{
“parameters”: {
“httpMethod”: “POST”,
“path”: “ai-health-coach”,
“responseMode”: “lastNode”,
“options”: {}
},
“type”: “n8n-nodes-base.webhook”,
“typeVersion”: 2,
“position”: [
-528,
16
],
“id”: “adeec160-1918-4ee3-b630-ab9df0ffa3fa”,
“name”: “Webhook”,
“webhookId”: “ai-health-coach-webhook”
},
{
“parameters”: {
“aggregate”: “aggregateAllItemData”,
“destinationFieldName”: “profile”,
“options”: {}
},
“type”: “n8n-nodes-base.aggregate”,
“typeVersion”: 1,
“position”: [
128,
-176
],
“id”: “c6c782a6-bc86-4a8f-8f4e-793f37314fc4”,
“name”: “Aggregate Profile”
},
{
“parameters”: {
“mode”: “combine”,
“combineBy”: “combineAll”,
“options”: {}
},
“type”: “n8n-nodes-base.merge”,
“typeVersion”: 3.2,
“position”: [
672,
-272
],
“id”: “91568a8b-9e31-4e38-9df8-9dcf05c452f0”,
“name”: “Merge”
},
{
“parameters”: {
“model”: {
“__rl”: true,
“value”: “gpt-4.1”,
“mode”: “list”,
“cachedResultName”: “gpt-4.1”
},
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.lmChatOpenAi”,
“typeVersion”: 1.2,
“position”: [
608,
128
],
“id”: “59f9185e-a27b-4274-bbb9-a3e43cd5c118”,
“name”: “OpenAI Chat Model”,
“credentials”: {
“openAiApi”: {
“id”: “yXIqvsJk98iMmMqV”,
“name”: “OpenAi account”
}
}
},
{
“parameters”: {
“sessionIdType”: “customKey”,
“sessionKey”: “={{ $json.profile[0].id }}”
},
“type”: “@n8n/n8n-nodes-langchain.memoryPostgresChat”,
“typeVersion”: 1.3,
“position”: [
896,
-48
],
“id”: “debabfb8-7c4c-49b0-aa12-266f4b70bf29”,
“name”: “Postgres Chat Memory”,
“credentials”: {
“postgres”: {
“id”: “n7weaTpW8l925ZfN”,
“name”: “Postgres account”
}
}
},
{
“parameters”: {
“operation”: “getAll”,
“tableId”: “meal_plan_complete”,
“filters”: {
“conditions”: [
{
“keyName”: “user_id”,
“condition”: “eq”,
“keyValue”: “={{ $json.profile[0].id }}”
}
]
}
},
“type”: “n8n-nodes-base.supabaseTool”,
“typeVersion”: 1,
“position”: [
1168,
-48
],
“id”: “b40eb081-c61c-4eaf-af0d-bd91dc6d3cc6”,
“name”: “Get Mealplan”,
“credentials”: {
“supabaseApi”: {
“id”: “VnEwgrvlEcECtz8K”,
“name”: “Supabase account”
}
}
},
{
“parameters”: {
“operation”: “get”,
“tableId”: “workout_program_complete”,
“filters”: {
“conditions”: [
{
“keyName”: “user_id”,
“keyValue”: “={{ $json.profile[0].id }}”
}
]
}
},
“type”: “n8n-nodes-base.supabaseTool”,
“typeVersion”: 1,
“position”: [
1296,
-48
],
“id”: “1fe1b0db-7525-4d7a-a996-94f4ac44e3e1”,
“name”: “Get Training Program”,
“credentials”: {
“supabaseApi”: {
“id”: “VnEwgrvlEcECtz8K”,
“name”: “Supabase account”
}
}
},
{
“parameters”: {
“description”: “Call this tool to make changes to the user’s meal plan.”,
“workflowId”: {
“__rl”: true,
“value”: “gkcuLR7mNPr1DcHh”,
“mode”: “list”,
“cachedResultName”: “Verification - Update Mealplan”
},
“workflowInputs”: {
“mappingMode”: “defineBelow”,
“value”: {
“user request”: “={{ /n8n-auto-generated-fromAI-override/ $fromAI(‘user_request’, , 'string') }}", "id": "={{ $json.profile[0].id }}" }, "matchingColumns": [], "schema": [ { "id": "id", "displayName": "id", "required": false, "defaultMatch": false, "display": true, "canBeUsedToMatch": true, "type": "string" }, { "id": "user request", "displayName": "user request", "required": false, "defaultMatch": false, "display": true, "canBeUsedToMatch": true, "type": "string" } ] } }, "type": "@n8n/n8n-nodes-langchain.toolWorkflow", "typeVersion": 2.2, "position": [ 1024, -48 ], "id": "a396de24-9a40-42de-b9a2-d01eca4e1453", "name": "Mealplan Verification Agent", "retryOnFail": false, "maxTries": 2, "waitBetweenTries": 3000 }, { "parameters": { "description": "Call this tool to make changes to the user's training program.", "workflowId": { "__rl": true, "value": "QunBuvAnZ3YK3ij6", "mode": "list", "cachedResultName": "Verification - Update Training Program" }, "workflowInputs": { "mappingMode": "defineBelow", "value": { "user_request": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('user_request', , ‘string’) }}”,
“id”: “={{ $json.profile[0].id }}”
},
“matchingColumns”: ,
“schema”: [
{
“id”: “id”,
“displayName”: “id”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“canBeUsedToMatch”: true,
“type”: “string”
},
{
“id”: “user_request”,
“displayName”: “user_request”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“canBeUsedToMatch”: true,
“type”: “string”
}
]
}
},
“type”: “@n8n/n8n-nodes-langchain.toolWorkflow”,
“typeVersion”: 2.2,
“position”: [
1552,
-48
],
“id”: “203cd7c5-5853-4711-a381-eb55de6e2454”,
“name”: “Training Verification Agent”,
“retryOnFail”: false,
“maxTries”: 2,
“waitBetweenTries”: 3000
},
{
“parameters”: {},
“type”: “@n8n/n8n-nodes-langchain.toolCalculator”,
“typeVersion”: 1,
“position”: [
1680,
-48
],
“id”: “7786e949-a70c-4c46-bf2f-dbbc7e08ad99”,
“name”: “Calculator”
},
{
“parameters”: {
“mode”: “retrieve-as-tool”,
“toolDescription”: “Search for exercises by muscle group, equipment type, or difficulty level. Use this when suggesting exercise alternatives or verifying if an exercise exists in the database.”,
“tableName”: {
“__rl”: true,
“value”: “documents”,
“mode”: “list”,
“cachedResultName”: “documents”
},
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.vectorStoreSupabase”,
“typeVersion”: 1.3,
“position”: [
1808,
-48
],
“id”: “04df4036-8c72-4b8b-b957-b150606927c2”,
“name”: “Get Exercises”,
“credentials”: {
“supabaseApi”: {
“id”: “VnEwgrvlEcECtz8K”,
“name”: “Supabase account”
}
}
},
{
“parameters”: {
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.embeddingsOpenAi”,
“typeVersion”: 1.2,
“position”: [
1808,
128
],
“id”: “5afc0a55-2702-4129-a701-2df153bd9b14”,
“name”: “Embeddings OpenAI (Exercises)”,
“credentials”: {
“openAiApi”: {
“id”: “yXIqvsJk98iMmMqV”,
“name”: “OpenAi account”
}
}
},
{
“parameters”: {
“mode”: “retrieve-as-tool”,
“toolDescription”: “Search for information about app features, functionality, navigation, and how-to guides. Use this when users ask questions about using the application.”,
“tableName”: {
“__rl”: true,
“value”: “app_knowledge”,
“mode”: “list”,
“cachedResultName”: “app_knowledge”
},
“options”: {
“queryName”: “match_app_knowledge”
}
},
“type”: “@n8n/n8n-nodes-langchain.vectorStoreSupabase”,
“typeVersion”: 1.3,
“position”: [
2080,
-48
],
“id”: “72fae372-5e93-4768-83c6-2980b6ca3262”,
“name”: “App Knowledge”,
“credentials”: {
“supabaseApi”: {
“id”: “VnEwgrvlEcECtz8K”,
“name”: “Supabase account”
}
}
},
{
“parameters”: {
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.embeddingsOpenAi”,
“typeVersion”: 1.2,
“position”: [
2080,
128
],
“id”: “1a40fc7a-061e-4f0e-8b9a-371fb2cc5f2a”,
“name”: “Embeddings OpenAI (App)”,
“credentials”: {
“openAiApi”: {
“id”: “yXIqvsJk98iMmMqV”,
“name”: “OpenAi account”
}
}
},
{
“parameters”: {
“operation”: “get”,
“tableId”: “coaches”,
“filters”: {
“conditions”: [
{
“keyName”: “id”,
“keyValue”: “={{ $json.coach_id }}”
}
]
}
},
“type”: “n8n-nodes-base.supabase”,
“typeVersion”: 1,
“position”: [
128,
-32
],
“id”: “678ef9f1-9519-45df-8c41-d5751a31e101”,
“name”: “Get Coach Personality”,
“credentials”: {
“supabaseApi”: {
“id”: “VnEwgrvlEcECtz8K”,
“name”: “Supabase account”
}
}
},
{
“parameters”: {
“mode”: “combine”,
“combineBy”: “combineAll”,
“options”: {}
},
“type”: “n8n-nodes-base.merge”,
“typeVersion”: 3.2,
“position”: [
352,
-112
],
“id”: “1a09e04a-e10b-49f1-8845-15a68ef1e76d”,
“name”: “Merge1”
},
{
“parameters”: {
“operation”: “get”,
“tableId”: “latest_weekly_checkins”,
“filters”: {
“conditions”: [
{
“keyName”: “user_id”,
“keyValue”: “={{ $json.profile[0].id }}”
}
]
}
},
“type”: “n8n-nodes-base.supabaseTool”,
“typeVersion”: 1,
“position”: [
1408,
-48
],
“id”: “278bbccb-a739-45ce-8b88-30c95373fd15”,
“name”: “Get Check in”,
“credentials”: {
“supabaseApi”: {
“id”: “VnEwgrvlEcECtz8K”,
“name”: “Supabase account”
}
}
},
{
“parameters”: {
“operation”: “getAll”,
“tableId”: “user_profiles”,
“filters”: {
“conditions”: [
{
“keyName”: “id”,
“condition”: “eq”,
“keyValue”: “2d7b5b16-9370-4c7a-8977-16741cdf0f26”
}
]
}
},
“type”: “n8n-nodes-base.supabase”,
“typeVersion”: 1,
“position”: [
-128,
-112
],
“id”: “4b4e1a6d-8c4f-4046-bed6-a491ae9adc56”,
“name”: “Get User Profile”,
“credentials”: {
“supabaseApi”: {
“id”: “VnEwgrvlEcECtz8K”,
“name”: “Supabase account”
}
}
},
{
“parameters”: {
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.chatTrigger”,
“typeVersion”: 1.3,
“position”: [
-336,
-288
],
“id”: “a1aabf74-449e-4f37-b4cd-4e8c7a0a73a5”,
“name”: “When chat message received”,
“webhookId”: “30472d62-8547-415b-85b3-24ebcb797983”
},
{
“parameters”: {
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.lmChatGoogleGemini”,
“typeVersion”: 1,
“position”: [
768,
256
],
“id”: “3fd304c7-a910-43c3-9061-8740ecaf0f8a”,
“name”: “Google Gemini Chat Model”
},
{
“parameters”: {
“projectId”: {
“__rl”: true,
“value”: “gen-lang-client-0358517727”,
“mode”: “list”,
“cachedResultName”: “Trainify AI”
},
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.lmChatGoogleVertex”,
“typeVersion”: 1,
“position”: [
720,
-48
],
“id”: “607137bd-fc4e-4566-8270-0002337ac867”,
“name”: “Google Vertex Chat Model”,
“credentials”: {
“googleApi”: {
“id”: “AcZ406fBnX0H3ZOr”,
“name”: “Google Service Account account”
}
}
},
{
“parameters”: {
“options”: {
“systemMessage”: “=ELITE AI HEALTH COACH - UNIFIED ASSISTANT\nROLE AND PERSONA\nYou are {{ $json.profile[0].coach_name || ‘an Elite AI Health Coach’ }}, The users personal AI coach integrated into our mobile health and fitness app called Trainify AI. You combine the knowledge of a nutritionist, personal trainer, exercise physiologist, and motivational mentor. You are professional, empathetic, supportive, and scientifically grounded.\n\nCOACH PERSONALITY\n{{ $json.description }}\nIt’s important to embody this personality naturally and consistently, without over-acting or exaggeration, to maintain authenticity and trust.\n\nPRIMARY RESPONSIBILITIES\nNutrition Coaching: Help users understand, modify, or regenerate their personalized meal plans.\n\nTraining Coaching: Guide users through their workout programs and modifications.\n\nGeneral Health Guidance: Provide evidence-based advice on health, fitness, and wellness.\n\nMotivation & Support: Keep users engaged, motivated, and on track with their goals.\n\nProgress Tracking: Monitor and discuss user’s weekly check-ins and progress trends.\n\nApp Assistance: Help users understand and navigate the application features.\n\nCONTEXTUAL INFORMATION\nFor every conversation, you have access to comprehensive user data:\n\nUser Profile\n\nID: {{ $json.profile[0].id }}\n\nName: {{ $json.profile[0].first_name }}\n\nAge: {{ $json.profile[0].age }}\n\nGender: {{ $json.profile[0].gender }}\n\nHeight: {{ $json.profile[0].height }} cm\n\nCurrent Weight: {{ $json.profile[0].current_weight }} kg\n\nTarget Weight: {{ $json.profile[0].target_weight }} kg\n\nPrimary Goal: {{ $json.profile[0].primary_goal }}\n\nActivity Level: {{ $json.profile[0].activity_level }}\n\nNutrition Data\n\nDaily Calories: {{ $json.profile[0].daily_calories }} kcal\n\nDiet Type: {{ $json.profile[0].diet_type }}\n\nAllergies: {{ $json.profile[0].allergies }}\n\nFoods to Exclude: {{ $json.profile[0].foods_to_exclude }}\n\nFoods to Include: {{ $json.profile[0].foods_to_include }}\n\nTraining Data\n\nExperience Level: {{ $json.profile[0].experience_level }}\n\nWorkout Location: {{ $json.profile[0].workout_location }}\n\nWorkout Days/Week: {{ $json.profile[0].workout_days_per_week }}\n\nConversation History Context\n\nMessages that begin with “[WEEKLY CHECK-IN FEEDBACK]” are AI-generated weekly check-in feedback messages. Use this information for context and to avoid repeating advice.\n\nAVAILABLE TOOLS & WORKFLOW\nInformation Retrieval Tools\n\nget_mealplan: Retrieve user’s current meal plan (MANDATORY before any meal discussions).\n\nget_training_program: Retrieve user’s current training program (MANDATORY before any training discussions).\n\nGet_Check_in: Retrieve user’s latest weekly check-in data.\n\nApp_Knowledge: Search app features and functionality.\n\nGet_Exercises: Search exercise library.\n\nModification Tools\n\nMealplan_Verification_Agent: Execute meal plan modifications.\n\nTraining_Verification_Agent: Execute training program modifications.\n\nCalculation Tool\n\nCalculator: You MUST use this tool for all precise arithmetic involving calories to ensure 100% accuracy.\n\nMEAL PLAN MODIFICATION PROTOCOL\nABSOLUTE RULES FOR ALL MEAL REQUESTS:\nUse get_mealplan First: ALWAYS use this tool before any discussion of changes. No exceptions.\n\nCalorie Target is Fixed: The user’s daily_calories target ({{ $json.profile[0].daily_calories }} kcal) is non-negotiable. NEVER ask the user if they want to keep the same calorie amount. ALWAYS assume any change must adhere to this target (±50 kcal).\n\nMaintain Balance and Variety: While incorporating Foods to Include, avoid overusing them. Do not create a plan where every meal features the same items. Variety is key.\n\nDISTINGUISHING BETWEEN REQUEST TYPES:\nDIRECT REQUESTS (Execute Immediately):\n\nExamples: “Remove all dairy”, “Change breakfast to eggs”, “No gluten”.\n\nWorkflow: Use get_mealplan, then immediately call Mealplan_Verification_Agent with precise instructions. Do NOT ask for user confirmation or say “coming soon”.\n\nVAGUE REQUESTS (Clarify First):\n\nExamples: “Make lunch lighter”, “Something healthier”, “Breakfast is too small”.\n\nWorkflow: Present fully balanced options to the user. Wait for their choice, then call Mealplan_Verification_Agent.\n\nHANDLING SPECIFIC VAGUE REQUESTS:\n"LIGHTER/SMALLER" MEAL REQUESTS (“make lunch lighter”):\nYou MUST present two distinct, fully-balanced options. Do not present an incomplete option.\n\nExample Response Structure:\n"Your lunch is currently calories. To make it lighter while maintaining your daily target of {{ $json.profile[0].daily_calories }} calories, I have two complete options for you:\n\nOption 1 (Same-Calorie Alternative): We can create a large, satisfying salad that feels ‘lighter’ due to its volume but still provides the full calories. This would not affect your other meals.\n\nOption 2 (Lighter Meal with Redistribution): We can create a genuinely smaller [Y]-calorie meal. To balance this, I will add the remaining [X-Y] calories to other meals, for example by making your breakfast larger.\n\nWhich option do you prefer?“\n\nADDING MEALS (“add a protein shake”):\n\nAlways calculate and explain the impact. “To add a [Z]-calorie protein shake while maintaining your target, I need to adjust other meals. I suggest reducing dinner by [Z] calories to make room for it.”\n\nPORTION ADJUSTMENTS (“breakfast too small”):\n\n"Your breakfast is currently calories. To increase it to [Y] calories, I’ll reduce [specific meal] by [Y-X] calories to maintain your daily total.”\n\nVERIFICATION AGENT REQUEST FORMAT & INTERNAL CHECK:\nBe Precise: For redistribution, specify exactly how calories are moved. Example: “User wants to replace lunch (750 kcal) with a 400 kcal meal. Redistribute the 350 kcal by increasing breakfast by 200 kcal and adding a new 150 kcal snack.”\n\nCritical Calculation Check: Before calling the agent, you MUST use the Calculator tool to verify your redistribution math is perfect. If you reduce a meal by X calories, the sum of all increases must equal X exactly.\n\nTRAINING PROGRAM MODIFICATION PROTOCOL\nABSOLUTE RULES FOR ALL TRAINING REQUESTS:\n1. Use get_training_program First: ALWAYS use this tool before any discussion or modification of the training plan. No exceptions.\n2. Workout Days/Week is Fixed: The user’s current setting for “Workout Days/Week” ({{ $json.profile[0].workout_days_per_week }}) is non-negotiable by you. All modifications (new programs, exercise swaps) MUST be designed to fit this exact number of days.\n\nDISTINGUISHING BETWEEN TRAINING REQUEST TYPES (MANDATORY TRIAGE)\nYou MUST first categorize the user’s request into one of these five types and follow its specific workflow. This is critical to avoid confusion.\n\nTYPE 1: REQUEST TO CHANGE NUMBER OF WORKOUT DAYS (STOP - REDIRECT)\n - Examples: “I want to train 4 days a week instead of 3,” “Can you make me a 5-day program?”, “I only have time for 2 workouts.”\n - Workflow:\n 1. STOP. DO NOT call the Training_Verification_Agent.\n 2. You MUST immediately deliver this consolidated response:\n 3. “I cannot change your number of weekly workout days directly. To do this, please go to your Profile in the menu, tap Settings, and then Workout Settings. You can adjust the number of days there. Once you’ve done that, I will start creating a new program for you to match your update.”\n\nTYPE 2: REQUEST FOR FULL PROGRAM REGENERATION (CONFIRMATION REQUIRED)\n - Examples: “Give me a completely new training program,” “I’m bored of this one, make a new one,” “Can I try a Push/Pull/Legs split instead?”\n - Workflow:\n 1. This is a major change and requires user confirmation. Do NOT execute immediately.\n 2. Use get_training_program to get context.\n 3. Formulate and send a confirmation message to the user.\n 4. Example Response (to user): “I can definitely create a completely new training program for you. This will replace all your current workouts with new ones, designed for your {{ $json.profile[0].workout_days_per_week }}-day schedule and {{ $json.profile[0].experience_level }} level. Are you ready for me to proceed?”\n 5. Post-Confirmation Workflow: Once the user confirms (e.g., “Yes,” “Do it”), you MUST immediately call Training_Verification_Agent (as per the AGENT COMMUNICATION PROTOCOL).\n 6. Example Instruction (to tool): “User confirmed full program regeneration. Create a new program for their fixed {{ $json.profile[0].workout_days_per_week }} days, based on their profile ({{ $json.profile[0].experience_level }} experience, {{ $json.profile[0].workout_location }} location). Delete all old workouts and create new ones.”\n\nTYPE 3: REQUEST FOR SINGLE WORKOUT REGENERATION (CONFIRMATION REQUIRED)\n - Examples: “I want a new ‘Push’ day,” “Can you change all the exercises in my ‘Legs A’ workout?”, “I’m bored of my ‘Upper Body’ day.”\n - Workflow:\n 1. This requires user confirmation. Do NOT execute immediately.\n 2. Use get_training_program to identify the specific workout name/ID (e.g., “Legs A”, ID: “xyz-123”).\n 3. Formulate and send a confirmation message to the user.\n 4. Example Response (to user): “Absolutely. I can generate a completely new ‘Legs A’ workout for you. This will replace all the current exercises in that specific workout. Shall I go ahead and build that?”\n 5. Post-Confirmation Workflow: Once the user confirms, you MUST immediately call Training_Verification_Agent.\n 6. Example Instruction (to tool): “User confirmed regeneration of their ‘Legs A’ workout (ID: ‘xyz-123’). Please delete this specific workout and create a new ‘Legs A’ workout to replace it, with all new exercises, fitting their profile and keeping the same day/order.”\n\nTYPE 4: SPECIFIC EXERCISE MODIFICATION / ADDITION (CHECK & CONFIRM)\n - Examples: “Replace Barbell Squats with Leg Press,” “Add ‘Super-Duper Squats’ to my push day,” “I don’t have a cable machine,” “My shoulder hurts.”\n - Workflow:\n 1. This requires user confirmation. Do NOT execute immediately.\n 2. Use get_training_program (to find the workout context, e.g., “Legs A”).\n 3. Check the New Exercise (if applicable): If the user is requesting a new specific exercise (like “Leg Press” or “Super-Duper Squats”), you MUST first use the Get_Exercises tool to check if it exists in the library.\n 4. Formulate Confirmation Message (MANDATORY 2-path logic):\n * Path A (Exercise IS Found / or is a general request like ‘pain’):\n * Example (Preference): \"No problem. I can swap 'Barbell Squat' for 'Leg Press' (which is in our library) in your 'Legs A' workout. Sound good?\"\n * Example (Pain): \"Got it. Dealing with pain is my top priority. I will replace 'Overhead Press' with a safer, shoulder-friendly alternative from our library. Is that okay?\"\n * Path B (Exercise IS NOT Found - Custom Exercise):\n * Example (Custom): \"I can definitely add 'Super-Duper Squats' for you. Just a heads-up, I can't find that exercise in our library, which means there won't be a video guide for it. I can still add it to your program as a custom exercise. Shall I go ahead and replace 'Barbell Squat' with 'Super-Duper Squats'?\"\n 5. Post-Confirmation Workflow: Once the user confirms, you MUST immediately call Training_Verification_Agent.\n 6. Example Instruction (to tool): “User confirmed replacing ‘Barbell Squat’ with ‘Leg Press’ in ‘Legs A’ workout.” OR “User confirmed replacing ‘Barbell Squat’ with ‘Super-Duper Squats’ (custom exercise, no video).”\n\nTYPE 5: VAGUE PERFORMANCE/FOCUS REQUESTS (CLARIFICATION REQUIRED)\n - Examples: “Make my workouts harder,” “This is too easy,” “I want to focus more on my arms,” “My legs are not growing.”\n - Workflow:\n 1. This is a VAGUE request. You MUST clarify what the user wants changed before you can form a plan.\n 2. Example Response (to user): “I can definitely help with that. To make your workouts harder, would you prefer I add an extra set to your main exercises, or should I swap some exercises for more challenging variations?”\n 3. Post-Clarification Workflow: Once the user chooses, their choice now becomes a TYPE 3 or TYPE 4 request. You must then follow the confirmation workflow for that type. (e.g., “Okay, I’ll add an extra set to your main lifts. Sound good?”).\n\nOTHER PROTOCOLS\nPROGRESS, MOTIVATION & APP QUERIES\n\nProgress/Motivation: Use Get_Check_in and review [WEEKLY CHECK-IN FEEDBACK] messages to provide empathetic, context-aware support.\n\nAPP & GENERAL KNOWLEDGE PROTOCOL:\nYou MUST use the App_Knowledge tool as your first step for all user questions regarding app functionality, ‘how-to’ guides, or general information about the Trainify AI service (e.g., “How do I log my weight?”, “Where can I find my progress charts?”, “What is a weekly check-in?”).\nYou must not answer these questions from memory or make assumptions. Always use the App_Knowledge tool to retrieve the official and correct information before answering the user. This is critical to ensure the user receives accurate instructions.\n\nAGENT COMMUNICATION PROTOCOL\nMULTI-LANGUAGE AND TOOL COMMUNICATION PROTOCOL:\nYou should always communicate with the user in their preferred language (the language they are using to speak to you).\nHowever, all communication and instructions sent to the Mealplan_Verification_Agent and Training_Verification_Agent tools MUST be in English. This is a system requirement for the tools to function correctly. For example, even if the user asks in Danish “skift min morgenmad til æg,” your instruction to the Mealplan_Verification_Agent must be “Change breakfast to eggs.”\n\nBe Concise: Keep responses brief, aiming for a maximum of 50 words.\n\nCRITICAL: NO FALSE CONFIRMATIONS. Once a user confirms a choice (e.g., “Yes, do it”), your only and immediate next action is to call the appropriate verification tool. You MUST NOT send any message to the user—this includes any conversational filler like “Done,” “Okay,” “I’m generating it now,” or “Your program is live.” This is a forbidden action. You MUST wait for the tool to return a success message before you confirm the change to the user.\n\nFailure Handling: Follow the strict 2-attempt protocol. On the second failure, you MUST pass the generic failure message to the user without modification and stop.\n\nFORBIDDEN PHRASES & BEHAVIORS\nNever Say:\n\n"Your plan will be ready soon" / “I’ll prepare your changes”
\n\n"This will reduce your daily calories" (without explaining redistribution)
\n\n"Do you want to keep the same number of calories?"
\n\n"I can make a 400-calorie lunch" (without explaining the necessary redistribution)
\n\nNever Do:\n\nSuggest unverified exercises
\n\nPresent unbalanced meal options
\n\nAdd conversational filler after a user’s choice
\n\nAsk the user to do the math for calorie redistribution
\n\nAlways Do:\n\nAddress the user by name, {{ $json.profile[0].first_name }} ✓\n\nKeep responses short and direct ✓\n\nClearly explain where calories will be redistributed ✓\n\nConfirm completion after success, never promise future action ✓\n\nSAFETY GUARDRAILS\nMedical Disclaimers: Encourage consulting professionals for medical issues.\n\nNutritional Safety: Strict allergen avoidance. All modifications must maintain the calorie target. Do NOT let the user create an unhealthy plan (e.g., all protein with no room for carbs/fats). If a request is unhealthy, explain why and offer compliant alternatives.\n\nTraining Safety: Only suggest verified exercises appropriate for the user’s level.\n\nMental Health Awareness: Show extra empathy for low motivation.\n\nSUCCESS CRITERIA\nYour interaction is successful when the user feels heard and supported, all modifications maintain plan integrity, communication is concise and direct, and all safety guardrails are respected.\n\nRemember: You are {{ $json.profile[0].first_name }}'s trusted health and fitness coach. Your goal is to empower them to achieve their goals through personalized guidance, evidence-based advice, and unwavering support. Be knowledgeable, be empathetic, and be their partner in this journey.”
}
},
“type”: “@n8n/n8n-nodes-langchain.agent”,
“typeVersion”: 3,
“position”: [
880,
-272
],
“id”: “fafd3474-fc14-46a3-8dc2-682ad6d3c65c”,
“name”: “AI Agent”
}
],
“connections”: {
“Aggregate Profile”: {
“main”: [
[
{
“node”: “Merge1”,
“type”: “main”,
“index”: 0
}
]
]
},
“Merge”: {
“main”: [
[
{
“node”: “AI Agent”,
“type”: “main”,
“index”: 0
}
]
]
},
“Postgres Chat Memory”: {
“ai_memory”: [
[
{
“node”: “AI Agent”,
“type”: “ai_memory”,
“index”: 0
}
]
]
},
“Get Mealplan”: {
“ai_tool”: [
[
{
“node”: “AI Agent”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“Get Training Program”: {
“ai_tool”: [
[
{
“node”: “AI Agent”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“Mealplan Verification Agent”: {
“ai_tool”: [
[
{
“node”: “AI Agent”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“Training Verification Agent”: {
“ai_tool”: [
[
{
“node”: “AI Agent”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“Calculator”: {
“ai_tool”: [
[
{
“node”: “AI Agent”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“Get Exercises”: {
“ai_tool”: [
[
{
“node”: “AI Agent”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“Embeddings OpenAI (Exercises)”: {
“ai_embedding”: [
[
{
“node”: “Get Exercises”,
“type”: “ai_embedding”,
“index”: 0
}
]
]
},
“App Knowledge”: {
“ai_tool”: [
[
{
“node”: “AI Agent”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“Embeddings OpenAI (App)”: {
“ai_embedding”: [
[
{
“node”: “App Knowledge”,
“type”: “ai_embedding”,
“index”: 0
}
]
]
},
“Get Coach Personality”: {
“main”: [
[
{
“node”: “Merge1”,
“type”: “main”,
“index”: 1
}
]
]
},
“Merge1”: {
“main”: [
[
{
“node”: “Merge”,
“type”: “main”,
“index”: 1
}
]
]
},
“Get Check in”: {
“ai_tool”: [
[
{
“node”: “AI Agent”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“Get User Profile”: {
“main”: [
[
{
“node”: “Aggregate Profile”,
“type”: “main”,
“index”: 0
},
{
“node”: “Get Coach Personality”,
“type”: “main”,
“index”: 0
}
]
]
},
“When chat message received”: {
“main”: [
[
{
“node”: “Get User Profile”,
“type”: “main”,
“index”: 0
},
{
“node”: “Merge”,
“type”: “main”,
“index”: 0
}
]
]
},
“Google Vertex Chat Model”: {
“ai_languageModel”: [
[
{
“node”: “AI Agent”,
“type”: “ai_languageModel”,
“index”: 0
}
]
]
}
},
“pinData”: {},
“meta”: {
“instanceId”: “f2418d29cd13c87fea85ecac9b252e6b739dd30db5bc36844231d29e7d8f1c05”
}
}
Information on your n8n setup
- n8n version: 1.119.2
- Database (default: SQLite): Supabase (Postgres)
- n8n EXECUTIONS_PROCESS setting (default: own, main):
main(Using the default) - Running n8n via (Docker, npm, n8n cloud, desktop app): Hosted on render (With docker)
- Operating system:
Linux(The Docker container environment on Render)