You know that feeling on Friday afternoon when you realize you need to write a weekly review? You open your inbox, check your CRM, look at your bank app, scroll through project notes... and 90 minutes later you have a paragraph that says "busy week, good progress."
There's a better way.
I built an n8n workflow that pulls data from Gmail, Google Calendar, a CRM spreadsheet, and a project tracker — then uses AI to write a structured weekly review in about 30 seconds. Here's the full workflow, with the importable JSON.
What the Agent Does
Every Friday at 4 PM, it:
- Scans Gmail for emails sent and received this week
- Pulls Google Calendar events from the past 7 days
- Reads a CRM spreadsheet for deals moved, new leads, closed won/lost
- Checks a project tracker for tasks completed, blocked, or overdue
- Synthesizes everything into a structured weekly review
- Saves the review to Google Docs and emails it to you
The output looks like this:
## Weekly Review — June 9–15, 2026
### Wins
- Closed [Client Name] proposal ($4,200) — sent Tuesday, signed Friday
- 12 new leads from blog content (vs. 8 last week, +50%)
- Completed client onboarding for [Project] ahead of schedule
### In Progress
- [Client Name] estimate — awaiting site measurements (expected Mon)
- Blog content pipeline: 2 drafts, 1 scheduled
### Blocked / At Risk
- [Client Name] invoice overdue 14 days — follow-up sent Wed, no response
- [Project] waiting on permit approval (submitted May 28)
### Next Week Priorities
- Follow up on overdue invoice (escalate to call)
- Submit 2 proposals in pipeline
- Publish 3 blog posts
That's the kind of summary that used to take 90 minutes of tab-switching. Now it's automatic.
The n8n Workflow
Here's the full workflow. Copy this JSON and import it directly into n8n (Settings → Import from JSON):
{
"name": "Weekly Business Review Agent",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 16 * * 5"
}
]
}
},
"id": "cron-trigger",
"name": "Every Friday 4PM",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [0, 0]
},
{
"parameters": {
"resource": "message",
"operation": "getAll",
"returnAll": false,
"limit": 50,
"filters": {
"query": "newer_than:7d"
}
},
"id": "gmail-scan",
"name": "Scan Gmail (Last 7 Days)",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [250, -100]
},
{
"parameters": {
"resource": "event",
"operation": "getAll",
"returnAll": false,
"limit": 50,
"filters": {
"startTimeMin": "={{ $today.minus({days: 7}).toISO() }}",
"endTimeMax": "={{ $today.toISO() }}"
}
},
"id": "calendar-pull",
"name": "Pull Calendar Events",
"type": "n8n-nodes-base.googleCalendar",
"typeVersion": 1,
"position": [250, 100]
},
{
"parameters": {
"operation": "read",
"documentId": {
"__rl": true,
"value": "YOUR_CRM_SPREADSHEET_ID",
"mode": "id"
},
"range": "Deals!A:Z"
},
"id": "crm-read",
"name": "Read CRM Spreadsheet",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [250, 300]
},
{
"parameters": {
"operation": "read",
"documentId": {
"__rl": true,
"value": "YOUR_PROJECT_TRACKER_ID",
"mode": "id"
},
"range": "Tasks!A:Z"
},
"id": "project-read",
"name": "Read Project Tracker",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [250, 500]
},
{
"parameters": {
"mode": "combine",
"combinationMode": "mergeByPosition"
},
"id": "merge-data",
"name": "Merge All Data",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [500, 200]
},
{
"parameters": {
"model": "gpt-4o-mini",
"messages": {
"values": [
{
"content": "You are a business analyst. Write a concise weekly review based on the data provided."
},
{
"content": "=## Raw Data\n\n**Emails this week:**\n{{ $node['Scan Gmail (Last 7 Days)'].json.map(e => '- From: ' + e.from + ' | Subject: ' + e.subject).join('\\n') }}\n\n**Calendar events:**\n{{ $node['Pull Calendar Events'].json.map(e => '- ' + e.summary + ' (' + e.start.dateTime + ')').join('\\n') }}\n\n**CRM deals:**\n{{ $node['Read CRM Spreadsheet'].json.map(d => '- ' + d.DealName + ': ' + d.Status + ' ($' + d.Value + ')').join('\\n') }}\n\n**Project tasks:**\n{{ $node['Read Project Tracker'].json.map(t => '- ' + t.Task + ': ' + t.Status).join('\\n') }}\n\n---\n\nWrite a weekly review with these sections:\n1. **Wins** — deals closed, tasks completed, positive metrics\n2. **In Progress** — active deals, drafts, ongoing work\n3. **Blocked / At Risk** — overdue items, stalled deals, unfollowed leads\n4. **Next Week Priorities** — top 3-5 actions based on this week's data\n\nBe specific. Use actual names and numbers from the data. Keep it under 300 words."
}
]
},
"options": {
"temperature": 0.3,
"maxTokens": 800
}
},
"id": "ai-review",
"name": "AI Weekly Review Writer",
"type": "n8n-nodes-base.openAi",
"typeVersion": 1.8,
"position": [750, 200]
},
{
"parameters": {
"operation": "create",
"title": "=Weekly Review — {{ $today.minus({days:7}).toFormat('MMM d') }}–{{ $today.toFormat('MMM d, y') }}",
"body": "={{ $node['AI Weekly Review Writer'].json.message.content }}"
},
"id": "save-doc",
"name": "Save to Google Docs",
"type": "n8n-nodes-base.googleDocs",
"typeVersion": 2,
"position": [1000, 100]
},
{
"parameters": {
"fromEmail": "your-email@gmail.com",
"toEmail": "your-email@gmail.com",
"subject": "=Weekly Review — {{ $today.minus({days:7}).toFormat('MMM d') }}–{{ $today.toFormat('MMM d, y') }}",
"text": "={{ $node['AI Weekly Review Writer'].json.message.content }}"
},
"id": "email-review",
"name": "Email Review to Me",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [1000, 300]
}
],
"connections": {
"Every Friday 4PM": {
"main": [
[
{ "node": "Scan Gmail (Last 7 Days)", "type": "main", "index": 0 },
{ "node": "Pull Calendar Events", "type": "main", "index": 0 },
{ "node": "Read CRM Spreadsheet", "type": "main", "index": 0 },
{ "node": "Read Project Tracker", "type": "main", "index": 0 }
]
]
},
"Scan Gmail (Last 7 Days)": {
"main": [
[{ "node": "Merge All Data", "type": "main", "index": 0 }]
]
},
"Pull Calendar Events": {
"main": [
[{ "node": "Merge All Data", "type": "main", "index": 0 }]
]
},
"Read CRM Spreadsheet": {
"main": [
[{ "node": "Merge All Data", "type": "main", "index": 0 }]
]
},
"Read Project Tracker": {
"main": [
[{ "node": "Merge All Data", "type": "main", "index": 0 }]
]
},
"Merge All Data": {
"main": [
[{ "node": "AI Weekly Review Writer", "type": "main", "index": 0 }]
]
},
"AI Weekly Review Writer": {
"main": [
[
{ "node": "Save to Google Docs", "type": "main", "index": 0 },
{ "node": "Email Review to Me", "type": "main", "index": 0 }
]
]
}
}
}
Setup Instructions
1. Connect Your Accounts
In n8n, you'll need 4 credentials:
- Gmail OAuth2 — for email scanning and sending
- Google Calendar OAuth2 — for event data
- Google Sheets OAuth2 — for CRM and project tracker
- OpenAI API — for the AI review writer
2. Set Up Your CRM Spreadsheet
Create a Google Sheet with columns like:
| DealName | Status | Value | Contact | LastContact |
|---|---|---|---|---|
| ACME Proposal | Closed Won | 4200 | jane@acme.com | 2026-06-13 |
3. Set Up Your Project Tracker
Another Google Sheet:
| Task | Status | Due | Assigned |
|---|---|---|---|
| Onboard new client | Completed | 2026-06-12 | You |
| Submit permit | Blocked | 2026-06-10 | Pending |
4. Update the Spreadsheet IDs
Replace YOUR_CRM_SPREADSHEET_ID and YOUR_PROJECT_TRACKER_ID in the JSON with your actual Google Sheet IDs (the long string in the sheet URL).
5. Customize the Prompt
The AI prompt in the workflow asks for 4 sections (Wins, In Progress, Blocked, Next Week). Adjust these to match how you think about your week. Common additions:
- Revenue this week — if you track daily sales
- Team updates — if you have employees or contractors
- Customer feedback — if you want to surface support tickets
What This Costs to Run
| Component | Monthly Cost |
|---|---|
| n8n (self-hosted) | $0 |
| n8n (cloud starter) | $20/mo |
| OpenAI API (4 prompts/week × ~500 tokens) | ~$0.15/mo |
| Google Workspace | Already paying |
| Total additional | $0.15/mo (self-hosted) or $20.15/mo (cloud) |
If you're already using n8n, this adds basically nothing to your costs.
Why This Beats Manual Reviews
Consistency. A manual weekly review is the first thing that gets skipped when you're busy. An automated one runs every Friday at 4 PM whether you remember it or not.
Completeness. When you write a review from memory, you remember the fires and forget the wins. This agent pulls from actual data — every closed deal, every completed task, every overdue invoice. No optimism bias.
Time. 90 minutes of tab-switching → 30 seconds of reading an email.
Actionability. The "Next Week Priorities" section isn't wishful thinking — it's derived from what's blocked and what's in progress. The AI connects the dots between "invoice overdue 14 days" and "next priority: follow up on invoice."
Common Questions
"What if I don't use Google Sheets for CRM?" Swap the Google Sheets nodes for whatever you use. HubSpot, Airtable, Notion — n8n has integrations for all of them. The workflow structure stays the same: pull data → merge → AI synthesize → save/email.
"Can I use this for daily standups?" Change the cron trigger from 0 16 * * 5 (Friday 4 PM) to 0 9 * * 1-5 (9 AM weekdays) and adjust the Gmail query to newer_than:1d. The rest of the workflow works the same.
"What about sensitive data in emails?" The AI sees email subjects and senders, not full bodies. If you want even more privacy, filter the Gmail node to only return metadata (subject, from, date) without snippets.
What to Do Next
If you want more n8n workflows like this, I've been building a collection of them. There's a free AI Automation Cheat Sheet with 15 copy-paste prompts at ai-automation-cheat-sheet.vercel.app, and a Boring Automation Pack with 5 complete workflows (including this one) at smbscaleup.gumroad.com/l/boring-automation-pack.
The cheat sheet is free. The automation pack is $15 CAD and includes the n8n JSON for all 5 workflows plus a setup checklist.
We're building these tools and sharing what we learn along the way. If you set this up, I'd love to hear how it goes — drop a comment below.
Top comments (0)