{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "78c17a2b-6458-42e5-acb6-74b350d17e4a",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -592,
        -32
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "41b2c6a0-7063-446e-9403-478e6c7b325b",
      "name": "Call NewsAPI",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -80,
        -32
      ],
      "parameters": {
        "url": "https://newsapi.org/v2/everything",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpQueryAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "from",
              "value": "={{ DateTime.fromISO($json.timestamp).minus({ days: 7 }) }}"
            },
            {
              "name": "q",
              "value": "={{ $json.topics.replaceAll(\",\", \" OR \") }}"
            },
            {
              "name": "sortBy",
              "value": "relevancy"
            }
          ]
        }
      },
      "credentials": {
        "httpQueryAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "81bdbf07-dc4a-4fef-9e69-eef731f4bb14",
      "name": "Send a text message",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1376,
        -32
      ],
      "parameters": {
        "text": "={{ \n  $json.output.map(article => {\n    const title = JSON.stringify(article.title).slice(1, -1);\n    const content = JSON.stringify(article.content).slice(1, -1);\n    const source = JSON.stringify(article.source).slice(1, -1);\n    const url = JSON.stringify(article.url).slice(1, -1);\n\n    return `*${title}*\\n${content}\\nSource: [${source}](${url})`;\n  }).join('\\n\\n')\n}}",
        "chatId": "89066090",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a522827f-0470-452e-9b9a-1268dbc97ba2",
      "name": "Split Out",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        528,
        -32
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "message.content.articles"
      },
      "typeVersion": 1
    },
    {
      "id": "d34cda05-2f22-4358-8890-f53ec36600f9",
      "name": "Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        944,
        192
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"title\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n\t\t\"content\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n        \"source\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n        \"url\": {\n\t\t\t\"type\": \"string\"\n\t\t}\n\t}\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "d1fe8abe-76cf-4ce2-934d-5c78c4de8662",
      "name": "Tavily",
      "type": "@tavily/n8n-nodes-tavily.tavilyTool",
      "position": [
        816,
        192
      ],
      "parameters": {
        "query": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Query', ``, 'string') }}",
        "options": {}
      },
      "credentials": {
        "tavilyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "137623d3-5bd0-44a8-a915-36e9e0db1331",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1152,
        -32
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "output"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d9fdf9e3-b954-43cb-98f7-503f6015e2f3",
      "name": "Set topics and language",
      "type": "n8n-nodes-base.set",
      "position": [
        -368,
        -32
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "2e1993fe-ae4d-46e0-be9f-6b02a18cc610",
              "name": "topics",
              "type": "string",
              "value": "AI,n8n"
            },
            {
              "id": "2c6e2dad-d54a-4387-9bf5-4751037f99d9",
              "name": "language",
              "type": "string",
              "value": "English"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "f96519e3-2626-4651-9157-30ab40ffbf60",
      "name": "Newsletter AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        752,
        -32
      ],
      "parameters": {
        "text": "=You are a research writer that updates short news summaries into concise, factual articles.\n\n**Input:**\nTitle: {{ $json[\"title\"] }}\nSummary: {{ $json[\"summary\"] }}\nSource: {{ $json[\"source\"] }}\nOriginal URL: {{ $json[\"url\"] }}\nLanguage: {{ $('Set topics and language').item.json.language }}\n\n**Instructions:**\n\n1. Use **Tavily Search** to gather 2\u20133 reliable, recent, and relevant sources on this topic.\n2. Update the **title** if a more accurate or engaging one exists.\n3. Write **1\u20133 sentences** summarizing the topic, combining the original summary and information from the new sources.\n4. Return the original source name and url as well.\n\n**Output (JSON):**\n\n```json\n{\n  \"title\": \"final article title\",\n  \"content\": \"concise 1\u20133 sentence article content\",\n  \"source\": \"the name of the original source\",\n  \"url\": \"the url of the original source\"\n}\n```\n\n**Rules:**\n\n* Ensure the topic is relevant, informative, and timely.\n* Translate the article if necessary to comply with the desired language {{ $('Set topics and language').item.json.language }}.",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "699ff0a8-4412-45cb-b20d-ac4fa39c6077",
      "name": "AI Topic Selector",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        176,
        -32
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.1",
          "cachedResultName": "GPT-5.1"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=You are an assistant that selects the most relevant news articles for a user.\n\nInstructions:  \n1. Choose the **5 most relevant non-overlapping articles** based on the user topics.  \n2. For each article, provide:  \n   - title  \n   - short summary (1\u20132 sentences)  \n   - source name  \n   - url\n3. Output the results in the language specified by the user.\n\nOutput as a \"articles\" JSON array of objects, each with \"title\", \"summary\", \"source\" and \"url\".\n\nUser topics of interest: {{ $('Set topics and language').item.json.topics }}\nOutput language: {{ $('Set topics and language').item.json.language }}\n\nNewsAPI articles:\n\n{{ \n  $json.articles.map(\n    article => \n      `Title: ${article.title}\nDescription: ${article.description}\nContent: ${article.content}\nSource: ${article.source.name}\nURL: ${article.url}`\n  ).join('\\n---\\n')\n}}\n"
            }
          ]
        },
        "jsonOutput": true
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "56bd39e6-6c7f-4357-898e-b5a85457e04a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1296,
        -256
      ],
      "parameters": {
        "width": 640,
        "height": 608,
        "content": "# AI Newsletter Workflow\n\n## How it works\nThis workflow runs weekly, fetches fresh news for your chosen topics, lets an AI pick the five most relevant articles, enriches each with additional research, and then sends a compact Markdown newsletter to Telegram. It combines NewsAPI for discovery, GPT\u20115 for reasoning and writing, and Tavily for fact-checked enrichment.\n\n## Setup steps\n1. Configure the schedule (weekly, Sunday 09:00 or your preferred time).  \n2. Set `topics` (comma-separated) and `language` in `Set topics and language`.  \n3. Add credentials: NewsAPI (query auth), OpenAI, Tavily, and Telegram bot/chat ID.  \n\n## Customization\n- Tweak `topics` and `language` for different audiences or languages.  \n- Adjust the schedule (day/time) to control when newsletters go out.  \n- Change the number of selected articles or the AI prompts if you want shorter or more in\u2011depth summaries."
      },
      "typeVersion": 1
    },
    {
      "id": "11b0c727-a68c-4849-a2a9-58cfaacc1e9a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -640,
        -256
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 608,
        "content": "## Schedule & Configuration\n\n\u2022 **Schedule Trigger**: Runs at 9am every Sunday per default.\n\u2022 **Set topics and language**: Configure your topics (comma-separated) and output language."
      },
      "typeVersion": 1
    },
    {
      "id": "72a31337-843c-41a2-9e1e-19dee208cd01",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -192,
        -256
      ],
      "parameters": {
        "color": 7,
        "width": 848,
        "height": 608,
        "content": "## Fetch & Select articles\n\n- **Call NewsAPI**: Queries the last 7 days of news for your topics.  \n- **AI Topic Selector**: Uses GPT\u20115.1 to select 5 non-overlapping, relevant articles.  \n- **Split Out**: Turns the selected list into one item per article."
      },
      "typeVersion": 1
    },
    {
      "id": "7a1c47b9-48cb-40bd-ad7e-81d36c0180bb",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        -256
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 608,
        "content": "## Enrich Articles using AI\n\n- **Newsletter AI Agent**: Orchestrates GPT\u20115, Tavily and the parser per article.  \n- **GPT-5.1**: Writes short, clear newsletter-style summaries.  \n- **Tavily**: Adds fresh sources for grounding and factual checks.  \n- **Parser**: Enforces JSON with `title`, `content`, `source`, `url`."
      },
      "typeVersion": 1
    },
    {
      "id": "9b3ce9c9-34d5-419a-a53a-20b4c08ca57f",
      "name": "GPT-5.1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        688,
        192
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.1",
          "cachedResultName": "gpt-5.1"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "2fe6ee6c-9964-4bb0-be1d-30f9485637bf",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1104,
        -256
      ],
      "parameters": {
        "color": 7,
        "width": 496,
        "height": 608,
        "content": "## Aggregate & Send\n\n- **Aggregate**: Combines all enriched article objects into one list.  \n- **Send a text message**: Formats the newsletter in Markdown and posts it to Telegram."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Newsletter AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Tavily": {
      "ai_tool": [
        [
          {
            "node": "Newsletter AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "GPT-5.1": {
      "ai_languageModel": [
        [
          {
            "node": "Newsletter AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Send a text message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Newsletter AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call NewsAPI": {
      "main": [
        [
          {
            "node": "AI Topic Selector",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Set topics and language",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Topic Selector": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Newsletter AI Agent": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a text message": {
      "main": [
        []
      ]
    },
    "Set topics and language": {
      "main": [
        [
          {
            "node": "Call NewsAPI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}