{ "kind": "open-flow-workflow", "version": 1, "name": "Morning Brief to LINE", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_69c369082dd0a709": { "name": "Every morning", "kind": "cron", "cronTimes": [ { "type": "cron", "expression": "0 8 * * *", "timezone": "UTC" } ] }, "n_f15bf5269578126d": { "inputs": { "tasks": { "kind": "value", "value": [ "Check emails", "Team standup at 10am", "Review pull requests" ] }, "timezone": { "kind": "value", "value": "UTC" } }, "name": "Build morning context", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "string" } }, "nullable": false, "handle": "tasks" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "timezone" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "date" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "tasks" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "prompt" } ], "name": "Build morning context", "moduleId": "n_43dd04703406d7e5", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_ada89af3ac69f3ad": { "inputs": { "prompt": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_f15bf5269578126d", "output": "prompt" } ] } }, "name": "Generate morning brief", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "items": { "type": "object" }, "type": "array" }, "nullable": true, "handle": "messages", "value": null }, { "jsonSchema": { "items": { "type": "object" }, "minItems": 1, "type": "array" }, "nullable": false, "handle": "template", "value": [ { "role": "user", "content": "{{prompt}}" } ] }, { "jsonSchema": { "type": "object" }, "nullable": false, "handle": "model", "value": { "model": "claude-haiku-4-5", "max_tokens": 300 } }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "prompt" } ], "outputs": [ { "description": "Generated response.", "jsonSchema": { "type": "string" }, "nullable": false, "handle": "output" } ], "name": "Generate morning brief", "executor": { "kind": "llm", "mode": "chat" } } }, "n_059045e3e378b2bc": { "inputs": { "summary": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ada89af3ac69f3ad", "output": "output" } ] } }, "name": "Format LINE message", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "summary" } ], "outputs": [ { "jsonSchema": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 5000, "description": "A non-empty text message preserved exactly as provided." }, "minItems": 1, "maxItems": 5, "description": "The text messages to send in order." }, "nullable": false, "handle": "texts" } ], "name": "Format LINE message", "moduleId": "n_ecd10232efa13b13", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_4b8fb3d55f45036c": { "inputs": { "to": { "kind": "value", "value": "YOUR_LINE_USER_ID" }, "texts": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_059045e3e378b2bc", "output": "texts" } ] } }, "name": "Send morning brief", "kind": "task", "task": { "inputs": [ { "description": "The target LINE user, group, or room ID.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The target LINE user, group, or room ID." }, "nullable": false, "handle": "to" }, { "description": "The text messages to send in order.", "jsonSchema": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 5000, "description": "A non-empty text message preserved exactly as provided." }, "minItems": 1, "maxItems": 5, "description": "The text messages to send in order." }, "nullable": false, "handle": "texts" }, { "description": "Whether LINE should suppress push notifications for the sent messages.", "jsonSchema": { "type": "boolean", "description": "Whether LINE should suppress push notifications for the sent messages." }, "nullable": true, "handle": "notificationDisabled", "value": null }, { "description": "An optional caller-generated UUID used by LINE to deduplicate a retried request.", "jsonSchema": { "type": "string", "format": "uuid", "description": "An optional caller-generated UUID used by LINE to deduplicate a retried request." }, "nullable": true, "handle": "retryKey", "value": null } ], "outputs": [ { "description": "The accepted LINE messages.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "The message identifier assigned by LINE." }, "quoteToken": { "type": "string", "description": "The token that can be used to quote this message." } }, "required": [ "id" ], "additionalProperties": false, "description": "A message accepted by LINE." }, "description": "The accepted LINE messages." }, "nullable": false, "handle": "sentMessages" } ], "name": "Send morning brief", "executor": { "kind": "connector", "action": "line.send_push_text" } } } }, "edges": [ { "source": "n_69c369082dd0a709", "target": "n_f15bf5269578126d" }, { "source": "n_f15bf5269578126d", "target": "n_ada89af3ac69f3ad" }, { "source": "n_ada89af3ac69f3ad", "target": "n_059045e3e378b2bc" }, { "source": "n_059045e3e378b2bc", "target": "n_4b8fb3d55f45036c" } ] } }, "modules": { "n_43dd04703406d7e5": { "name": "Build morning context", "imports": [], "source": "export default function buildContext({ tasks, timezone }) {\n if (!Array.isArray(tasks) || !tasks.every((task) => typeof task === 'string' && task.trim())) {\n throw new Error('tasks must be a list of non-empty strings');\n }\n const date = new Date().toLocaleDateString('en-US', {\n weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', timeZone: timezone,\n });\n const taskList = tasks.join('\\n- ');\n return {\n date,\n tasks: taskList,\n prompt: `Today is ${date}.\\n\\nMy tasks for today:\\n- ${taskList}\\n\\nPlease give me a motivating, concise morning brief (3-5 sentences) that:\\n1. Acknowledges today's date/day\\n2. Highlights the key priorities\\n3. Ends with one actionable focus tip`,\n };\n}\n" }, "n_ecd10232efa13b13": { "name": "Format LINE message", "imports": [], "source": "export default function lineText({ summary }) {\n if (typeof summary !== 'string' || !summary.trim()) throw new Error('The model returned no morning brief');\n const text = '🌅 Morning Brief\\n\\n' + summary;\n if (text.length > 5000) throw new Error('The morning brief exceeds the LINE message limit');\n return { texts: [text] };\n}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }