unholdCallstableResume call
Stops the hold music started by an earlier "Place caller on hold" step and clears the on-hold flag. Auto-advances to the next step.
What it does
Takes the caller off hold. The node stops whatever audio is playing on the
caller leg, closes the most recent open row in call_holds (stamping its
endedAt and computing durationSecs), and clears the on-hold state
flag. The flow auto-advances to the next node immediately — there's no
hold-specific event to wait for.
Use this any time you've called Hold call earlier in the flow and the
work that prompted the hold is done. The caller hears the music stop and
silence (until a subsequent say, bridge, or playback brings audio back).
If no open hold row exists when this runs (the caller wasn't actually on
hold), the close is a no-op and the playback-stop is harmless — so it's
safe as a defensive resume.
When to use it
- Right after a
customScriptlookup completes, before bridging the caller to an agent - After a successful
transferthat's about to bridge — stop the music so the caller hears the agent's hello - At the top of a recovery branch when re-entering the main flow from a hold-and-resume sub-flow
- As a defensive cleanup before terminal nodes if your flow has multiple hold paths and you want a single "definitely-not-on-hold" point
Configuration
The node has no configuration fields — it just resumes.
Stops the hold music started by an earlier "Place caller on hold" step and clears the on-hold flag. Auto-advances to the next step.
This node has no configurable fields.
Examples
Resume after a CRM lookup
Closes out an earlier holdCall once the lookup is done, then continues
to a personalized greeting.
{
"id": "resume-after-lookup",
"type": "unholdCall",
"config": {},
"on": { "call.hangup": "end" }
}
The flow auto-advances after the music stops. Like holdCall, the worker
takes the first transition in on for forward progress.
Gotchas
- Auto-advance picks the first transition. The worker uses
Object.values(node.on)[0]to find the next node. Keeponsmall — if you wire multiple edges, only the first one (in object order) is followed on entry. playback_stopis unconditional. The worker stops all playback on the caller leg, not just the hold music. If you've layered asayorplayAudioon top of hold music (rare, but possible), this cuts both. Sequence carefully.- No open hold row is fine. If
unholdCallruns without a matchingholdCallupstream, the close is a no-op (logged at warn level). The state flag still flips to false, which is what you want for defensive resumes. - Fires
onCallUnholdsynchronously before auto-advance. Symmetric withholdCallfiringonCallHold: the worker callsrunTriggerChains('onCallUnhold')after the playback stop and thecall_holdsclose, but before picking the next node. Side-chains on that trigger seevars._onHold === falseand run in an isolated state branch, so they can post webhooks or update CRMs without affecting the main flow's position. - Caller-initiated hangup during hold. If the caller hangs up while
on hold, the worker's hangup path closes any open hold row
automatically — you don't need to chase a manual
unholdCallfirst.
