
🍎 Grocery Agent Workflow
Description
Categories
🤖 AI & Machine Learning
Nodes Used
n8n-nodes-base.setn8n-nodes-base.switchn8n-nodes-base.telegramn8n-nodes-base.telegramn8n-nodes-base.asanaTooln8n-nodes-base.asanaTooln8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNote
PriceFree
Views0
Last Updated11/28/2025
workflow.json
{
"id": "vGvH6zfx9LuwHfoC",
"meta": {
"instanceId": "78a1670eff69dde15237f8eb0f091c143c10cc5aee229aa0485d9ac17fc48ce6",
"templateCredsSetupCompleted": true
},
"name": "🍎 Grocery Agent Workflow",
"tags": [],
"nodes": [
{
"id": "2fb8eb78-7430-4d93-b4e2-bc8ef7937887",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-928,
-480
],
"webhookId": "0b400435-c749-49bf-834f-d35b50cf96e1",
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"id": "GroO0akGb3u44nyE",
"name": "Telegram: PA"
}
},
"typeVersion": 1.2
},
{
"id": "5c7d4876-0440-48c4-8c83-b7ef81983d5d",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1536,
-784
],
"parameters": {
"width": 528,
"height": 944,
"content": "## Update Grocery Lists in Asana via Telegram using Natural Language AI\nThis n8n workflow demonstrates how to use AI to update your grocery list in Asana via Telegram chat or voice. \n\n## Use cases\n- Update grocery list details in Asana eg. check or uncheck the items, update expiry dates, update quantities etc.\n\n## How it works\n- Instruct telegram bot (via chat or voice) to update a grocery item using natural language. For example, \"we just bought 10 cartons of milk that expires in 6 months\".\n- If via text, just the text message will be sent to the Grocery Agent.\n- If via voice, voice file will be downloaded then transcribed into text using OpenAI.\n- Once Grocery agent receives the text, it will search the item in your grocery list in Asana. It will then check the item since it's bought, and update the quantity and expiry date accordingly.\n- Once task is done, it will respond with the changes it made and insert a hyperlink to Asana if you want to see it.\n\n## How to set up\n- Set up Telegram bot via Botfather. See setup instructions [here](https://core.telegram.org/bots/tutorial) \n- Setup OpenAI API for transcription services (Credits required) [here](https://openai.com/index/openai-api/)\n- Set up Openrouter account. See details [here](https://openrouter.ai/docs/api-reference/authentication)\n- Set up Asana API using the account where you have your grocery list set in. See details [here](https://developers.asana.com/docs/api-explorer)\n\n## Customization Options\n- You can have other custom fields you use to track other than expiry dates or quantity. For example, food type, date purchased etc. \n\n## Requirements\n- Asana account where you manage your grocery list\n- Telegram bot\n- Open AI account\n- Open Router account\n"
},
"typeVersion": 1
},
{
"id": "d3e3cd4d-e68b-4182-841d-b78ba7b9fd9e",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-992,
-672
],
"parameters": {
"color": 4,
"width": 432,
"height": 464,
"content": "## 1. Trigger\nSetup Telegram bot - details [here](https://core.telegram.org/bots/tutorial).\n"
},
"typeVersion": 1
},
{
"id": "20899615-f262-4916-b11e-025c088b470e",
"name": "Download Voice File",
"type": "n8n-nodes-base.telegram",
"position": [
-480,
-384
],
"webhookId": "69f34549-fd79-4081-b656-2ff293f16b34",
"parameters": {
"fileId": "={{ $json.message.voice.file_id }}",
"resource": "file",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"id": "GroO0akGb3u44nyE",
"name": "Telegram: PA"
}
},
"typeVersion": 1.2
},
{
"id": "f9d25bdc-96b8-420a-956a-2c48d79967e1",
"name": "Get Text Field",
"type": "n8n-nodes-base.set",
"position": [
-384,
-544
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "288d85a5-a000-4ecd-8efd-8249018b9846",
"name": "text",
"type": "string",
"value": "={{ $json.message.text }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "c1777520-3ccf-431a-9fa4-698bda89fcfc",
"name": "Transcribe a recording",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
-288,
-384
],
"parameters": {
"options": {},
"resource": "audio",
"operation": "transcribe"
},
"credentials": {
"openAiApi": {
"id": "bNSgNFwMYVwTQBvV",
"name": "n8n free OpenAI API credits"
}
},
"typeVersion": 1.8
},
{
"id": "71b06cdc-3ef6-4fbd-ba55-ccfc17fb03e1",
"name": "Grocery Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
144,
-544
],
"parameters": {
"text": "={{ $json.text }}",
"options": {
"systemMessage": "=# Overview\nYou are a grocery agent who is excited about updating grocery lists according to requests.\n\n## Tools\n- Use \"Search for Grocery Item\" to search for the specific item(s) in the grocery list\n- Use \"Check or Uncheck Grocery Item\" to check or uncheck the grocery list depending on request\n- Use \"Update Expiry Date & Quantity\" to update the expiry date and quantity of the specific item\n\n\n## Rules\n- Do not assume anything. If unsure, check with user.\n\n## Instructions\n- You must first use \"Search for Grocery Item\" to get the details of the item.\n- If user says \"need\", \"out of\", \"need to top up\", \"add\" or anything that suggests that this item is needed, if item is already in the list, update the task to be unchecked. Alternatively, if item is not in the list, add it into the list.\n- if user says \"just got\", \"bought\", \"have\" or anything that suggests that item has been purchased, use \"Check or Uncheck Grocery Item\" to update the task to be checked or completed. If item is not already in the existing list, add to the list. If item is in the list, then update the task to be completed.\n- As long as user mentions a quantity or an expiry date to the item, use \"Update Expiry Date & Quantity\" tool.\n- At the end of the message, add a hyperlink to the asana grocery page for user. eg. \"Here's the [link](insert link here) for updates made.\"\n\n## Example\n- The query is \"we need eggs\". You would use \"Search for Item in Grocery List\" to check if \"eggs\" are in there. If \"eggs\" are in there AND checked, uncheck the item because the user needs eggs. If \"eggs\" are in there AND unchecked, leave it as is, and notify user accordingly. If \"eggs\" are not in there, add it in and notify user accordingly. In final message to user, add a link to the Asana Grocery page for user to access directly if needed. \n- The query is \"we just bought 6 cartons of oat milk that expires 1 june 2026\". You would use \"Search for Item in Grocery List\" to check if \"oat milk\" are in there. If \"oat milk\" is in there AND checked, leave it as is and notify user accordingly. If \"oat milk\" is in there AND unchecked, check the item. If \"oat milk\" is not in there, add it in and notify user accordingly. Since there is a quantity and expiry date, use \"Update Expiry Date & Quantity\" to update the expiry date to 1 June 2026 and quantity to 6 accordingly. In final message to user, add a link to the Asana Grocery page for user to access directly if needed. \n\n## Notes\nFor reference, today's date is {{ $now }}\n"
},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "b7fa365d-0877-43d0-9cd6-0c5d5023f0c4",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-544,
-672
],
"parameters": {
"color": 5,
"width": 432,
"height": 464,
"content": "## 2. Voice/Text\nSet fields that Agent will take in. For voice files, transcribe to text.\n"
},
"typeVersion": 1
},
{
"id": "183e4683-17b4-4c04-b8ad-fb4d15fb8dbe",
"name": "GPT 4o mini",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"position": [
-48,
-368
],
"parameters": {
"model": "openai/gpt-4o-mini",
"options": {}
},
"credentials": {
"openRouterApi": {
"id": "8YhGo1rl7F0epmIo",
"name": "OpenRouter account"
}
},
"typeVersion": 1
},
{
"id": "60dc16fe-3bf1-4967-bef8-75fcb8931651",
"name": "Search for Grocery Item",
"type": "n8n-nodes-base.asanaTool",
"position": [
128,
-368
],
"parameters": {
"operation": "search",
"workspace": "1208616855003281",
"authentication": "oAuth2",
"searchTaskProperties": {
"text": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Text', ``, 'string') }}"
}
},
"credentials": {
"asanaOAuth2Api": {
"id": "XNxBVunK2x0PeTsm",
"name": "Asana account"
}
},
"typeVersion": 1
},
{
"id": "d46489de-29b9-4ade-a867-d0272b34dada",
"name": "Check or Uncheck Grocery Items",
"type": "n8n-nodes-base.asanaTool",
"position": [
304,
-368
],
"parameters": {
"id": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Task_ID', ``, 'string') }}",
"operation": "update",
"authentication": "oAuth2",
"otherProperties": {
"completed": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Completed', ``, 'boolean') }}"
}
},
"credentials": {
"asanaOAuth2Api": {
"id": "XNxBVunK2x0PeTsm",
"name": "Asana account"
}
},
"typeVersion": 1
},
{
"id": "3d6dd43b-7d8f-4377-85ac-ac1649372d82",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
-672
],
"parameters": {
"color": 3,
"width": 720,
"height": 464,
"content": "## 3. Grocery Updates\nAgent takes in instructions which includes the grocery item, quantity and expiry date to be updated. It will first search for the item, then check/uncheck it, then update the quantity and expiry date."
},
"typeVersion": 1
},
{
"id": "ac1b8783-7997-4dd0-b73b-75b0dc51651b",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
640,
-672
],
"parameters": {
"color": 4,
"width": 320,
"height": 464,
"content": "## 4. Response\nReply will summarise what was updated and include a hyperlink to Asana if you wish to see it directly in Asana."
},
"typeVersion": 1
},
{
"id": "1e6e953d-753c-43a7-b8ed-32d3f4b55c44",
"name": "Reply in Chat",
"type": "n8n-nodes-base.telegram",
"position": [
752,
-464
],
"webhookId": "72c93971-2254-4f0e-a3d2-f44d8f90df54",
"parameters": {
"text": "={{ $json.output }}",
"chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
"additionalFields": {
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"id": "GroO0akGb3u44nyE",
"name": "Telegram: PA"
}
},
"typeVersion": 1.2
},
{
"id": "c13c8083-7339-47ef-9d0a-bda7ba44fb70",
"name": "Update Expiry Date & Qty",
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
"position": [
480,
-368
],
"parameters": {
"workflowId": {
"__rl": true,
"mode": "list",
"value": "6xj0T4s40s9NgWjC",
"cachedResultName": "🍎 Update Expiry & Quantity"
},
"description": "Call this tool to update expiry date or quantity of items",
"workflowInputs": {
"value": {
"TaskID": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('TaskID', `this is the item whose expiry date and quantity needs to be updated`, 'number') }}",
"QuantityValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('QuantityValue', `this is the quantity to be updated`, 'number') }}",
"ExpiryDateValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('ExpiryDateValue', `this is the expiry date (without the time) to be updated`, 'string') }}"
},
"schema": [
{
"id": "TaskID",
"type": "number",
"display": true,
"required": false,
"displayName": "TaskID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ExpiryDateValue",
"display": true,
"required": false,
"displayName": "ExpiryDateValue",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "QuantityValue",
"type": "number",
"display": true,
"required": false,
"displayName": "QuantityValue",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
}
},
"typeVersion": 2.2
},
{
"id": "5e54818e-0699-4790-b867-0f8d150c75e5",
"name": "Route Text or Voice",
"type": "n8n-nodes-base.switch",
"position": [
-736,
-480
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "Text",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e73aaadf-ae52-4fef-b4d7-bb51a2f35c39",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.message.text }}",
"rightValue": ""
}
]
},
"renameOutput": true
},
{
"outputKey": "Voice",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "3ba5e049-2039-4001-adb6-09c654bb9b38",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.message.voice.file_id }}",
"rightValue": ""
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.2
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "ac31830f-0085-4a52-8a97-9648b1ba48dc",
"connections": {
"GPT 4o mini": {
"ai_languageModel": [
[
{
"node": "Grocery Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Grocery Agent": {
"main": [
[
{
"node": "Reply in Chat",
"type": "main",
"index": 0
}
]
]
},
"Get Text Field": {
"main": [
[
{
"node": "Grocery Agent",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger": {
"main": [
[
{
"node": "Route Text or Voice",
"type": "main",
"index": 0
}
]
]
},
"Download Voice File": {
"main": [
[
{
"node": "Transcribe a recording",
"type": "main",
"index": 0
}
]
]
},
"Route Text or Voice": {
"main": [
[
{
"node": "Get Text Field",
"type": "main",
"index": 0
}
],
[
{
"node": "Download Voice File",
"type": "main",
"index": 0
}
]
]
},
"Transcribe a recording": {
"main": [
[
{
"node": "Grocery Agent",
"type": "main",
"index": 0
}
]
]
},
"Search for Grocery Item": {
"ai_tool": [
[
{
"node": "Grocery Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Update Expiry Date & Qty": {
"ai_tool": [
[
{
"node": "Grocery Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Check or Uncheck Grocery Items": {
"ai_tool": [
[
{
"node": "Grocery Agent",
"type": "ai_tool",
"index": 0
}
]
]
}
}
}