AI Tool Pipelines — Automate Your WorkflowsAI Tool Pipelines

Automating Social Media Content with LLMs and n8n

6 min read · Updated Mar 30, 2026

n8n workflow for automated social media content generation

Automating social media with n8n and an LLM works if you respect three rules: the AI drafts, a human approves, and the image gets generated in the same workflow run as the caption (never separately). Skip any of the three and your brand voice drifts within a month. This guide walks the production-ready workflow — the one that has survived 12+ weeks running for real businesses — not the demo that goes off the rails on day 14.

Key takeaways

  • Generate the caption and the image in the same workflow run. Splitting them = caption and image drift apart.
  • Always gate publishing behind a manual approval step for the first 30 days. Always.
  • Use 2–3 of your highest-performing past posts as few-shot examples in the prompt. This single change drops "doesn’t sound like us" rejections from ~60% to ~15%.
  • One workflow per platform output type, not one mega-workflow. Easier to debug, swap, and pause.
  • Volume target: 3–5 posts/week per platform. The "10 posts/day" automation pitch is how brands sound robotic.

The workflow shape that actually ships

Five n8n nodes, in order, doing one thing each.
#NodeJob
1Schedule TriggerMondays 8 a.m. — fires the weekly batch
2RSS / Notion sourcePulls 5–10 topic seeds (your blog, industry RSS, planned themes)
3AI: Caption + Image promptOne LLM call returns { caption, image_prompt } as JSON — paired
4AI: Image genDALL-E / Flux / SDXL renders the image from the same workflow run
5Approval gate → BufferSlack DM with caption + image preview; approve = schedules to Buffer

The "caption + image_prompt in one JSON" trick

The single biggest improvement to my social pipeline came when I stopped generating captions and images in two separate workflow runs. When they’re separate, the LLM that writes the caption doesn’t know what image you’ll actually attach, and the image model doesn’t know what the caption says. Within two weeks you get captions describing an idea that no longer matches the picture. Force them together: one LLM call returns both the caption and the image_prompt as paired fields in one JSON object, then the image gen runs immediately after using that prompt. Captions and visuals stay coherent. Cost: maybe 30 extra output tokens per post.

text
You are a social media post generator for <BRAND>. Read the topic seed below
and return ONE JSON object exactly matching this schema (no prose, no markdown):

{
  "platform": "linkedin" | "twitter" | "instagram",
  "caption": "the actual post text",
  "image_prompt": "a detailed visual description for an image model (max 80 words)",
  "hashtags": ["#tag1", "#tag2", "#tag3"]
}

Brand voice rules:
- Tone: confident, plain-spoken, no exclamation marks, no emojis.
- Max 220 characters for twitter, 1,200 for linkedin, 2,200 for instagram.
- Never use: "exciting", "thrilled", "leverage", "unlock", "supercharge".
- Open with a fact or a number, never with "Did you know".

Reference (your 3 highest-performing past posts):
---
{{ past_post_1 }}
---
{{ past_post_2 }}
---
{{ past_post_3 }}
---

Topic seed:
"""
{{ topic }}
"""

Platform-specific post length and constraint table

Useful limits to bake into the prompt and a validation step.
PlatformCaption maxImage best sizeHashtag sweet spot
LinkedIn~3,000 chars (but engagement drops above 1,200)1200×6273–5
Twitter / X280 chars (free), 4,000 chars (premium)1600×9001–2
Instagram2,200 chars (first 125 shown in feed)1080×1080 or 1080×13508–12
FacebookNo real limit (best <500 chars)1200×6301–3

The approval gate that prevents most disasters

After image generation, the workflow posts to Slack: caption preview, image preview, three buttons — Approve, Edit, Reject. Approve schedules to Buffer for the next available slot. Edit opens a Notion page where someone tweaks the caption then re-approves. Reject logs the reason to a Sheet so you can spot patterns in what the AI gets wrong. n8n’s built-in Wait for Webhook node holds the workflow execution until a Slack button is clicked — no polling, no fragility.

json
{
  "name": "Slack approval message",
  "blocks": [
    { "type": "section", "text": { "type": "mrkdwn", "text": "*Caption preview*\n>>>{{ $json.caption }}" } },
    { "type": "image", "image_url": "{{ $json.image_url }}", "alt_text": "generated visual" },
    {
      "type": "actions",
      "elements": [
        { "type": "button", "text": { "type": "plain_text", "text": "Approve" }, "value": "approve", "url": "{{ $execution.resumeUrl }}?action=approve" },
        { "type": "button", "text": { "type": "plain_text", "text": "Edit" }, "value": "edit", "url": "{{ $execution.resumeUrl }}?action=edit" },
        { "type": "button", "text": { "type": "plain_text", "text": "Reject" }, "value": "reject", "url": "{{ $execution.resumeUrl }}?action=reject" }
      ]
    }
  ]
}

