AutomationFlowsAI & RAG › Time Tracker - 15min Ping (template)

Time Tracker - 15min Ping (template)

Time Tracker - 15min Ping (Template). Uses slack, openAi, airtable, httpRequest. Scheduled trigger; 17 nodes.

Cron / scheduled trigger★★★★☆ complexityAI-powered17 nodesSlackOpenAIAirtableHTTP Request
AI & RAG Trigger: Cron / scheduled Nodes: 17 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Airtable → 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
{
  "name": "Time Tracker - 15min Ping (Template)",
  "description": "A customizable workflow that pings for time tracking every 15 minutes, categorizes activities via AI, logs to Airtable, and generates end-of-day reflections.\n\n## Setup Instructions\n\n### 1. Replace Placeholders\n\nBefore importing, update the following in your n8n instance:\n\n- `YOUR_SLACK_USER_ID_HERE` \u2192 Your actual Slack user ID (format: U0A9XXXXXX). Get this from Slack's user profile or use the @mention syntax to find it.\n- `YOUR_AIRTABLE_BASE_ID` \u2192 Your Airtable base ID (format: app...). Find in Airtable URL: https://airtable.com/app{BASE_ID}/...\n- `YOUR_LOGS_TABLE_ID` \u2192 Table ID for daily time logs (format: tbl...). Find in Airtable API docs.\n- `YOUR_REFLECTIONS_TABLE_ID` \u2192 Table ID for EOD reflections (format: tbl...).\n\nAll credential IDs will be auto-populated when you add the nodes to your n8n instance.\n\n### 2. Required Tables in Airtable\n\n**Logs Table** (for 15-min pings):\n- timestamp (DateTime)\n- date (Date)\n- time_slot (Single line text)\n- activity (Long text)\n- type (Single select: Work/Personal)\n- task_value (Single line text)\n- energy (Single line text: Sucks/Gives/Neutral)\n- summary (Single line text)\n- cost (Number)\n\n**Reflections Table** (for EOD summaries):\n- Date (Date)\n- Day Summary (Long text)\n- Leverage Ratio (Percent)\n- Energy Balance (Single select: Net Positive/Balanced/Net Negative)\n- Top Distraction (Single line text)\n- Biggest Win (Single line text)\n- Focus Work Done (Checkbox)\n- Q1-Q3 Dynamic/Priorities/Goal fields (Long text)\n- Key Insight (Long text)\n- Tomorrow Priority (Long text)\n\n### 3. Schedule Configuration\n\nThe workflow runs every 15 minutes from 9 AM to 8 PM UTC. Adjust the cron expression in the \"Every 15 Minutes\" trigger if needed:\n- Current: `0 */15 9-20 * * *` (9 AM - 8 PM)\n- Change 9-20 to your desired hours\n\n### 4. Customization Options\n\n**AI Categorization Prompt** (\"AI Categorize Activity\" node):\n- Edit the context to match your business model\n- Adjust task value categories (low/medium/high)\n- Modify energy evaluation criteria\n\n**EOD Reflection Logic** (\"Build EOD Prompt\" node):\n- Customize the business context and daily requirements\n- Adjust leverage ratio calculations\n- Modify focus work detection keywords\n\n**EOD Questions** (\"Parse EOD\" node):\n- Q1 is dynamically generated per n8n LLM evaluation\n- Q2 and Q3 are static - edit directly in the code if needed\n\n### 5. Testing\n\n1. After import, configure credentials for Slack, OpenAI, and Airtable\n2. Test the \"Send and Wait for Reply\" node by sending a test message to yourself\n3. Manually trigger the EOD webhook to test the reflection flow\n4. Once validated, activate the workflow\n\n---\n\n**Architecture Overview:**\n- **15-min Trigger Loop**: Schedule trigger \u2192 Slack sendAndWait \u2192 AI categorization \u2192 Airtable logging\n- **EOD Reflection Loop**: Webhook trigger \u2192 Query today's logs \u2192 Build dynamic prompt \u2192 OpenAI LLM \u2192 Slack form \u2192 Extract insights \u2192 Airtable logging\n\n**Original Author Notes:**\nThis template was sanitized from a production personal productivity system. All business context has been generalized and credential IDs replaced with placeholders. The core logic (time blocking, AI classification, and structured reflection) is portable to any context.",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 */15 9-20 * * *"
            }
          ]
        }
      },
      "id": "schedule-trigger",
      "name": "Every 15 Minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "time_slot",
              "name": "time_slot",
              "value": "={{ $now.setZone('UTC').toFormat('h:mm a') }}",
              "type": "string"
            },
            {
              "id": "date",
              "name": "date",
              "value": "={{ $now.setZone('UTC').toFormat('yyyy-MM-dd') }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "set-time-slot",
      "name": "Set Time Slot",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        224,
        0
      ]
    },
    {
      "parameters": {
        "operation": "sendAndWait",
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SLACK_USER_ID_HERE"
        },
        "message": "=*Time Check* ({{ $json.time_slot }})\n\nWhat did you do the last 15 min?",
        "responseType": "freeText",
        "options": {
          "limitWaitTime": {
            "values": {
              "resumeAmount": 2
            }
          }
        }
      },
      "id": "slack-send-wait",
      "name": "Send and Wait for Reply",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        448,
        0
      ],
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "condition-1",
                    "leftValue": "={{ $json.data.text }}",
                    "rightValue": "",
                    "operator": {
                      "type": "string",
                      "operation": "notEmpty",
                      "singleValue": true
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "User Responded"
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "id": "check-timeout",
      "name": "Check for Timeout",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        672,
        0
      ]
    },
    {
      "parameters": {},
      "id": "timeout-skip",
      "name": "Timeout Skip",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        960,
        96
      ]
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "messages": {
          "values": [
            {
              "content": "=Categorize this activity for a time audit:\n\nActivity: {{ $json.data.text }}\n\nContext: User is tracking their time allocation. High leverage = strategic work, focus areas, revenue-generating activities. Low leverage = admin, email, manual tasks.\n\nIMPORTANT: If the user mentions a duration like \"last 30 minutes\", \"past 45 min\", \"for an hour\", \"last hour\", extract that duration in minutes. If no duration is mentioned, default to 15.\n\nReturn ONLY valid JSON (no markdown, no code blocks):\n{\"type\": \"Work\" or \"Personal\", \"task_value\": \"low\" or \"medium\" or \"high\", \"energy\": \"draining\" or \"energizing\" or \"neutral\", \"summary\": \"Brief 5-word description\", \"duration_minutes\": number (15, 30, 45, 60, etc)}"
            }
          ]
        },
        "options": {
          "maxTokens": 150,
          "temperature": 0.3
        }
      },
      "id": "ai-categorize",
      "name": "AI Categorize Activity",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        896,
        -96
      ],
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "let aiResponse = $input.first().json.message?.content || $input.first().json.text || '{}';\naiResponse = aiResponse.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\nconst originalText = $('Send and Wait for Reply').first().json.data?.text || '';\nconst dateVal = $('Set Time Slot').first().json.date;\nlet parsed;\ntry { parsed = JSON.parse(aiResponse); } catch (e) { parsed = { type: 'Work', task_value: 'medium', energy: 'neutral', summary: 'Activity logged', duration_minutes: 15 }; }\nconst durationMinutes = parsed.duration_minutes || 15;\nconst numBlocks = Math.ceil(durationMinutes / 15);\nconst valueMap = { 'low': '\ud83d\udcb0', 'medium': '\ud83d\udcb0\ud83d\udcb0', 'high': '\ud83d\udcb0\ud83d\udcb0\ud83d\udcb0\ud83d\udcb0' };\nconst energyMap = { 'draining': 'Sucks \u26a1', 'energizing': 'Gives \u26a1', 'neutral': 'Neutral' };\nconst now = $now.setZone('UTC');\nconst entries = [];\nfor (let i = 0; i < numBlocks; i++) {\n  const blockTime = now.minus({ minutes: (i + 1) * 15 });\n  entries.push({ json: { timestamp: new Date().toISOString(), date: blockTime.toFormat('yyyy-MM-dd'), time_slot: blockTime.toFormat('h:mm a'), activity: originalText, type: parsed.type || 'Work', task_value: valueMap[parsed.task_value] || '\ud83d\udcb0\ud83d\udcb0', energy: energyMap[parsed.energy] || 'Neutral', summary: parsed.summary || 'Activity logged', block_number: i + 1, total_blocks: numBlocks } });\n}\nreturn entries;"
      },
      "id": "parse-response",
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1248,
        -96
      ]
    },
    {
      "parameters": {
        "operation": "create",
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_AIRTABLE_BASE_ID"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_LOGS_TABLE_ID"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "timestamp": "={{ $json.timestamp }}",
            "date": "={{ $json.date }}",
            "time_slot": "={{ $json.time_slot }}",
            "activity": "={{ $json.activity }}",
            "type": "={{ $json.type }}",
            "task_value": "={{ $json.task_value }}",
            "energy": "={{ $json.energy }}",
            "summary": "={{ $json.summary }}",
            "cost": 0
          }
        },
        "options": {
          "typecast": true
        }
      },
      "id": "log-airtable",
      "name": "Log to Airtable",
      "type": "n8n-nodes-base.airtable",
      "typeVersion": 2.1,
      "position": [
        1472,
        -96
      ],
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "path": "eod-reflection",
        "options": {}
      },
      "id": "eod-webhook",
      "name": "EOD Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        400
      ]
    },
    {
      "parameters": {
        "operation": "search",
        "base": {
          "__rl": true,
          "value": "YOUR_AIRTABLE_BASE_ID",
          "mode": "id"
        },
        "table": {
          "__rl": true,
          "value": "YOUR_LOGS_TABLE_ID",
          "mode": "id"
        },
        "filterByFormula": "IS_SAME({date}, TODAY(), 'day')",
        "options": {}
      },
      "id": "query-today",
      "name": "Query Today Logs",
      "type": "n8n-nodes-base.airtable",
      "typeVersion": 2.1,
      "position": [
        224,
        400
      ],
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const logs = $input.all();\nconst sum = logs.map(t => `- ${t.json.time_slot}: ${t.json.activity} (${t.json.task_value||'?'}, ${t.json.energy||'?'})`).join('\\n');\nlet h=0,l=0,up=0,dn=0,sp=false;\nlogs.forEach(t=>{\n  const v=t.json.task_value||'',e=t.json.energy||'',a=(t.json.activity||'').toLowerCase();\n  if(v.includes('\ud83d\udcb0\ud83d\udcb0\ud83d\udcb0\ud83d\udcb0'))h++;else if(v.includes('\ud83d\udcb0'))l++;\n  if(e.includes('Gives'))up++;else if(e.includes('Sucks'))dn++;\n  if(a.includes('focus work')||a.includes('strategic work'))sp=true;\n});\nconst tot=logs.length||1;\nconst rat=Math.round((h/tot)*100);\nconst bal=up>dn?'positive':(dn>up?'negative':'balanced');\n\nconst sys=`You are analyzing today's time logs to generate a personalized end-of-day reflection.\n\nBUSINESS CONTEXT:\n- User is tracking time allocation and leverage\n- Leverage hierarchy: Strategic > Planning > Execution > Admin\n- Goal: Improve focus time and energy management\n- Daily requirement: 60-90 min focus work\n\nANALYZE:\n1. Calculate leverage ratio (high-value vs low-value time)\n2. Calculate energy balance\n3. Identify biggest time sink (low-leverage)\n4. Identify biggest win (high-leverage)\n5. Check: Was focus work logged?\n\nGENERATE:\n- A 3-4 sentence day summary (address as \"you\")\n- ONE dynamic question based on today's specific activities\n  - Reference something specific from the logs\n  - Challenge assumptions or patterns\n  - Help identify what to delegate or change\n\nNote: Questions 2 and 3 are fixed - only generate Q1.\n\nReturn ONLY valid JSON (no markdown):\n{\"summary\":\"...\",\"leverage_ratio\":${rat},\"energy_balance\":\"${bal}\",\"top_distraction\":\"...\",\"biggest_win\":\"...\",\"focus_work_done\":${sp},\"q1_dynamic\":\"Your contextual question here...\"}`;\n\nconst usr=`${logs.length} time log entries today:\\n${sum||'None'}\\nMetrics: ${rat}% high-leverage, ${bal} energy, focus work: ${sp}`;\nreturn [{json:{systemPrompt:sys,userPrompt:usr,leverageRatio:rat,energyBalance:bal,focusWork:sp,count:logs.length}}];"
      },
      "id": "build-eod",
      "name": "Build EOD Prompt",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        448,
        400
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "openAiApi",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({model:'gpt-4o',messages:[{role:'system',content:$json.systemPrompt},{role:'user',content:$json.userPrompt}],temperature:0.7}) }}",
        "options": {}
      },
      "id": "eod-ai",
      "name": "EOD AI",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        672,
        400
      ],
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "let c=$input.first().json.choices[0].message.content.replace(/```json\\n?/g,'').replace(/```\\n?/g,'').trim();\nlet p;\ntry{p=JSON.parse(c);}\ncatch{p={summary:c,leverage_ratio:0,energy_balance:'unknown',top_distraction:'N/A',biggest_win:'N/A',focus_work_done:false,q1_dynamic:'What went well today?'};}\n\nconst q2 = \"What changed in your priorities today? Any achievements or blockers?\";\nconst q3 = \"What's your most important goal right now? What's the one action that would move it forward tomorrow?\";\n\nconst msg=`\ud83d\udcca *Here's your day:*\\n\\n${p.summary}\\n\\n*Metrics:* ${p.leverage_ratio}% leverage | ${p.energy_balance} energy | Focus work: ${p.focus_work_done?'\u2705':'\u274c'}\\n*Top distraction:* ${p.top_distraction}\\n*Biggest win:* ${p.biggest_win}\\n\\n---\\n\\n*Q1:* ${p.q1_dynamic}\\n\\n*Q2:* ${q2}\\n\\n*Q3:* ${q3}\\n\\n_Reply with your answers (A1, A2, A3 or just numbered)._`;\n\nreturn [{json:{...p,q1:p.q1_dynamic,q2:q2,q3:q3,slackMessage:msg}}];"
      },
      "id": "parse-eod",
      "name": "Parse EOD",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        896,
        400
      ]
    },
    {
      "parameters": {
        "operation": "sendAndWait",
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SLACK_USER_ID_HERE"
        },
        "message": "={{ $json.slackMessage }}",
        "responseType": "customForm",
        "defineForm": "json",
        "jsonOutput": "[\n  {\n    \"fieldLabel\": \"A1: Answer to Q1 (above)\",\n    \"fieldType\": \"textarea\",\n    \"requiredField\": true\n  },\n  {\n    \"fieldLabel\": \"A2: Priority Update\",\n    \"fieldType\": \"textarea\",\n    \"requiredField\": true\n  },\n  {\n    \"fieldLabel\": \"A3: Top Goal Action\",\n    \"fieldType\": \"textarea\",\n    \"requiredField\": true\n  }\n]",
        "options": {
          "limitWaitTime": {
            "values": {
              "resumeAmount": 4
            }
          }
        }
      },
      "id": "eod-slack",
      "name": "EOD Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        1120,
        400
      ],
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const formData = $json.data || $json;\nconst prev = $('Parse EOD').first().json;\n\nconst a1 = formData['A1: Answer to Q1 (above)'] || formData.a1 || '';\nconst a2 = formData['A2: Priority Update'] || formData.a2 || '';\nconst a3 = formData['A3: Top Goal Action'] || formData.a3 || '';\n\nconst tp = a3.substring(0, 100) || 'Not specified';\n\nconst allText = [a1, a2, a3].filter(x => x).join(' ');\nconst sentences = allText.split(/[.!?]/).filter(s => s.trim().length > 10);\nconst ki = sentences[0]?.trim().substring(0, 100) || 'No insight captured';\n\nreturn [{\n  json: {\n    date: new Date().toISOString().split('T')[0],\n    daySummary: prev.summary,\n    leverageRatio: prev.leverage_ratio / 100,\n    energyBalance: prev.energy_balance === 'positive' ? 'Net Positive' : (prev.energy_balance === 'negative' ? 'Net Negative' : 'Balanced'),\n    topDistraction: prev.top_distraction,\n    biggestWin: prev.biggest_win,\n    focusWorkDone: prev.focus_work_done,\n    q1Dynamic: prev.q1,\n    a1Dynamic: a1,\n    q2Priorities: prev.q2,\n    a2Priorities: a2,\n    q3Goal: prev.q3,\n    a3Goal: a3,\n    keyInsight: ki,\n    tomorrowPriority: tp\n  }\n}];"
      },
      "id": "extract-ins",
      "name": "Extract Insights",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1344,
        400
      ]
    },
    {
      "parameters": {
        "operation": "create",
        "base": {
          "__rl": true,
          "value": "YOUR_AIRTABLE_BASE_ID",
          "mode": "id"
        },
        "table": {
          "__rl": true,
          "value": "YOUR_REFLECTIONS_TABLE_ID",
          "mode": "id"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Date": "={{ $json.date }}",
            "Day Summary": "={{ $json.daySummary }}",
            "Leverage Ratio": "={{ $json.leverageRatio }}",
            "Energy Balance": "={{ $json.energyBalance }}",
            "Top Distraction": "={{ $json.topDistraction }}",
            "Biggest Win": "={{ $json.biggestWin }}",
            "Focus Work Done": "={{ $json.focusWorkDone }}",
            "Q1 Dynamic": "={{ $json.q1Dynamic }}",
            "A1 Dynamic": "={{ $json.a1Dynamic }}",
            "Q2 Priorities": "={{ $json.q2Priorities }}",
            "A2 Priorities": "={{ $json.a2Priorities }}",
            "Q3 Goal": "={{ $json.q3Goal }}",
            "A3 Goal": "={{ $json.a3Goal }}",
            "Key Insight": "={{ $json.keyInsight }}",
            "Tomorrow Priority": "={{ $json.tomorrowPriority }}"
          }
        },
        "options": {
          "typecast": true
        }
      },
      "id": "log-refl",
      "name": "Log Reflection",
      "type": "n8n-nodes-base.airtable",
      "typeVersion": 2.1,
      "position": [
        1568,
        400
      ],
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "select": "user",
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SLACK_USER_ID_HERE"
        },
        "text": "=\u2705 Logged! Your priority tomorrow: {{ $json.tomorrowPriority || 'Check your reflection' }}. Good night! \ud83c\udf19",
        "otherOptions": {}
      },
      "id": "eod-done",
      "name": "EOD Done",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        1792,
        400
      ],
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Every 15 Minutes": {
      "main": [
        [
          {
            "node": "Set Time Slot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Time Slot": {
      "main": [
        [
          {
            "node": "Send and Wait for Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send and Wait for Reply": {
      "main": [
        [
          {
            "node": "Check for Timeout",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for Timeout": {
      "main": [
        [
          {
            "node": "AI Categorize Activity",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Timeout Skip",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Categorize Activity": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Log to Airtable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "EOD Webhook": {
      "main": [
        [
          {
            "node": "Query Today Logs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Query Today Logs": {
      "main": [
        [
          {
            "node": "Build EOD Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build EOD Prompt": {
      "main": [
        [
          {
            "node": "EOD AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "EOD AI": {
      "main": [
        [
          {
            "node": "Parse EOD",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse EOD": {
      "main": [
        [
          {
            "node": "EOD Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "EOD Slack": {
      "main": [
        [
          {
            "node": "Extract Insights",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Insights": {
      "main": [
        [
          {
            "node": "Log Reflection",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Reflection": {
      "main": [
        [
          {
            "node": "EOD Done",
            "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

Time Tracker - 15min Ping (Template). Uses slack, openAi, airtable, httpRequest. Scheduled trigger; 17 nodes.

Source: https://gist.github.com/meirworkspace99-eng/99803b16e879be3e6e48b29786ea2d60 — 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 automatically fetches product reviews from your WooCommerce store, analyzes the sentiment of each review using AI, stores the results in Airtable and sends a summary of positive, neutral

HTTP Request, OpenAI, Airtable +1
AI & RAG

A scheduled process aggregates content from eight distinct data sources and standardizes all inputs into a unified format. AI models perform sentiment scoring, detect conspiracy or misinformation sign

HTTP Request, OpenAI, Postgres +2
AI & RAG

This workflow automatically turns any audio file uploaded to Google Drive into a complete podcast episode. It handles transcription, content generation, blog drafting, social copy creation, thumbnail

Google Drive Trigger, Google Drive, OpenAI +3
AI & RAG

Imagine a dedicated financial expert tirelessly working behind the scenes, sifting through every transaction, every investment move, and every accounting entry. That's exactly what this automated syst

HTTP Request, Google Sheets, OpenAI +3
AI & RAG

AI-Powered Fake Review Detection Workflow Using n8n & Airtable. Uses httpRequest, airtable, openAi, slack. Webhook trigger; 27 nodes.

HTTP Request, Airtable, OpenAI +1