Anyone running one-person multi-platform content has lived this: every morning open a dozen RSS feeds, pick what is worth posting, rewrite it into the formats that fit Telegram, an email list, a Feishu group, and a newsletter, then paste into each platform one by one. Two hours gone -- and you still miss posts, send to the wrong channel, or mangle the formatting. The bottleneck is not content ability; it is hauling. Repetitive, mechanical, error-prone work that a human should never own.
This SOP ships a reusable n8n workflow template: an RSS Feed Read Trigger pulls sources -> an AI node rewrites and adapts each item to per-platform formats -> a Switch node routes by content type -> multiple outputs fan out to Telegram, email, and a Feishu (Lark) webhook. Every step gives the real node name, key parameters, and expressions so you can reproduce it on the canvas. Node names follow the n8n official docs; parameters I could not verify online are marked "per official docs" rather than fabricated.
One-line framing: this workflow is not "AI writes your articles." It is "AI takes one RSS item and rewrites it into N platform-specific formats, then publishes them automatically." It kills the distribution hauling, not the creative work.
One: Scenario and Pain Points
Picture an AI-tools reviewer who subscribes to 20 AI news RSS feeds (Hacker News, vendor blogs, GitHub Releases). Hundreds of new items a day -- you cannot post them all, but you cannot afford to miss the ones that matter. The pain clusters in three places:
- Hauling is exhausting. The same story needs a short sentence plus link for Telegram, a long summary for the email list, and a tagged structured card for the Feishu group. Rewriting it three times by hand burns every hour on copy-paste.
- Missed and mistaken posts. Paste into the wrong channel, forget a platform, or ship a draft as the final. Manual scheduling has no state tracking, so errors are hard to trace.
- Lost timing. A breaking story two hours late loses most of its traffic. By the time you are free to handle it manually, the moment is gone.
The root tension: distribution is a deterministic pipeline (receive content -> transform -> deliver), but it gets packaged as a creative task that needs a human watching it. n8n turns it back into an automated pipeline -- humans own only the selection rules and the prompt, machines own the hauling.
Two: Tool Selection -- Why n8n
Plenty of tools do multi-platform distribution. Why build this pipeline on n8n:
| Dimension | n8n | Coze | Zapier/Make |
|---|---|---|---|
| Hosting | Self-hostable (Docker), data stays in-house | Pure SaaS, data in cloud | Pure SaaS |
| Integrations | 400+ nodes + arbitrary HTTP | Domestic ecosystem focused | Many but pricey |
| AI nodes | Native AI Agent / Language Model, any OpenAI-compatible model | Built-in ByteDance models | Needs third-party glue |
| Cost | Self-host free, only hardware limits | Free tier | Per-task billing, expensive |
| Custom | HTTP Request hits any webhook, Code node runs JS | Closed loop, weak external APIs | Medium flexibility |
The core reasons to pick n8n: self-host free + native AI nodes + HTTP Request can hit any platform webhook. Feishu has no official n8n node, but a Feishu custom bot is just a webhook -- one HTTP Request and it works, which is exactly n8n's "eats anything" value. Coze onboards faster but is closed-source, cloud-only, and weak at external webhooks, making "multi-platform webhook fan-out" awkward.
Prerequisites: an n8n instance (self-host with
docker run -d --name n8n -p 5678:5678 -v ~/.n8n:/home/node/.n8n n8nio/n8n, or use the n8n.io cloud), an API key for an OpenAI-compatible model, and per-platform credentials (Telegram Bot Token, SMTP, Feishu bot webhook URL).
Three: Build Step by Step -- RSS -> AI Rewrite -> Multi-Platform
The main trunk is five nodes plus a dedup step. Draw the trunk first, harden it after.
RSS Feed Read Trigger -> [Dedup Filter] -> AI Agent (rewrite) -> Switch (route) -> Multi-output
|-> Telegram
|-> Email Send
|-> HTTP Request (Feishu webhook)Step 1: Trigger -- RSS Feed Read Trigger
Drag in an RSS Feed Read Trigger node. It is itself a trigger (with built-in polling), so you do not need a separate Schedule Trigger. Key config:
URL: https://hnrss.org/frontpage # your RSS source URL
Limit: 20 # max items per pull
Poll Times: every 30 minutes # poll frequency, set by source refresh rateEach item the node emits has fields (from the underlying rss-parser; per official docs): title, link, content, contentSnippet, pubDate, guid, isoDate, creator. The AI node and the dedup step both rely on these.
You can also combine Schedule Trigger + RSS Feed Read (the non-trigger version): Schedule runs on a timer, RSS Feed Read reads once. The difference is that the trigger version remembers state for "new items only"; the combo forces you to dedup yourself. For beginners, RSS Feed Read Trigger is less hassle.
Step 2: AI Rewrite -- Adapt to Each Platform's Format
Drag in an AI Agent node, feed it the RSS output. Attach a Language Model sub-node (pick OpenAI Chat Model; store the API key as an n8n Credential -- never hardcode; for domestic models pick the OpenAI-compatible type and set the Base URL).
The AI job here is not "freelance writing"; it is "rewrite one RSS item into three platform formats plus a category tag," so the output shape must be pinned down. Example System Prompt:
You are a multi-platform distribution rewriter. You receive one RSS item (title + link + content).
Output strict JSON with these fields:
- telegram: a summary <=200 chars, ending with the link
- email: a 300-500 word summary, Markdown, keeping the link
- feishu: a one-line title plus 3 bullet points
- category: one of [breaking, digest, skip]
Rules: do not fabricate facts not in the source; items unrelated to AI get category=skip; output JSON only, no markdown code fence.The AI Agent emits text; downstream needs structured fields, so add a Code node to parse the JSON string into an object:
// Code node: parse the AI output JSON
const raw = $json.text || $json.output; // field name per your AI Agent output
const parsed = JSON.parse(raw);
return { json: { ...$('RSS Feed Read Trigger').item.json, ...parsed } };For something simpler, swap AI Agent for a Basic LLM Chain node -- it is single-turn prompt -> LLM -> output, with no tools or memory, which is exactly what a deterministic rewrite needs. AI Agent's edge is attaching tools (e.g. letting the model fetch the full article); this example does not need that.
Step 3: Switch Routing
Drag in a Switch node, feed it the Code node output. Switch routes data to different exits by condition. Here we route on the category the AI assigned:
Routing:
Rule 1: {{ $json.category }} equals "breaking" -> output 0 (instant Telegram push)
Rule 2: {{ $json.category }} equals "digest" -> output 1 (email digest + Feishu)
Rule 3: {{ $json.category }} equals "skip" -> output 2 (drop)
Fallback (no match) -> output 3 (manual review queue)Switch earns its keep by conditional delivery: breaking goes the instant lane, digest goes the batch lane, skip gets dropped -- so not every item blasts every platform.
Step 4: Multi-Output
Each Switch output wires to its publishing node.
Telegram (instant push) -- use the Telegram node:
Credential: Telegram Bot API (store Bot Token, from @BotFather)
Resource / Operation: Message / Send
Chat ID: {{ $env.TELEGRAM_CHANNEL_ID }} # channel ID, via env var, not hardcoded
Text: {{ $json.telegram }} # reference the AI-generated short summaryEmail (digest subscription) -- use the Email Send node (SMTP credential):
Credential: SMTP (store SMTP account/password)
To: [email protected]
Subject: AI News Daily - {{ $now.toFormat('yyyy-MM-dd') }}
Text / HTML: {{ $json.email }}Feishu webhook (group card) -- no official n8n node for Feishu; use an HTTP Request to hit the custom bot webhook:
Method: POST
URL: {{ $env.FEISHU_WEBHOOK_URL }} # Feishu group bot webhook URL
Headers: Content-Type: application/json
Body (JSON):
{
"msg_type": "text",
"content": { "text": "{{ $json.feishu }}" }
}Feishu bots support interactive cards (
msg_type: interactive); the card JSON is involved -- per the Feishu Open Platform docs. Get the text message working first, then upgrade to cards.
Step 5: Dedup and Activate
RSS Feed Read Trigger ships with "new items only," but if you restart the instance or swap the trigger, old items will re-fire. Harden it: before the AI node, add a Filter or Code node that dedups on guid -- store processed guids in a Postgres / SQLite / Google Sheets node, and filter out the ones already seen each pull:
// Code node: simple dedup (pseudocode; data source per your chosen store)
const seen = $('Postgres').item.json.ids || []; // query stored guid set, per official docs
const fresh = $('RSS Feed Read Trigger').all.filter(
item => !seen.includes(item.json.guid)
);
return fresh;Once it works, click the top-right Active toggle and the workflow runs on its Poll Times. While testing, use a Manual Trigger to feed data by hand -- do not enable polling until it works.
Four: Pitfall Quick Reference
| Pitfall | Symptom | Fix |
|---|---|---|
| RSS source rate-limits | Source returns 429; RSS node errors or returns empty | Widen Poll Times (e.g. 30 min -> 1 hour); stagger high-frequency sources with Schedule Trigger; some sources are User-Agent sensitive -- use HTTP Request with a custom Header (per source rules) |
| AI rewrite drops key info | Summary loses the link, numbers, or names | System Prompt must require "keep the link, do not fabricate facts"; have the AI output structured JSON fields, not free text -- structure cuts information loss; pass critical fields (link) through directly with {{ $json.link }}, never through the AI |
| Platform formats differ | Same text is too long for Telegram, too short for email | Do not "one draft, many posts." Have the AI emit three length-specific fields (telegram/email/feishu) at once; each downstream reads its own field; write length thresholds into the prompt |
| Duplicate publishing | Restart re-fires old items; same guid pushed twice | Dedup on guid; store in Postgres/Google Sheets; Filter node drops processed items; "new items only" depends on instance state -- do not wipe the DB casually |
| Hardcoded API key leaks | Exported workflow JSON carries the token | Store every Key/Token in n8n Credentials; reference the credential by name in nodes; env vars via {{ $env.XXX }}; confirm credentials are excluded before exporting JSON; use sk-xxx placeholders, never real values |
| Feishu webhook fails | HTTP Request returns 200 but no message in the group | If signature verification is on, a missing timestamp/sign in the Body is silently dropped; check that msg_type is valid; per Feishu Open Platform docs |
FAQ
Q1: What is the difference between RSS Feed Read Trigger and RSS Feed Read? A: The former is a trigger with built-in polling and "new items only" state memory -- once active it runs itself. The latter is a regular node that reads once and returns all items; it needs a Schedule Trigger to run on a timer and forces you to dedup yourself. Beginners should use the trigger version; use the combo when you want fine control over polling logic.
Q2: Can I skip AI and forward the original text to every platform?
A: Yes. Remove the AI Agent and Code node; wire Switch straight to the RSS output; downstream passes through {{ $json.contentSnippet }}. But then every platform gets the same format -- Telegram overflows, email is too thin -- which defeats the point of distribution. The AI rewrite exists precisely for "one source, many shapes."
Q3: How do I connect DeepSeek / Qwen and other domestic models? A: In the Language Model sub-node pick the OpenAI-compatible type, set the Base URL to the provider's OpenAI-compatible endpoint, store the API key as a Credential, and set the model name per the provider's docs. DeepSeek, Qwen, and Zhipu all offer OpenAI-compatible endpoints; exact endpoints and model names per each provider's docs.
Q4: Feishu has no n8n node -- what do I do?
A: Use an HTTP Request node to hit the Feishu custom bot webhook URL, with the Body in Feishu's message JSON format (msg_type + content). This is n8n's universal answer -- any platform with a webhook or API is reachable via HTTP Request, with no need for an official node.
Q5: What specs does self-hosted n8n need for this workflow?
A: 2-core 4GB is enough for personal testing. This pipeline is light; what eats resources is AI call frequency and RSS pull volume. If you connect many sources and poll densely, scale to 4-core 8GB. For production, always add a reverse proxy + HTTPS + a strong password + the N8N_ENCRYPTION_KEY env var to encrypt credentials.
References
- n8n official docs: https://docs.n8n.io
- n8n integration node library: https://docs.n8n.io/integrations
- RSS Feed Read Trigger node docs: https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.rssfeedreadtrigger/
- n8n template library (RSS workflow templates): https://n8n.io/workflows/
- n8n GitHub repo (n8n-io/n8n): https://github.com/n8n-io/n8n
- Feishu Open Platform - custom bot: https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot
- Node names and parameters in this article follow the official n8n docs; due to network restrictions I could not verify each node parameter online, so unverified items are marked "per official docs" -- cross-check against docs.n8n.io while building