https://retellai.com/?utm_source=discord&utm_medium=seo logo
i have made a batch call through my app in retell...
# ❓・ai-evy-support
c
@AI Evy i have made a batch call through my app in retell but a lot of calls were voicemail and that automatic voice replying press 1 to speak with someone or even wrost a inifinity press x number menu how can we avoid this? i want to set as option that the ai can choose one of the options to talk with someone? or and if this is not possible that when is this type of call we hang up, including voicemail , also i watn to return the reuslts of this call the reason for hang up in my app like, voicemail, the automatic menu recorded and etc
a
Thanks for tagging me @Client Nexus. I'll look through relevant sources and get back to you shortly.
### Answer --- You can handle these scenarios with a few Retell features: ## Voicemail Detection Navigate to your agent settings → call settings and enable "Voicemail Detection". [(1) ]() You can choose one of two behaviors: - **Hang up**: The agent will disconnect when it detects a voicemail - **Leave a message**: The agent will leave a message after it's the agent's turn to speak If the call is detected as voicemail and the action was taken successfully, the call will have a disconnection reason of
voicemail_reached
. ## IVR Navigation (Press Digit) Your Retell AI agents can automatically navigate IVR menus using DTMF (digit-press) inputs. [(2) ]() Use the Press Digit node in the agent builder to configure when and what digits to press. ## Getting the Disconnection Reason To return results to your app, use the [Get Call]() API. The response includes a
disconnection_reason
field with values like: [(3) ]() -
voicemail_reached
-
user_hangup
-
agent_hangup
-
dial_busy
-
dial_no_answer
- And others
Copy code
javascript
const callResponse = await client.call.retrieve('119c3f8e47135a29e65947eeb34cf12d') ;
console.log(callResponse.disconnection_reason) ;
The
call_analysis
object in the response also includes an
in_voicemail
boolean field. ---
​ To learn more, see the sources I considered: [[1] Handle voicemail](https://docs.retellai.com/build/handle-voicemail) [[2] Platform Changelogs | Retell AI](https://www.retellai.com/changelog) [[3] Get Call](https://docs.retellai.com/api-references/get-call) ​
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
c
@AI Evy n Retell batch call details, is there any field like metadata / external_id / custom_id that we can set per lead (e.g., campaign_lead_id)?
a
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
### Answer Yes, in the Create Batch Call API, each task in the
tasks
array supports custom fields you can use to track leads. [(1) ]() Looking at the task object structure, you can use: -
retell_llm_dynamic_variables
– Key-value pairs of strings that inject into your prompt. You can store identifiers like
campaign_lead_id
here. -
metadata
– An arbitrary object for storage purposes only. You can put anything here like your internal customer ID or campaign lead ID associated with the call. It's not used for processing but can be retrieved later from the call object. [(2) ]() Example task structure:
Copy code
javascript
tasks: [
  {
    to_number: '+12137774445',
    retell_llm_dynamic_variables: {
      customer_name: 'John Doe',
      campaign_lead_id: 'your_lead_id_here'
    }
  }
]
[(1) ]() After the call completes, you can retrieve the
metadata
and
retell_llm_dynamic_variables
from the call object using the Get Call API to match results back to your leads.
​ To learn more, see the sources I considered: [[1] Create Batch Call](https://docs.retellai.com/api-references/create-batch-call) [[2] Create Phone Call](https://docs.retellai.com/api-references/create-phone-call) ​
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
c
@AI Evy We run outbound AI calls from Retell. In our app (Supabase + edge functions), campaigns/leads remain “pending” although Retell shows completed calls and recordings. Campaign: “Cold Call Sky 001 [99]” on subaccount “New Sky AI”. Retell batch_call_id: batch_call_298104f7ff9bcf636cb11. We need a reliable way to map Retell call results back to our leads. Questions: Does batch call API return per-call fields including recording_url, duration, outcome, error, and a stable lead identifier? Can we pass a per-lead metadata or external_id when creating batch calls, and will it be echoed back in webhook events / batch results? What webhook event(s) should we subscribe to for batch call completion & per-call updates? Please share payload examples.
a
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
### Answer --- ## 1. Per-Call Fields from the Get Call API Yes, you can retrieve detailed per-call fields using the Get Call API. The response includes: [(1) ]() -
recording_url
– URL to the call recording -
duration_ms
– Duration of the call in milliseconds -
disconnection_reason
– Outcome/error reason (e.g.,
agent_hangup
,
user_hangup
,
dial_failed
,
voicemail_reached
, etc.) -
call_id
– Unique identifier for the call -
metadata
– Your custom storage object passed when creating the call -
retell_llm_dynamic_variables
– Dynamic variables you passed (can include your lead identifier)
Copy code
javascript
import Retell from 'retell-sdk';
const client = new Retell({
  apiKey: 'YOUR_RETELL_API_KEY',
}) ;
const callResponse = await client.call.retrieve('119c3f8e47135a29e65947eeb34cf12d') ;
console.log(callResponse) ;
## 2. Passing Per-Lead Metadata in Batch Calls Based on community feedback, the batch call API does not currently support passing
metadata
or
override_agent_id
per individual task. [(2) ]() However, you can use
retell_llm_dynamic_variables
to pass identifiers like
campaign_lead_id
per task, and these will be available when you retrieve the call. [(1) ]() ## 3. Webhook Events for Call Updates Subscribe to these webhook events: [(3) ]() | Event Type | Description | |------------|-------------| |
call_started
| Triggered when a call begins | |
call_ended
| Triggered when a call completes, transfers, or errors | |
call_analyzed
| Triggered when post-call analysis completes | The
call_ended
webhook includes all fields from the call object except
call_analysis
. Sample webhook payload:
Copy code
json
{
  "event": "call_ended",
  "call": {
    "call_type": "phone_call",
    "from_number": "+12137771234",
    "to_number": "+12137771235",
    "direction": "inbound",
    "call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6",
    "agent_id": "oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD",
    "call_status": "registered",
    "metadata": {},
    "retell_llm_dynamic_variables": {
      "customer_name": "John Doe"
    },
    "start_timestamp": 1714608475945,
    "end_timestamp": 1714608491736,
    "disconnection_reason": "user_hangup",
    "transcript": "..."
  }
}
Key notes: - The webhook has a 10-second timeout and retries up to 3 times if no 2xx response is received - If
metadata
and
retell_llm_dynamic_variables
are not provided, they will be omitted from the webhook payload ## Recommended Approach Since per-task
metadata
isn't supported in batch calls yet, use
retell_llm_dynamic_variables
to pass your
campaign_lead_id
, then match it back in your
call_ended
webhook handler or when polling via Get Call API.
​ To learn more, see the sources I considered: [[1] Get Call](https://docs.retellai.com/api-references/get-call) [[2] Discord message from @gabe9001 on 2025-05-05](https://discord.com/channels/1186424376300679209/1186462578310910112/1368978866374181067) [[3] Webhook Overview](https://docs.retellai.com/features/webhook-overview) ​
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
c
@AI Evy what else besides ivr and voicemail detection rtell have to avoid calls that are not good, like much time with no response, no lead reply and etc?
a
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
### Answer --- Beyond IVR navigation and voicemail detection, Retell offers several agent settings to handle unproductive calls: ## End Call After Silence If users stay silent for a period after agent speech, the call will automatically end. [(1) ]() - Minimum value: 10,000 ms (10 seconds) - Default: 600,000 ms (10 minutes) You can configure
end_call_after_silence_ms
to a shorter duration to end calls faster when leads don't respond. [(2) ]() ## Reminder System for Unresponsive Users Configure the agent to prompt silent users before ending: [(1) ]() -
reminder_trigger_ms
– Triggers a reminder if the user is silent for the specified duration after agent speech. Default is 10,000 ms (10 seconds) . -
reminder_max_count
– Controls how many times the agent will remind an unresponsive user. Default is 1 (remind once) . Set to 0 to disable reminders entirely. ## Maximum Call Duration Set
max_call_duration_ms
to force-end calls that run too long: - Minimum: 60,000 ms (1 minute) - Maximum: 7,200,000 ms (2 hours) - Default: 3,600,000 ms (1 hour) ## Voicemail Detection Timeout
voicemail_detection_timeout_ms
configures when to stop running voicemail detection, since it becomes unlikely to hit voicemail after a couple minutes. - Minimum: 5,000 ms (5 seconds) - Maximum: 180,000 ms (3 minutes) - Default: 30,000 ms (30 seconds) These settings combined let you automatically end calls with no response, limit wasted time on unproductive calls, and get corresponding
disconnection_reason
values for tracking in your app.
​ To learn more, see the sources I considered: [[1] List Voice Agents](https://docs.retellai.com/api-references/list-agents) [[2] Get Agent Versions](https://docs.retellai.com/api-references/get-agent-versions) ​
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
c
@AI Evy can you confirm if i have the correct set up? Retell API Integration - Verified Correct: Feature Retell API Parameter Our Implementation Status Voicemail Detection enable_voicemail_detection ✅ Lines 206-226 in sync-agent Correct Voicemail Action voicemail_option.action.type ✅ hang_up or static_text Correct Voicemail Timeout voicemail_detection_timeout_ms ✅ Line 208 Correct Silence Reminder reminder_trigger_ms ✅ Line 230 Correct Reminder Count reminder_max_count ✅ Line 231 Correct End After Silence end_call_after_silence_ms ✅ Line 236 Correct Webhook Handling - Verified: handleCallEnded (lines 1709-1757) checks for voicemail_reached in disconnection_reason and correctly sets callOutcome = 'voicemail' Campaign leads are updated with the correct outcome One Minor Gap Found: The IVR handling UI exists but Retell's API doesn't have a direct parameter for IVR digit navigation - this is handled by Retell internally. The settings are stored for potential future use. Summary: The implementation is correct. Voicemail detection, silence reminders, and end-call-after-silence will sync to Retell and work when you save an agent. The webhook correctly tracks voicemail outcomes.
a
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
### Answer Based on the Retell AI API documentation, your parameter mapping looks correct. Here's confirmation against the documented fields: Voicemail Settings: -
enable_voicemail_detection
– Detects whether the call enters a voicemail (phone calls only) [(1) ]() -
voicemail_option.action.type
– Supports
static_text
(leave message) or
hang_up
-
voicemail_detection_timeout_ms
– Valid range: 5,000 ms to 180,000 ms, default 30,000 ms Silence/Reminder Settings: -
reminder_trigger_ms
– Triggers reminder after user silence, default 10,000 ms -
reminder_max_count
– Controls reminder count, default 1, set to 0 to disable -
end_call_after_silence_ms
– Minimum 10,000 ms, default 600,000 ms Voicemail Option Example Structure:
Copy code
json
{
  "action": {
    "type": "static_text",
    "text": "Please give us a callback tomorrow at 10am."
  }
}
Your webhook handling for
disconnection_reason
with
voicemail_reached
is the correct approach. Regarding IVR navigation: the API documentation for agent configuration does not expose a direct parameter for IVR digit navigation in the agent create/update endpoints. [(2) ]() , [(3) ]()
​ To learn more, see the sources I considered: [[1] Get Agent Versions](https://docs.retellai.com/api-references/get-agent-versions) [[2] Create Voice Agent](https://docs.retellai.com/api-references/create-agent) ​
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
c
@AI Evy Here's how delays between campaign steps work, check below and let me know fi will work with retell batch campaigns? Step Configuration: Each step in a campaign has waitTime and waitUnit properties (e.g., waitTime: 2, waitUnit: 'days') After Step Completion: When a step completes (e.g., call ends), the retell-call-webhook calculates the next step's scheduled time: waitMs = waitTime × unit_multiplier scheduledFor = now + waitMs minutes → waitTime × 60,000 ms hours → waitTime × 3,600,000 ms days → waitTime × 86,400,000 ms Scheduling: A record is inserted into scheduled_campaign_steps with scheduled_for timestamp and status: 'pending' Processing: The process-campaign-steps function (runs on cron) queries for pending steps where scheduled_for <= now() and executes them Stop Conditions: Before execution, it checks if: Campaign is still active Contact has replied (if stopOnReply enabled) Contact was manually stopped The delay is per-step (configured in each step's waitTime/waitUnit), not the campaign-level delay_minutes which is for rotation between accounts. Here's how delays between campaign steps work: Step Configuration: Each step in a campaign has waitTime and waitUnit properties (e.g., waitTime: 2, waitUnit: 'days') After Step Completion: When a step completes (e.g., call ends), the retell-call-webhook calculates the next step's scheduled time: waitMs = waitTime × unit_multiplier scheduledFor = now + waitMs minutes → waitTime × 60,000 ms hours → waitTime × 3,600,000 ms days → waitTime × 86,400,000 ms Scheduling: A record is inserted into scheduled_campaign_steps with scheduled_for timestamp and status: 'pending' Processing: The process-campaign-steps function (runs on cron) queries for pending steps where scheduled_for <= now() and executes them Stop Conditions: Before execution, it checks if: Campaign is still active Contact has replied (if stopOnReply enabled) Contact was manually stopped The delay is per-step (configured in each step's
a
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
### Answer Your multi-step campaign workflow approach is compatible with Retell batch calls, but you'll need to orchestrate the delays and scheduling on your side since Retell's batch call feature doesn't natively handle multi-step sequences with delays between steps. What Retell Batch Call Supports: - Immediate dispatch ("Send Now") or single scheduled time (
trigger_timestamp
as Unix timestamp in milliseconds) [(1) ]() - Call time windows to restrict when calls can run (specific hours and days of the week) [(2) ]()
Copy code
javascript
const batchCallResponse = await client.batchCall.createBatchCall({
  from_number: '+14157774444',
  tasks: [{ to_number: '+12137774445' }],
}) ;
[(1) ]() Your Approach Works Because: 1. You're using Retell's
call_ended
webhook to trigger your next step calculation 2. Your cron job (
process-campaign-steps
) creates new batch calls when
scheduled_for <= now()
3. Each step triggers a separate Retell batch call API request Key Integration Points: - Use
retell_llm_dynamic_variables
per task to track your
campaign_lead_id
so you can match call results back to your scheduled steps - Listen for
call_ended
webhooks to update your
scheduled_campaign_steps
table and calculate the next step's
scheduledFor
- Your stop conditions (campaign active, contact replied, manually stopped) are handled before calling the Retell API—this is correct Retell doesn't provide built-in multi-step campaign sequencing with delays, so your external orchestration via Supabase + cron is the right pattern.
​ To learn more, see the sources I considered: [[1] Create Batch Call](https://docs.retellai.com/api-references/create-batch-call) [[2] Platform Changelogs | Retell AI](https://www.retellai.com/changelog) ​
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
c
@AI Evy can you advise us in the below 1. CALENDAR FILTER INSTRUCTIONS (AI Selects Calendar) We have a "Filtered" calendar mode where the AI should intelligently select which calendar to book based on natural language instructions (e.g., "Use Sales Calendar for enterprise clients, Support Calendar for existing customers"). Options we're considering: A) System Prompt Injection: Include the filter instructions directly in the system prompt B) Tool Description: Add the instructions to the check_available_timeslots tool description C) Dynamic Variable: Pass as retell_llm_dynamic_variables with key like calendar_selection_rules Question: Which approach works best for the LLM to understand and apply calendar selection logic? Should the AI return a calendar_id parameter when calling the booking tool, or should it pass selection criteria that our backend interprets?
a
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
### Answer Based on Retell's documented features, here's guidance for your calendar selection approach: ## Recommended Approach: Combine System Prompt + Tool Description *Option A (System Prompt) * is best for defining the overall logic and decision criteria. The prompt engineering guide recommends structuring prompts with clear task instructions and using explicit tool calling instructions. [(1) ]() *Option B (Tool Description) * should include explicit triggers for when to call the tool and what parameters to pass. The documentation states: "Always specify exact conditions for tool usage in your prompts. Reference tools by their exact names." Example structure in your prompt:
Copy code
///## Tool Usage Instructions
1. Gather initial information about the customer's issue.
## Using Dynamic Variables for Context *Option C (Dynamic Variables) * works well for passing call-specific context like customer type. Dynamic variables can be used in tool descriptions and are injected at runtime. [(2) ]() You can pass context like:
Copy code
json
{
  "customer_name": "John Smith",
  "customer_type": "enterprise"
}
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
​ To learn more, see the sources I considered: [[1] Prompt Engineering Guide](https://docs.retellai.com/build/prompt-engineering-guide) [[2] Dynamic Variables](https://docs.retellai.com/build/dynamic-variables) [[3] Check Calendar Availability](https://docs.retellai.com/build/check-availability) ​
Dynamic variables work in tool descriptions, so you could reference
{{customer_type}}
in your tool description to help the LLM make the right selection. ## Architecture Recommendation Have the AI return a
calendar_id
parameter when calling the booking tool. This is cleaner because: 1. The LLM makes the selection based on your prompt instructions 2. Your backend receives a deterministic calendar ID 3. You can validate the selection server-side The Cal.com integration requires an
event_type_id
for each calendar/event type. [(3) ]() If you have multiple calendars, you'd configure separate tools or have the AI pass the appropriate ID based on your prompt logic.
### Answer --- ## Recommended Pattern: Conversation Flow + Tool Parameters Based on Retell's architecture, *Option B (Conversation Flow) * combined with *Option A (Tool Parameters) * is the recommended approach. ### Using Conversation Flow for Data Collection Conversation flows let you split complex conversations into distinct stages, each with its own prompt and allowed tools. [(1) ]() You can create nodes that sequentially collect information before reaching the booking tool:
Copy code
javascript
nodes: [
  {
    id: 'collect_info',
    type: 'conversation',
    instruction: {
      type: 'prompt',
      text: 'Ask the customer for their name and contact information.'
    }
  }
]
### Using LLM States for Multi-Step Collection If using Retell LLM (single/multi-prompt agent) , the
states
feature helps reduce prompt length and tool choices when the call can be broken into distinct states: [(2) ]()
Copy code
javascript
states: [
  {
    name: 'information_collection',
    state_prompt: 'You will follow the steps below to collect information...',
    edges: [
      {
        destination_state_name: 'appointment_booking',
        description: 'Transition to book an appointment.'
      }
    ]
  }
]
### Tool Parameter Structure For the booking tool itself, custom tools support parameters defined as an object with properties: [(3) ]()
Copy code
javascript
parameters: {
  type: 'object',
  properties: {
    message: {
      type: 'string',
​ To learn more, see the sources I considered: [[1] Create Conversation Flow](https://docs.retellai.com/api-references/create-conversation-flow) [[2] Create Retell LLM](https://docs.retellai.com/api-references/create-retell-llm) [[3] Integrate Function Calling](https://docs.retellai.com/integrate-llm/integrate-function-calling) ​
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
c
@AI Evy 2. RESTAURANT/BAR BOOKING - DATA COLLECTION For restaurant reservations, we need the AI to collect: party size, special requests (allergies, accessibility), reservation type (dining, bar, private event), and time preferences. Options we're considering: A) Tool Parameters: Add these as required/optional parameters in the book_appointment tool definition B) Pre-Booking Questions: Use a separate conversation flow before calling the booking tool C) Conversation Context: Let the AI collect naturally in conversation, then pass all data in a single booking_details object Question: What's the recommended pattern for collecting multiple booking details before executing a tool? Should each field be a separate tool parameter, or should we use a nested object structure?
a
You can define each field as a separate property within the
parameters
object, or use a nested structure depending on your backend requirements. ### Summary - Use conversation flow nodes or LLM states to guide the AI through collecting party size, special requests, reservation type, and time preferences - Define your booking tool with structured parameters (either flat or nested object) - Transition to the booking state/node only after required information is collected ---
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
c
@AI Evy 3. CALENDAR SELECTION FLOW When AI needs to select from multiple calendars based on context: Options we're considering: A) AI Selects Calendar ID: AI determines and passes specific calendar_id to booking tool B) AI Provides Criteria: AI passes criteria (e.g., client_type: "enterprise"), backend selects calendar C) Two-Step Flow: First call get_available_calendars tool, then call check_availability with selected calendar Question: Which flow provides the best accuracy and reliability? Does Retell support multi-step tool calling where the second call depends on the first call's response?
a
[(2) ]() The LLM receives this result and can then decide to call another tool based on the returned data. Accuracy consideration: Option B (backend selection) is most reliable for deterministic outcomes since your backend logic handles the mapping, but Option C gives the AI more context to make informed decisions during the conversation.
​ To learn more, see the sources I considered: [[1] Integrate Function Calling](https://docs.retellai.com/integrate-llm/integrate-function-calling) [[2] LLM WebSocket](https://docs.retellai.com/api-references/llm-websocket) [[3] Check Calendar Availability](https://docs.retellai.com/build/check-availability) ​
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
### Answer ## Multi-Step Tool Calling Support Yes, Retell supports multi-step tool calling where subsequent calls depend on previous results. The function calling integration allows the LLM to intelligently choose to output JSON containing arguments to call one or many functions. [(1) ]() When a tool call completes, you can send the result back and the LLM can then make additional tool calls based on that response. [(2) ]() ## Recommended Approach: Option A or C *Option A (AI Selects Calendar ID) * is simpler and works well if you include clear selection criteria in your prompt. The Cal.com integration requires an
event_type_id
for each calendar/event type. [(3) ]() *Option C (Two-Step Flow) * provides better accuracy for complex scenarios. You can: 1. First tool call:
get_available_calendars
returns list of calendars with IDs 2. Second tool call:
check_calendar_availability
or
book_appointment
with the selected calendar's
event_type_id
The LLM will process the first tool's response and use that information to make the second call. [(1) ]() ## Tool Call Result Handling When implementing multi-step flows, send tool call results back through the WebSocket:
Copy code
json
{
  "response_type": "tool_call_result",
  "tool_call_id": "unique_id",
  "content": "result_string"
}
### Answer ## Recommended Approach: Option B or C For tool call responses (like your booking tool) , return structured data that the AI can use to generate a natural confirmation. [(1) ]() ### Tool Call Response Structure When your booking tool completes, return the result as a string in the
content
field. The LLM will process this and generate a natural response. Recommended response structure:
Copy code
json
{
  "confirmation_number": "RES-12345",
  "status": "confirmed",
  "party_size": 4,
  "date": "2025-01-15",
  "time": "7:00 PM",
  "special_requests": "window seat, dairy allergy",
  "next_steps": "Arrive 10 minutes early. Cancellation requires 24-hour notice."
}
### Why Let the AI Generate Confirmation Naturally Based on how Retell handles tool results, returning structured data (Option B/C) is better than a verbatim
speak_message
because: 1. The LLM receives the tool result and incorporates it naturally into conversation 2. The AI can adapt tone and phrasing to match the conversation context 3. You avoid robotic-sounding verbatim readings ### Include Next Steps (Option C) Including
next_steps
or follow-up instructions in your response gives the AI additional context to communicate naturally—e.g., "You're all set for 7 PM on January 15th for 4 guests. Just a heads up, please arrive 10 minutes early and let us know at least 24 hours ahead if you need to cancel." Key point: The AI will use the returned data to construct its confirmation message, so include all details you want communicated.
​ To learn more, see the sources I considered: [[1] Inbound webhook](https://docs.retellai.com/features/inbound-call-webhook) ​
c
@AI Evy 4. WEBHOOK RESPONSE DATA After successful restaurant booking, what data should we return in the webhook response? Options we're considering: A) Confirmation Only: Just confirmation number and status B) Full Booking Details: Confirmation + all collected details (party size, requests, etc.) C) Confirmation + Follow-up: Include next steps or additional instructions for the AI to communicate Question: What's the optimal response structure for the AI to naturally confirm the booking with the customer? Should we include a speak_message field for the AI to read verbatim, or let it generate confirmation naturally from the data?
a
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
### Answer ## Recommended Approach: Handle Default in Backend Based on Retell's Cal.com integration, the
check_calendar_availability
function supports an optional timezone parameter that you can set during configuration. [(1) ]() From the setup steps: > "(optional) : add a timezone to be used in the function" ### Why Backend Default is Preferred 1. Simpler tool definition – Keep timezone as an optional parameter in your tool. If the AI doesn't pass it, your backend applies the business default. 2. Consistent behavior – Conditionally modifying tool parameters (required vs optional) between calls can introduce complexity. The LLM receives the tool definition at conversation start, so dynamically changing requirements mid-conversation isn't straightforward. 3. Fallback logic – Your backend can check: if
timezone
is provided, use it; otherwise, apply the business default timezone. ### Implementation Pattern For your two modes: - **Auto-detect mode**: Include timezone as an optional parameter. Instruct the AI in your prompt to ask for timezone if the customer hasn't mentioned it. - **Default timezone mode**: Include timezone as optional. Your backend applies the default when the parameter is omitted. This keeps your tool definition stable while letting your backend handle the conditional logic based on your mode setting.
​ To learn more, see the sources I considered: [[1] Check Calendar Availability](https://docs.retellai.com/build/check-availability) ​
### Answer Your tool definitions align with Retell's Cal.com integration structure. Here's confirmation: ## Check Availability Tool The documented setup includes: [(1) ]() - API Key from cal.com - Event Type ID - Tool description - (optional) : add a timezone to be used in the function ## Book Appointment Tool The documented structure shows: [(2) ]() - API Key from cal.com - Event Type ID - Tool description - (optional) : add a timezone to be used in the function ## API Response Structure Reference From the Retell LLM API, the
book_appointment_cal
tool type includes: [(3) ]()
Copy code
json
{
  "type": "book_appointment_cal",
  "name": "book_appointment",
  "description": "Book an annual check up.",
  "cal_api_key": "cal_live_xxxxxxxxxxxx",
  "event_type_id": 60444,
  "timezone": "America/Los_Angeles"
}
## Important Note on
{{current_time}}
Community feedback indicates you should include
{{current_time}}
in your prompt for date handling: [(4) ]() > "You have to use
{{current_time}}
in your prompt" > "You can say something like: This is today's date and time:
{{current_time}}
. Please consider this in checking calendar availability and booking." This helps prevent issues with relative dates ("tomorrow", "next week") being misinterpreted. [(5) ]() Your parameter structure looks correct. The main adjustment would be ensuring
{{current_time}}
is referenced in your prompts for accurate date handling.
​ To learn more, see the sources I considered: [[1] Check Calendar Availability](https://docs.retellai.com/build/check-availability) [[2] Book Calendar](https://docs.retellai.com/build/book-calendar) [[3] List Retell LLMs](https://docs.retellai.com/api-references/list-retell-llms) [[4] Issue with book_appointment function](https://discord.com/channels/1186424376300679209/1341725205445476413) [[5] Discord message from @melvinglenford on 2025-03-06](https://discord.com/channels/1186424376300679209/1186462578310910112/1347206753783250995) ​
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
c
@AI Evy Current Tool Definitions Reference: { "check_available_timeslots": { "parameters": { "date": "required - YYYY-MM-DD format", "timezone": "conditionally required based on agent config" } }, "book_appointment": { "parameters": { "date": "required", "time": "required", "timezone": "required", "customer_name": "required", "customer_email": "optional", "customer_phone": "optional" } } }
@AI Evy 5. TIMEZONE HANDLING CONFIRMATION We currently have two modes: Auto-detect: AI asks customer for timezone if not known Default timezone: Use business default without asking We implement this by conditionally including timezone as a required parameter in the check_available_timeslots tool. Question: Is conditionally modifying tool parameters (required vs optional) the correct approach, or should we always include timezone and handle the default in our backend?
a
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
c
@AI Evy is this correct? we had an issue where we launch the campaign in our app but ithe emtrics were not update there even though it was in retell 📋 Retell Batch Call Integration Setup Outbound Flow (Your App → Retell) execute-campaign → Retell create-batch-call API Payload sent to Retell: { "from_number": "+14159425808", "override_agent_id": "agent_xxx", "name": "Campaign: Campaign Name (timestamp)", "tasks": [ { "to_number": "+1234567890", "retell_llm_dynamic_variables": { "__subaccount_id__": "uuid", "__agent_id__": "uuid", "__contact_id__": "uuid", "campaign_lead_id": "uuid", // Key for tracking "campaign_id": "uuid", "contact_name": "John Doe", // ... other variables }, "metadata": { "campaign_id": "uuid", "contact_id": "uuid", "subaccount_id": "uuid", "source": "batch_campaign" } } ] } Inbound Flow (Retell → Your App) Retell sends webhooks to retell-webhook-handler: call_started → Creates/updates call record with campaign metadata call_ended → Updates campaign_leads with outcome, duration, recording call_analyzed → Adds transcript and AI summary Manual Sync (sync-batch-call-results) Call this to pull latest results from Retell: POST /functions/v1/sync-batch-call-results { "campaignId": "uuid" }
a
Thanks for the follow-up, @Client Nexus. I'll get back to you soon.
### Answer --- Your batch call payload structure looks correct based on the documented API. [(1) ]() ## Create Batch Call API Structure The required fields are: -
from_number
(required) - E.164 format -
tasks
(required) - Array of call tasks -
name
(optional) - For your reference Each task supports: -
to_number
-
retell_llm_dynamic_variables
-
metadata
## Webhook Events for Tracking Retell sends these webhook events: [(2) ]() | Event Type | Description | |------------|-------------| |
call_started
| Triggered when a new call begins | |
call_ended
| Triggered when a call completes, transfers, or encounters an error | |
call_analyzed
| Triggered when call analysis is complete | Important: If the call did not connect (like
dial_failed
) , the
call_started
webhook will not be triggered, but
call_ended
and
call_analyzed
will still fire. ## Likely Issue: Metrics Not Updating Your webhook flow looks correct. If metrics aren't updating in your app but appear in Retell, check: 1. Webhook delivery - Retell has a 10-second timeout and retries up to 3 times if no 2xx response is received 2. Matching call data - Use the
metadata
and
retell_llm_dynamic_variables
you pass to match calls back to your campaign records. These are returned in the webhook payload. 3. Manual sync fallback - You can retrieve call details using the Get Call API with the
call_id
[(3) ]() or List Calls API [(4) ]() to pull results if webhooks fail. Regarding batch call completion notifications: there's no documented batch-level webhook event when all calls finish. [(5) ](
505937952/1337135932528136287) You'd need to track individual
call_ended
events or poll the API.
Feel free to tag @AI Evy with additional questions. I also appreciate feedback, it helps me improve.