Mohammed Roshan Ibrahim ABack to the main page

n8n workflows

I build n8n pipelines that connect databases, APIs, WhatsApp Business, Razorpay, Google and Microsoft 365 to LLM and vector-store nodes, and I run them self-hosted. These are eight of them.

Selected project in my work history

Citizen-support RAG assistant

Answers from your own documents, on your own server.

  • n8n
  • Ollama
  • pgvector
  • Postgres
  • 14 nodes, 9 AI

A support team needed answers grounded in official PDFs, with nothing leaving the building. The model and the vector store both run self-hosted, and every answer is logged for audit.

How it runs

  1. Ingestion: a PDF arrives on a webhook, is split into overlapping chunks, embedded with a local model, and upserted into pgvector.
  2. Query: a question arrives on a second webhook. The retriever pulls the closest chunks and a local chat model writes the answer from them only.
  3. Every question, answer and source chunk is written to Postgres before the reply goes out.

What keeps it safe

  • The prompt tells the model to answer from the retrieved context only, and to say it does not know when the context does not contain the answer.
  • The audit write happens before the response, so a logged answer always exists for anything a user saw.
Upload PDF (Webhook) Upload PDF Webhook Extract text (Extract from file) Extract text Extract from file Load document (Document loader) Load document Document loader Split into chunks (Text splitter) Split into chunks Text splitter Embed (local) (Ollama embeddings) Embed (local) Ollama embeddings Store in pgvector (PGVector store) Store in pgvector PGVector store Question (Webhook) Question Webhook Answer from sources (Q&A chain) Answer from sources Q&A chain Local chat model (Ollama chat model) Local chat model Ollama chat model Retriever (Vector retriever) Retriever Vector retriever Search pgvector (PGVector store) Search pgvector PGVector store Embed query (Ollama embeddings) Embed query Ollama embeddings Write audit log (Postgres) Write audit log Postgres Reply (Respond to webhook) Reply Respond to webhook

Download n8n JSON

Selected project in my work history

Multi-channel client onboarding

From a new lead to a paid, verified client without a person in the loop.

  • n8n
  • WhatsApp Business
  • Razorpay
  • Google Sheets
  • Slack
  • 13 nodes

Onboarding meant a person chasing documents on WhatsApp, sending a payment link, and updating a tracker by hand. The workflow runs that sequence end to end and cut manual onboarding time by about 70%.

How it runs

  1. A new lead lands on a webhook and is logged in a Google Sheet.
  2. The lead gets a WhatsApp message asking for the KYC details. Their reply resumes the run.
  3. If the details are complete, a Razorpay payment link is created over HTTP and sent back on WhatsApp.
  4. A second webhook receives the Razorpay payment event, marks the row paid and alerts the team on Slack.

What keeps it safe

  • An incomplete KYC reply gets a message naming exactly what is still missing, instead of a generic retry.
  • The Razorpay webhook signature is verified before any row is changed.
  • Payment and status updates key on the Razorpay order id, so a repeated webhook does not double-update.
true false New lead (Webhook) New lead Webhook Log lead (Google Sheets) Log lead Google Sheets Ask for KYC details (WhatsApp Business) Ask for KYC details WhatsApp Business KYC reply (WhatsApp trigger) KYC reply WhatsApp trigger Validate details (Code) Validate details Code Complete? (If) Complete? If Ask again (WhatsApp Business) Ask again WhatsApp Business Create payment link (HTTP request) Create payment link HTTP request Send payment link (WhatsApp Business) Send payment link WhatsApp Business Payment event (Webhook) Payment event Webhook Verify signature (Code) Verify signature Code Mark paid (Google Sheets) Mark paid Google Sheets Tell the team (Slack) Tell the team Slack

Download n8n JSON

Selected project in my work history (Hyrowah IoT fleet)

Anomaly-to-ticket pipeline

A sensor misbehaves, the right person gets a ticket that already explains why.

  • n8n
  • MQTT
  • Ollama
  • Jira
  • Slack
  • 11 nodes, 2 AI

Field units publish readings over MQTT. Someone had to notice a bad reading, work out what it meant, and file a ticket. This flow scores each reading, has a language model write the incident summary, and routes the ticket by severity.

How it runs

  1. An MQTT trigger subscribes to the sensor topic and receives every reading.
  2. A code step keeps a rolling window per device and computes a z-score against that device's own history.
  3. Only readings past the threshold continue. A local model turns the reading and its recent history into a short incident summary.
  4. A switch routes by severity. Critical anomalies create a high-priority Jira issue and ping Slack; the rest create a normal issue.

