AutomationFlowsWeb Scraping › Weekly Business Status Report (local Llm)

Weekly Business Status Report (local Llm)

Weekly Business Status Report (local LLM). Uses emailSend, httpRequest. Event-driven trigger; 13 nodes.

Event trigger★★★★☆ complexity13 nodesEmail SendHTTP Request
Web Scraping Trigger: Event Nodes: 13 Complexity: ★★★★☆ Added:

This workflow follows the Emailsend → 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": "Weekly Business Status Report (local LLM)",
  "nodes": [
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -1120,
        -260
      ],
      "id": "6eaee0b1-f210-4b41-807c-1039621cee03",
      "name": "Manual Trigger (dev)",
      "notes": "Manual trigger for local testing only. In production, prefer the Cron trigger."
    },
    {
      "parameters": {
        "triggerTimes": [
          {
            "item": {
              "hour": 8,
              "weekday": "1"
            }
          }
        ]
      },
      "type": "n8n-nodes-base.cron",
      "typeVersion": 1,
      "position": [
        -1120,
        -80
      ],
      "id": "b7d9f1b3-8b5f-4f55-9f7c-1234567890ab",
      "name": "Weekly Schedule (prod)",
      "notes": "Runs every Monday at 08:00 server time. Adjust schedule in n8n UI for client-specific needs."
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        920,
        -260
      ],
      "id": "bf52c7eb-6ca3-4a77-929e-f64167aa28d2",
      "name": "Send email"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "1b5a3a91-86a4-4128-8592-e512d2f28005",
              "name": "highlights",
              "value": "Closed a key client in SaaS vertical; shipped v1 of feature",
              "type": "string"
            },
            {
              "id": "4fadb193-e76c-4206-8e0f-844f9846950a",
              "name": "sales_pipeline",
              "value": "5 new leads, 2 opps to proposal stage, 1 deal closed",
              "type": "string"
            },
            {
              "id": "aed02fee-91e3-4db6-9352-ab00a25c966f",
              "name": "marketing",
              "value": "Ran LinkedIn campaign, CTR up 15%, newsletter sent",
              "type": "string"
            },
            {
              "id": "e8243aed-9004-4a5c-917f-5dce7f895229",
              "name": "operations",
              "value": "Onboarded 2 customers; support backlog cleared",
              "type": "string"
            },
            {
              "id": "5096fdb8-5f0f-4063-9f87-b9cda52a0384",
              "name": "product_tech",
              "value": "Feature X shipped; bug Y fixed; began refactor of module Z",
              "type": "string"
            },
            {
              "id": "42f90ae5-7610-433a-98e6-26d1682e53c3",
              "name": "finance_admin",
              "value": "3 invoices sent, 2 paid; renewed software subscription",
              "type": "string"
            },
            {
              "id": "7ef5a6eb-eb28-4273-a37a-569f2b0880e9",
              "name": "risks",
              "value": "Dependence on single vendor; tight timeline for feature",
              "type": "string"
            },
            {
              "id": "d4ea19cd-34bc-4df7-8069-ba538d9f2116",
              "name": "next_week",
              "value": "Focus on onboarding, close 2 deals, finish refactor",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -900,
        -260
      ],
      "id": "3c4083cd-1177-43c5-b680-6d29c30ff45d",
      "name": "Set Raw Inputs"
    },
    {
      "parameters": {
        "jsCode": "const item = items[0]?.json ?? {};\n\n// Use ISO date for stable, auditable reports\nconst dateStr = new Date().toISOString().slice(0, 10);\n\nconst prompt = `\nYou are an operations consultant producing a clear, concise **weekly business status report** for leadership.\n\nWrite a Markdown report using the following structure and data. Be concise but readable. Use bullet points where appropriate.\n\n# Weekly Business Status Report - ${dateStr}\n\n## 1. Highlights\nUse \"highlights\" to summarise key wins and notable updates.\n\n## 2. Sales & Pipeline\nUse \"sales_pipeline\" to describe new leads, pipeline movement, and closed deals.\n\n## 3. Marketing & Growth\nUse \"marketing\" to summarise campaigns, channel performance, and experiments.\n\n## 4. Operations & Delivery\nUse \"operations\" to cover project delivery, operational issues, and process improvements.\n\n## 5. Product / Technology\nUse \"product_tech\" to summarise shipped features, bugs fixed, and tech debt work.\n\n## 6. Finance & Admin\nUse \"finance_admin\" to highlight important expenses, invoicing, and cashflow-related notes.\n\n## 7. Risks & Issues\nUse \"risks\" to describe current risks and mitigations.\n\n## 8. Priorities for Next Week\nUse \"next_week\" to list the top 3-5 priorities and any dependencies.\n\nHere is the raw data (JSON):\n\n${JSON.stringify(item, null, 2)}\n\nReturn **only** the final Markdown report, no commentary.\n`.trim();\n\nreturn [\n  {\n    json: {\n      date: dateStr,\n      prompt,\n    },\n  },\n];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -460,
        -260
      ],
      "id": "aa08d6d0-1d86-4615-9f98-7a24ed4aa907",
      "name": "Build Prompt"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://localhost:5001/completions",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "content-type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "prompt",
              "value": "={{ $json[\"prompt\"] }}"
            },
            {
              "name": "alias",
              "value": "general"
            }
          ]
        },
        "options": {
          "timeout": 120000,
          "retryOnFail": true,
          "maxRetries": 3
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -240,
        -260
      ],
      "id": "7c0ac0a7-6df0-45be-a618-d1ec38f29292",
      "name": "Call Local LLM",
      "notes": "Calls the local LLM endpoint. Production template includes timeout/retry settings and an error output connected to the failure-alert path.",
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "jsCode": "const source = items[0]?.json ?? {};\n\nfunction firstString(...values) {\n  for (const value of values) {\n    if (typeof value === 'string' && value.trim()) {\n      return value.trim();\n    }\n  }\n  return '';\n}\n\n// Common local/OpenAI-compatible/llama.cpp/Ollama-ish response shapes.\nlet content = firstString(\n  source.response,\n  source.report,\n  source.content,\n  source.text,\n  source.output,\n  source.generated_text,\n  source.message?.content,\n  source.choices?.[0]?.message?.content,\n  source.choices?.[0]?.text,\n  source.results?.[0]?.text,\n  source.data?.response,\n  source.data?.report,\n  source.data?.content,\n  source.data?.text,\n  source.data?.output,\n  source.data?.message?.content,\n  source.data?.choices?.[0]?.message?.content,\n  source.data?.choices?.[0]?.text\n);\n\n// Some wrappers return an array of generated parts.\nif (!content && Array.isArray(source.output)) {\n  content = source.output\n    .map(part => typeof part === 'string' ? part : part?.content || part?.text || '')\n    .filter(Boolean)\n    .join('\\n')\n    .trim();\n}\n\nif (!content) {\n  const availableKeys = Object.keys(source).sort().join(', ');\n  throw new Error(`LLM response did not contain an expected report field. Available top-level fields: ${availableKeys}`);\n}\n\nreturn [{\n  json: {\n    ...source,\n    report: content,\n  },\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -20,
        -260
      ],
      "id": "c1d23dac-c9e3-4556-8721-b8e00c9be87c",
      "name": "Extract Report",
      "notes": "Normalises common local/OpenAI-compatible response shapes into report. Unexpected response shapes flow to the failure-alert path.",
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "jsCode": "const source = items[0]?.json ?? {};\nconst report = source.report;\n\nif (typeof report !== 'string' || !report.trim()) {\n  throw new Error('Preview / Save Report expected a non-empty report field');\n}\n\nconst generatedAt = new Date().toISOString();\n\nreturn [\n  {\n    json: {\n      ...source,\n      report,\n      preview_markdown: report,\n      generated_at: generatedAt,\n      delivery_status: 'ready_for_email',\n    },\n  },\n];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        -260
      ],
      "id": "9c8f5a12-8af9-4d64-b9a7-1f4db4b8b0d3",
      "name": "Preview / Save Report",
      "notes": "Creates a previewable report payload. In production, replace or extend this with file storage, database insert, Google Drive, Notion, or Slack."
    },
    {
      "parameters": {
        "jsCode": "const source = items[0]?.json ?? {};\n\nconst required = [\n  'highlights',\n  'sales_pipeline',\n  'marketing',\n  'operations',\n  'product_tech',\n  'finance_admin',\n  'risks',\n  'next_week',\n];\n\nconst missing = [];\nconst tooShort = [];\n\nfor (const field of required) {\n  const value = source[field];\n  if (typeof value !== 'string' || !value.trim()) {\n    missing.push(field);\n    continue;\n  }\n  if (value.trim().length < 8) {\n    tooShort.push(field);\n  }\n}\n\nif (missing.length || tooShort.length) {\n  throw new Error([\n    missing.length ? `Missing required inputs: ${missing.join(', ')}` : '',\n    tooShort.length ? `Inputs too short to produce a useful report: ${tooShort.join(', ')}` : '',\n  ].filter(Boolean).join('; '));\n}\n\nconst totalInputLength = required\n  .map(field => source[field].trim().length)\n  .reduce((sum, length) => sum + length, 0);\n\nif (totalInputLength < 120) {\n  throw new Error('Input quality guardrail failed: not enough business context to generate a useful weekly report');\n}\n\nreturn [{\n  json: {\n    ...source,\n    input_quality: {\n      status: 'passed',\n      checked_fields: required,\n      total_input_length: totalInputLength,\n    },\n  },\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -680,
        -260
      ],
      "id": "e529be64-b735-435e-9b40-94d3f110bbd1",
      "name": "Validate Inputs / Guardrails",
      "notes": "Stops empty or low-quality weekly input data before the workflow spends LLM time or sends a weak report."
    },
    {
      "parameters": {
        "jsCode": "const source = items[0]?.json ?? {};\n\nif (typeof source.report !== 'string' || !source.report.trim()) {\n  throw new Error('Audit log expected a non-empty report field');\n}\n\nconst auditRecord = {\n  audit_id: `weekly-status-${source.date || new Date().toISOString().slice(0, 10)}-${Date.now()}`,\n  generated_at: source.generated_at || new Date().toISOString(),\n  report_date: source.date,\n  delivery_status: source.delivery_status || 'ready_for_email',\n  source_data: {\n    highlights: source.highlights,\n    sales_pipeline: source.sales_pipeline,\n    marketing: source.marketing,\n    operations: source.operations,\n    product_tech: source.product_tech,\n    finance_admin: source.finance_admin,\n    risks: source.risks,\n    next_week: source.next_week,\n  },\n  report_markdown: source.report,\n};\n\nreturn [{\n  json: {\n    ...source,\n    audit_record: auditRecord,\n    audit_status: 'captured_in_workflow_output',\n  },\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        -260
      ],
      "id": "ed0742fe-aec8-4442-b007-50bf85225055",
      "name": "Log Audit Snapshot (demo)",
      "notes": "Demo audit checkpoint. For client production, replace or extend with database, Google Drive, Notion, filesystem, or logging platform storage."
    },
    {
      "parameters": {
        "jsCode": "const source = items[0]?.json ?? {};\n\n// Demo placeholder: pass through by default so the workflow remains runnable.\n// For senior leadership or external recipients, replace this node with a Wait/Form/approval workflow.\nconst approvalRequired = source.approval_required ?? false;\nconst approved = source.approved ?? true;\n\nif (approvalRequired && !approved) {\n  throw new Error('Human approval required before email delivery');\n}\n\nreturn [{\n  json: {\n    ...source,\n    approval: {\n      required: approvalRequired,\n      approved,\n      mode: 'demo_auto_approved_placeholder',\n    },\n  },\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        690,
        -260
      ],
      "id": "97ef7a2a-ab6d-4886-aa75-90f22a4cff9e",
      "name": "Optional Human Approval Gate (demo)",
      "notes": "Pass-through demo approval gate. Replace with n8n Wait/Form/Slack approval before sending reports to senior leadership or external recipients."
    },
    {
      "parameters": {
        "jsCode": "const source = items[0]?.json ?? {};\nconst error = source.error ?? source;\n\nconst message = error.message || error.description || source.message || 'Unknown LLM workflow failure';\nconst failedAt = new Date().toISOString();\n\nconst alertMarkdown = [\n  '# Weekly Status Report Workflow Failure',\n  '',\n  `Time: ${failedAt}`,\n  `Node / stage: ${source.node?.name || source.node || source.stage || 'LLM response path'}`,\n  `Error: ${message}`,\n  '',\n  'Recommended action:',\n  '- Check whether the local LLM endpoint is running and reachable.',\n  '- Check the HTTP response shape returned by the model endpoint.',\n  '- Review the input guardrail output and source business notes.',\n].join('\\n');\n\nreturn [{\n  json: {\n    alert_type: 'weekly_status_report_failure',\n    failed_at: failedAt,\n    alert_subject: 'Weekly status report workflow failed',\n    alert_markdown: alertMarkdown,\n    original_payload: source,\n  },\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -20,
        40
      ],
      "id": "0dc69dd2-a6f3-4521-b2c6-8f494c1b4c72",
      "name": "Prepare Failure Alert",
      "notes": "Builds an alert payload when the LLM call fails or the response cannot be extracted. Replace the next demo node with Slack, email, PagerDuty, etc."
    },
    {
      "parameters": {
        "jsCode": "const source = items[0]?.json ?? {};\n\nreturn [{\n  json: {\n    ...source,\n    alert_delivery_status: 'prepared_demo_payload_replace_with_slack_email_or_incident_node',\n  },\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        40
      ],
      "id": "c9a34e7d-a110-4368-ae7d-d5365d005efb",
      "name": "Failure Alert Output (demo)",
      "notes": "Demo alert output. In production, replace or extend with Slack, email, PagerDuty, Opsgenie, or incident-management integration."
    }
  ],
  "connections": {
    "Manual Trigger (dev)": {
      "main": [
        [
          {
            "node": "Set Raw Inputs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Schedule (prod)": {
      "main": [
        [
          {
            "node": "Set Raw Inputs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Raw Inputs": {
      "main": [
        [
          {
            "node": "Validate Inputs / Guardrails",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Prompt": {
      "main": [
        [
          {
            "node": "Call Local LLM",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call Local LLM": {
      "main": [
        [
          {
            "node": "Extract Report",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare Failure Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Report": {
      "main": [
        [
          {
            "node": "Preview / Save Report",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare Failure Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Preview / Save Report": {
      "main": [
        [
          {
            "node": "Log Audit Snapshot (demo)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Inputs / Guardrails": {
      "main": [
        [
          {
            "node": "Build Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Audit Snapshot (demo)": {
      "main": [
        [
          {
            "node": "Optional Human Approval Gate (demo)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Optional Human Approval Gate (demo)": {
      "main": [
        [
          {
            "node": "Send email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Failure Alert": {
      "main": [
        [
          {
            "node": "Failure Alert Output (demo)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "ccb95c49-a3ed-4fb7-97d6-66a185f2e45b",
  "id": "VBUssfbH7rSvBzld",
  "tags": []
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Weekly Business Status Report (local LLM). Uses emailSend, httpRequest. Event-driven trigger; 13 nodes.

Source: https://github.com/tfest-dev/n8n-workflows/blob/main/reports-weekly-status-local-llm/reports-weekly-status-local-llm.json — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Web Scraping

The Sora 2 API allows seamless generation of CGI ads, turning text prompts into stunning videos. This workflow automates the entire process from video generation to upload, notification, and file shar

Form Trigger, HTTP Request, Email Send +1
Web Scraping

Storyboard I2V Pipeline (17 shots) with Retry/Wait/State/Notify. Uses httpTrigger, httpRequest, emailSend. Event-driven trigger; 28 nodes.

Http Trigger, HTTP Request, Email Send
Web Scraping

Create CGI ads effortlessly by integrating the Google Veo3 API for video generation and uploading to Google Drive with seamless email notifications. On form submission: Triggers the workflow when a fo

Form Trigger, HTTP Request, Email Send +1
Web Scraping

This workflow automates the process of generating videos using the Veo 3 Fast API, uploading the video to Google Drive, and notifying the user via email. All tasks are executed seamlessly, ensuring a

Form Trigger, HTTP Request, Email Send +1
Web Scraping

This workflow automates the process of sending voice calls for verification purposes and combines it with email verification. It uses the ClickSend API for voice calls and integrates with SMTP for ema

HTTP Request, Form Trigger, Email Send +1