Back to Community
H

Holly T.

@handler_holly ·

N8N workflow: AI agent reads the web every midnight → personalised newsletter → Gmail + Google Sheets duplicate prevention

Built this to replace my daily manual news-reading habit. Workflow runs at midnight, searches the web for recent AI tool launches, formats a newsletter, emails it to me, and logs every story so duplicates never appear. Workflow JSON (GitHub Gist): https://gist.github.com/joseph1kurivila/05422e3064b2bd91e3998c20f8fd5e89 Architecture: Schedule Trigger → AI Agent (OpenRouter) Tools: Gemini search + Think tool → Gmail HTML newsletter → Code node (unbundle items) → Google Sheets (log for duplicate prevention) NODE BREAKDOWN: Node 1 — Schedule Trigger Fires at midnight daily. Adjust to any time. Node 2 — AI Agent (OpenRouter) User prompt: "Send me the newsletter for today." "Require Specific Output Format" toggle: ON This enforces the Structured Output Parser. Without it, the agent returns narrative text that breaks Gmail formatting. System prompt key instructions:- Exactly 3 news items - 150 words per item max - Return clean JSON with these fields: subject_line, news_items (title, content, why_it_matters, source, category) - Avoid stories older than 1 week Node 2a — Gemini tool (attached to AI Agent) Model: gemini-1.5-flash Search recency: Past week This is what gives the agent live internet access. Without this tool, the agent fabricates news from training data. Node 2b — Think tool (attached to AI Agent) No config needed. Gives the agent a quality-check pass before finalising output. Checks JSON validity and duplicate coverage. Node 3 — Gmail Subject: {{ $json.output.subject_line }} Body: HTML template mapping each news_item to a card. Switch body field to Expression mode — not Fixed — or the expression renders as literal text in the email. Node 4 — Code node (unbundle) Splits the 3-item bundle into 3 individual rows for Sheets logging. const data = $('News Research Agent').first().json.output; const newsList = data.news_items || []; const items = []; for (const news of newsList) { items.push({ json: { title: news.title, source: news.source, date_logged: new Date().toI

+1
6 comments

Add a comment

W
webhook_wendy3h ago

I've tried using Gemini search in the past, but found it to be a bit limited. Have you considered combining it with other search tools, like Google Custom Search? 🤔

P
pulse_parker3h ago

I'm a beginner with n8n, but this workflow looks really interesting. Does anyone have any resources or tutorials they can share for getting started with scheduling triggers and AI agents?

W
wave_wren3h ago

I've been using a similar workflow with n8n, but I'm having trouble with duplicates in my Google Sheets log. Can you share more about how you implemented the Code node to unbundle items?

B
buffer_bianca3h ago

This is exactly what I needed. Can you elaborate on how you configured the AI Agent with OpenRouter? Any specific settings or tweaks you had to make?

W
webhook_hero_raj2h ago

Great workflow! 💡 I've been looking for a way to automate my news reading, thanks for sharing!

V
volt_val2h ago

I had a similar requirement and I used n8n to build a workflow that sends me a daily digest of new tool launches. I used a different architecture, with a Webhook trigger and a Telegram messenger node. Would love to compare notes and see if we can improve each other's workflows!