What keeps it safe

  • Baselines are per device and stored in workflow static data, so one noisy unit cannot skew another.
  • If the language model is unreachable, the ticket is still created with the raw numbers and a note that the summary failed.
  • An error trigger reports any failed execution to Slack. Set the workflow as its own error workflow in its settings to activate it.
true critical warning Sensor readings (MQTT trigger) Sensor readings MQTT trigger Score against history (Code) Score against history Code Anomalous? (If) Anomalous? If Write incident summary (Basic LLM chain) Write incident summary Basic LLM chain Local chat model (Ollama chat model) Local chat model Ollama chat model By severity (Switch) By severity Switch Critical ticket (Jira) Critical ticket Jira Page the team (Slack) Page the team Slack Warning ticket (Jira) Warning ticket Jira Failed run (Error trigger) Failed run Error trigger Report failure (Slack) Report failure Slack

Download n8n JSON

Selected project in my work history

Executive report generator

Monday-morning KPIs, written up and waiting in Notion before anyone asks.

  • n8n
  • Postgres
  • Claude
  • Notion
  • Slack
  • 7 nodes, 2 AI

Leadership wanted a weekly brief, and someone was assembling it by hand from database queries. The workflow pulls the numbers, computes the week-on-week change in code, and asks Claude to write only what the numbers support.

How it runs

  1. A schedule trigger fires every Monday at 07:30.
  2. One Postgres query returns this week and last week per KPI.
  3. A code step computes the deltas, so the model never does arithmetic.
  4. Claude turns the table into a fixed-structure brief: headline, what moved, what to watch.
  5. The brief is filed as a Notion page and a link is posted to Slack.

What keeps it safe

  • All arithmetic happens in code and the prompt forbids new numbers, so the narrative cannot contradict the table.
  • If a KPI is missing for the week, the brief says the data is missing instead of filling the gap.
Every Monday 07:30 (Schedule) Every Monday 07:30 Schedule Pull weekly KPIs (Postgres) Pull weekly KPIs Postgres Compute deltas (Code) Compute deltas Code Write the brief (Basic LLM chain) Write the brief Basic LLM chain Claude (Claude chat model) Claude Claude chat model File in Notion (Notion) File in Notion Notion Post the link (Slack) Post the link Slack

Download n8n JSON

Selected project in my work history

Compliance-aware email triage agent

The model drafts. A person decides what goes out.

  • n8n
  • Gmail
  • LLM classifier
  • Slack approval
  • 13 nodes, 4 AI

An inbox mixed routine requests with messages that carried compliance risk. The agent classifies each email, drafts a reply for the routine ones, and stops for a human approval before anything is sent.

How it runs

  1. A Gmail trigger picks up each new inbound email.
  2. A classifier labels it by route, urgency and compliance flag, and returns a confidence score.
  3. Low confidence, or any compliance flag, skips drafting and goes straight to a person with a label.
  4. Otherwise a model drafts a reply into Gmail, and Slack asks a reviewer to approve or reject it.
  5. Only an approval sends the email.

What keeps it safe

  • Nothing is sent without an explicit approval, including when the classifier is confident.
  • The low-confidence path exists so an uncertain classification is routed to a person instead of being guessed.
  • Approval requests expire after four hours, so a draft cannot sit waiting indefinitely.
true false true false New email (Gmail trigger) New email Gmail trigger Classify (Text classifier) Classify Text classifier Classifier model (Ollama chat model) Classifier model Ollama chat model Safe to draft? (Code) Safe to draft? Code Draftable? (If) Draftable? If Draft reply (Basic LLM chain) Draft reply Basic LLM chain Drafting model (Ollama chat model) Drafting model Ollama chat model Save as Gmail draft (Gmail) Save as Gmail draft Gmail Ask reviewer (Slack) Ask reviewer Slack Approved? (If) Approved? If Send reply (Gmail) Send reply Gmail Label for a person (Gmail) Label for a person Gmail Flag rejected thread (Gmail) Flag rejected thread Gmail

Download n8n JSON

Everyone's Tomorrow: webhook-driven journeys across WhatsApp and email

Payment-to-follow-up journey

A payment lands, the right message goes out on the right channel.

  • n8n
  • Razorpay
  • Postgres
  • WhatsApp Business
  • Gmail
  • 12 nodes

Supporters should hear back quickly and differently depending on who they are. A first-time supporter needs a welcome; a returning one needs recognition. This workflow decides which and sends it.

