{ "kind": "open-flow-workflow", "version": 1, "name": "Notify Workflow Failures on Slack", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_d7670004983846ce": { "name": "Receive a workflow failure", "kind": "error", "sourceFlowIds": [] }, "n_c7d45d1e705ebecc": { "inputs": { "workflow": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_d7670004983846ce", "output": "workflow" } ] }, "execution": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_d7670004983846ce", "output": "execution" } ] }, "error": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_d7670004983846ce", "output": "error" } ] } }, "name": "Prepare failure details", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "workflow" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "execution" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "error" } ], "outputs": [ { "jsonSchema": { "type": "string", "description": "Plain text message content. When blocks are provided, Slack uses this as notification and accessibility fallback text." }, "nullable": true, "handle": "text" } ], "name": "Prepare failure details", "moduleId": "n_8eb0d6d652c6ed18", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_c0bb07ef98da13e7": { "inputs": { "channelId": { "kind": "value", "value": "YOUR_SLACK_CHANNEL_ID" }, "text": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c7d45d1e705ebecc", "output": "text" } ] } }, "name": "Send Slack alert", "kind": "task", "task": { "inputs": [ { "description": "The Slack conversation or channel ID.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The Slack conversation or channel ID." }, "nullable": false, "handle": "channelId" }, { "description": "Plain text message content. When blocks are provided, Slack uses this as notification and accessibility fallback text.", "jsonSchema": { "type": "string", "description": "Plain text message content. When blocks are provided, Slack uses this as notification and accessibility fallback text." }, "nullable": true, "handle": "text", "value": null }, { "description": "Slack Block Kit blocks to render in the message.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "A Slack Block Kit block object. Pass the block exactly as Slack documents it." }, "minItems": 1, "description": "Slack Block Kit blocks to render in the message." }, "nullable": true, "handle": "blocks", "value": null }, { "description": "Slack legacy attachments to include in the message.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "A Slack legacy attachment object. Prefer blocks for new messages when possible." }, "minItems": 1, "description": "Slack legacy attachments to include in the message." }, "nullable": true, "handle": "attachments", "value": null }, { "description": "Whether Slack should unfurl links in the message.", "jsonSchema": { "type": "boolean", "description": "Whether Slack should unfurl links in the message." }, "nullable": true, "handle": "unfurlLinks", "value": null }, { "description": "Whether Slack should unfurl media in the message.", "jsonSchema": { "type": "boolean", "description": "Whether Slack should unfurl media in the message." }, "nullable": true, "handle": "unfurlMedia", "value": null }, { "description": "Slack message metadata to attach to the message.", "jsonSchema": { "type": "object", "properties": {}, "additionalProperties": true, "description": "Slack message metadata to attach to the message." }, "nullable": true, "handle": "metadata", "value": null } ], "outputs": [ { "description": "The timestamp identifier of the posted message.", "jsonSchema": { "type": "string", "description": "The timestamp identifier of the posted message." }, "nullable": false, "handle": "ts" }, { "description": "The channel ID where the message was posted.", "jsonSchema": { "type": "string", "description": "The channel ID where the message was posted." }, "nullable": false, "handle": "channelId" } ], "name": "Send Slack alert", "executor": { "kind": "connector", "action": "slack.post_message" } } } }, "edges": [ { "source": "n_d7670004983846ce", "target": "n_c7d45d1e705ebecc" }, { "source": "n_c7d45d1e705ebecc", "target": "n_c0bb07ef98da13e7" } ] } }, "modules": { "n_8eb0d6d652c6ed18": { "name": "Prepare failure details", "imports": [], "source": "export default function prepare({workflow,execution,error}) {\n if (typeof workflow?.name !== 'string' || !workflow.name || typeof execution?.runId !== 'string' || !execution.runId || typeof error?.message !== 'string') throw Error('Missing workflow failure details');\n const escape = value => String(value).replace(/&/g, '&').replace(//g, '>');\n const text = `Workflow: ${escape(workflow.name)}\\nRun ID: ${escape(execution.runId)}\\nLast node ID: ${escape(error.nodeId || 'not available')}\\nError: ${escape(error.message)}`;\n if (text.length > 40000) throw Error('Failure alert exceeds Slack message limit');\n return {text};\n}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }