Managed callback actions
Managed LLM providers can continue a call by returning messages, and can also ask Delphi to run configured call actions. This page is the field-level reference for those callback action payloads.
The most important rule: callback actions are requests, not permissions. The Flow Designer still controls which actions are enabled, which sources may send them, and which platform/team restrictions apply.
Where actions appear
For TOBi-style callbacks, actions are sent in the top-level actions array of the webhook body:
{
"conversation": {"identifier": {"id": "channel-123"}},
"messages": {
"message": [
{
"content": {
"textMessage": {
"textPlain": "I will connect you now."
}
}
}
]
},
"actions": [
{
"name": "transfer",
"value": {
"transferTarget": "tel:+491701234567",
"transferSipHeaders": [{"name": "X-Queue", "value": "care"}]
}
}
]
}
Each item has:
| Field | Type | Meaning |
|---|---|---|
name | string | Action name. Supported call-control names are transfer, handover, and hangup. |
value | object | Action-specific parameters. Unknown fields are ignored by the managed action mapper. |
handover is treated as a synonym for transfer.
Resolution and safety
When a callback action arrives, Delphi normalizes it into a runtime command with source: "external_llm", then resolves it against the flow's managed gateway settings.
Order of precedence:
- Callback action fields override the managed action defaults for that one call.
- Flow defaults in
gatewayProfile.actions.transfer/gatewayProfile.actions.hangupfill missing values. - Hard defaults apply only when neither the callback nor the flow sets a value.
gatewayProfile.commandPoliciesmust allow the command type fromexternal_llm.- Platform restrictions still apply: blocked destinations, missing trunks, SIP routing failure, or disabled managed actions can still reject the request.
SIP header arrays are limited to 100 headers and 12,000 total characters across names and values.
Failover and bot readiness use the same transfer/hangup action shapes, but they are configured in the flow rather than sent by the provider callback. See Failover activities and Bot readiness.
Runtime configuration updates
v0.9.14 lets managed providers update a small set of live-call runtime settings without granting separate transfer or hangup permissions.
| Command | Typical fields | Effect |
|---|---|---|
update_dtmf_config | maxDigits, timeoutMs, interDigitTimeoutMs, terminator, enabled | Changes how Delphi collects keypad input for the active TOBi-managed call. |
update_bot_delay_config | botNoInputTimeoutMs, botNoInputSpeech, botNoInputUrl, botNoInputRetries, botNoInputGiveUpTimeoutMs, resumeRecognitionTimeoutMs | Changes intermediate comfort-message and final give-up behavior while waiting for bot responses. |
These updates are runtime configuration changes for the current call. They do not bypass transfer restrictions, hangup policy, or provider permissions for actual call-control actions.
Example DTMF config update:
{
"name": "update_dtmf_config",
"value": {
"enabled": true,
"maxDigits": 6,
"timeoutMs": 8000,
"interDigitTimeoutMs": 2500,
"terminator": "#"
}
}
Example bot-delay config update:
{
"name": "update_bot_delay_config",
"value": {
"botNoInputTimeoutMs": 10000,
"botNoInputSpeech": "One moment, I am still checking that.",
"botNoInputRetries": 1,
"botNoInputGiveUpTimeoutMs": 30000
}
}
Transfer action
Use name: "transfer" or name: "handover" to request a handoff.
Transfer fields
| Callback field | Type | Maps to | Meaning |
|---|---|---|---|
transferTarget | string | target | Destination phone number, tel: URI, sip: URI, or sips: URI. A leading tel: prefix is stripped before execution. |
target | string | target | Alternative name for transferTarget. |
transferMethod | string | method | Transfer execution method. Supported values: sip_refer, sip_refer_replace, sip_invite, sip_invite_bridge, sip_invite_reinvite_p2p, sip_bye. |
transferReferredByURL | string | referredBy | Value for SIP Referred-By metadata when the method uses SIP referral semantics. |
transferNotifications | boolean | transferNotifications | Whether Delphi should keep notification/control behavior for transfer outcome handling when supported by the integration. |
transferNotificationsHangupMS | number | notificationsHangupMs | Grace period in milliseconds before disconnecting after a successful transfer notification path. Maximum 10000. |
transferRoutingPool | string | routingPool | Routing pool selector for number targets. Ignored for full SIP URI targets, which route by URI host. |
transferSipHeaders | array | sipHeaders | Explicit SIP headers to add to the transfer request. Overrides configured default headers for this call. |
transferSipQueryParams | object or array | sipQueryParams | Query parameters appended to the target / Refer-To URI. |
sipQueryParams | object or array | sipQueryParams | Alternative name for transferSipQueryParams. |
transferMessage | string | message | Alias for the transfer announcement message. |
transferPlayMessage | boolean | playMessage | Alias that controls whether Delphi plays the configured transfer message. |
transferCanConfirm | boolean | canConfirm | Alias that controls whether the provider may ask for confirmation before transfer. |
handoverReason | string | reason | SIP Reason text for sip_bye disconnect-reconnect transfers. |
hangupReason | string | reason | Fallback reason when handoverReason is not set. Used by sip_bye. |
transferTarget is required for all transfer methods except sip_bye. With sip_bye, the carrier can reroute based on BYE headers instead of a target URI.
Transfer methods
| Method | Behavior |
|---|---|
sip_refer | Blind SIP REFER handoff. |
sip_refer_replace | SIP REFER with replace/attended semantics where supported. |
sip_invite | Originates a new outbound leg and keeps the gateway in the media path. |
sip_invite_bridge | INVITE-based bridge behavior. |
sip_invite_reinvite_p2p | INVITE setup with peer-to-peer RTP re-INVITE when supported. |
sip_bye | Disconnect-reconnect handoff. Sends BYE with routing headers/reason so the carrier can reroute the caller. |
Header format
Use {name, value} objects for SIP headers:
{
"name": "transfer",
"value": {
"transferTarget": "sip:agent@pbx.example.com",
"transferSipHeaders": [
{"name": "X-Genesys-IPCC_Skill", "value": "care"},
{"name": "X-Delphi-Intent", "value": "billing"}
]
}
}
Query parameter format
transferSipQueryParams accepts either an object:
{
"name": "transfer",
"value": {
"transferTarget": "sip:agent@pbx.example.com",
"transferSipQueryParams": {
"X-Case": "12345",
"X-Language": "de-DE"
}
}
}
or an array of {name, value} pairs:
{
"name": "transfer",
"value": {
"transferTarget": "sip:agent@pbx.example.com",
"sipQueryParams": [
{"name": "X-Case", "value": "12345"},
{"name": "X-Language", "value": "de-DE"}
]
}
}
Transfer examples
Basic PSTN transfer:
{
"name": "transfer",
"value": {
"transferTarget": "tel:+491701234567"
}
}
Transfer through a routing pool with SIP headers:
{
"name": "transfer",
"value": {
"transferTarget": "+49301234567",
"transferRoutingPool": "support-pool",
"transferSipHeaders": [{"name": "X-Delphi-Reason", "value": "customer_requested_agent"}]
}
}
Disconnect-reconnect transfer using BYE headers:
{
"name": "transfer",
"value": {
"transferMethod": "sip_bye",
"handoverReason": "reroute_to_queue",
"transferSipHeaders": [
{"name": "X-Reroute", "value": "queue-7"},
{"name": "X-Caller-Language", "value": "de-DE"}
]
}
}
Hangup action
Use name: "hangup" when the provider decides the call should end.
Hangup fields
| Callback field | Type | Maps to | Meaning |
|---|---|---|---|
hangupReason | string | reason | Reason recorded for the hangup and, where applicable, placed on SIP signaling / call status data. |
hangupSipHeaders | array | sipHeaders | SIP headers to add to the BYE message. Overrides configured default BYE headers for this call. |
botOperationResult | string | botOperationResult | Bot outcome recorded for CDR/call-status use. Supported values: success, failure. |
botOperationData | object | botOperationData | Additional structured bot outcome data recorded with the operation result. |
Hangup execution also uses the flow's configured hangup defaults. Full playback and disconnect order: Speech playback and hangup.
| Flow setting | Effect |
|---|---|
waitForSilence | Whether Delphi waits for active TTS playback before disconnecting. Defaults to true. |
farewellMessage | Optional message Delphi can play before the hangup. |
allowMessageOverride | Whether a runtime hangup command may replace the configured farewell message. |
delayBotDisconnectMs | Grace period after wait-for-silence, before the channel hangup. Maximum 30000. |
headerRules | Outbound Channel Data Forwarding rules that produce BYE headers from call metadata. |
Hangup examples
End the call with a reason:
{
"name": "hangup",
"value": {
"hangupReason": "conversationCompleted"
}
}
End the call and add BYE headers:
{
"name": "hangup",
"value": {
"hangupReason": "conversationCompleted",
"hangupSipHeaders": [
{"name": "X-Genesys-hangupReason", "value": "conversationCompleted"},
{"name": "X-Genesys-IPCC_Skill", "value": "care"}
]
}
}
Record a bot operation outcome:
{
"name": "hangup",
"value": {
"hangupReason": "done",
"botOperationResult": "success",
"botOperationData": {
"feedback": "cooperative",
"intent": "appointment_confirmed"
}
}
}
Failover activities
Failover activities are configured on the managed gateway profile, not sent by callback. They describe what Delphi should do when a runtime failure happens after the call is already active.
Failover is stored under gatewayProfile.failover:
{
"gatewayProfile": {
"failover": {
"enabled": true,
"botNoInputGiveUpTimeoutMs": 30000,
"botNoInputTimeoutMs": 10000,
"botNoInputSpeech": "One moment, I am still checking that.",
"botNoInputRetries": 1,
"policies": [
{
"triggers": ["bot_timeout"],
"action": "transfer",
"transfer": {
"target": "+49301234567",
"method": "sip_refer",
"routingPool": "support-pool",
"sipHeaders": [{"name": "X-Failover", "value": "bot_timeout"}]
}
},
{
"triggers": ["bot_error", "system_error"],
"action": "hangup",
"hangup": {
"reason": "failover",
"sipHeaders": [{"name": "X-End-Reason", "value": "failover"}]
}
}
]
}
}
}
Failover fields
| Field | Type | Meaning |
|---|---|---|
enabled | boolean | Enables failover processing for the managed gateway profile. |
botNoInputGiveUpTimeoutMs | number | Final no-response watchdog for bot_timeout. Replaces botResponseTimeoutMs; allowed range depends on the active flow validation. |
botNoInputTimeoutMs | number | Intermediate no-input timeout before playing a comfort message. |
botNoInputSpeech / botNoInputUrl | string | Comfort message text or media URL played while waiting for the bot. |
botNoInputRetries | number | Number of intermediate comfort attempts before the final give-up timeout. |
policies[] | array | Ordered failover steps. Delphi evaluates matching policies in array order. Maximum 10. |
policies[].triggers[] | array | Failure classes that activate the policy. |
policies[].action | string | transfer or hangup. |
policies[].transfer | object | Transfer action shape. Uses the same fields as managed transfer defaults: target, method, mediaMode, message, playMessage, canConfirm, maxRingTime, callerId, referredBy, disconnectBotLeg, transferNotifications, notificationsHangupMs, routingPool, sipHeaders, sipQueryParams, reason. |
policies[].hangup | object | Hangup action shape. Uses the same fields as managed hangup defaults: reason, waitForSilence, sipHeaders, delayBotDisconnectMs, botOperationResult, botOperationData. |
policies[].description | string | Optional human-readable note for reviewers. |
Failover triggers
| Trigger | When it fires |
|---|---|
bot_timeout | The managed bot/LLM reaches the final botNoInputGiveUpTimeoutMs watchdog without producing a response. |
bot_error | The managed bot/LLM returns or raises an error. |
stt_error | Speech-to-text setup or runtime processing fails. |
tts_error | Text-to-speech setup or runtime playback fails. |
system_error | Internal gateway/runtime error. |
Transfer failover is converted into a normalized runtime command with source: "flow_engine" and then follows the same transfer validation as callback-triggered transfer. Hangup failover follows the same hangup validation and SIP BYE header handling as callback-triggered hangup.
Bot readiness
Bot readiness is pre-answer inbound handling. It decides whether Delphi answers immediately or waits until provider preparation, such as TOBi createConversation, succeeds.
Readiness can be configured as a flow-wide default under gatewayProfile.inbound, and entry points can override it with their own inbound block.
{
"gatewayProfile": {
"inbound": {
"answerWhen": "ready",
"readyTimeoutMs": 5000,
"onNotReady": "transfer",
"transfer": {
"target": "+49301234567",
"method": "sip_refer",
"routingPool": "support-pool",
"sipHeaders": [{"name": "X-Not-Ready", "value": "tobi_timeout"}]
}
}
}
}
Readiness fields
| Field | Type | Meaning |
|---|---|---|
answerWhen | string | ready waits until inbound readiness gates pass before sending SIP 200 OK; immediate answers without waiting. Default ready. |
readyTimeoutMs | number | Maximum wait for readiness before onNotReady runs. Maximum 60000; default 5000. Ignored when answerWhen is immediate. |
onNotReady | string | What to do when readiness fails or times out. Values: busy, hangup, transfer. Default busy. |
hangup | object | Used when onNotReady is hangup. Supports reason, sipHeaders, and headerRules. |
transfer | object | Used when onNotReady is transfer. Supports target, method, mediaMode, routingPool, sipHeaders, headerRules, maxRingTime, callerId, referredBy, and reason. |
Not-ready actions
onNotReady | Behavior |
|---|---|
busy | Rejects the inbound call with SIP busy behavior before answer. |
hangup | Ends the call with optional SIP Reason/header data. This path resolves through the managed hangup action with waitForSilence: false. |
transfer | Answers, then transfers the caller to the configured target. This path resolves through the managed transfer action. |
Use readiness for failures before the provider is ready to talk to the caller. Use failover for failures after the live managed interaction has started.
Related flow settings
The callback values above are per-call overrides. Persistent defaults live in the Flow Designer:
- Managed action inspector — UI for transfer and hangup defaults.
- Source view — JSON shape of
gatewayProfile.actions. - Webhooks — callback endpoint, auth, and delivery behavior.
- Speech playback and hangup — TTS queueing,
waitForSilence, anddelayBotDisconnectMsbehind hangup callbacks.