How it runs

  1. Razorpay posts a payment event to a webhook, and the signature is verified first.
  2. The order is upserted in Postgres and the supporter's history is read back.
  3. A switch segments them: first-time, returning, or a larger gift.
  4. Each segment gets its own WhatsApp message, with an email as the fallback when no WhatsApp number is on file.
  5. On the WhatsApp path, a wait node resumes three days later and sends a short follow-up.

What keeps it safe

  • The signature check runs before anything is written, so a forged request changes nothing.
  • Supporters are upserted by email, so a repeated webhook does not create a duplicate supporter.
  • The email fallback means a supporter without WhatsApp is still acknowledged.
large gift returning first-time true false Payment captured (Webhook) Payment captured Webhook Verify signature (Code) Verify signature Code Upsert supporter (Postgres) Upsert supporter Postgres Segment (Switch) Segment Switch Personal note (Edit fields) Personal note Edit fields Recognition (Edit fields) Recognition Edit fields Welcome (Edit fields) Welcome Edit fields Has WhatsApp? (If) Has WhatsApp? If Send on WhatsApp (WhatsApp Business) Send on WhatsApp WhatsApp Business Send by email (Gmail) Send by email Gmail Wait three days (Wait) Wait three days Wait Follow-up (WhatsApp Business) Follow-up WhatsApp Business

Download n8n JSON

Everyone's Tomorrow: Meta Ads pipeline and Google Analytics attribution

Ads and analytics attribution report

Spend from Meta, sessions and conversions from GA4, joined on the campaign.

  • n8n
  • Meta Marketing API
  • Google Analytics 4
  • Postgres
  • Slack
  • 8 nodes

Ad spend lives in Meta and conversions live in Google Analytics, so nobody could say what a campaign actually cost per result. This workflow joins them daily on the campaign tag and flags campaigns that overspend.

How it runs

  1. A schedule runs every morning.
  2. One branch pulls yesterday's spend per campaign from the Meta Marketing API over HTTP; the other pulls conversions per campaign from GA4.
  3. A merge joins them on the campaign name.
  4. A code step computes cost per conversion and flags campaigns above their target.
  5. Rows are upserted into Postgres, and any flagged campaign is posted to Slack.

What keeps it safe

  • The join is on the exact campaign name, so a renamed campaign drops out of the join visibly instead of merging into a different one.
  • Cost per conversion is computed in code from the two sources, so the Slack flag and the stored row always agree.
true Every morning (Schedule) Every morning Schedule Meta spend (HTTP request) Meta spend HTTP request GA4 conversions (Google Analytics) GA4 conversions Google Analytics Join on campaign (Merge) Join on campaign Merge Cost per conversion (Code) Cost per conversion Code Save to Postgres (Postgres) Save to Postgres Postgres Over target? (If) Over target? If Flag in Slack (Slack) Flag in Slack Slack

Download n8n JSON

Recurring data-quality validation from my analytics work

Data-quality monitor

Checks the data before the dashboards do.

  • n8n
  • Postgres
  • Claude
  • Slack
  • Jira
  • 12 nodes, 2 AI

A dashboard is only as good as the table under it. This workflow runs freshness, null-rate and duplicate checks on a schedule, so a broken feed is caught before a stakeholder sees a wrong number.

How it runs

  1. A schedule runs hourly.
  2. Three Postgres queries measure freshness (minutes since the last row), null rate on key columns, and duplicate keys.
  3. A merge collects them and a code step compares each against its threshold.
  4. If any check fails, Claude writes a short plain-language summary of what broke and what depends on it.
  5. The summary goes to Slack and opens a Jira issue. Every run, pass or fail, is logged to Postgres.

What keeps it safe

  • Every run is logged, so a monitor that stopped running is itself detectable by a missing row.
  • The model only summarises failed checks. Pass or fail is decided in code with fixed thresholds.
true Hourly (Schedule) Hourly Schedule Freshness (Postgres) Freshness Postgres Null rate (Postgres) Null rate Postgres Duplicates (Postgres) Duplicates Postgres Collect checks (Merge) Collect checks Merge Compare to thresholds (Code) Compare to thresholds Code Any failures? (If) Any failures? If Explain the break (Basic LLM chain) Explain the break Basic LLM chain Claude (Claude chat model) Claude Claude chat model Alert data channel (Slack) Alert data channel Slack Open issue (Jira) Open issue Jira Log the run (Postgres) Log the run Postgres

Download n8n JSON