AutomationFlows β€Ί AI & RAG β€Ί Imessage Food Photo Nutritional Analysis with Gpt-4 Vision & Memory Storage

Imessage Food Photo Nutritional Analysis with Gpt-4 Vision & Memory Storage

ByDavid Harvey @xtgyβœ“ on n8n.io

> πŸ“Œ What it looks like in use:

Webhook triggerβ˜…β˜…β˜…β˜…β˜† complexityAI-powered19 nodesHTTP RequestAgentOpenAI ChatMemory Postgres Chat
AI & RAG Trigger: Webhook Nodes: 19 Complexity: β˜…β˜…β˜…β˜…β˜† AI nodes: yes Added:

This workflow corresponds to n8n.io template #5461 β€” we link there as the canonical source.

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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "22f351db-4581-450b-a260-b50962f4f35a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1220,
        0
      ],
      "parameters": {
        "width": 880,
        "height": 1000,
        "content": "## Using the n8n HTTP Request Node to Send a Blooio.com Message\n\nFollow these steps to configure your existing HTTP Request node in n8n so you can send SMS or email via the Blooio.com API.\n\n---\n\n### 1. Open Your HTTP Request Node\n\n- In your workflow, click on the HTTP Request node you\u2019ve already added (e.g. **Send Message**).\n\n---\n\n### 2. Set Up the Request\n\n| Field                 | Value                                              |\n|-----------------------|----------------------------------------------------|\n| **Request Method**    | `POST`                                             |\n| **URL**               | `https://api.blooio.com/send-message`              |\n| **Response Format**   | `JSON`                                             |\n| **Body Content Type** | `JSON (application/json)`                          |\n\n---\n\n### 3. Add Required Headers\n\nAdd three headers exactly as shown:\n\n```text\nAccept:        application/json\nAuthorization: Bearer YOUR_TOKEN_HERE\nContent-Type:  application/json"
      },
      "typeVersion": 1
    },
    {
      "id": "334e086c-872b-4a75-8a33-aaec66ec3f02",
      "name": "Send Message",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1280,
        780
      ],
      "parameters": {
        "url": "https://api.blooio.com/send-message",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "identifier",
              "value": "={{ $('Receive Message (From Blooio)').item.json.body.message.sender }}"
            },
            {
              "name": "message",
              "value": "={{ $json.output }}"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "d4df3023-17d3-44f1-bafd-1a70a370f98f",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2000,
        980
      ],
      "parameters": {
        "color": 3,
        "width": 780,
        "height": 360,
        "content": "## Message Read Webhook:\n```\n{\n  \"type\": \"updated-message\",\n  \"message\": {\n    \"messageId\": \"218BCBB7-92E5-455B-AF47-380DB39ACD16\",\n    \"content\": \"Test\",\n    \"sender\": \"+11111111111\",\n    \"selfMessage\": true,\n    \"sentAt\": 1750755023004,\n    \"technology\": \"iMessage\",\n    \"delivered\": true,\n    \"deliveredAt\": 1750755023334,\n    \"readAt\": 1750755049887,\n    \"attachments\": [],\n    \"conversation\": null\n  }\n}\n```"
      },
      "typeVersion": 1
    },
    {
      "id": "9330aeee-82ed-4549-9927-c7802a809cd9",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2000,
        380
      ],
      "parameters": {
        "color": 6,
        "width": 780,
        "height": 580,
        "content": "## Message Received Webhook:\n```\n{\n  \"type\": \"new-message\",\n  \"message\": {\n    \"messageId\": \"B525F710-521F-4D39-8C8F-A44BB737A3B6\",\n    \"content\": \"Attached the csv file for you\",\n    \"sender\": \"+11111111111\",\n    \"selfMessage\": false,\n    \"sentAt\": 1750757604774,\n    \"technology\": \"iMessage\",\n    \"delivered\": true,\n    \"deliveredAt\": null,\n    \"readAt\": null,\n    \"attachments\": [\n      {\n        \"id\": \"F933522B-8DC1-47DB-9274-7508B16D15BF\",\n        \"filename\": \"high_volume_b2b_laser_cnc_products.csv\",\n        \"mimeType\": \"text/csv\",\n        \"url\": \"https://bucket.blooio.com/custom-webhook-attachments/-xxxx.csv\",\n        \"size\": 1962,\n        \"expiresAt\": \"2025-07-24T09:33:26.934Z\",\n        \"expiresAtUnix\": 1753349606934\n      }\n    ],\n    \"conversation\": {\n      \"id\": \"iMessage;-;+11111111111\",\n      \"recipient\": \"+11111111111\",\n      \"name\": null\n    }\n  }\n}\n```"
      },
      "typeVersion": 1
    },
    {
      "id": "b7a92947-9617-4639-8c1a-b80242bb3571",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -160,
        780
      ],
      "parameters": {
        "text": "=User message: {{ $('Receive Message (From Blooio)').item.json.body.message.content }}",
        "options": {
          "systemMessage": "<identity>\nYou are a world-class AI Nutrition Analyst trained to estimate nutrition from food photos using visual analysis, expert knowledge, and common food portion assumptions.\n</identity>\n\n<mission>\nYour task is to analyze a single food photo and provide a complete nutritional summary, without asking the user for any additional information. You must visually identify all items, estimate portion sizes, and calculate total calories and nutrients. Your response should be accurate, clear, and formatted as a friendly iMessage-style explanation \u2014 no JSON, no technical markup.\n\n</mission>\n\n<analysis_protocol>\n1. **Identify** all foods and beverages in the image.\n2. **Estimate** portion sizes using visual cues and standard serving sizes.\n3. **Calculate** total:\n   - Calories\n   - Protein\n   - Carbs\n   - Fat\n   - Fiber\n   - Sugar\n   - Sodium\n4. **Score**:\n   - Confidence Score (0.0 to 1.0): How sure you are based on image clarity, food visibility, and assumptions.\n   - Health Score (0 to 10): Nutritional quality based on processing, balance, and content.\n\n</analysis_protocol>\n\n<response_format>\nRespond in a conversational tone. Start by describing the identified meal. Then list the estimated nutrition facts in simple bullet points. Finally, include:\n- A health rating from 0\u201310.\n- A confidence rating from 0.0\u20131.0.\n- A short, friendly rationale for your estimate and assumptions.\n\n\u26a0\ufe0f Do NOT ask the user for input or confirmation.\n\u26a0\ufe0f Do NOT include JSON, markdown, or structured code output.\n\u26a0\ufe0f Speak as if you're texting back a friend with a nutrition summary.\n\nGive the user a day report so far, a week report so far and a month report so far.</response_format>\n\n<error_handling>\nIf the image is unclear or does not show food, reply kindly to get the user to upload a different image or images.\n</error_handling>",
          "passthroughBinaryImages": true
        },
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "79696185-e706-4c36-83c1-8f7294f5ec8b",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -160,
        960
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini",
          "cachedResultName": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "cc4c91c1-aacc-4a43-a530-5f902cb4274f",
      "name": "Postgres Chat Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
      "position": [
        -160,
        1120
      ],
      "parameters": {
        "tableName": "n8n_calorie_tracker",
        "sessionKey": "={{ $('Receive Message (From Blooio)').item.json.body.message.conversation.id }}",
        "sessionIdType": "customKey",
        "contextWindowLength": 200
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "3860f4f4-1af7-4951-a52c-3d7c7f07cb9a",
      "name": "Receive Message (From Blooio)",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1440,
        760
      ],
      "parameters": {
        "path": "receive-event",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2
    },
    {
      "id": "40a29005-81ce-4fea-9572-230d27a79894",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        400,
        400
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "7b06c8a8-c330-45bc-a3a1-5dd1353b8603",
      "name": "If has images, download them",
      "type": "n8n-nodes-base.if",
      "position": [
        -700,
        760
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "551f9536-48c3-4757-a58b-35ee1ef81a80",
              "operator": {
                "type": "array",
                "operation": "lengthGt",
                "rightType": "number"
              },
              "leftValue": "={{ $('Receive Message (From Blooio)').item.json.body.message.attachments }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e3bb4c52-b673-4d97-b9b5-e980349366ec",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        40,
        380
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3
    },
    {
      "id": "f14e056e-2756-4ed9-8233-61fb4a86ee62",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        -280,
        380
      ],
      "parameters": {
        "jsCode": "let output = [];\n\nfor (const item of $input.first().json.body.message.attachments) {\n  output.push({\n    json: {\n      url: item.url\n    }\n  });\n}\n\nreturn output;"
      },
      "typeVersion": 2
    },
    {
      "id": "4bd4284d-fafe-4aca-976e-c822a8170823",
      "name": "AI Agent1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        600,
        780
      ],
      "parameters": {
        "text": "={{ $json.data.toJsonString() }}",
        "options": {
          "systemMessage": "Summarize these messages and give the user a report that will be send in an iMessage. Do not say \"here's the summary\" or anything like that. Just respond with the summary by itself."
        },
        "promptType": "define"
      },
      "typeVersion": 2
    },
    {
      "id": "274b2815-92bf-4a8a-bcd6-98fdb977dfa0",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        260,
        780
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "ddc20f94-42a0-4227-ad11-afb0feb34db5",
      "name": "OpenAI Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        620,
        940
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "21264d57-60f5-4594-b450-07662078b23e",
      "name": "Don't respond to yourself",
      "type": "n8n-nodes-base.if",
      "position": [
        -960,
        760
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cecd3adf-a9e5-41d3-87ae-4a9699bd641b",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              },
              "leftValue": "={{ $json.body.message.selfMessage }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a098d03a-a4af-4b9a-aac2-5f5b57fd30e0",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -360,
        260
      ],
      "parameters": {
        "color": 4,
        "width": 980,
        "height": 400,
        "content": "## Image downloader \n"
      },
      "typeVersion": 1
    },
    {
      "id": "4a009bbd-4457-4bc9-8a03-9de40736f931",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2000,
        -700
      ],
      "parameters": {
        "width": 760,
        "height": 1040,
        "content": "## \ud83d\ude80 Start Here: Blooio Nutrition Tracker Setup\n\nWelcome! Before this n8n workflow can analyze meal photos and send nutrition summaries via SMS or iMessage, follow these steps to get set up:\n\n---\n\n### \u2705 Step 1: Get Your Blooio API Token\n1. Visit [https://blooio.com](https://blooio.com)\n2. Sign up for a dedicated instance\n3. Navigate to **Settings \u2192 API Keys**\n4. Generate a new token and **copy** it.\n\n> \ud83d\udd10 Keep it safe! You\u2019ll paste it in the HTTP Request node where it says `YOUR_API_TOKEN`.\n\n---\n\n### \u2705 Step 2: Connect Blooio to This Workflow\nIn the **Send Message** node:\n- Replace the value of the `Authorization` header with:\n\n\n### \u2705 Step 3: Test the Webhook\nSend an iMessage with a meal photo or description to your Blooio-connected number.\n\nThis will:\n- Trigger the `Receive Message (From Blooio)` webhook\n- Analyze the meal using AI\n- Return a nutrition breakdown with daily/weekly/monthly stats\n\n---\n\n### \ud83d\udcf7 What You Can Send\n- Meal photos (ideal!)\n- Text descriptions of meals\n- Multiple items in one image\n\nEnjoy tracking your nutrition effortlessly! \ud83e\udd66\ud83d\udcca\ud83d\udce9"
      },
      "typeVersion": 1
    },
    {
      "id": "eb88206b-19c3-41cb-a409-2b924c780852",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1220,
        -700
      ],
      "parameters": {
        "width": 680,
        "height": 1040,
        "content": "![Description](https://i.imgur.com/bOPrv4H.png)\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Code": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent1": {
      "main": [
        [
          {
            "node": "Send Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "AI Agent1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Postgres Chat Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Don't respond to yourself": {
      "main": [
        [
          {
            "node": "If has images, download them",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If has images, download them": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive Message (From Blooio)": {
      "main": [
        [
          {
            "node": "Don't respond to yourself",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

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

&gt; πŸ“Œ What it looks like in use:

Source: https://n8n.io/workflows/5461/ β€” 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

CLINICAINTEGRAL_secretary. Uses postgres, mcpClientTool, googleDriveTool, toolWorkflow. Webhook trigger; 89 nodes.

Postgres, Mcp Client Tool, Google Drive Tool +14
AI & RAG

Remi 1.1. Uses lmChatOpenAi, memoryPostgresChat, openAi, postgres. Webhook trigger; 89 nodes.

OpenAI Chat, Memory Postgres Chat, OpenAI +7
AI & RAG

'Elena AI' is a powerful n8n workflow that transforms your automation platform into a full-fledged, multi-agent AI hub. πŸ€–βœ¨ By combining Redis state management with specialized β€œtool” sub-workflows, yo

Redis, HTTP Request, Supabase +7
AI & RAG

WhatsApp β†’ AlfaCRM Sales Funnel (Main, v2 Advanced). Uses httpRequest, openAi, agent, lmChatOpenAi. Webhook trigger; 43 nodes.

HTTP Request, OpenAI, Agent +2
AI & RAG

Delivery. Uses memoryPostgresChat, lmChatOpenAi, toolCalculator, redis. Webhook trigger; 37 nodes.

Memory Postgres Chat, OpenAI Chat, Tool Calculator +6