All projectsCase study

RFP Scout: an AI bid-qualification pipeline.

Built for Max Cacchione's custom-software consultancy, which wins its work through public-sector and healthcare RFPs. Every morning two n8n workflows read every digest and feed, score each opportunity against the firm's own bid rubric, and hand the team a ranked sheet with the reasoning written out.

RFP Scout pipeline — email digests and RSS feeds flow through n8n into GPT-4o-mini scoring and a Google Sheet, with team feedback looping back into the prompt
5.0 on Upwork“RFP AI based process” · completed successfullySee the review

See it run

The scoring loop during a real run, at 2x speed: nine new listings in two batches of five, each scored by the AI node and appended to the sheet. Recorded on a local copy with sample RFPs; for this demo the scoring step calls Claude Opus 5.5, while the client's production workflow uses GPT-4o-mini with the same prompt.

The Problem

Finding the right bids meant someone reading four daily email digests (BidBanana, RFPMart, eVA Virginia and Periscope S2G) plus hundreds of RSS listings every morning, opening each notice and deciding by gut whether it was worth a bid. Good opportunities were missed, and hours went into notices that were never a fit: federal work the firm can't bid on, K-12 districts it avoids, license renewals, and projects far below its minimum deal size.

How it works

The email scanner polls Gmail for the four digests. Digests are free text listing 5 to 20 opportunities each, so one AI pass does two jobs at once: it pulls every opportunity out of the email as structured JSON (buyer, title, RFP number, link, due date, value) and scores each one. Duplicates are dropped against the sheet by link, or by title when a digest has no link.

The email workflow in n8n after a run: digest emails are fetched, their text extracted, reviewer feedback read from the sheet, one AI call extracts and scores every opportunity, duplicates are filtered and new rows appended
The email workflow after a run: two digests in, five opportunities extracted and scored in one AI pass, duplicates checked against the sheet.

The feed scanner runs daily at 7 AM Eastern across eight category feeds, about 400 listings a run. Each listing is normalized first: RFP number, state, budget and deadline are parsed out of the title, and obvious problems like RFIs and license renewals are pre-flagged before the model sees them. New listings are scored in batches of five with a pause between batches to stay inside API rate limits.

The full feed workflow in n8n after a run: eight RSS feeds merge into one list, which is normalized, checked against the sheet, and scored in a batch loop
The whole feed workflow after the same run: eight feeds fan in on the left, the scoring loop runs on the right.

The scoring model

The prompt encodes the firm's own fit check, not a generic “is this relevant?” question. Hard filters force an automatic Skip, with the reason named: federal procurement, passed deadlines, hardware, website-only work, IT support only, RFIs, renewals and sole-source notices. Everything else gets a 100-point weighted score across project type, industry, deal size, scope fit, competition, delivery risk, strategic value and pricing, plus a verdict and a rationale that shows the sub-scores, so any number can be checked in seconds. When a notice doesn't state a budget, the model estimates one from industry price anchors.

Scored rows from the demo run: two healthcare platforms at 94 and High Probability, a university grants system and a justice case management platform at 68, and five Skips including a federal FedRAMP bid, a license renewal, a website-only project, an RFI and a K-12 district app
The rows that demo run produced, with the model's own reasoning. The K-12 app is a Skip because of the team's feedback note, not a hard filter.

The feedback loop

The sheet has a Feedback column only the client's team writes in: “website-only, skip these”, “under our floor”. On every run, the latest 25 notes are fed back into the prompt as examples of the team's judgment. Scoring keeps moving toward how the partners actually decide, and nobody has to edit a prompt to get there.

Problems worth knowing about

Rows multiplied by the sheet

Reading the sheet inside a per-item flow ran the read once per item, so N listings times M rows came out the other side. The fix was collapsing to a single trigger item before the read and pulling the original listings back by node reference afterwards.

Batches that lost data

Running 400+ listings through a batch loop dropped AI results until each response was re-joined to its original listing by position from a stashed copy, instead of trusting what flowed out of the HTTP node.

Cloud platform limits

n8n Cloud blocks environment variables, so the API key moved into a credential. Long runs also outlive the 100-second webhook limit, so production uses a scheduled trigger and testing uses a capped webhook.

Free-text digests

Each email service formats its digest differently. Rather than a parser per sender, the text is extracted once and the model returns every opportunity in one JSON response, which kept a fourth and fifth source cheap to add.

Where it landed

~400 Listings read a day5 Sources, one sheet249 Opportunities scored at go-live25 Feedback notes in every prompt

Every source is read before the team starts work. Federal, K-12, renewals and under-floor deals are filtered with the reason written down, so nobody re-reads them, and the scoring learns from the team's notes without prompt edits. It shipped ahead of a hard deadline.

Tech Stack

n8n CloudOpenAI GPT-4o-miniJSON modeGmail APIRSSGoogle SheetsJavaScript
Your turn

Drowning in listings? Let's talk it through.