Alchemy RecipeIntermediateworkflow

Digital Agency Client Proposal Generation from Brief to Final Deck

Published

Digital agencies live in a perpetual time crunch. Your client sends a brief on Monday morning. You need a polished proposal deck by Wednesday. Your team spends two days pulling information from the brief, writing sections, summarising key points, and formatting everything into slides. Then someone has to manually copy text between documents, check for consistency, and rebuild the structure in your presentation software....... For more on this, see Agencies Scaling Client Work: Which Tools Give the Best R....

This workflow wastes skilled time on work that machines can handle. The brief contains all the information needed; the proposal structure is predictable; the content transformations are mechanical. Yet your team repeats this process for every client, losing hours to copy-pasting and reformatting.

What if you could hand off a brief to an automated system and receive a finished proposal deck the next morning? No manual steps. No email chains asking "did you finish the summary section?" No manually importing content into slides. This post shows you exactly how to build that system using four AI tools connected through an orchestration platform, turning a two-day process into a two-minute workflow.

The Automated Workflow

We'll use ChatGPT Writer to generate proposal copy from the brief, Resoomer AI to condense lengthy sections, Ai-boost to refine and structure content, and Preswald AI to build the actual presentation deck. The orchestration happens in n8n, a self-hosted workflow engine that gives you full control over API calls and error handling. For more on this, see Wispr Flow AI vs ChatGPT Writer vs HyperWrite: AI Writing....

Why n8n for this workflow?

We could use Zapier or Make, but they charge per task when your proposal workflow might trigger 20-30 individual API calls. n8n is self-hosted or cloud-hosted with a flat fee, making it economical for complex workflows. It also handles parallel processing, letting you generate multiple proposal sections simultaneously rather than waiting for them to complete sequentially.

The workflow architecture

Here's the flow:


Brief (text input) 
  → ChatGPT Writer (generate sections)
    → Parallel processing:
      - Resoomer (summarise key sections)
      - Ai-boost (structure and refine)
    → Consolidate outputs
      → Preswald AI (generate slides)
        → Store final deck URL

The brief enters as a webhook trigger. It doesn't need to come from anywhere specific; you can paste it into an n8n form, send it via API, or have it arrive via email and get extracted by n8n's email parser.

Step 1:

Receive and parse the brief

Set up an n8n webhook trigger that accepts the brief as JSON. This could come from a form, an API call, or even a Zapier action if you're triggering this from another tool.

{
  "client_name": "TechStart Solutions",
  "project_title": "Mobile App Development",
  "budget": "£45,000",
  "timeline": "6 months",
  "deliverables": "iOS and Android apps with backend API",
  "target_audience": "Small business owners aged 25-45",
  "key_goals": "Increase customer engagement, automate booking process",
  "background": "Client currently uses manual booking system, losing leads"
}

In n8n, your webhook node should validate this JSON and extract the fields. Use a function node to format the brief into a natural language prompt:

const brief = $input.first().json;

const briefText = `
Client: ${brief.client_name}
Project: ${brief.project_title}
Budget: ${brief.budget}
Timeline: ${brief.timeline}
Deliverables: ${brief.deliverables}
Target Audience: ${brief.target_audience}
Key Goals: ${brief.key_goals}
Background: ${brief.background}
`;

return { briefText, clientName: brief.client_name };

This function normalises the input and passes it to the next step.

Step 2:

Generate proposal sections with ChatGPT Writer

ChatGPT Writer isn't a traditional API; it's typically a Chrome extension. However, you can use the OpenAI API directly (which ChatGPT Writer uses under the hood) to generate your proposal sections. If you want to use ChatGPT Writer specifically, you'll need to make HTTP calls to trigger it if their API is available, or use a workaround with a webhook.

For this workflow, we'll use the OpenAI API, which is more reliable for automation:

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4",
    "messages": [
      {
        "role": "system",
        "content": "You are a senior proposal writer for a digital agency. Write professional, persuasive proposal sections."
      },
      {
        "role": "user",
        "content": "Generate a proposal executive summary based on this brief: [BRIEF TEXT]"
      }
    ],
    "temperature": 0.7,
    "max_tokens": 500
  }'

