{ "kind": "open-flow-workflow", "version": 1, "name": "Reddit n8n Post Digest", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_66310fcb10f430ad": { "name": "Start Reddit search", "kind": "start", "inputDefs": [] }, "n_6133690727420ad2": { "inputs": { "previousState": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_6133690727420ad2", "output": "state" } ] }, "page": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c6d4b5024bc07988", "output": "posts" } ] }, "after": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c6d4b5024bc07988", "output": "after" } ] } }, "name": "Collect up to 100 posts", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": true, "handle": "previousState" }, { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": true, "handle": "page" }, { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "after" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "more" }, { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "cursor" }, { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "posts" } ], "name": "Collect up to 100 posts", "moduleId": "n_869064ad13441be3", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_5d13c37609340aee": { "inputs": {}, "name": "More Reddit results", "kind": "condition", "matchMode": "first", "cases": [ { "output": "fetch", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_6133690727420ad2", "output": "more" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_c6d4b5024bc07988": { "inputs": { "query": { "kind": "value", "value": "n8n" }, "sort": { "kind": "value", "value": "new" }, "limit": { "kind": "value", "value": 100 }, "after": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_6133690727420ad2", "output": "cursor" } ] } }, "name": "Search Reddit", "kind": "task", "task": { "inputs": [ { "description": "The Reddit search query.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The Reddit search query." }, "nullable": false, "handle": "query" }, { "description": "The subreddit name without the r/ prefix.", "jsonSchema": { "type": "string", "description": "The subreddit name without the r/ prefix." }, "nullable": true, "handle": "subreddit", "value": null }, { "description": "The Reddit search sort order.", "jsonSchema": { "type": "string", "enum": [ "relevance", "hot", "top", "new", "comments" ], "description": "The Reddit search sort order." }, "nullable": true, "handle": "sort", "value": null }, { "description": "The search time range.", "jsonSchema": { "type": "string", "enum": [ "hour", "day", "week", "month", "year", "all" ], "description": "The search time range." }, "nullable": true, "handle": "time", "value": null }, { "description": "The maximum number of items to return, from 1 through 100.", "jsonSchema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "The maximum number of items to return, from 1 through 100." }, "nullable": true, "handle": "limit", "value": null }, { "description": "The Reddit fullname cursor after which to continue the listing.", "jsonSchema": { "type": "string", "description": "The Reddit fullname cursor after which to continue the listing." }, "nullable": true, "handle": "after", "value": null }, { "description": "The Reddit fullname cursor before which to continue the listing.", "jsonSchema": { "type": "string", "description": "The Reddit fullname cursor before which to continue the listing." }, "nullable": true, "handle": "before", "value": null } ], "outputs": [ { "description": "The posts returned in this page.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "The raw object returned by the Reddit Data API." }, "description": "The posts returned in this page." }, "nullable": false, "handle": "posts" }, { "description": "The fullname cursor for the next page, or null.", "jsonSchema": { "type": [ "string", "null" ], "description": "The fullname cursor for the next page, or null." }, "nullable": true, "handle": "after" }, { "description": "The fullname cursor for the previous page, or null.", "jsonSchema": { "type": [ "string", "null" ], "description": "The fullname cursor for the previous page, or null." }, "nullable": true, "handle": "before" } ], "name": "Search Reddit", "executor": { "kind": "connector", "action": "reddit.search_posts" } } }, "n_ff1327dcd7cbae2a": { "inputs": { "posts": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_6133690727420ad2", "output": "posts" } ] }, "timezone": { "kind": "value", "value": "UTC" } }, "name": "Filter recent posts", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "posts" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "timezone" } ], "outputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "posts" } ], "name": "Filter recent posts", "moduleId": "n_567c30618f12cd5d", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_549f9752e0fe9a00": { "inputs": { "posts": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ff1327dcd7cbae2a", "output": "posts" } ] }, "previousState": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_549f9752e0fe9a00", "output": "state" } ] }, "summary": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_8242a77744c5012f", "output": "output" }, { "kind": "node", "nodeId": "n_edef12474cedc890", "output": "summary" } ] } }, "name": "Prepare one post", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "posts" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": true, "handle": "previousState" }, { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "summary" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "more" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "prompt" }, { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "results" } ], "name": "Prepare one post", "moduleId": "n_a1a2a02853b9b26a", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_d269617a788ac946": { "inputs": {}, "name": "More eligible posts", "kind": "condition", "matchMode": "first", "cases": [ { "output": "classify", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_549f9752e0fe9a00", "output": "more" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_438796405e78a4ad": { "inputs": { "post": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_549f9752e0fe9a00", "output": "prompt" } ] } }, "name": "Check n8n relevance", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "post" } ], "outputs": [ { "description": "The final result produced by the Agent.", "jsonSchema": { "type": "string" }, "nullable": false, "handle": "output" } ], "name": "Check n8n relevance", "executor": { "kind": "agent", "code": false, "model": "gpt-4o-mini", "prompt": "Decide whether a reddit post is about n8n.io, a workflow automation low code tool that can be self-hosted, or not.\nReddit Post: {{post}}\nAbout n8n?: Yes/No", "maxRounds": 1, "tools": [] } } }, "n_6c99930c14789c5d": { "inputs": { "answer": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_438796405e78a4ad", "output": "output" } ] } }, "name": "Apply relevance decision", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "answer" } ], "outputs": [ { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "relevant" } ], "name": "Apply relevance decision", "moduleId": "n_e7638b08373c15ac", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_4ce3da9bbba0d0b5": { "inputs": {}, "name": "Post is relevant", "kind": "condition", "matchMode": "first", "cases": [ { "output": "summarize", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_6c99930c14789c5d", "output": "relevant" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_8242a77744c5012f": { "inputs": { "post": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_549f9752e0fe9a00", "output": "prompt" } ] } }, "name": "Summarize the post", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "post" } ], "outputs": [ { "description": "The final result produced by the Agent.", "jsonSchema": { "type": "string" }, "nullable": false, "handle": "output" } ], "name": "Summarize the post", "executor": { "kind": "agent", "code": false, "model": "gpt-4o-mini", "prompt": "Summarise what this is talking about in a meta way in only 1 sentence.\n\n{{post}}", "maxRounds": 1, "tools": [] } } }, "n_edef12474cedc890": { "inputs": {}, "name": "Skip unrelated post", "kind": "task", "task": { "inputs": [], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "summary" } ], "name": "Skip unrelated post", "moduleId": "n_98fdf7f6ef261dbb", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_2425efe642d7af17": { "name": "Return post digest", "kind": "outputs", "outputDefs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "additionalProperties": true } }, "nullable": false, "handle": "posts" } ], "outputMappings": { "posts": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_549f9752e0fe9a00", "output": "results" } ] } } } }, "edges": [ { "source": "n_66310fcb10f430ad", "target": "n_6133690727420ad2" }, { "source": "n_6133690727420ad2", "target": "n_5d13c37609340aee" }, { "source": "n_5d13c37609340aee", "target": "n_c6d4b5024bc07988", "sourceHandle": "fetch" }, { "source": "n_c6d4b5024bc07988", "target": "n_6133690727420ad2" }, { "source": "n_5d13c37609340aee", "target": "n_ff1327dcd7cbae2a", "sourceHandle": "otherwise" }, { "source": "n_ff1327dcd7cbae2a", "target": "n_549f9752e0fe9a00" }, { "source": "n_549f9752e0fe9a00", "target": "n_d269617a788ac946" }, { "source": "n_d269617a788ac946", "target": "n_438796405e78a4ad", "sourceHandle": "classify" }, { "source": "n_d269617a788ac946", "target": "n_2425efe642d7af17", "sourceHandle": "otherwise" }, { "source": "n_438796405e78a4ad", "target": "n_6c99930c14789c5d" }, { "source": "n_6c99930c14789c5d", "target": "n_4ce3da9bbba0d0b5" }, { "source": "n_4ce3da9bbba0d0b5", "target": "n_8242a77744c5012f", "sourceHandle": "summarize" }, { "source": "n_4ce3da9bbba0d0b5", "target": "n_edef12474cedc890", "sourceHandle": "otherwise" }, { "source": "n_8242a77744c5012f", "target": "n_549f9752e0fe9a00" }, { "source": "n_edef12474cedc890", "target": "n_549f9752e0fe9a00" } ] } }, "modules": { "n_869064ad13441be3": { "name": "Collect up to 100 posts", "imports": [], "source": "export default function pages({previousState,page,after}){const old=previousState??{posts:[],started:false,seen:[]};if(!old.started)return{state:{...old,started:true},more:true,cursor:null,posts:[]};if(!Array.isArray(page))throw new Error('Invalid Reddit page');const posts=[...old.posts,...page].slice(0,100);if(after!==null&&typeof after!=='string')throw new Error('Invalid Reddit cursor');const more=posts.length<100&&after!==null&&after!=='';if(more&&(page.length===0||old.seen.includes(after)))throw new Error('Reddit cursor did not make progress');return{state:{posts,started:true,seen:more?[...old.seen,after]:old.seen},more,cursor:more?after:null,posts};}\n" }, "n_567c30618f12cd5d": { "name": "Filter recent posts", "imports": [], "source": "export default function select({posts,timezone}){let local;try{local=new Intl.DateTimeFormat('en-CA',{timeZone:timezone,year:'numeric',month:'2-digit',day:'2-digit'}).formatToParts(new Date());}catch{throw new Error('Invalid timezone')}const parts=Object.fromEntries(local.map(x=>[x.type,x.value]));const date=Date.UTC(+parts.year,+parts.month-1,+parts.day-7);let midnight=date;for(let i=0;i<3;i++){const p=Object.fromEntries(new Intl.DateTimeFormat('en-CA',{timeZone:timezone,year:'numeric',month:'2-digit',day:'2-digit',hour:'2-digit',minute:'2-digit',second:'2-digit',hourCycle:'h23'}).formatToParts(new Date(midnight)).map(x=>[x.type,x.value]));midnight+=date-Date.UTC(+p.year,+p.month-1,+p.day,+p.hour,+p.minute,+p.second)}const chosen=[];for(const p of posts){if(typeof p.created!=='number'||typeof p.ups!=='number'||typeof p.selftext!=='string')throw new Error('Reddit post lacks expected fields');if(p.ups>=5&&p.selftext!==''&&p.created*1000>midnight)chosen.push({upvotes:p.ups,subredditSize:p.subreddit_subscribers??null,selftextTrimmed:p.selftext.substring(0,500),subreddit:p.subreddit??'',date:new Intl.DateTimeFormat('en-US',{timeZone:timezone}).format(new Date(p.created*1000)),url:p.url??''})}return{posts:chosen};}\n" }, "n_a1a2a02853b9b26a": { "name": "Prepare one post", "imports": [], "source": "export default function next({posts,previousState,summary}){const old=previousState??{index:0,results:[]};let results=old.results;if(old.index>0&&summary!=null){const {upvotes,subredditSize,subreddit,date,url}=posts[old.index-1];results=[...results,{upvotes,subredditSize,subreddit,date,url,bulletSummary:summary}]}if(old.index>=posts.length)return{state:{index:old.index,results},more:false,prompt:'',results};return{state:{index:old.index+1,results},more:true,prompt:posts[old.index].selftextTrimmed,results};}\n" }, "n_e7638b08373c15ac": { "name": "Apply relevance decision", "imports": [], "source": "export default function classify({answer}){if(typeof answer!=='string')throw new Error('Invalid classification');return{relevant:!answer.includes('No')};}\n" }, "n_98fdf7f6ef261dbb": { "name": "Skip unrelated post", "imports": [], "source": "export default function skip(){return{summary:null};}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }