How to Escalate High-Priority Customer Emails to Slack and an On-Call Approver
Forward customer escalations to a Spojit mailhook, classify their severity with an Agent-mode Connector node, alert a Slack channel, and require an on-call approver to acknowledge the issue before the workflow closes.
What This Integration Does
When a customer escalation lands in your shared inbox, the slow part is not the reply: it is getting a human to notice, judge how serious it is, and own it. This workflow removes that gap. You forward escalation mail to a dedicated Spojit address, an Agent-mode Connector node reads the message and rates its severity, a Slack channel gets an instant alert with the summary, and a named on-call approver must acknowledge the alert in Spojit before the run is allowed to finish. Nothing falls silently through the cracks, and you keep an auditable record of who acknowledged each escalation.
The run starts the moment mail reaches your Mailhook address (push, within seconds, no mailbox or polling). Each message produces one execution: the email body flows into a Connector node in Agent mode that returns a structured severity rating, a Condition node branches on that rating, a Slack message is posted, and a Human node pauses the run until the on-call approver responds. Mailhook deduplicates per message, so a forwarded duplicate will not double-alert. If the approver rejects or the acknowledgement times out, the run halts and is recorded as not approved, which is exactly the signal you want for a missed escalation.
Prerequisites
- A Slack connection in Spojit (Connections -> Add connection -> Slack) with access to the channel where you want escalation alerts. See the Slack connector article and setting up an OAuth connection.
- The Slack channel created in advance, with the channel ID (for example
C0123456789) or channel name to hand. - The on-call approver added to your Spojit workspace as a user, role, or team so they can be selected as an approval slot. See creating and managing teams.
- A way to route escalation mail to one address (a forwarding rule in your help desk or an alias such as
escalations@yourcompany.com).
Step 1: Start the workflow with a Mailhook trigger
Create a new workflow and open the Trigger node. Set Trigger Type to Mailhook, give it an Address prefix such as escalations (1 to 24 characters), then click Generate email address. Spojit creates a unique address like escalations-3f9a17c4be2105d8@mailhook.spojit.com. Copy it and point your forwarding rule or alias at it.
To keep noise out, set the optional From allowlist to the addresses that are allowed to escalate (for example your help-desk forwarder), and an optional Subject regex such as (?i)escalat|urgent|sev. The trigger output is available downstream as {{ input }}, including {{ input.subject }}, {{ input.text }}, {{ input.from }}, and {{ input.replyTo }}.
Step 2: Classify severity with a Connector node in Agent mode
Add a Connector node, choose the code connector, and switch it to Agent mode so the agent reads the email and decides the rating. (Agent mode is the right choice here because severity is a judgement, not a fixed field.) Give it a prompt that feeds in the email content:
Read this customer escalation and rate its severity.
Subject: {{ input.subject }}
From: {{ input.from }}
Body:
{{ input.text }}
Return the severity as one of: critical, high, normal.
Critical = outage, data loss, security, or legal risk.
High = a paying customer is blocked with no workaround.
Normal = everything else.
Write one short sentence summarising the issue.
Define a Response Schema so the output is reliable JSON rather than prose:
{
"type": "object",
"properties": {
"severity": { "type": "string", "enum": ["critical", "high", "normal"] },
"summary": { "type": "string" }
},
"required": ["severity", "summary"]
}
Set the Output Variable to triage so later steps can read {{ triage.severity }} and {{ triage.summary }}. For more on forcing JSON, see using structured output for reliable AI data extraction.
Step 3: Branch on severity with a Condition node
Add a Condition node so only genuine escalations page a human. Configure the condition to test whether {{ triage.severity }} equals critical or high. Wire the true branch into the Slack alert in Step 4. On the false branch (a normal rating) you can add a Send Email node that simply replies to {{ input.replyTo }} confirming the message was received, then let the run end without paging anyone. This keeps the on-call channel reserved for real escalations. See using Condition nodes for the comparison options.
Step 4: Post the alert with the Slack connector
On the true branch, add a Connector node, choose the Slack connector in Direct mode, and pick the send-message tool. Map channel to your escalation channel ID (for example C0123456789) and build the text from the triage output and the original sender:
:rotating_light: *{{ triage.severity }}* escalation
{{ triage.summary }}
From: {{ input.from }}
Subject: {{ input.subject }}
Awaiting on-call acknowledgement in Spojit.
Direct mode is correct here because this is a single, predictable call with no AI cost. If you want the channel to react visually, you can follow with a second Slack Connector node using add-reaction on the posted message. To resolve a person from their email instead of hardcoding a channel, the Slack connector also exposes lookup-user-by-email.
Step 5: Require an on-call acknowledgement with a Human node
Add a Human node immediately after the Slack alert so the run cannot close until someone owns the escalation. Set the Label to something like On-call acknowledgement and the Message to explain what is needed, pulling in context with variables:
{{ triage.severity }} escalation from {{ input.from }}.
{{ triage.summary }}
Acknowledge to confirm you are taking ownership.
Set Urgency to High and a Timeout (minutes) that matches your on-call SLA, for example 30. In Approval slots, add one slot containing your on-call approver as a User, Role, or Team atom (any atom in a slot satisfies it; every slot must be satisfied for the run to continue). Turn on Email approvers if you want them emailed in addition to seeing it in the Approvals inbox at /approvals. When the approver clicks Approve, the node outputs { approved: true, approvalId, outcome: "APPROVED" } and the run continues. A rejection or a timeout halts the run and records it as not approved. See using Human approval nodes and reviewing and responding to approvals.
Step 6: Confirm ownership back in Slack and reply to the customer
After the Human node, add one more Slack Connector node in Direct mode using send-message to confirm the escalation was acknowledged, so the channel sees it is being handled:
:white_check_mark: Acknowledged: {{ triage.severity }} escalation from {{ input.from }}.
Approval ID {{ acknowledgement.approvalId }}
Use the Human node's Output Variable (for example acknowledgement) to reference {{ acknowledgement.approvalId }}. Finally add a Send Email node that replies to the customer at {{ input.replyTo }} letting them know a named owner is now on the case. The Send Email node uses Spojit's built-in mail service, so no connection is required; just confirm the recipient is covered by your org allowlist under Settings -> General -> Email recipients. See using Send Email nodes.
Tips
- Build the skeleton fast with Miraxa, the intelligent layer across your automation: try "Build a workflow that watches a mailhook, rates the email severity, posts to Slack, and pauses on a Human approval node," then fine-tune each node in the properties panel.
- Keep the Response Schema enum tight (
critical,high,normal). A small fixed set makes the Condition node trivial and prevents surprise branch values. - Set the Human node Timeout (minutes) to your real SLA. A timed-out acknowledgement halts the run, which is the audit trail you want when an escalation went unanswered.
- Use the From allowlist and Subject regex on the trigger to stop newsletters or auto-replies from spawning escalation runs.
Common Pitfalls
- Mailhook is always asynchronous: there is no response to the sender. To reply to the customer, use a Send Email node to
{{ input.replyTo }}, not the trigger. - Every approval slot must be satisfied before the run continues (AND across slots). If you add the on-call person to two slots by mistake, the run waits for both. One slot is enough for a single acknowledger.
- Reject and timeout both halt the run; there is no "on reject do X" branch. If you need a fallback (for example escalate to a manager), put that logic before the Human node or in a separate workflow.
- Slack
send-messageneeds the bot to be a member of the target channel. If posts fail, invite the connection's app to the channel and confirm the channel ID is correct. - The forwarder address must be on the trigger From allowlist. If your help desk rewrites the From header, allowlist the rewritten address or the run will be filtered out.
Testing
Before you point real escalations at it, send a single test email to the Mailhook address with an obviously critical subject and body, then open the execution in your run history. Confirm the Connector node returned {{ triage.severity }} as critical, the Condition took the true branch, the Slack alert appeared in a test channel, and the Human node is paused in the Approvals inbox at /approvals. Approve it as the on-call user and verify the confirmation Slack message and the customer reply both send. Repeat with a normal-severity email to confirm it skips the Slack alert and the approval. Once both paths behave, widen the trigger's From allowlist to your live forwarder and enable the workflow.