Callbacks let a campaign honor “call me back later” requests. The bot detects the request during the call, CXB API resolves a time, and CXB Dialler re-dials that contact with the highest priority once the time is due.

The double-gate

Callback detection only activates when both switches are on:
1

Bot: callback_prompt_injection

The bot has its callback toggle enabled. This injects the callback-detection instructions into the post-call analysis prompt so the LLM emits callback fields.
2

Campaign: config.callback_detection.enabled

The campaign running the call has callback detection enabled.
Both conditions are required: the API service injects the callback analysis prompt only when bot.callback_prompt_injection and campaign.config.callback_detection.enabled. Enabling one without the other does nothing.

What the bot extracts

When detection is active, post-call analysis emits these standard keys:
FieldMeaning
callback_requestedtrue if the customer asked to be called back, or the bot promised to call back.
callback_preferred_time_textThe customer’s exact words about when (e.g. “5 min baad”, “kal subah”, “shaam ko”).
callback_reasonShort reason (e.g. “busy”, “driving”, “not free”).
callback_confidence0.01.0 (≈0.95 clear request, ≈0.8 implied).
A callback is scheduled only when detection is enabled and callback_requested is true.

Time resolution

CXB API converts the free-text time into a concrete scheduled time in the campaign timezone (resolve_callback_time):
  • Relative phrases (“30 min”, “half an hour”, “2 hours”, “aadhe ghante”) add to the current time.
  • Day markers (“kal”/tomorrow, “parso”/day-after) and dayparts (“subah”/morning ≈ 10:00, “shaam”/evening ≈ 18:00) set the target day/time.
  • If no clear time is given, it falls back to the retry delay.
  • The resolved time is always clipped into the campaign’s calling window. Times outside the window move to the next valid window.

Scheduling and priority

A scheduled callback puts the contact into the callback_scheduled state with a due time (next_retry_at). When that time arrives, CXB Dialler leases it before fresh pending contacts and before retries:
callbacks  >  pending  >  retries
This is the dialler’s lease priority. Callbacks are dialled first so customer appointments are honored on time. See Pacing & retries. The callback attempt is tagged (kind="callback", with a callback_sequence) and the bot receives callback context (callback_preferred_time_text, callback_reason) in the connected event so it can open appropriately.

Single-day window cancellation

For a single_day campaign, when the calling window ends any still-waiting callback_scheduled contacts are cancelled — moved to window_closed with callback.status = "cancelled" and counted in callback_cancelled. They are not carried over.

Callback stats

The campaign tracks callbacks separately from ordinary retries:
StatMeaning
callback_pendingScheduled and waiting to be dialled.
callback_completedCallback attempts that reached a terminal state.
callback_cancelledCancelled (e.g. single-day window closed before due).
callback_exhaustedRan out of attempts.
A callback that fails on a retryable outcome is re-scheduled back into callback_scheduled (not retry_scheduled), so it keeps top priority. When it exhausts attempts or is torn down (e.g. amd_machine, abandoned), the callback is closed and the counters update.

Ops checklist

  • Bot callback toggle enabled.
  • Campaign callback detection enabled.
  • Post-call analysis prompt actually emits the callback keys (run a test call asking to be called back).
  • Campaign timezone is the customer’s contactable timezone (callback times are clipped to its window).
  • Watch callback_pending / callback_completed on the campaign to confirm callbacks are firing.