Language Reference
Design communication flows with Callr Actions — a declarative, YAML-based framework inspired by GitHub Actions.Whether you're routing calls, triggering events, or integrating with external services, Callr Actions lets you compose complex voice logic with simple building blocks.
This page describes the language of a scenario: branches, expressions, variables, conditions, goto and defaults. New to Callr Actions? Start with the Introduction. The parameters, results and examples of each action are in Actions.
TipWe recommend using the Callr Console to create your Callr Actions scenarios. It features a built-in code editor with autocomplete, inline documentation, and live testing to help you build faster.
Architecture
Call flows in Callr Actions are organized around branches – sequences of actions that determine your call’s behavior. There are four special branches:
inbound-call: The entry point for an Inbound Call.inbound-sms: The entry point for an Inbound SMS.api-initiated: The entry point for actions triggered via the API.hangup: Executed for Inbound Calls once the call is hung up.
You can also create additional branches to organize your logic. To jump between branches, use the built-in goto statement:
branches:
inbound-call:
actions:
- # your initial actions...
- if: '!$dial.ok'
goto:
branch: voicemail
voicemail:
actions:
- action: play@v3
params:
tts:
text: Sorry, we are not available at the moment.
JSON Schema ReferenceCallr Actions are defined by a JSON Schema, available here: YAML. You can use the schema to enable validation and auto-completion in your favorite code editor.
💡 Tip: The Callr Console includes a built-in code editor with autocomplete and live validation – no setup required.
Expressions
Expressions, enclosed in double curly braces ${{ expression }}, can be used in any params object. They are evaluated at runtime using a modern JavaScript engine.
- action: play@v3
params:
tts:
text: Hello! Your number is ${{ call.fromNumber }}.
- action: play@v3
params:
tts:
text: >
I know that 1 + 1 equals ${{ 1+1 }}
- action: play@v3
params:
tts:
text: >
Your ticket ID is ${{ $ticketID.split('').join(' ') }}User-defined variables
You can define your own variables to use in expressions. These variables must start with a dollar sign and be valid JavaScript identifiers. The variable type is inferred from the value and preserved when used in expressions.
variables:
$errorCode: 0 # an int
$pi: 3.14159265359 # a float
$user: # an object
name: John # a string
age: 42 # an int
$list: # an array
- apples
- orangesFor example, you can reference these variables in a branch:
branches:
inbound-call:
actions:
- action: play@v3
params:
tts:
text: >
Hello ${{ $user.name }}!
You look like you are ${{ $user.age/2 }} years old!Conditions
Use the if statement to conditionally execute actions. Conditions are expressions evaluated with a modern JavaScript engine.
- if: call.fromNumber.match(/^\+33/)
action: play@v3
params:
tts:
text: Bonjour. Comment allez-vous?
language: fr-FRFor multiple actions under one condition, use the if-then structure:
- if: call.fromNumber == '+33199004242'
then:
- action: play@v3
params:
tts:
text: Hello boss!
- action: play@v3
params:
tts:
text: How are you today?
- action: play@v3
params:
tts:
text: See you later!
- action: hangup@v1Goto & Labels
The goto lets you jump to another branch or a specific label within a branch. This is useful for looping or branching logic.
compat:
version: "2025-09-01"
branches:
inbound-call:
actions:
- label: gather # Define a label
action: gather@v4
params:
maxDigits: 1
tts:
text: Hello! Press 1 to accept the call
result: $digits
- if: $digits.input == '1'
goto:
branch: accept # Jump to a different branch
- action: play@v3
params:
tts:
text: >
Sorry, I didn't get your answer.
- goto:
label: gather # Jump back to the label
accept: # New branch defined here
actions:
- action: play@v3
params:
tts:
text: >
OK! I'm going to connect you to the other party.
- action: bridge@v3Defaults
Defaults allow you to define common behavior at the top level of your scenario or for specific branches. These values can be overridden by branch-level defaults.
compat:
version: "2025-09-01"
defaults:
language: en-US # Default language for speech (TTS/STT)
voice: en-US-Ava:DragonHDLatest # Default voice for TTS
autoAnswer: true # If false, you need to use answer@v1
branches:
voicemail:
defaults:
language: en-GB # the voicemail uses a British accent
actions:
- action: play@v3
params:
tts:
text: Sorry, we are not available at the moment.List of actions
Each action has its own page with its parameters, its result and examples: click its name, or browse them by family in Actions.
| Action | Description |
|---|---|
amd@v3 | Detects answering machines. |
answer@v1 | Answers an Inbound Call if autoAnswer is set to false. |
bridge@v3 | Bridges an Outbound Call with the other leg of a dial action. |
conference@v1 | Puts the caller in a conference room. See Conference Calls. |
dial@v2 | Dials a phone number, initiating an Outbound Call. |
dtmf@v1 | Sends DTMF tones. |
email@v1 | Sends an email. |
fetch@v3 | Communicates with HTTP(s), synchronously or asynchronously. |
gather@v4 | Waits for DTMF input. |
googleAnalytics@v1 | Pushes events to GA4. |
hangup@v1 | Hangs up the call. |
javascript@v1 | Runs JavaScript in a sandbox, useful for data manipulation. |
log@v1 | Logs data. |
memcache@v1 | Stores data in a temporary memory store. |
mixpanel@v1 | Pushes events to MixPanel. |
openai@v3 | Communicates with OpenAI platform. |
play@v3 | Plays a text-to-speech prompt (tts) or an uploaded audio file (audioFile). See Audio Files. |
playRecordingFile@v1 | Plays a temporary audio recording (record@v1). |
saveRecordingFile@v1 | Saves a temporary audio recording. See Recordings. |
recognize@v3 | Recognizes audio (STT - Speech-to-Text). |
record@v1 | Records audio to a temporary file. |
ringing@v1 | Plays a ringing tone before an Inbound Call is answered (autoAnswer: false). |
say@v3 | Alias of play@v3 (same parameters). Prefer play@v3. |
sms@v1 | Sends an SMS message. |
startRecording@v2 | Starts recording the call, automatically creating a Recording. |
stopRecording@v2 | Stops the call recording. Its result is the Recording SID, in lowercase. |
voicebot@v1 | Initiates a Voice AI Agent. |
wait@v1 | Pauses execution for a set duration. |
waitForSilence@v1 | Waits until the caller stops speaking. |
Older versions
Older versions keep working in existing scenarios. Use the current version in new scenarios:
| Older versions | Current | What changes |
|---|---|---|
say@v1, say@v2, play@v1, play@v2 | play@v3 | One way to play audio: tts (text-to-speech) or audioFile (sid). say@v3 is an alias of play@v3 |
gather@v1 to gather@v3 | gather@v4 | Prompt with tts or audioFile |
recognize@v1, recognize@v2 | recognize@v3 | Prompt with tts or audioFile |
amd@v1, amd@v2 | amd@v3 | Prompt with tts or audioFile |
dial@v1 | dial@v2 | cli becomes callerId, ring becomes an audioFile |
bridge@v1, bridge@v2 | bridge@v3 | Beep before bridging set with feedback |
fetch@v1, fetch@v2 | fetch@v3 | audio becomes feedback |
openai@v1, openai@v2 | openai@v3 | audio becomes feedback |
startRecording@v1, stopRecording@v1 | startRecording@v2, stopRecording@v2 | The result is the Recording SID in lowercase |
Templates
Complete scenarios to copy, also available in the template gallery of the Callr Console. Browse them all in Templates:
- Route calls: call forwarding, phone menus, opening hours, call screening, AI intent routing
- Never miss a call: voicemail with transcription, missed-call SMS
- AI agents: AI receptionist, outbound AI agent, voice AI over SIP, AI SMS agent
- Call data: recording, transcription and AI summaries
- Connect people: click-to-call, conference rooms, number masking
- Reminders & alerts: appointment reminders, voice OTP, alert escalation
- SMS: SMS auto-reply, links by SMS during a call
- Call tracking: tracking per campaign, advanced call tracking
- Integrations: your API, Salesforce, your own ElevenLabs voice
Updated 5 days ago