In n8n, create an HTTP request node with this configuration. Set up three parallel HTTP request nodes, each asking for a different section:

  1. Executive Summary (300 words)
  2. Scope and Deliverables (400 words)
  3. Timeline and Milestones (300 words)

Configure each request with a different prompt that references {{ $json.briefText }} from the previous function node. Set max_tokens appropriately for each section to control length.

Step 3:

Summarise lengthy sections with Resoomer AI

If any of your generated sections exceed a target length, use Resoomer AI to condense them. Resoomer's API is straightforward:

curl -X POST https://api.resoomer.com/api/summarize \
  -H "Authorization: Bearer $RESOOMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Your lengthy text here",
    "percent": 50
  }'

The percent parameter controls how much of the original text to keep. Set it to 50 for aggressive summarisation.

In n8n, add a conditional node after your ChatGPT Writer calls. If the "Scope and Deliverables" section exceeds 400 words, trigger a Resoomer HTTP request to compress it:

const scopeLength = $input.first().json.scope.split(' ').length;
if (scopeLength > 400) {
  return { shouldSummarise: true, text: $input.first().json.scope };
} else {
  return { shouldSummarise: false, text: $input.first().json.scope };
}

Route the conditional output: if shouldSummarise is true, call Resoomer; otherwise, pass the text through unchanged.

Step 4:

Structure and refine with Ai-boost

Ai-boost helps you format and structure content. While Ai-boost may not have a direct REST API, many AI enhancement tools work via webhook or have integration layers. If Ai-boost supports n8n integration natively (check their documentation), use that.

If not, you can use a generic HTTP node to send content to Ai-boost's API endpoint:

curl -X POST https://api.ai-boost.io/enhance \
  -H "Authorization: Bearer $AIBOOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Your proposal section",
    "style": "professional",
    "tone": "persuasive",
    "max_length": 400
  }'

In n8n, apply this to all three sections (executive summary, scope, timeline) using a loop node:

const sections = [
  { name: "Executive Summary", content: $input.first().json.executiveSummary },
  { name: "Scope and Deliverables", content: $input.first().json.scope },
  { name: "Timeline and Milestones", content: $input.first().json.timeline }
];

return sections.map(section => ({
  url: 'https://api.ai-boost.io/enhance',
  body: {
    content: section.content,
    style: 'professional',
    tone: 'persuasive',
    max_length: 400
  }
}));

Create an HTTP request node set to loop mode, calling the Ai-boost API for each section.

Step 5:

Generate the presentation deck with Preswald AI

Preswald AI is designed to create presentation decks from content. The API typically accepts a JSON structure describing your slides:

curl -X POST https://api.preswald.io/create-presentation \
  -H "Authorization: Bearer $PRESWALD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Project Proposal: Mobile App Development",
    "client": "TechStart Solutions",
    "slides": [
      {
        "type": "title",
        "content": {
          "title": "Project Proposal",
          "subtitle": "TechStart Solutions - Mobile App Development"
        }
      },
      {
        "type": "text",
        "content": {
          "title": "Executive Summary",
          "body": "Summarised content here"
        }
      },
      {
        "type": "text",
        "content": {
          "title": "Scope and Deliverables",
          "body": "Deliverables content here"
        }
      },
      {
        "type": "text",
        "content": {
          "title": "Timeline",
          "body": "Timeline content here"
        }
      }
    ],
    "theme": "professional-blue"
  }'

In n8n, create a function node that structures the refined content from previous steps into Preswald's required format:

const briefData = $input.first().json;
const refinedSections = $input.all()[0].json;

const slides = [
  {
    type: "title",
    content: {
      title: "Project Proposal",
      subtitle: `${briefData.clientName} - ${briefData.projectTitle}`
    }
  },
  {
    type: "text",
    content: {
      title: "Executive Summary",
      body: refinedSections[0].content
    }
  },
  {
    type: "text",
    content: {
      title: "Scope and Deliverables",
      body: refinedSections[1].content
    }
  },
  {
    type: "text",
    content: {
      title: "Timeline and Milestones",
      body: refinedSections[2].content
    }
  },
  {
    type: "text",
    content: {
      title: "Investment",
      body: `Budget: ${briefData.budget}`
    }
  }
];

