Inbound Runtime Variables
When an inbound call is bridged to an agent, Callaro passes a set of runtime_vars to the voice runtime in addition to the usual variables. Your prompt can branch on these to greet the caller appropriately, acknowledge the campaign they're returning to, or skip the introduction entirely.
These variables are only present on inbound calls. Outbound prompts continue to use existing campaign/contact variables.
Variables
| Key | Type | Description |
|---|---|---|
direction |
string | Always "inbound" for inbound calls. |
routing_reason |
string | Which layer of smart routing matched. One of active_campaign, retry_pending, active_followup, last_outbound, did_fallback, no_active_match. |
routing_layer |
string | Same as routing_reason but stable across renames; safe to switch on. |
inbound_routing_decision_id |
integer | DB id for the persisted decision trace; useful for support tickets. |
contact_id |
integer or null | Matched contact, if found. |
campaign_id |
integer or null | Matched bulk_call_campaign_id (when routing_reason is active_campaign or retry_pending). |
task_id |
integer or null | Matched bulk_call_task_id (when applicable). The task is closed as contacted_inbound before the agent picks up. |
follow_up_id |
integer or null | Matched follow_up_id (when routing_reason is active_followup). The follow-up is closed as contacted_inbound before the agent picks up. |
The full list of canonical contact variables (e.g. contact.first_name, contact.metadata.*) is also resolved when a contact is matched.
Sample prompt branches
You can branch greetings and intent based on routing_reason. Pseudocode for the agent prompt's opening lines:
{{#if routing_reason == "active_campaign"}}
Hi {{contact.first_name}}, thanks for calling back about
{{campaign.name}} — I was just trying to reach you.
{{else if routing_reason == "retry_pending"}}
Hi {{contact.first_name}}, perfect timing — I had a follow-up
scheduled for you on {{campaign.name}}.
{{else if routing_reason == "active_followup"}}
Hi {{contact.first_name}}, thanks for calling back —
I had a follow-up note for our last conversation.
{{else if routing_reason == "last_outbound"}}
Hi {{contact.first_name}}, thanks for getting back to me.
{{else}}
Hi, you've reached {{agent.name}}. How can I help?
{{/if}}
For non-conversational logic (tools, branches), prefer routing_layer since the value is stable across product renames.
Tips
- The
task_idandfollow_up_idare already closed by the time the agent answers. Do not call task-completion tools again — instead, use the IDs to look up history when you need it. direction == "inbound"is the easiest gate to keep inbound-only language out of outbound prompts.- For DID fallback (
routing_reason == "did_fallback"), most inbound-specific variables are null. Treat it like a cold inbound call. - If you see
routing_reason == "no_active_match", smart routing decided no agent was eligible; the call was bridged to the DID's agent (or unknown agent) anyway. This is rare and usually indicates an agent went inactive between the inbound webhook and the bridge.