Case Study
Concept BuildThe Proposal Autopilot
A discovery-call-to-PDF proposal system built in n8n. It reads the call transcript, drafts the proposal from what was actually said, and sends the finished PDF, with nobody re-listening to the recording.
Concept Build with Illustrative Metrics
Adapted from an internal course project and rebuilt with real bug fixes and Soulwire's own architecture. The test result below is a confirmed fact from the build log: 14 of 14 nodes succeeded on a manual run, and the finished PDF landed in the test inbox. The time-saved and monthly-volume figures are illustrative estimates, not numbers confirmed by a client. This has not yet been deployed for a named client.
At a Glance
01
Executive Summary
The moment a client record is marked ready in Airtable, this system finds the matching call in Fireflies, pulls the full transcript, and hands it to Claude. Claude drafts four sections from the conversation itself. A code node assembles those sections into a branded HTML proposal using the client's name, business, and logo already sitting in Airtable, converts it to a PDF, and emails it.
Nobody opens a template. Nobody plays back a recording to remember what was quoted. It was tested end to end on a manual run against a test client record: all 14 nodes succeeded, the transcript matched correctly, and the finished PDF, logo and pricing included, landed in the inbox.
02
The Problem
After a discovery call, someone has to turn a conversation into a document: re-listen to the call, draft what was discussed, translate it into something that looks professional, and get it into the client's inbox before the moment cools off. None of that work is hard. All of it is manual, all of it repeats for every prospect, and all of it competes with the time that should go to the next call.
- The failure mode isn't usually a bad proposal. It's a slow one, or an inconsistent one
- The person writing it is working from memory of a conversation that happened hours or days earlier
- Every proposal is the same four questions answered from scratch, by hand, at the exact moment attention is worth the most elsewhere
03
The Approach
One AI call, constrained to the words already spoken. Claude reads the full transcript and drafts four sections: What We Discussed, Key Takeaways, What Happens Next, and Pricing. The system prompt instructs it to work only from the transcript, so the proposal can't quote a number or a commitment that never came up on the call.
Deterministic HTML, not a second AI call. The original version used a second GPT call to turn the drafted JSON into HTML, and that is where most of the debugging time went: broken image tags, escaped characters, output that would not start with an html tag no matter how the prompt was worded. Replacing that step with a code node that assembles the HTML directly from Airtable fields plus the AI-drafted sections removed an entire category of failure, at zero extra AI cost.
Transcript matching by content, not position. The original build filtered on the first transcript in the account. That works by coincidence when there is exactly one call on file and breaks silently the moment there is a second. It was replaced with a code node that searches the full transcript list for a title containing the client's email, and throws a clear, loud error if nothing matches. A wrong proposal is worse than a failed run, and a failed run is at least visible.
Real bugs, caught in testing rather than production. Airtable's API returns record data nested under .fields, not flat on the record, so every expression reading Airtable data had to be corrected after a full failed run surfaced it. A later, unrelated node edit silently dropped the Gmail node's operation parameter, which showed up as a validation error rather than a runtime one. And PDF.co's authentication needs the API key in a header literally named x-api-key, not a Bearer-prefixed token, which looks like a broken integration until you know it.
04
Architecture
| Layer | Implementation |
|---|---|
| Trigger | Manual for testing; Airtable status-change automation in production |
| Client data | Airtable Clients table (email, name, business, logo) |
| Call transcript | Fireflies GraphQL API, matched by client email in the transcript title |
| Drafting | Claude, AI Agent node with a Structured Output Parser, returning four labeled sections as JSON |
| Document build | Code node, assembles branded HTML from Airtable fields plus the AI sections |
| PDF conversion | PDF.co, HTML to PDF on the free tier, no Placid license required |
| Delivery | Gmail OAuth2, sends the PDF to the client's email on file |
05
Results
The test result is a confirmed fact from the build log. The time and volume figures are illustrative estimates, not client-confirmed numbers.
06
Why This Matters
The interesting decision here was taking work away from the AI. A second model call to write the HTML sounds like the modern answer, and it is the part that broke constantly: tags that would not close, characters that escaped themselves, output that refused to start where it was told. Handing that job to a code node made the proposal render correctly every time, for free. Claude writes the words. The system builds the document.
The transcript matching is the same lesson in a different place. Grabbing the first transcript in the account passes every test you run with one call on file, then quietly sends the wrong client the wrong proposal the day there are two. Matching on the client's email and throwing a loud error when nothing matches means the system fails visibly instead of confidently. That is the trade worth making every time.
If this gets attached to a real client's numbers later, their actual time-per-proposal and monthly call volume should replace the modeled figures before anything publishes with a dollar amount on it.
Stack

