{ "kind": "open-flow-workflow", "version": 1, "name": "Summarize Reddit n8n Discussions", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_9dae45c52c7c7e67": { "name": "Start Reddit search", "kind": "start", "inputDefs": [] }, "n_fa79ab5fbf6bb56e": { "inputs": { "previousState": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_fa79ab5fbf6bb56e", "output": "state" } ] }, "page": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_58ca8b571395a84f", "output": "posts" } ] }, "after": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_58ca8b571395a84f", "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_7389eae7efe9f32e", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_250c674a3b73a28a": { "inputs": {}, "name": "More Reddit results", "kind": "condition", "matchMode": "first", "cases": [ { "output": "fetch", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_fa79ab5fbf6bb56e", "output": "more" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_58ca8b571395a84f": { "inputs": { "query": { "kind": "value", "value": "n8n" }, "sort": { "kind": "value", "value": "new" }, "limit": { "kind": "value", "value": 100 }, "after": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_fa79ab5fbf6bb56e", "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_efea6cc2cb0535d9": { "inputs": { "posts": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_fa79ab5fbf6bb56e", "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_52484f6aa0724c72", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_99ce5fe99069748d": { "inputs": { "posts": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_efea6cc2cb0535d9", "output": "posts" } ] }, "previousState": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_99ce5fe99069748d", "output": "state" } ] }, "summary": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_60be6ad3b7af251e", "output": "output" }, { "kind": "node", "nodeId": "n_92453ad574a02fd5", "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_3376012ee3b8336a", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_19a6058b83db3ab9": { "inputs": {}, "name": "More eligible posts", "kind": "condition", "matchMode": "first", "cases": [ { "output": "classify", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_99ce5fe99069748d", "output": "more" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_b675cdf07667080c": { "inputs": { "post": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_99ce5fe99069748d", "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_fa06132bb4e1c812": { "inputs": { "answer": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b675cdf07667080c", "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_e007a3a32720d53b", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_0f27eb11fb70ee3b": { "inputs": {}, "name": "Post is relevant", "kind": "condition", "matchMode": "first", "cases": [ { "output": "summarize", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_fa06132bb4e1c812", "output": "relevant" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_60be6ad3b7af251e": { "inputs": { "post": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_99ce5fe99069748d", "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_92453ad574a02fd5": { "inputs": {}, "name": "Skip unrelated post", "kind": "task", "task": { "inputs": [], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "summary" } ], "name": "Skip unrelated post", "moduleId": "n_d4f91475af84185a", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_4728b8408fc5140b": { "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_99ce5fe99069748d", "output": "results" } ] } } } }, "edges": [ { "source": "n_9dae45c52c7c7e67", "target": "n_fa79ab5fbf6bb56e" }, { "source": "n_fa79ab5fbf6bb56e", "target": "n_250c674a3b73a28a" }, { "source": "n_250c674a3b73a28a", "target": "n_58ca8b571395a84f", "sourceHandle": "fetch" }, { "source": "n_58ca8b571395a84f", "target": "n_fa79ab5fbf6bb56e" }, { "source": "n_250c674a3b73a28a", "target": "n_efea6cc2cb0535d9", "sourceHandle": "otherwise" }, { "source": "n_efea6cc2cb0535d9", "target": "n_99ce5fe99069748d" }, { "source": "n_99ce5fe99069748d", "target": "n_19a6058b83db3ab9" }, { "source": "n_19a6058b83db3ab9", "target": "n_b675cdf07667080c", "sourceHandle": "classify" }, { "source": "n_19a6058b83db3ab9", "target": "n_4728b8408fc5140b", "sourceHandle": "otherwise" }, { "source": "n_b675cdf07667080c", "target": "n_fa06132bb4e1c812" }, { "source": "n_fa06132bb4e1c812", "target": "n_0f27eb11fb70ee3b" }, { "source": "n_0f27eb11fb70ee3b", "target": "n_60be6ad3b7af251e", "sourceHandle": "summarize" }, { "source": "n_0f27eb11fb70ee3b", "target": "n_92453ad574a02fd5", "sourceHandle": "otherwise" }, { "source": "n_60be6ad3b7af251e", "target": "n_99ce5fe99069748d" }, { "source": "n_92453ad574a02fd5", "target": "n_99ce5fe99069748d" } ] } }, "modules": { "n_7389eae7efe9f32e": { "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_52484f6aa0724c72": { "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_3376012ee3b8336a": { "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_e007a3a32720d53b": { "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_d4f91475af84185a": { "name": "Skip unrelated post", "imports": [], "source": "export default function skip(){return{summary:null};}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }