The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Incident Response Orchestrator",
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-976,
208
],
"id": "b3a32eb5-5bf3-4d70-bd98-dc44f0edb39c",
"name": "Manual Trigger (dev)",
"notes": "Manual trigger for local testing. Use the example payload node after this trigger."
},
{
"parameters": {
"httpMethod": "POST",
"path": "incident-response-orchestrator",
"responseMode": "lastNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-976,
464
],
"id": "96fc2b85-fc03-41f7-bd42-5a43392b412f",
"name": "Incident Webhook (prod)",
"notes": "Production entry point for PagerDuty, Opsgenie, Grafana, custom alerting, or another alert source. Configure authentication before external use."
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "52a6abdb-9fbb-4042-9eaa-db218dd09a25",
"name": "incident_id",
"value": "inc_2025_0012",
"type": "string"
},
{
"id": "3e0055ec-b9b8-4f65-96fb-77537da838e3",
"name": "service",
"value": "payments-api",
"type": "string"
},
{
"id": "d955fc84-2b7a-4b02-9cf7-a56794523b47",
"name": "severity",
"value": "SEV1",
"type": "string"
},
{
"id": "3a81d847-56d1-467f-8a4a-6bea25652a8f",
"name": "summary",
"value": "Payments API latency > 5s for 30% of requests",
"type": "string"
},
{
"id": "fa231414-0a01-41de-9553-dd89bff9fc11",
"name": "url",
"value": "https://pagerduty.com/incidents/inc_2025_0012",
"type": "string"
},
{
"id": "3ff5313d-c768-431b-82c3-43be423280d6",
"name": "environment",
"value": "production",
"type": "string"
},
{
"id": "b98eea2a-53c4-4a4d-9a80-db0efd9f19cc",
"name": "simulate_failures",
"value": "{}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-736,
208
],
"id": "a891d995-61c8-4682-9cf7-81de8737cdbc",
"name": "Set Example Alert Payload"
},
{
"parameters": {
"jsCode": "const payload = items[0]?.json ?? {};\nconst body = payload.body && typeof payload.body === 'object' ? payload.body : payload;\n\nconst required = ['incident_id', 'service', 'severity', 'summary'];\nconst missing = required.filter(field => body[field] === undefined || body[field] === null || String(body[field]).trim() === '');\nif (missing.length) {\n throw new Error(`Missing required incident fields: ${missing.join(', ')}`);\n}\n\nconst severity = String(body.severity).trim().toUpperCase();\nconst processSeverity = ['SEV1', 'SEV2'].includes(severity);\nlet simulateFailures = {};\ntry {\n simulateFailures = typeof body.simulate_failures === 'string'\n ? JSON.parse(body.simulate_failures || '{}')\n : (body.simulate_failures ?? {});\n} catch (error) {\n throw new Error('simulate_failures must be valid JSON');\n}\n\nconst normalised = {\n incident_id: String(body.incident_id).trim(),\n service: String(body.service).trim(),\n severity,\n summary: String(body.summary).trim(),\n url: body.url || body.alert_url || '',\n environment: body.environment || 'production',\n received_at: new Date().toISOString(),\n process_incident: processSeverity,\n ignored_reason: processSeverity ? null : 'Only SEV1/SEV2 incidents are orchestrated by this workflow',\n simulate_failures: simulateFailures,\n};\n\nreturn [{ json: normalised }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-496,
208
],
"id": "727ee5df-de0d-4c36-b007-5967b21f29a3",
"name": "Validate & Route Incident",
"notes": "Validates the alert payload, normalises severity and marks low-severity incidents as ignored rather than escalating them."
},
{
"parameters": {
"jsCode": "const incident = items[0]?.json ?? {};\nconst runAt = new Date().toISOString();\nconst base = `${incident.incident_id}:${incident.service}:${incident.severity}`;\nconst actions = ['collaboration', 'ticketing', 'status_page', 'on_call', 'incident_record'];\nconst idempotencyKeys = Object.fromEntries(actions.map(action => [action, `${base}:${action}`]));\n\nconst serviceMap = {\n 'payments-api': { team: 'payments-platform', on_call: 'alice@yourcompany.com', ticket_prefix: 'PAY', status_component: 'Payments API' },\n 'auth-api': { team: 'identity-platform', on_call: 'identity-oncall@yourcompany.com', ticket_prefix: 'AUTH', status_component: 'Authentication' },\n 'web-app': { team: 'web-platform', on_call: 'web-oncall@yourcompany.com', ticket_prefix: 'WEB', status_component: 'Web Application' },\n};\n\nconst owner = serviceMap[incident.service] ?? {\n team: 'platform-operations',\n on_call: 'platform-oncall@yourcompany.com',\n ticket_prefix: 'OPS',\n status_component: incident.service,\n};\n\nreturn [{\n json: {\n ...incident,\n owner,\n control: {\n generated_at: runAt,\n idempotency_keys: idempotencyKeys,\n retry_policy: {\n max_attempts: 3,\n backoff: 'exponential',\n retry_on: ['429', '408', '5xx', 'network_timeout'],\n notes: 'Apply this policy to real alerting, Slack/Teams, ticketing, status page and incident-store connector nodes.'\n },\n severity_policy: {\n orchestrate: ['SEV1', 'SEV2'],\n sev1_public_status_page: true,\n sev2_internal_status_page_default: true,\n }\n },\n enrichment_results: {},\n action_results: {},\n },\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-256,
208
],
"id": "4a5c6178-9b48-4cdd-9cae-5f7ffdf14299",
"name": "Prepare Incident Control",
"notes": "Adds owning team, on-call contact, retry policy and idempotency keys for all downstream orchestration actions."
},
{
"parameters": {
"jsCode": "const incident = { ...items[0].json };\nconst startedAt = new Date().toISOString();\ntry {\n if (incident.simulate_failures?.deploys) throw new Error('Simulated deploy history source failure');\n const deploys = [\n { id: 'deploy_8821', service: incident.service, version: '2025.04.18.3', deployed_at: '2025-04-18T09:41:00Z', actor: 'ci@yourcompany.com' },\n { id: 'deploy_8819', service: incident.service, version: '2025.04.18.1', deployed_at: '2025-04-18T07:15:00Z', actor: 'ci@yourcompany.com' },\n ];\n return [{ json: { ...incident, recent_deploys_result: { source: 'deploys', status: 'success', checked_at: startedAt, completed_at: new Date().toISOString(), count: deploys.length, deploys } } }];\n} catch (error) {\n return [{ json: { ...incident, recent_deploys_result: { source: 'deploys', status: 'failed', checked_at: startedAt, completed_at: new Date().toISOString(), error: error.message, deploys: [] } } }];\n}"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
0,
0
],
"id": "92fbf602-4060-4a19-93a4-f52fa130a821",
"name": "Fetch Recent Deploys (placeholder)",
"notes": "Credential-free enrichment placeholder. Replace with real HTTP/native connector nodes and keep the same structured status shape."
},
{
"parameters": {
"jsCode": "const incident = { ...items[0].json };\nconst startedAt = new Date().toISOString();\ntry {\n if (incident.simulate_failures?.related_tickets) throw new Error('Simulated related ticket source failure');\n const tickets = [\n { id: 'SUP-7712', title: 'Checkout timeout reports', status: 'open', priority: 'high' },\n { id: 'BUG-2219', title: 'Payments latency regression investigation', status: 'in_progress', priority: 'critical' },\n ];\n return [{ json: { ...incident, related_tickets_result: { source: 'related_tickets', status: 'success', checked_at: startedAt, completed_at: new Date().toISOString(), count: tickets.length, tickets } } }];\n} catch (error) {\n return [{ json: { ...incident, related_tickets_result: { source: 'related_tickets', status: 'failed', checked_at: startedAt, completed_at: new Date().toISOString(), error: error.message, tickets: [] } } }];\n}"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
0,
224
],
"id": "60d5f583-2101-4d9d-b553-33d2d98c29dc",
"name": "Fetch Related Tickets (placeholder)",
"notes": "Credential-free enrichment placeholder. Replace with real HTTP/native connector nodes and keep the same structured status shape."
},
{
"parameters": {
"jsCode": "const incident = { ...items[0].json };\nconst startedAt = new Date().toISOString();\ntry {\n if (incident.simulate_failures?.on_call_lookup) throw new Error('Simulated on-call lookup failure');\n const onCall = {\n email: incident.owner?.on_call || 'platform-oncall@yourcompany.com',\n escalation_policy: `${incident.owner?.team || 'platform'}-primary`,\n source: 'static_service_map_demo',\n };\n return [{ json: { ...incident, on_call_result: { source: 'on_call', status: 'success', checked_at: startedAt, completed_at: new Date().toISOString(), on_call: onCall } } }];\n} catch (error) {\n return [{ json: { ...incident, on_call_result: { source: 'on_call', status: 'failed', checked_at: startedAt, completed_at: new Date().toISOString(), error: error.message, on_call: null } } }];\n}"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
0,
448
],
"id": "11f47ef3-1424-431d-97c0-eba7e1b75efc",
"name": "Resolve On-call Contact (placeholder)",
"notes": "Credential-free enrichment placeholder. Replace with real HTTP/native connector nodes and keep the same structured status shape."
},
{
"parameters": {
"mode": "combine",
"combinationMode": "mergeByPosition",
"options": {}
},
"type": "n8n-nodes-base.merge",
"typeVersion": 2,
"position": [
272,
128
],
"id": "821cbbc9-876d-476e-bc0a-4fff30a2d37c",
"name": "Merge Deploys + Related Tickets"
},
{
"parameters": {
"mode": "combine",
"combinationMode": "mergeByPosition",
"options": {}
},
"type": "n8n-nodes-base.merge",
"typeVersion": 2,
"position": [
512,
304
],
"id": "c475137b-cabf-4b42-8861-69a19734db28",
"name": "Merge Enrichment + On-call"
},
{
"parameters": {
"jsCode": "const source = items[0]?.json ?? {};\nconst enrichment = {\n deploys: source.recent_deploys_result,\n related_tickets: source.related_tickets_result,\n on_call: source.on_call_result,\n};\n\nconst warnings = Object.values(enrichment)\n .filter(result => result && result.status !== 'success')\n .map(result => `${result.source}: ${result.status}${result.error ? ` (${result.error})` : ''}`);\n\nreturn [{\n json: {\n ...source,\n enrichment_results: enrichment,\n enrichment_warnings: warnings,\n },\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
752,
304
],
"id": "cdf6ea86-813e-40f9-807d-2c7a1a5b6c79",
"name": "Build Enriched Incident Object",
"notes": "Aggregates enrichment source statuses and carries source warnings into the live incident object."
},
{
"parameters": {
"jsCode": "const incident = { ...items[0].json };\nconst startedAt = new Date().toISOString();\nconst action = 'collaboration';\ntry {\n if (incident.simulate_failures?.collaboration) throw new Error('Simulated Slack/Teams channel creation failure');\n const channelName = `#inc-${incident.severity.toLowerCase()}-${incident.incident_id}`.replace(/[^#a-z0-9_-]/gi, '-').toLowerCase();\n const result = {\n action,\n status: 'success',\n idempotency_key: incident.control.idempotency_keys.collaboration,\n started_at: startedAt,\n completed_at: new Date().toISOString(),\n channel_name: channelName,\n channel_url: `https://your-slack-workspace.slack.com/archives/${channelName.replace('#','')}`,\n invited: [incident.enrichment_results?.on_call?.on_call?.email || incident.owner.on_call, 'incident-commander@yourcompany.com'],\n };\n return [{ json: { ...incident, collaboration_action_result: result } }];\n} catch (error) {\n return [{ json: { ...incident, collaboration_action_result: { action, status: 'failed', idempotency_key: incident.control?.idempotency_keys?.collaboration, started_at: startedAt, completed_at: new Date().toISOString(), error: error.message } } }];\n}"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1008,
0
],
"id": "4c749d9f-2be7-49e3-a58f-1f14554b85d5",
"name": "Setup Collaboration Channel",
"notes": "Demo-safe orchestration branch. Replace with real connector/API nodes while keeping structured action status and idempotency metadata."
},
{
"parameters": {
"jsCode": "const incident = { ...items[0].json };\nconst startedAt = new Date().toISOString();\nconst action = 'ticketing';\ntry {\n if (incident.simulate_failures?.ticketing) throw new Error('Simulated Jira/Linear ticket failure');\n const prefix = incident.owner?.ticket_prefix || 'OPS';\n const numeric = Math.abs([...incident.incident_id].reduce((sum, ch) => sum + ch.charCodeAt(0), 0)) % 9000 + 1000;\n const ticketId = `${prefix}-${numeric}`;\n const result = {\n action,\n status: 'success',\n idempotency_key: incident.control.idempotency_keys.ticketing,\n started_at: startedAt,\n completed_at: new Date().toISOString(),\n ticket_id: ticketId,\n ticket_url: `https://your-jira-instance/browse/${ticketId}`,\n };\n return [{ json: { ...incident, ticketing_action_result: result } }];\n} catch (error) {\n return [{ json: { ...incident, ticketing_action_result: { action, status: 'failed', idempotency_key: incident.control?.idempotency_keys?.ticketing, started_at: startedAt, completed_at: new Date().toISOString(), error: error.message } } }];\n}"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1008,
224
],
"id": "c06c7d64-134a-46b2-90a5-c8c2249eae3b",
"name": "Create or Update Incident Ticket",
"notes": "Demo-safe orchestration branch. Replace with real connector/API nodes while keeping structured action status and idempotency metadata."
},
{
"parameters": {
"jsCode": "const incident = { ...items[0].json };\nconst startedAt = new Date().toISOString();\nconst action = 'status_page';\ntry {\n if (incident.simulate_failures?.status_page) throw new Error('Simulated status page API failure');\n const shouldPublish = incident.severity === 'SEV1' || incident.control?.severity_policy?.sev2_internal_status_page_default;\n if (!shouldPublish) {\n return [{ json: { ...incident, status_page_action_result: { action, status: 'skipped', reason: 'Status page update not required by policy', started_at: startedAt, completed_at: new Date().toISOString() } } }];\n }\n const statusPageId = `sp_${incident.incident_id}`;\n const result = {\n action,\n status: 'success',\n idempotency_key: incident.control.idempotency_keys.status_page,\n started_at: startedAt,\n completed_at: new Date().toISOString(),\n status_page_id: statusPageId,\n status_page_url: `https://status.yourcompany.com/incidents/${statusPageId}`,\n audience: incident.severity === 'SEV1' ? 'public_or_customer_visible_by_policy' : 'internal',\n };\n return [{ json: { ...incident, status_page_action_result: result } }];\n} catch (error) {\n return [{ json: { ...incident, status_page_action_result: { action, status: 'failed', idempotency_key: incident.control?.idempotency_keys?.status_page, started_at: startedAt, completed_at: new Date().toISOString(), error: error.message } } }];\n}"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1008,
448
],
"id": "9947287e-ca1b-4011-b5fa-e6f3175195dd",
"name": "Create or Update Status Page",
"notes": "Demo-safe orchestration branch. Replace with real connector/API nodes while keeping structured action status and idempotency metadata."
},
{
"parameters": {
"jsCode": "const incident = { ...items[0].json };\nconst startedAt = new Date().toISOString();\nconst action = 'on_call';\ntry {\n if (incident.simulate_failures?.on_call_notify) throw new Error('Simulated on-call notification failure');\n const onCall = incident.enrichment_results?.on_call?.on_call?.email || incident.owner?.on_call || 'platform-oncall@yourcompany.com';\n const result = {\n action,\n status: 'success',\n idempotency_key: incident.control.idempotency_keys.on_call,\n started_at: startedAt,\n completed_at: new Date().toISOString(),\n notified: onCall,\n notification_channel: 'pager_or_dm_placeholder',\n };\n return [{ json: { ...incident, on_call_action_result: result } }];\n} catch (error) {\n return [{ json: { ...incident, on_call_action_result: { action, status: 'failed', idempotency_key: incident.control?.idempotency_keys?.on_call, started_at: startedAt, completed_at: new Date().toISOString(), error: error.message } } }];\n}"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1008,
672
],
"id": "a63a71cb-1386-4377-83cc-f9ce3e8e41e8",
"name": "Notify On-call Engineer",
"notes": "Demo-safe orchestration branch. Replace with real connector/API nodes while keeping structured action status and idempotency metadata."
},
{
"parameters": {
"mode": "combine",
"combinationMode": "mergeByPosition",
"options": {}
},
"type": "n8n-nodes-base.merge",
"typeVersion": 2,
"position": [
1264,
128
],
"id": "50a70be1-a9ef-4a9d-8655-db13889d826c",
"name": "Merge Collaboration + Ticketing"
},
{
"parameters": {
"mode": "combine",
"combinationMode": "mergeByPosition",
"options": {}
},
"type": "n8n-nodes-base.merge",
"typeVersion": 2,
"position": [
1264,
544
],
"id": "78d0354e-33c0-410d-9c74-17764b933e69",
"name": "Merge Status Page + On-call"
},
{
"parameters": {
"mode": "combine",
"combinationMode": "mergeByPosition",
"options": {}
},
"type": "n8n-nodes-base.merge",
"typeVersion": 2,
"position": [
1504,
352
],
"id": "df471f53-62f6-44c1-8002-8a2f3d9a1448",
"name": "Merge Incident Actions"
},
{
"parameters": {
"jsCode": "const source = items[0]?.json ?? {};\nconst actions = {\n collaboration: source.collaboration_action_result,\n ticketing: source.ticketing_action_result,\n status_page: source.status_page_action_result,\n on_call: source.on_call_action_result,\n};\nconst actionValues = Object.values(actions).filter(Boolean);\nconst failed = actionValues.filter(a => a.status === 'failed');\nconst succeeded = actionValues.filter(a => a.status === 'success');\nconst skipped = actionValues.filter(a => a.status === 'skipped');\n\nconst orchestration_status = failed.length\n ? (succeeded.length ? 'partial_success' : 'failed')\n : 'success';\n\nconst liveIncident = {\n incident_id: source.incident_id,\n service: source.service,\n severity: source.severity,\n summary: source.summary,\n environment: source.environment,\n owner_team: source.owner?.team,\n on_call_engineer: source.on_call_action_result?.notified || source.enrichment_results?.on_call?.on_call?.email || source.owner?.on_call,\n orchestration_status,\n slack_channel: source.collaboration_action_result?.channel_name,\n ticket_id: source.ticketing_action_result?.ticket_id,\n status_page_id: source.status_page_action_result?.status_page_id,\n links: {\n alert: source.url,\n collaboration: source.collaboration_action_result?.channel_url,\n ticket: source.ticketing_action_result?.ticket_url,\n status_page: source.status_page_action_result?.status_page_url,\n },\n enrichment_warnings: source.enrichment_warnings || [],\n failed_actions: failed.map(a => ({ action: a.action, error: a.error })),\n};\n\nreturn [{\n json: {\n ...source,\n action_results: actions,\n orchestration_status,\n live_incident: liveIncident,\n },\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1744,
352
],
"id": "0a42c545-8388-4e86-a647-0a11d178cef5",
"name": "Build Live Incident Object",
"notes": "Aggregates action outputs into one live incident object with links, owners, status and failed-action visibility."
},
{
"parameters": {
"jsCode": "const source = items[0]?.json ?? {};\nconst failedActions = Object.values(source.action_results ?? {}).filter(action => action?.status === 'failed');\nconst failedEnrichment = Object.values(source.enrichment_results ?? {}).filter(result => result?.status && result.status !== 'success');\nconst alerts = [];\nfor (const action of failedActions) {\n alerts.push({\n alert_type: 'incident_orchestration_action_failure',\n severity: source.severity,\n incident_id: source.incident_id,\n action: action.action,\n error: action.error,\n recommended_action: 'Check the connector/API credentials, rate limits, destination availability and idempotency record before retrying.',\n });\n}\nfor (const result of failedEnrichment) {\n alerts.push({\n alert_type: 'incident_enrichment_source_warning',\n severity: source.severity,\n incident_id: source.incident_id,\n source: result.source,\n status: result.status,\n error: result.error || null,\n recommended_action: 'Review whether the missing enrichment affects incident response decisions.',\n });\n}\nreturn [{ json: { ...source, operations_alerts: alerts } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1984,
352
],
"id": "f235ff20-dc8b-472c-8ae0-25aff1339bc0",
"name": "Prepare Operations Alerts",
"notes": "Creates alert payloads for failed orchestration actions or degraded enrichment sources. Replace/extend with Slack, email, PagerDuty or Opsgenie."
},
{
"parameters": {
"jsCode": "const source = items[0]?.json ?? {};\nconst inc = source.live_incident;\nconst lines = [];\nlines.push(`# ${inc.severity} Incident: ${inc.service}`);\nlines.push('');\nlines.push(`Incident ID: ${inc.incident_id}`);\nlines.push(`Summary: ${inc.summary}`);\nlines.push(`Owner team: ${inc.owner_team}`);\nlines.push(`On-call: ${inc.on_call_engineer}`);\nlines.push(`Orchestration status: ${inc.orchestration_status}`);\nlines.push('');\nlines.push('## Links');\nfor (const [label, url] of Object.entries(inc.links || {})) {\n if (url) lines.push(`- ${label}: ${url}`);\n}\nif (inc.enrichment_warnings?.length) {\n lines.push('');\n lines.push('## Enrichment warnings');\n for (const warning of inc.enrichment_warnings) lines.push(`- ${warning}`);\n}\nif (inc.failed_actions?.length) {\n lines.push('');\n lines.push('## Failed orchestration actions');\n for (const failure of inc.failed_actions) lines.push(`- ${failure.action}: ${failure.error}`);\n}\nlines.push('');\nlines.push('## Immediate next steps');\nlines.push('- Confirm incident commander and technical lead.');\nlines.push('- Confirm customer impact and mitigation plan.');\nlines.push('- Post first update according to communication policy.');\n\nreturn [{\n json: {\n ...source,\n incident_channel_update_markdown: lines.join('\\n'),\n notification_status: 'prepared_demo_payload_replace_with_slack_teams_or_email',\n },\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2224,
352
],
"id": "76672ce7-267d-4280-ae53-31273bd2f574",
"name": "Prepare Incident Channel Update",
"notes": "Builds the message that would be posted into the incident channel or sent to stakeholders."
},
{
"parameters": {
"jsCode": "const source = items[0]?.json ?? {};\nconst inc = source.live_incident ?? {};\nconst timeline = [\n { time: source.received_at, event: 'Incident alert received' },\n { time: source.control?.generated_at, event: 'Incident orchestration started' },\n { time: new Date().toISOString(), event: 'Live incident object assembled' },\n];\n\nconst prompt = `\nYou are drafting a post-incident review starting point for an engineering leadership team.\n\nUse only the incident facts below. Do not invent root cause, customer impact, financial impact, or corrective actions. Mark unknowns explicitly.\n\nIncident:\n${JSON.stringify(inc, null, 2)}\n\nTimeline:\n${JSON.stringify(timeline, null, 2)}\n\nRelated deploys:\n${JSON.stringify(source.enrichment_results?.deploys?.deploys || [], null, 2)}\n\nRelated tickets:\n${JSON.stringify(source.enrichment_results?.related_tickets?.tickets || [], null, 2)}\n\nReturn a Markdown post-incident review draft with sections: Summary, Impact, Timeline, Detection, Response, Known Unknowns, Follow-up Actions.\n`.trim();\n\nreturn [{\n json: {\n ...source,\n post_incident_review: {\n status: 'prompt_prepared_optional_llm_step_not_executed_in_live_response_path',\n data_policy: 'Use after the incident is stable or resolved. Keep deterministic incident records as the authority.',\n prompt,\n timeline,\n },\n },\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2464,
352
],
"id": "0155b7ef-730b-4671-8897-98aeda6cd8e1",
"name": "Prepare Post-Incident Review Prompt",
"notes": "Optional post-incident documentation prompt. Keep this outside the live response critical path; use it after stabilisation or resolution."
},
{
"parameters": {
"jsCode": "const source = items[0]?.json ?? {};\nconst auditRecord = {\n audit_type: 'incident_response_orchestration_result',\n logged_at: new Date().toISOString(),\n incident_id: source.incident_id,\n service: source.service,\n severity: source.severity,\n orchestration_status: source.orchestration_status,\n live_incident: source.live_incident,\n enrichment_results: source.enrichment_results,\n action_results: source.action_results,\n operations_alerts: source.operations_alerts,\n idempotency_keys: source.control?.idempotency_keys,\n retry_policy: source.control?.retry_policy,\n incident_channel_update_markdown: source.incident_channel_update_markdown,\n post_incident_review: source.post_incident_review,\n};\n\nreturn [{ json: { ...source, audit_record: auditRecord, audit_status: 'ready_for_durable_store' } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2704,
352
],
"id": "70438e3b-7f07-4c64-a9fd-473daa9b2ab9",
"name": "Log Audit Snapshot (demo)",
"notes": "Demo audit checkpoint. Replace or extend with an incidents database, object storage, Google Drive, Notion, Jira/Linear update, or data warehouse write."
}
],
"connections": {
"Manual Trigger (dev)": {
"main": [
[
{
"node": "Set Example Alert Payload",
"type": "main",
"index": 0
}
]
]
},
"Set Example Alert Payload": {
"main": [
[
{
"node": "Validate & Route Incident",
"type": "main",
"index": 0
}
]
]
},
"Incident Webhook (prod)": {
"main": [
[
{
"node": "Validate & Route Incident",
"type": "main",
"index": 0
}
]
]
},
"Validate & Route Incident": {
"main": [
[
{
"node": "Prepare Incident Control",
"type": "main",
"index": 0
}
]
]
},
"Prepare Incident Control": {
"main": [
[
{
"node": "Fetch Recent Deploys (placeholder)",
"type": "main",
"index": 0
},
{
"node": "Fetch Related Tickets (placeholder)",
"type": "main",
"index": 0
},
{
"node": "Resolve On-call Contact (placeholder)",
"type": "main",
"index": 0
}
]
]
},
"Fetch Recent Deploys (placeholder)": {
"main": [
[
{
"node": "Merge Deploys + Related Tickets",
"type": "main",
"index": 0
}
]
]
},
"Fetch Related Tickets (placeholder)": {
"main": [
[
{
"node": "Merge Deploys + Related Tickets",
"type": "main",
"index": 1
}
]
]
},
"Merge Deploys + Related Tickets": {
"main": [
[
{
"node": "Merge Enrichment + On-call",
"type": "main",
"index": 0
}
]
]
},
"Resolve On-call Contact (placeholder)": {
"main": [
[
{
"node": "Merge Enrichment + On-call",
"type": "main",
"index": 1
}
]
]
},
"Merge Enrichment + On-call": {
"main": [
[
{
"node": "Build Enriched Incident Object",
"type": "main",
"index": 0
}
]
]
},
"Build Enriched Incident Object": {
"main": [
[
{
"node": "Setup Collaboration Channel",
"type": "main",
"index": 0
},
{
"node": "Create or Update Incident Ticket",
"type": "main",
"index": 0
},
{
"node": "Create or Update Status Page",
"type": "main",
"index": 0
},
{
"node": "Notify On-call Engineer",
"type": "main",
"index": 0
}
]
]
},
"Setup Collaboration Channel": {
"main": [
[
{
"node": "Merge Collaboration + Ticketing",
"type": "main",
"index": 0
}
]
]
},
"Create or Update Incident Ticket": {
"main": [
[
{
"node": "Merge Collaboration + Ticketing",
"type": "main",
"index": 1
}
]
]
},
"Create or Update Status Page": {
"main": [
[
{
"node": "Merge Status Page + On-call",
"type": "main",
"index": 0
}
]
]
},
"Notify On-call Engineer": {
"main": [
[
{
"node": "Merge Status Page + On-call",
"type": "main",
"index": 1
}
]
]
},
"Merge Collaboration + Ticketing": {
"main": [
[
{
"node": "Merge Incident Actions",
"type": "main",
"index": 0
}
]
]
},
"Merge Status Page + On-call": {
"main": [
[
{
"node": "Merge Incident Actions",
"type": "main",
"index": 1
}
]
]
},
"Merge Incident Actions": {
"main": [
[
{
"node": "Build Live Incident Object",
"type": "main",
"index": 0
}
]
]
},
"Build Live Incident Object": {
"main": [
[
{
"node": "Prepare Operations Alerts",
"type": "main",
"index": 0
}
]
]
},
"Prepare Operations Alerts": {
"main": [
[
{
"node": "Prepare Incident Channel Update",
"type": "main",
"index": 0
}
]
]
},
"Prepare Incident Channel Update": {
"main": [
[
{
"node": "Prepare Post-Incident Review Prompt",
"type": "main",
"index": 0
}
]
]
},
"Prepare Post-Incident Review Prompt": {
"main": [
[
{
"node": "Log Audit Snapshot (demo)",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate",
"availableInMCP": false
},
"versionId": "6de299cb-ccca-4d64-8093-6024d2040085",
"id": "nL9GDJWxsy4rl5eC",
"tags": []
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Incident Response Orchestrator. Event-driven trigger; 23 nodes.
Source: https://github.com/tfest-dev/n8n-workflows/blob/main/incident-response-orchestrator/incident-response-orchestrator.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Reagendamiento. Uses executeWorkflowTrigger, redis, n8n-nodes-evolution-api, dataTable. Event-driven trigger; 73 nodes.
Blotato. Uses googleSheets, @blotato/n8n-nodes-blotato. Event-driven trigger; 65 nodes.
This template is a hands-on, practical exam designed to help you master n8n Expressions—the key to accessing and manipulating data in your workflows.
This template is a hands-on, practical exam designed to test your understanding of the fundamental JSON data types. It's the perfect way to solidify your knowledge after learning the basics.
Agendamiento. Uses n8n-nodes-evolution-api, redis, dataTable, executeWorkflowTrigger. Event-driven trigger; 60 nodes.