New to Kestra?
Use blueprints to kickstart your first workflows.
Trigger an n8n canary workflow via webhook, classify its response status, and alert Slack when n8n stops responding correctly.
n8n workflows quietly glue together lead routing, alerting, and integration logic that nobody notices is broken until a customer complains. A webhook misconfiguration, an expired credential inside a workflow node, or n8n itself being down all look identical from the outside unless something actually calls the webhook and checks the response. This blueprint uses plugin-n8n's TriggerWorkflow task to call a dedicated canary workflow on a schedule and classify exactly what kind of failure, if any, comes back.
trigger_canary_workflow (io.kestra.plugin.n8n.TriggerWorkflow) POSTs a small JSON payload to the canary workflow's webhook and waits for its response. plugin-n8n's own task implementation treats any non-200 HTTP response as a task failure, not a captured output, so allowFailure: true is what lets this flow tell "unreachable or non-200" apart from "reachable with the wrong content" instead of aborting outright.classify_canary_status (io.kestra.plugin.core.debug.Return) checks whether outputs.trigger_canary_workflow.statusCode is defined at all. If it is missing, the classification is PROBE_FAILED, covering both connectivity failures and non-200 responses. If it is defined and the response body's status field matches expected_status_value, the classification is CANARY_HEALTHY; otherwise CANARY_UNHEALTHY, meaning the webhook answered with HTTP 200 but the workflow itself reported something unexpected.route_by_canary_status (io.kestra.plugin.core.flow.Switch) branches on that string. CANARY_UNHEALTHY runs evaluate_alert_toggle (io.kestra.plugin.core.flow.If), which pages Slack via dispatch_canary_unhealthy_alert only when send_slack_alert is true, naming the exact mismatch, logging a suppressed-alert line otherwise. CANARY_HEALTHY logs a clean audit line. PROBE_FAILED pages Slack directly since canary health is now unknown. The defaults branch logs a fallback line that is unreachable under normal operation.log_audit_summary records a status line on every run regardless of branch, so execution history reads as a continuous n8n uptime trend.errors block pages Slack separately if the sentinel flow itself fails outright.n8n_canary_schedule trigger polls every 15 minutes with explicit input overrides, shipped disabled: true until pointed at a real canary workflow.status output (CANARY_HEALTHY / CANARY_UNHEALTHY / PROBE_FAILED) other flows can gate on before depending on n8n-driven automations.A one-off curl against the webhook proves it works for one instant and leaves no record. This flow keeps every canary call in Kestra's execution history, turns the result into a typed status output other flows can depend on, and gives you an If/Switch branch to grow into real remediation (restarting a workflow, opening a ticket) without rewriting the probe itself.
{"status": "ok"} (or whatever value matches expected_status_value).{"status": "ok"}, then activate it.N8N_CANARY_WEBHOOK_URL secret with that workflow's Production webhook URL, and the SLACK_WEBHOOK secret.status reads CANARY_HEALTHY.n8n_canary_schedule.Loop task, reusing the same trigger-and-classify shape per webhook.status into a KV store to alert only on state transitions instead of every run.CANARY_UNHEALTHY, chain a follow-up n8n webhook call that attempts a safe workflow re-activation, gated behind a dry-run toggle.N8N_CANARY_WEBHOOK_URL: production webhook URL of the dedicated canary n8n workflow; plugin-n8n marks this property as secret-worthy since the URL itself often doubles as the webhook's access control.SLACK_WEBHOOK: Slack incoming webhook used for the unhealthy, probe-failure, and flow-failure alerts.SECRET_N8N_CANARY_WEBHOOK_URL and SECRET_SLACK_WEBHOOK as base64, for example echo -n "<your-value>" | base64.expected_status_value (STRING, default "ok"): value expected under the canary workflow's JSON status field.send_slack_alert (BOOLEAN, default true): when true, page Slack on an unhealthy result; when "false", only log it.{{ outputs.trigger_canary_workflow.statusCode }}: HTTP status code returned by the n8n webhook, populated only on a 200 response.{{ outputs.trigger_canary_workflow.body }}: parsed JSON (or raw text) response body from the canary workflow.{{ outputs.classify_canary_status.value }}: classification string, one of CANARY_HEALTHY, CANARY_UNHEALTHY, PROBE_FAILED.{{ outputs.status }}: flow-level alias of the same classification.TriggerWorkflow task fails outright on any non-200 response rather than returning a captured status code; this blueprint relies on that behavior to fold "unreachable" and "non-200" together into PROBE_FAILED via allowFailure: true, it does not distinguish a 404 from a timeout from a 500.N8N_CANARY_WEBHOOK_URL at the Production webhook URL.outputs.trigger_canary_workflow.body.status assumes the canary workflow responds with Content-Type: application/json; plugin-n8n only parses JSON when that header is present, otherwise body is a raw string and this comparison will not match.To start a local n8n instance for testing, execute:
docker volume create n8n_data docker run -d --name kestra-n8n -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n
Open http://localhost:5678, build the canary workflow described in Quick start, and copy its Production webhook URL into the N8N_CANARY_WEBHOOK_URL secret.
If Kestra is running inside a Docker network, connect the n8n container to Kestra's network:
docker network connect YOUR_KESTRA_NETWORK kestra-n8n
(Run docker network ls to verify your active Kestra network name.)
