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_id and follow_up_id are 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.

Related articles

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.