The line
Hold, transfer, a person, touch tones, a call back: the commands that act on a call already running.
Seven commands act on a call already running, and they are how an agent hands what it is doing to
somebody else. They travel down the app socket like every call-scoped command ("call": "<id>",
refused with no_session when no gateway of the platform runs that call), and every one but
call.opt_out answers in the call's own log: the outcome is an entry, never a return value. A
command reaches the call whichever gateway the app is connected to: it is told on the call's own
channel, and the gateway holding its worker's command stream, or running its written session,
takes it.
| command | what happens |
|---|---|
call.transfer |
the caller is sent on, or the far end dialled in (below); lands as call.transferred |
call.attention |
a person is wanted: the caller holds until a supervisor takes the line or wait_s runs out; attention.requested, then attention.answered |
call.hold · call.unhold |
the caller waits with the hold melody and the agent goes mute and deaf, and back; call.line |
call.dtmf |
touch tones down the caller's own leg, for an IVR on the far end: 0-9, *, #, a comma for a pause |
call.opt_out |
the caller asked never to be called again: the number joins the org's do-not-call list, with the call beside it; nothing lands in the log, so an SDK that predates it reads the call as before |
call.callback |
the caller wants ringing back; callback.requested with via: "agent", which GET /v1/callbacks lists beside the widget's and the overflow's |
A transfer is two different things#
Cold is a REFER on the caller's own SIP leg: the carrier takes the call, the leg leaves the
room, and this call ends as transferred. It needs a phone call.
Warm dials the destination into this call's room over the org's outbound trunk (Numbers). Nobody moves: the caller hears ringing, and when the far end answers the agent goes mute and deaf and the two people have the call, until either hangs up.
A dialled leg passes the org's dial guards and lands in the same ledger as POST /v1/agents/{slug}/dial: the number's shape, the dials this minute and today. Refused, nothing is
dialled and call.transferred names the guard. The one guard a leg does not pass is the stranger
fence: the colleague a caller is put through to never had to ring the org. room.invite is judged
the same way.
mode is optional; unsaid, it is cold for a caller on a SIP leg and warm for one in a browser.
Asked by name, it is refused rather than swapped. A written conversation has no line:
call.transferred comes back with ok: false and says to ask for a person instead.
Asking for a person#
call.attention {reason, wait_s}: the reason is what a supervisor reads before taking the line;
wait_s has no default, because how long a caller will hold is the app's to decide. While the ask
is open the caller is on hold and state.attention is open. It ends as a supervisor's takeover
(ok: true, with who), as wait_s passing (ok: false, the agent has the caller back), or with
the call. A tool that asked for a person is still running while the caller waits, so its own
timeout must outlast wait_s; and a tool that comes back while a supervisor holds the line
produces no reply.