The 14-day story that taught me about voice drift

August 2024, Sunday afternoon. A 5-person B2B SaaS in the HR-tech space had just turned on a fully-automated LinkedIn pipeline I’d built for them — 3 posts/week, n8n + GPT-4o-mini + Buffer, no approval gate because their CEO wanted "set and forget". Week one looked great. Week two felt off but acceptable. End of week three, their head of marketing flagged: "the last six posts use the word ‘thrilled’ four times and end with an emoji rocket every time. We don’t talk like that." I dug in. The system prompt was 80 tokens long and said "be professional and engaging". The few-shot examples were... none. The model had drifted into LinkedIn-generic voice within a fortnight because there was nothing pulling it back to brand. The fix: add 3 of their best past posts as few-shot examples in the prompt, add a banned-words list ("thrilled", "exciting", "leverage", "supercharge", any rocket emoji), and insert a Slack approval gate for the first 30 days. Day 30 we ran a survey of the team: "can you tell which posts are AI?" — 7 of 10 couldn’t guess above chance. We kept the approval gate on permanently because the marketing lead said "the gate isn’t about the AI, it’s about catching when our own message is wrong." She was right. The gate stays.

The opinion I will defend

Cost math

Per post: GPT-4o-mini for the caption + image prompt (~700 in + 300 out tokens) = ~$0.0003. DALL-E 3 standard 1024×1024 = $0.04 (OpenAI 2024 pricing). Buffer Free plan = $0 up to 30 scheduled posts/mo. n8n self-hosted on a $5 VPS = $5/mo. For 5 posts/week (~22/mo): about $0.88/month in AI + $5 infra = ~$6/month all in. Compare with hiring a part-time social coordinator at $400–$1,000/mo. The number only stops working if you start generating images with a premium model in bulk — stay on standard quality until you measure that you actually need HD.

Common pitfalls in week 2–3

  • Emoji drift. The model loves emojis. Add "no emojis" to the prompt explicitly AND add a post-processing step that strips them. Belt and braces.
  • Hashtag bloat. Cap hashtags in the JSON schema. Without a cap the model will return 30 hashtags for a tweet.
  • Image-caption mismatch. Always generate both in the same workflow run from a paired JSON. The drift is invisible at first and ugly within two weeks.
  • Buffer slot exhaustion. Buffer Free caps at 30 scheduled posts. If you batch a month ahead, the 31st post silently fails to schedule. Either upgrade or schedule weekly.
“Automation should help you reach the cadence you already wanted, not push you to a cadence you can’t sustain coherently.”

Frequently asked questions

Frequently asked questions

How do I automate social media with n8n and an LLM?

Five nodes: Schedule Trigger → source node (RSS or Notion seeds) → LLM call returning JSON with paired caption and image_prompt → image generation → Slack approval gate that schedules to Buffer on approve. Always generate caption and image in the same run, always include 2–3 past-approved posts as few-shot, always keep an approval gate for at least 30 days.

Can the AI sound like my brand?

Yes if you give it 2–3 of your best past posts as few-shot examples in the prompt, include a banned-words list, and review-and-refresh the examples every 4–6 weeks. Without few-shot examples the model drifts to platform-generic voice within ~14 days.

Should I auto-publish or require human approval?

Require human approval for at least the first 30 days. After 30 days, only auto-publish on topics where every post follows a tight template (e.g., job postings, event reminders). For anything brand-voice-sensitive, keep the gate — it’s 10 seconds of effort per post and prevents the embarrassments that compound.

What does this cost to run?

About $6–$10/month for 5 posts/week: $0.88 in GPT-4o-mini + DALL-E 3 standard, $5 for n8n on a tiny VPS, Buffer Free. Replace DALL-E with Flux/SDXL self-hosted and the marginal AI cost drops to ~$0.04/month, leaving infra as the dominant cost.

Which platforms can I cross-post to?

Buffer and Hootsuite both support LinkedIn, Twitter/X, Instagram, Facebook, Pinterest, TikTok, YouTube Shorts, and Threads from a single API. n8n has native Buffer and Hootsuite nodes. Generate one post per platform from the same seed rather than cross-posting the same text — each platform has its own optimal length and tone.

How many posts per week is realistic?

3–5 posts/week per platform is the realistic sustainable target. More than that and either quality drops or your audience treats your account as a feed they tune out. Use the saved hours to engage in comments — that’s where the actual reach in 2026 lives.