return {
  title: `Proposal: ${briefData.projectTitle}`,
  client: briefData.clientName,
  slides: slides,
  theme: "professional-blue"
};

This node references data from earlier steps, builds the presentation structure, and passes it to an HTTP request node that calls Preswald's API.

Step 6:

Store and deliver the result

After Preswald generates the deck, store the result and notify you. Use a simple function to extract the deck URL:

const deckUrl = $input.first().json.presentation_url;
const clientName = $input.first().json.client_name;

return {
  deckUrl: deckUrl,
  clientName: clientName,
  completedAt: new Date().toISOString()
};

Create a final n8n node to send you a notification (via email, Slack, or webhook) containing the deck URL:

return {
  to: 'proposals@youragency.com',
  subject: `Proposal Ready: ${clientName}`,
  body: `Your proposal deck for ${clientName} is ready. View it here: ${deckUrl}`
};

Or send it to Slack:

return {
  text: `Proposal generated for ${clientName}: ${deckUrl}`,
  channel: '#proposals'
};

The Manual Alternative

You might prefer not to automate everything at once. A hybrid approach works well: use ChatGPT Writer to generate the initial copy, then manually refine the sections using Ai-boost or your own editing, then export to Preswald for formatting.

This lets you maintain control over tone and accuracy while still saving time on the initial draft and final assembly. Simply run the ChatGPT Writer and Ai-boost steps, download the results, edit them in Google Docs or Word, then hand the final copy to Preswald.

The advantage is flexibility; the disadvantage is you lose the speed gain. For client work where quality matters more than turnaround, this middle ground is reasonable. For high-volume proposals where you trust the AI outputs, full automation saves the most time.

Pro Tips

Rate limiting and costs: ChatGPT Writer calls via OpenAI API cost roughly £0.01 per 1,000 tokens. A 400-word section uses about 500 tokens. If you're generating three sections, that's approximately £0.015 per proposal. Preswald and Resoomer have their own pricing. Check their current rates before scaling, and implement n8n's rate limiting to avoid unexpected costs.

Error handling: Add conditional error handling in n8n. If ChatGPT Writer fails, you want the workflow to pause and alert you, not silently produce an incomplete proposal. Use n8n's error node to catch failed HTTP requests and send yourself a detailed error message including the failed request body.

Testing with sample data: Before running this on real client briefs, test the entire workflow with dummy data. Feed in a complete test brief, run the automation, and review the generated proposal manually. This reveals issues like API authentication failures or formatting problems before they affect real proposals....... For more on this, see Legal contract review and client summary document generation.

API authentication: Store all API keys in n8n's credentials manager, never hardcoded in workflows. This prevents accidental exposure if you share workflow JSON or export logs.

Parallelisation speeds things up: The workflow runs ChatGPT Writer calls in parallel (generating executive summary, scope, and timeline simultaneously rather than sequentially). This reduces total execution time from roughly three minutes to under ninety seconds, depending on API response times.

Cost Breakdown

ToolPlan NeededMonthly CostNotes
ChatGPT WriterPay-as-you-go (OpenAI API)£0.50–5.00Depends on proposal volume; 500 tokens ≈ £0.002
Resoomer AIPro Plan£9.99300 API calls per month; sufficient for ~10 proposals
Ai-boostStarter Plan£19.99Unlimited API requests within plan limits
Preswald AIProfessional Plan£29.99Includes unlimited presentation generation
n8nSelf-hosted (free) or Cloud (£20+)£0–20.00Self-hosted has no monthly fee; cloud has starter plan
Total£60–65Covers approximately 30 proposals per month

For agencies generating 30+ proposals monthly, this automation saves roughly 60 hours per month, equivalent to one staff member's time. At £25/hour burdened cost, that's £1,500 saved monthly, providing a payback period of under three weeks.

More Recipes