Appearance
Calling SWML overview
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Calling SWML is the flavor of SWML used to handle voice calls, inbound calls arriving on a phone number configured with a SWML calling handler, outbound REST-initiated calls that point at a SWML URL, and re-fetches triggered by methods that hit an external URL.
For handling inbound SMS and MMS messages, see the Messaging SWML overview.
Document structure
A Calling SWML document follows the standard SWML document structure, a top-level sections map with sections.main as the entry point. Each section contains an array of calling methods that run sequentially.
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- play:
url: "say:Hello!"
- hangup: {}Webhook and variable payload
When SignalWire fetches a Calling SWML document from an external URL, it POSTs this payload to your server, on the initial inbound fetch and on every fetch triggered by a method that hits an external URL (execute with a remote URL, transfer, join_conference.wait_url, enter_queue.wait_url, and connect.confirm). Your server must respond with a valid SWML document using one of these content types: application/json, application/yaml, or text/x-yaml.
Inside the executing document, the call, params, and envs fields are available for variable expansion via ${...} (JavaScript expressions) and %{...} (path substitution). As the script runs, methods also populate the vars.* runtime scope, those values are not in the initial inbound payload, but they are propagated across transfer boundaries and delivered on subsequent fetches.
call
object
Information about the current call. Call-specific and read-only. Each call leg (A-leg, B-leg) has its own unique call object with different call_id, from, to, etc. When connecting to a new leg, the call object is re-initialized with the new leg’s data.
call.call_id
string
A unique identifier for the call.
call.call_state
string
The current state of the call.
call.direction
string
The direction of this call. Possible values: inbound, outbound.
call.from
string
The number/URI that initiated this call.
call.headers
object[]
The headers associated with this call.
call.headers[].name
string
The name of the header.
call.headers[].value
string
The value of the header.
call.node_id
string
A unique identifier for the node handling the call.
call.project_id
string
The Project ID this call belongs to.
call.segment_id
string
A unique identifier for the current call segment.
call.space_id
string
The Space ID this call belongs to.
call.to
string
The number/URI of the destination of this call.
call.type
string
The type of call. Possible values: sip, phone, webrtc.
call.sip_data
object
SIP-specific data for SIP calls. Only present when call.type is sip. Contains detailed SIP header information.
call.sip_data.sip_contact_host
string
The host portion of the SIP Contact header.
call.sip_data.sip_contact_params
object
Additional parameters from the SIP Contact header.
call.sip_data.sip_contact_port
string
The port from the SIP Contact header.
call.sip_data.sip_contact_uri
string
The full URI from the SIP Contact header.
call.sip_data.sip_contact_user
string
The user portion of the SIP Contact header.
call.sip_data.sip_from_host
string
The host portion of the SIP From header.
call.sip_data.sip_from_uri
string
The full URI from the SIP From header.
call.sip_data.sip_from_user
string
The user portion of the SIP From header.
call.sip_data.sip_req_host
string
The host portion of the SIP request URI.
call.sip_data.sip_req_uri
string
The full SIP request URI.
call.sip_data.sip_req_user
string
The user portion of the SIP request URI.
call.sip_data.sip_to_host
string
The host portion of the SIP To header.
call.sip_data.sip_to_uri
string
The full URI from the SIP To header.
call.sip_data.sip_to_user
string
The user portion of the SIP To header.
params
object
Parameters passed by the calling execute or transfer step. Empty {} on the initial inbound fetch. Section-scoped, each execute/transfer replaces (does not merge with) the caller’s params; when an execute returns, the caller’s original params are restored.
vars
object
Runtime variable scope, populated by methods as the script executes. Not part of theinitial inbound payload, values appear here only after a method that sets them has run. The full vars object is propagated across transfer boundaries (and on remote-URL execute) and delivered as a top-level vars field on subsequent webhook payloads.
Created by: set, explicitly create or update variables. Method outputs, many methods auto-populate variables (e.g., prompt_value, record_url, return_value). See each method’s reference page for what it sets.
Removed by: unset.
Scope: Global within a single call session. Variables persist across all sections and through execute calls. Connecting to a new call leg resets the vars object to an empty state.
Access: Variables can be accessed with or without the vars. prefix. When you reference a variable without a scope prefix (e.g., ${my_variable}), SWML first checks vars. If not found in vars, it automatically falls back to envs.
envs
object
Environment variables configured at the account or project level. Account/project-scoped and read-only. Set in your SignalWire account configuration, not within SWML scripts.
Fallback behavior: When you reference a variable without a scope prefix (e.g., ${my_variable}), SWML first checks vars. If not found in vars, it automatically falls back to envs.
The envs object is included in POST request bodies to external servers, but the ability to set environment variables in the SignalWire Dashboard is not yet available in production. This feature is coming soon.
See Variables for variable-expansion syntax, deployment-mode differences, and tips on accessing nested fields and array elements.
Methods
A method is a single step in a SWML document, each item in a sections.<name> array invokes one method. Each method’s reference page documents its parameters, defaults, and any output variables it sets. Methods below are grouped by what they do.
Conversational AI
Hand the call to an AI agent that holds a natural conversation, recognizes intent, and can call out to your backend via SWAIG functions or webhooks.
ai\ \ Hand the call to a SignalWire AI agent that holds a natural conversation and can invoke SWAIG functions. amazon_bedrock\ \ Hand the call to an Amazon Bedrock-backed AI agent.
Call lifecycle
Control when the call is answered, ended, and what kind of party is on the other end before deciding how to handle it.
answer\ \ Answer an inbound call. Some methods (e.g. play) auto-answer if needed. hangup\ \ End the call. detect_machine\ \ Detect whether the answering party is a human or an answering machine.
Audio & speech
Play audio to the caller, prompt for input, and stream live transcription or translation. Run background transcription of the call, and reduce noise for clearer audio.
play\ \ Play TTS speech, audio files, silence, or ring tones. prompt\ \ Play audio or speech and capture DTMF or speech input. live_transcribe\ \ Stream live transcription of the call. live_translate\ \ Stream live translation of the call. transcribe\ \ Transcribe the entire call in the background. transcribe_stop\ \ Stop a background transcription started by transcribe. denoise\ \ Start the noise reduction filter on the call audio. stop_denoise\ \ Stop the noise reduction filter.
Connecting parties
Bring other phones, SIP endpoints, video rooms, or queued agents into the call.
connect\ \ Dial out to other phone or SIP destinations, series, parallel, or mixed. join_conference\ \ Join the call to a conference room. join_room\ \ Join the call to a SignalWire video room. enter_queue\ \ Place the call in a queue with wait music, timeout, and status callbacks.
Recording & taps
Record the call to storage, or stream call media to an external sink in real time.
record\ \ Record audio and wait for completion before continuing execution. record_call\ \ Start a background recording of the call. stop_record_call\ \ Stop a background recording started by record_call. tap\ \ Stream call media to an RTP or WebSocket sink. stop_tap\ \ Stop a media stream started by tap. stream\ \ Stream call audio to a WebSocket endpoint in the background. stop_stream\ \ Stop a stream started by stream.
Messaging & side channels
Send messages, faxes, DTMF, and other out-of-band signals from inside a call. Also collects payments and emits custom project events.
send_sms\ \ Send an outbound SMS to a phone number. send_digits\ \ Send DTMF tones into the call. send_fax\ \ Send an outbound fax. receive_fax\ \ Interpret the inbound call as a fax and process it. sip_refer\ \ Transfer a SIP call by issuing a SIP REFER. pay\ \ Collect a PCI-compliant payment over the phone. user_event\ \ Emit a custom event onto the project’s event stream.
Control flow
Direct execution within a SWML document, call subroutines, jump between labels, branch on expressions, or tail-call into another document entirely.
execute\ \ Call a named section or external SWML URL as a subroutine. return\ \ Return from an execute-invoked section, optionally producing a return_value. transfer\ \ Tail-call into another section or external SWML document, does not return. goto\ \ Jump to a label within the current section, optionally repeating up to a limit. label\ \ Mark a jump target for goto. cond\ \ Branch on a JavaScript expression. switch\ \ Branch on a variable’s value with case matching.
State & integration
Manage script variables, pause execution, and reach your backend over HTTP.
set\ \ Set one or more script variables. unset\ \ Remove one or more script variables. sleep\ \ Pause execution for a specified duration. request\ \ Make an HTTP request to an external URL; optionally parse the response into variables.
ai
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Creates an AI agent that conducts voice conversations using automatic speech recognition (ASR), large language models (LLMs), and text-to-speech (TTS) synthesis. The agent processes caller speech in real-time, generates contextually appropriate responses, and can execute custom functions to interact with external systems and databases through SignalWire AI Gateway (SWAIG).
Since the prompt configuration is central to AI agent behavior, it is recommended to read the Prompting Best Practices guide.
Properties
ai
objectRequired
An object that defines an AI agent for conducting voice conversations. Accepts the following properties to configure the agent’s prompt, behavior, functions, language support, and other settings.
ai.prompt
objectRequired
Defines the AI agent’s personality, goals, behaviors, and instructions for handling conversations. The prompt establishes how the agent should interact with callers, what information it should gather, and how it should respond to various scenarios.
It is recommended to write prompts using markdown formatting as LLMs better understand structured content. Additionally it is recommended to read the Prompting Best Practices guide.
ai.global_data
object
A key-value object for storing data that persists throughout the AI session. Can be set initially in the SWML script or modified during the conversation using the set_global_data action.
The global_data object is accessible everywhere in the AI session: prompts, AI parameters, and SWML returned from SWAIG functions. Access properties using template strings (e.g ${global_data.property_name})
ai.hints
string[] | object[]
Provide an array of strings and/or objects to guide the AI’s pronunciation and understanding of specific words or phrases. Words that can commonly be mispronounced can be added to the hints to help the AI speak more accurately.
Hints as strings: Each string in the array gives the AI context on how to interpret certain words. For example, if a user says Toni and the hint is Tony, the AI understands that the user said Tony.
Hints as objects: An array of objects with the properties below to customize how the AI handles specific words.
hints[].hint
stringRequired
The hint to match. This will match the string exactly as provided.
hints[].pattern
stringRequired
A regular expression to match the hint against. This will ensure that the hint has a valid matching pattern before being replaced.
hints[].replace
stringRequired
The text to replace the hint with. This will replace the portion of the hint that matches the pattern.
hints[].ignore_case
booleanDefaults to false
If true, the hint will be matched in a case-insensitive manner. Defaults to false.
ai.languages
object[]
An array of JSON objects defining supported languages in the conversation.
See languages for more details.
ai.params
object
A JSON object containing parameters as key-value pairs.
See params for more details.
ai.post_prompt
object
The final set of instructions and configuration settings to send to the agent.
post_prompt.text
stringRequired
The instructions to send to the agent.
post_prompt.temperature
numberDefaults to 1.0
Randomness setting. Float value between 0.0 and 1.5. Closer to 0 will make the output less random.
post_prompt.top_p
numberDefaults to 1.0
Randomness setting. Alternative to temperature. Float value between 0.0 and 1.0. Closer to 0 will make the output less random.
post_prompt.confidence
numberDefaults to 0.6
Threshold to fire a speech-detect event at the end of the utterance. Float value between 0.0 and 1.0. Decreasing this value will reduce the pause after the user speaks, but may introduce false positives.
post_prompt.presence_penalty
numberDefaults to 0
Aversion to staying on topic. Float value between -2.0 and 2.0. Positive values increase the model’s likelihood to talk about new topics.
post_prompt.frequency_penalty
numberDefaults to 0
Aversion to repeating lines. Float value between -2.0 and 2.0. Positive values decrease the model’s likelihood to repeat the same line verbatim.
ai.post_prompt_url
string
The URL to which to send status callbacks and reports. Authentication can also be set in the url in the format of username:password@url. See post_prompt_url callback below.
ai.pronounce
object[]
An array of objects to clarify the AI’s pronunciation of certain words or expressions.
pronounce[].replace
stringRequired
The expression to replace.
pronounce[].with
stringRequired
The phonetic spelling of the expression.
pronounce[].ignore_case
booleanDefaults to true
Whether the pronunciation replacement should ignore case.
ai.SWAIG
object
An array of JSON objects to create user-defined functions/endpoints that can be executed during the dialogue.
See SWAIG for more details.
post_prompt_url callback
SignalWire will make a request to the post_prompt_url with the following parameters:
action
string
Action that prompted this request. The value will be “post_conversation”.
ai_end_date
integer
Timestamp indicating when the AI session ended.
ai_session_id
string
A unique identifier for the AI session.
ai_start_date
integer
Timestamp indicating when the AI session started.
app_name
string
Name of the application that originated the request.
call_answer_date
integer
Timestamp indicating when the call was answered.
call_end_date
integer
Timestamp indicating when the call ended.
call_id
string
ID of the call.
call_log
object
The complete log of the call, as a JSON object.
call_log.content
string
Content of the call log entry.
call_log.role
string
Role associated with the call log entry (e.g., “system”, “assistant”, “user”).
call_start_date
integer
Timestamp indicating when the call started.
caller_id_name
string
Name associated with the caller ID.
caller_id_num
string
Number associated with the caller ID.
content_disposition
string
Disposition of the content.
content_type
string
Type of content. The value will be text/swaig.
conversation_id
string
A unique identifier for the conversation thread, if configured via the AI parameters.
post_prompt_data
object
The answer from the AI agent to the post_prompt. The object contains the three following fields.
post_prompt_data.parsed
object
If a JSON object is detected within the answer, it is parsed and provided here.
post_prompt_data.raw
string
The raw data answer from the AI agent.
post_prompt_data.substituted
string
The answer from the AI agent, excluding any JSON.
project_id
string
ID of the Project.
space_id
string
ID of the Space.
SWMLVars
object
A collection of variables related to SWML.
swaig_log
object
A log related to SWAIG functions.
total_input_tokens
integer
Represents the total number of input tokens.
total_output_tokens
integer
Represents the total number of output tokens.
version
string
Version number.
Post prompt callback request example
Below is a JSON example of the callback request that is sent to the post_prompt_url:
{
"total_output_tokens": 119,
"caller_id_name": "[CALLER_NAME]",
"SWMLVars": {
"ai_result": "success",
"answer_result": "success"
},
"call_start_date": 1694541295773508,
"project_id": "[PROJECT_ID]",
"call_log": [\
{\
"content": "[AI INITIAL PROMPT/INSTRUCTIONS]",\
"role": "system"\
},\
{\
"content": "[AI RESPONSE]",\
"role": "assistant"\
},\
{\
"content": "[USER RESPONSE]",\
"role": "user"\
}\
],
"ai_start_date": 1694541297950440,
"call_answer_date": 1694541296799504,
"version": "2.0",
"content_disposition": "Conversation Log",
"conversation_id": "[CONVERSATION_ID]",
"space_id": "[SPACE_ID]",
"app_name": "swml app",
"swaig_log": [\
{\
"post_data": {\
"content_disposition": "SWAIG Function",\
"conversation_id": "[CONVERSATION_ID]",\
"space_id": "[SPACE_ID]",\
"meta_data_token": "[META_DATA_TOKEN]",\
"app_name": "swml app",\
"meta_data": {},\
"argument": {\
"raw": "{\n \"target\": \"[TRANSFER_TARGET]\"\n}",\
"substituted": "",\
"parsed": [\
{\
"target": "[TRANSFER_TARGET]"\
}\
]\
},\
"call_id": "[CALL_ID]",\
"content_type": "text/swaig",\
"ai_session_id": "[AI_SESSION_ID]",\
"caller_id_num": "[CALLER_NUMBER]",\
"caller_id_name": "[CALLER_NAME]",\
"project_id": "[PROJECT_ID]",\
"purpose": "Use to transfer to a target",\
"argument_desc": {\
"type": "object",\
"properties": {\
"target": {\
"description": "the target to transfer to",\
"type": "string"\
}\
}\
},\
"function": "transfer",\
"version": "2.0"\
},\
"command_name": "transfer",\
"epoch_time": 1694541334,\
"command_arg": "{\n \"target\": \"[TRANSFER_TARGET]\"\n}",\
"url": "https://example.com/here",\
"post_response": {\
"action": [\
{\
"say": "This is a say message!"\
},\
{\
"SWML": {\
"sections": {\
"main": [\
{\
"connect": {\
"to": "+1XXXXXXXXXX"\
}\
}\
]\
},\
"version": "1.0.0"\
}\
},\
{\
"stop": true\
}\
],\
"response": "transferred to [TRANSFER_TARGET], the call has ended"\
}\
}\
],
"total_input_tokens": 5627,
"caller_id_num": "[CALLER_NUMBER]",
"call_id": "[CALL_ID]",
"call_end_date": 1694541335435503,
"content_type": "text/swaig",
"action": "post_conversation",
"post_prompt_data": {
"substituted": "[SUMMARY_MESSAGE_PLACEHOLDER]",
"parsed": [],
"raw": "[SUMMARY_MESSAGE_PLACEHOLDER]"
},
"ai_end_date": 1694541335425164,
"ai_session_id": "[AI_SESSION_ID]"
}Responding to post prompt requests
The response to the callback request should be a JSON object with the following parameters:
{
"response": "ok"
}Examples
Minimal AI agent
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- ai:
prompt:
text: "You are a customer service agent. Answer questions about account status and billing."Hints
YAMLJSON
ai:
hints:
- Tony
- hint: swimmel
pattern: swimmel
replace: SWMLPronounce
YAMLJSON
version: 1.0.0
sections:
main:
- ai:
prompt:
text: |
You are an expert in the GIF file format. Tell the user whatever they'd like to know in this
field.
pronounce:
- replace: GIF
with: jifai_sidecar
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Attaches a real-time AI observer to a live call. The sidecar listens as a third party and never speaks on the call, after each customer turn, it sends agent-facing advice to your application as webhook callbacks that an agent’s UI (or any consumer) can render. Think of it as a coach watching over the agent’s shoulder: it runs alongside the call rather than driving it.
Use it for live sales coaching, real-time compliance flagging, intent-based UI navigation, voice-of-customer signal extraction, and supervisor-on-shoulder workflows. A common pattern is to attach ai_sidecar to coach a human agent on a connect-bridged call: the customer talks to the human, and the sidecar coaches the human’s screen.
How it works
The sidecar listens to the call but never speaks on it. A call can run either the sidecar or plain live transcription, but not both at once.
Each time the customer finishes speaking, the sidecar evaluates the conversation. This evaluation is called a tick, and every callback the sidecar produces carries a tick_id. On each tick:
- The sidecar detects the end of the customer’s turn, a final transcription result followed by a brief silence (
idle_timeout_ms), or the agent starting to speak. - It sends the running transcript to the model, along with your operator prompt and your SWAIG tools.
- The model returns a single line of agent-facing advice (an
insight), or calls the built-insidecar_skiptool to stay silent when no advice is needed. - Any tools the model calls (lookups, alerts, intent triggers) run through your SWAIG functions and MCP servers.
- Every step is reported as a structured callback your application can consume. See Webhook callbacks below for the full catalog.
Properties
ai_sidecar
objectRequired
An object that attaches a real-time AI observer to the call. Accepts the following properties to configure the sidecar’s prompt, language, model, tools, permissions, and other settings.
ai_sidecar.prompt
string | object
The operator prompt that instructs the sidecar how to coach the agent. May be a plain string, a Prompt Object Model (POM), or a server-side file reference. SignalWire automatically adds built-in instructions for the sidecar’s role, so your prompt only needs to describe the coaching behavior.
Optional, when omitted, the sidecar falls back to a minimal default prompt, so setting one is strongly recommended. See prompt for the supported forms.
ai_sidecar.lang
stringRequired
The conversation language as a single BCP-47 tag (e.g. en-US). Sets the speech-recognition language, and is shared with the model as a hint.
ai_sidecar.model
stringDefaults to gpt-4o-mini
The model used for the sidecar’s advice and its end-of-call summaries. Suggested values: gpt-4o-mini, gpt-4.1-mini, gpt-4.1-nano.
ai_sidecar.direction
string[]
The call legs to observe. Possible values: remote-caller, local-caller. Both legs are required; defaults to both legs.
ai_sidecar.customer_role
stringDefaults to remote-caller
Which leg is the customer, used as the turn-end trigger source. Possible values: remote-caller, local-caller.
ai_sidecar.url
string
The webhook URL the sidecar POSTs its callbacks to, both transcription events and sidecar callbacks. When unset, callbacks are published only on the relay topic (calling.ai.sidecar) and no webhook POST is made, the relay event always fires, the webhook is opt-in. Basic auth can be embedded in the URL in the format username:password@url.
See Webhook callbacks below for the callback payload shape.
ai_sidecar.SWAIG
object
SWAIG functions and MCP servers available to the sidecar.
See SWAIG for more details.
The function name sidecar_skip is reserved and auto-registered as a built-in, do not declare it.
ai_sidecar.permissions
object
SWAIG permission overrides. Defaults to all permissions enabled.
Setting act_on_channel to false overrides all of these, actions are reported as callbacks but never applied to the call.
permissions.swaig_allow_swml
booleanDefaults to true
Whether SWAIG tools may run SWML on the call.
permissions.swaig_allow_settings
booleanDefaults to true
Whether SWAIG tools may change the sidecar’s settings, such as the model.
permissions.swaig_set_global_data
booleanDefaults to true
Whether SWAIG tools may set the sidecar’s global data.
ai_sidecar.global_data
object
A key-value object for the initial global_data. You can reference it in the prompt with variable expansion (e.g. ${global_data.property_name}), and it is included in the requests sent to your tools.
It also persists across sessions on the same call leg through the ai_agents_global_data SWML variable, so later verbs on the same leg can read it as ${ai_agents_global_data.property_name}.
ai_sidecar.hints
string[]
Speech-recognition hints passed to ASR to bias recognition toward specific terms, product names, competitor names, jargon, customer names, or anything in your SWAIG enum lists. Strongly recommended. Example: ["ACME", "Globex", "FedRAMP", "SOC 2"].
ai_sidecar.params
object
An object containing tuning options for the sidecar.
See params for more details.
ai_sidecar.action
object
Summarize the conversation instead of starting a sidecar. When you include action.summarize, the request generates a one-off summary and returns rather than attaching a sidecar.
action.summarize
object
Generate a one-off summary of the conversation and send it to a webhook.
summarize.webhook
string
The webhook URL the summary is sent to. Defaults to the sidecar’s configured url.
summarize.prompt
string
The prompt used to write the summary. Defaults to the configured ai_summary_prompt.
Webhook callbacks
As it observes the call, the sidecar reports each step of its activity as a structured callback on two paths:
- Relay topic
calling.ai.sidecar, always fires. Subscribe with the SignalWire RELAY or browser SDK to consume callbacks in real time. - Webhook, fires only when
urlis set, as an HTTPPOSTto that URL with the callback body wrapped undersidecar_event.
Both paths carry the same payload, and each callback fires exactly once on the relay topic regardless of whether a webhook is configured, the relay always fires, the webhook is opt-in.
Callback body shape
Each callback is POSTed to your url with the event wrapped under sidecar_event, alongside a call_info envelope describing the call. project_id and space_id are included when available:
JSON
{
"call_info": {
"project_id": "...",
"space_id": "...",
"call_id": "...",
"content_type": "text/json",
"content_disposition": "post_data",
"conversation_type": "voice"
},
"sidecar_event": {
"type": "insight",
"ts": 1745870400123456,
"tick_id": 7,
"channel_data": { },
"raw": "Confirm the customer's address.",
"iter": 0,
"total_iters": 1
}
}The actual event is under sidecar_event, unwrap that in your code before reading type and the event’s fields. Every callback also carries type, ts (microsecond timestamp), tick_id, and a channel_data object (call_id, plus caller_id_name / caller_id_number / destination_number when available).
See the AI sidecar callback webhook page for the full payload reference. The per-type fields are listed below.
Callback types
Each callback carries a type field identifying what occurred, along with type-specific fields.
type | When | Key fields |
|---|---|---|
start | The sidecar attached to the call | model, tools (the tool names available), global_data |
turn | The customer finished a turn (an evaluation is about to run) | transcript_delta, customer_text, agent_text |
request | The sidecar called the model | model, iter, messages_count, messages_token_count, tool_choice |
thought | The model produced text while still working, for example alongside a tool call | text, iter |
insight | The sidecar’s advice for the agent | raw (the advice text), iter, total_iters |
skip | The model called sidecar_skip to stay silent for this turn | reason? |
tool_call | The model called one of your tools | name, arguments?, iter |
tool_result | One of your tools returned a result | name, response, iter |
action | A SWAIG action was returned (and, if enabled, executed) | action, source_function?, executed |
global_data_change | A set_global_data / unset_global_data action changed global_data | key, old_value?, new_value? |
history_pruned | The conversation history was trimmed to fit the token budget | dropped_count, kept_count, tokens_before, tokens_after |
error | Something failed, or an anti-loop guard tripped | error_reason, detail? |
ask_request | An ai_sidecar.ask was queued | question, ask_id |
ask_answer | The answer to an ai_sidecar.ask | raw, iter, total_iters, ask_id, triggered_by |
stop | The sidecar is shutting down | stop_reason |
final | The last callback before the sidecar stops, a full snapshot of the session | stop_reason, summary?, history, transcript?, event_log, stats (counts such as tool calls and insights), metrics, global_data, model, started_at, ended_at, duration_ms |
On the callbacks that come from a single evaluation (request, thought, tool_call, tool_result, insight), iter counts the steps within that evaluation, starting at 0, and total_iters on the insight is how many steps it took in total. Any callback produced while answering an ai_sidecar.ask also carries that ask’s ask_id and triggered_by: "ask", so you can match it to the question you sent.
Stop reasons
The final callback carries a stop_reason indicating why the sidecar stopped.
stop_reason | Trigger |
|---|---|
transcribe_close | The call ended normally |
transferred | A SWAIG transfer action terminated the call |
hung_up | A SWAIG hangup action terminated the call |
stop_action | A SWAIG stop action stopped the sidecar (transcription continues) |
api_stop | The sidecar was stopped programmatically |
Error reasons
The error callback carries an error_reason describing the failure.
error_reason | Trigger |
|---|---|
tool_loop | An anti-loop guard tripped (more than four tool calls in a tick, or the same tool was called with the same arguments repeatedly) |
swml_not_allowed | An SWML action was requested but swaig_allow_swml is false |
llm_error | The model call returned an error. detail carries the provider’s error message |
webhook_http_failure | A tool’s webhook request failed. Carries the function name, the http_code returned, and the curl_code |
event_log_truncated | The sidecar’s event log reached its size limit and older entries were dropped |
Tool webhook contract
When the model calls one of your SWAIG functions, the platform sends an HTTP POST to that function’s web_hook_url. Your webhook runs the function and returns the result. Both the request and the response are plain JSON.
Request
The platform sends the POST body shown below. The sidecar sends a smaller set of fields than the regular ai method’s SWAIG webhook, and it groups the caller details under channel_data.
See the AI sidecar SWAIG tool webhook webhook page for the full field reference.
Response
Your webhook must return a JSON object with the result and any actions to take:
response
string
The result the model sees. It becomes the tool result the model reads on its next step.
action
object | object[]
Optional. One action object, or an array of them, for the sidecar to perform. Each is keyed by an action name, see Supported SWAIG actions. When act_on_channel is true, the actions take effect on the call; otherwise they are reported as callbacks only.
Response (JSON)
{
"response": "ACME charges $99/seat. We're $79.",
"action": [\
{ "user_event": { "topic": "sidecar.alert", "level": "info" } },\
{ "set_global_data": { "last_lookup": "ACME" } }\
]
}Supported SWAIG actions
Each entry in the action array is an object keyed by the action name. The sidecar supports the following:
action[].user_event
object
Emits a user_event carrying your topic and any payload fields, the primary way to surface UI alerts and intent navigation to your application.
action[].set_global_data
object
A key-value object merged into global_data. Emits a global_data_change callback and persists across sessions on the same call leg.
action[].unset_global_data
string | object
The key to remove from global_data, or a new object to replace it.
action[].set_meta_data
object
A key-value object of session metadata.
action[].unset_meta_data
string | object
The metadata key to remove, or a new object to replace it.
action[].transfer
object
Transfers the call to a destination. Ends the sidecar and transcription.
transfer.dest
string
The destination, a phone number, SIP URI, or SWML URL.
transfer.summarize
booleanDefaults to false
Whether to include a conversation summary when transferring.
action[].hangup
boolean
When true, hangs up the call. Ends the sidecar and transcription.
action[].stop
boolean
When true, stops the sidecar only; transcription continues.
action[].say
string
Report-only in sidecar mode. The sidecar has no voice, so instead of speaking it fires an action callback with spoken: false and reason: "no_tts_in_sidecar".
action[].toggle_functions
object[]
Enables or disables functions mid-conversation. Each entry sets a function’s active state.
toggle_functions[].function
stringRequired
The name of the function to toggle.
toggle_functions[].active
booleanDefaults to true
Whether to enable or disable the function.
action[].settings
object
Changes the sidecar’s model settings, such as the model or temperature. Gated by swaig_allow_settings.
action[].SWML
object
A SWML document to run on the call. Gated by swaig_allow_swml. The transfer: true variant ends the sidecar.
action[].user_input
string
Injects a message into the conversation and triggers a new evaluation, use it to send the sidecar a question or instruction mid-call.
action[].back_to_back_functions
boolean | string
Controls whether the model may chain tool calls, true, or "forever" for unlimited chaining.
action[].extensive_data
boolean
Controls how much data is included in the webhook payload.
Setting act_on_channel to false makes all of these report-only, they still fire as callbacks but are not applied to the call.
Built-in sidecar_skip tool
The sidecar provides one built-in tool, sidecar_skip, that you do not declare. The model calls it when the latest customer turn needs no advice. The tick then ends silently, no insight callback fires, and a skip callback is emitted with the model’s reason.
Instruct the model in your prompt to call sidecar_skip when there is nothing useful to say, otherwise it will tend to fill silence with low-quality advice. The name sidecar_skip is reserved; do not define a function with that name.
Limitations
- One transcriber per call.
ai_sidecarand plainlive_transcribecannot run on the same call at the same time, starting one while the other is active is rejected. - Both legs required. A single-leg
direction(for example, onlyremote-caller) is rejected. - Turn detection is tuned for Deepgram.
deepgramis the default speech engine, and turn-end detection is calibrated for it. saydoesn’t speak. The sidecar has no voice on the call, so asayaction is reported as a callback instead of being spoken aloud.- The sidecar stops with the call. When the call hangs up or transcription stops, the sidecar’s
finalcallback fires and it stops. sidecar_skipis reserved. Do not define a function with that name.- Tool loops are capped. If the model calls tools in a runaway loop, too many calls in one tick, the same call repeated, or a tool that isn’t registered, the sidecar stops calling tools for that tick and returns an
errorcallback witherror_reason: tool_loop. Make sure your tools return clear, useful results and your prompt tells the model what to do after a tool returns.
Example
Answer the call, attach the sidecar with a prompt, language, webhook URL, hints, and a single SWAIG function, then bridge the call with connect and hang up.
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- ai_sidecar:
prompt: "You are a real-time sales copilot. After each customer turn, give the agent one concise piece of advice or call sidecar_skip if no advice is needed."
lang: "en-US"
url: "https://your-app.example.com/sidecar/events"
hints: ["ACME", "Globex", "FedRAMP", "SOC 2"]
SWAIG:
defaults:
web_hook_url: "https://your-app.example.com/sidecar/swaig"
functions:
- function: lookup_account
parameters:
type: object
properties:
customer_id:
type: string
required:
- customer_id
- connect:
from: "+15555550100"
to: "+15555550199"
answer_on_bridge: true
- hangup: {}params
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Tuning options that can be passed in ai_sidecar.params of the ai_sidecar method. All of these parameters are optional.
Properties
ai_sidecar.params
object
An object that accepts the following properties.
Reaction
Control how often the sidecar evaluates the conversation, how quickly it reacts to the customer, and whether tool actions take effect on the call.
params.idle_timeout_ms
integerDefaults to 200
How long the customer can be silent, in milliseconds, after they finish speaking before the sidecar evaluates the conversation. Lower values make the sidecar react faster. If the agent speaks while the customer’s turn is still pending, the sidecar evaluates immediately without waiting. Range: 50-5000.
params.min_interval_ms
integerDefaults to 0
The minimum time, in milliseconds, between evaluations, a throttle that limits how often the sidecar runs on a busy call. Range: 0-60000.
params.max_iters_per_tick
integerDefaults to 5
The maximum number of tool calls the sidecar will chain within a single evaluation before it must produce its advice. Range: 1-20.
params.max_history_tokens
integerDefaults to 8000
The token budget for the sidecar’s running conversation history. When the history grows past this, the oldest messages are dropped. Range: 1000-200000.
params.act_on_channel
booleanDefaults to true
Whether actions returned by your tools (such as transferring or hanging up the call) take effect on the call, or are only reported as callbacks.
Summaries
Generate summaries when the call ends.
params.final_summary
booleanDefaults to false
Whether to generate a closing summary of the sidecar’s session when the call ends. The result is included in the final callback.
params.ai_summary
booleanDefaults to false
Whether to generate an end-of-call summary of the conversation itself, distinct from final_summary (which summarizes the sidecar’s session).
params.ai_summary_prompt
string
A custom prompt for the end-of-call conversation summary.
params.summary_model
stringDefaults to gpt-4o-mini
The model used for the end-of-call conversation summary, distinct from model (the sidecar’s own model). Suggested values: gpt-4o-mini, gpt-4.1-mini, gpt-4.1-nano.
Transcription
Configure speech recognition and per-utterance callbacks.
params.live_events
booleanDefaults to false
Whether to emit a callback for each utterance the speech recognizer produces.
params.verbose_utterances
booleanDefaults to false
Whether each utterance callback includes full speech-recognition detail, such as word timings and alternatives. This increases the callback size, so leave it off unless you need it.
params.speech_engine
stringDefaults to deepgram
The speech recognition engine to use. Possible values: deepgram, google.
params.speech_timeout
integer
How long, in milliseconds, the recognizer waits before finalizing speech. Defaults to the speech engine’s own default.
params.vad_silence_ms
integer
The amount of silence, in milliseconds, used to detect the end of speech. Defaults to the speech engine’s own default.
params.vad_thresh
integer
How sensitively the recognizer detects speech. Defaults to the speech engine’s own default.
params.transcribe_prompt
string
A bias prompt passed to the speech recognizer to improve accuracy on expected terms, such as product or company names. This is distinct from the operator prompt.
Debug
Enable extra logging to help troubleshoot a sidecar.
params.debug_level
integerDefaults to 0
Speech-engine debug verbosity. Range: 0-100.
params.debug
booleanDefaults to false
Whether to enable verbose logging for the sidecar.
prompt
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
The operator prompt instructs the sidecar how to coach the agent, what to watch for, when to speak up, and when to stay silent. SignalWire automatically adds built-in instructions for the sidecar’s role, so your prompt only needs to describe the coaching behavior. It is recommended to write prompts using markdown formatting, as models better understand structured content.
prompt is optional. When omitted, the sidecar falls back to a minimal default prompt, so setting one is strongly recommended.
The sidecar prompt supports the text, POM, and file forms below. The model’s settings are configured separately, see the model field and params.
Prompt forms
There are three ways to define the prompt content:
- Text, A single string with the full prompt. Provide it as a bare string (
prompt: "...") or as an object with atextfield. Best for simple coaching instructions. - POM (Prompt Object Model), A structured array of sections with titles, body text, and bullets. SignalWire renders the POM into a markdown document before sending it to the model. Best for prompts that benefit from clear organization.
- File, A path to a server-side file whose contents become the prompt.
Properties
ai_sidecar.prompt
string | object
The operator prompt. Provide a plain string, or one of the objects below.
Text
POM
File
prompt.text
stringRequired
The full operator prompt as a single block of text. Equivalent to passing prompt as a bare string.
Variable expansion
The prompt supports variable expansion in any form. Reference values from global_data, from the persistent ai_agents_global_data, and from the following call variables:
${global_data.*}
string
Any value from the sidecar’s global_data, e.g. ${global_data.customer_id}.
${ai_agents_global_data.*}
string
Any value from ai_agents_global_data, which persists across sessions on the same call leg, e.g. ${ai_agents_global_data.deal.mrr}.
${caller_id_number}
string
The caller’s phone number.
${destination_number}
string
The destination phone number.
${customer_role}
string
Which leg is the customer, remote-caller or local-caller.
${local_date}
string
The current local date.
${local_time}
string
The current local time.
${local_tz}
string
The local timezone.
${session_uuid}
string
The unique identifier for the call session.
Examples
Text (YAML)Text (JSON)POM (YAML)POM (JSON)
version: 1.0.0
sections:
main:
- ai_sidecar:
prompt: "You are a real-time sales copilot. After each customer turn, give the agent one concise piece of advice, or call sidecar_skip if no advice is needed."
lang: "en-US"SWAIG
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
SWAIG (SignalWire AI Gateway) is SignalWire’s function-calling system for AI. It lets the sidecar’s model call functions that you define and run on your own server, so it can do more than just talk.
While the sidecar watches the call, the model can call a function whenever it needs to look something up or take an action, look up an account, flag a sales signal, update the agent’s screen, and so on. When it does, the sidecar sends a request to that function’s webhook (web_hook_url), your server runs the function and returns a result, and the model uses that result in its next response.
You define these functions under functions. You can also connect external MCP (Model Context Protocol) servers under mcp_servers, and their tools become available to the model the same way.
Properties
ai_sidecar.SWAIG
object
An object that defines the functions and MCP servers available to the sidecar.
SWAIG.defaults
object
Default settings applied to every function that does not override them.
defaults.web_hook_url
string
Default webhook URL for functions without their own web_hook_url. Basic auth can be embedded as username:password@url.
defaults.web_hook_auth_user
string
Default basic-auth username for the function webhook.
defaults.web_hook_auth_password
string
Default basic-auth password for the function webhook.
SWAIG.functions
object[]
An array of functions the model can call during the conversation.
functions[].function
stringRequired
The name of the function. This is the only required field, the model calls the function by this name.
functions[].description
string
A description of what the function does, sent to the model so it knows when to call it.
functions[].purpose
string
A fallback for description, used only when description is not set.
functions[].parameters
object
The JSON-Schema object describing the function’s arguments: type: object with a properties map and an optional required array. Each property allows only type, description, enum, and default, additional validation keywords such as pattern, minimum, and maximum are not accepted; express those constraints in the property description and validate them server-side. When omitted, the function takes no arguments.
functions[].web_hook_url
string
Webhook URL for this function. Falls back to defaults.web_hook_url. Basic auth can be embedded as username:password@url.
functions[].web_hook_auth_user
string
Basic-auth username for this function’s webhook. Falls back to defaults.web_hook_auth_user.
functions[].web_hook_auth_password
string
Basic-auth password for this function’s webhook. Falls back to defaults.web_hook_auth_password.
SWAIG.mcp_servers
object[]
An array of MCP (Model Context Protocol) servers whose tools and resources are made available to the AI. Each server’s tools are discovered at startup and registered as callable functions, so they can be invoked like any other SWAIG function.
mcp_servers[].url
stringRequired
The MCP server URL.
mcp_servers[].headers
object
HTTP headers sent to the MCP server. Authorization tokens go here, there is no separate auth field. Header values support variable expansion (e.g. Bearer ${global_data.token}).
mcp_servers[].resources
booleanDefaults to false
Whether to fetch the server’s resources into global_data, when the server advertises resource support.
mcp_servers[].resource_vars
object
Template variables passed to the MCP server when fetching resources. Used only when resources is enabled.
The function name sidecar_skip is reserved. It is auto-registered as a built-in tool, do not declare a function with that name. See Built-in sidecar_skip tool.
Examples
YAMLJSON
version: 1.0.0
sections:
main:
- ai_sidecar:
prompt: "Coach the agent."
lang: "en-US"
SWAIG:
defaults:
web_hook_url: "https://your-app.example.com/sidecar/swaig"
functions:
- function: lookup_competitor
parameters:
type: object
properties:
competitor:
type: string
required:
- competitor
mcp_servers:
- url: "https://crm.example.com/mcp"
headers:
Authorization: "Bearer ${global_data.crm_token}"
resources: true
resource_vars:
customer_id: "${global_data.customer_id}"languages
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Use ai.languages to configure the spoken language of your AI Agent, as well as the TTS engine, voice, and fillers.
Properties
ai.languages
object[]
An array of objects that accept the following properties.
languages[].name
stringRequired
Name of the language (“French”, “English”, etc). This value is used in the system prompt to instruct the LLM what language is being spoken.
languages[].code
stringRequired
Set the language code for ASR (Automatic Speech Recognition) (STT (Speech-to-text)) purposes. By default, SignalWire uses Deepgram’s Nova-3 STT engine, so this value should match a code from Deepgram’s Nova-3 language codes table.
If a different STT model was selected using the openai_asr_engine parameter, you must select a code supported by that engine.
languages[].voice
stringRequired
String format: <engine id>.<voice id>. Select engine from gcloud, polly, elevenlabs, deepgram, cartesia, rime, inworld, or minimax. Select voice from TTS provider reference. For example, "gcloud.fr-FR-Neural2-B". See voice usage for more details.
languages[].emotion
stringDefaults to None
Enables automatic emotion for the set TTS engine. This allows the AI to express emotions when speaking. A global emotion or specific emotions for certain topics can be set within the prompt of the AI. Valid values:auto
Only works with the Cartesia and MiniMax TTS engines. For a fixed MiniMax emotion, use params.emotion instead.
languages[].function_fillers
string[]Defaults to None
An array of strings to be used as fillers in the conversation when the agent is calling a SWAIG function. The filler is played asynchronously during the function call.
languages[].model
stringDefaults to None
The model to use for the specified TTS engine (e.g. arcana). Check the TTS provider reference for the available models.
languages[].speech_fillers
string[]Defaults to None
An array of strings to be used as fillers in the conversation. This helps the AI break silence between responses.
speech_fillers are used between every ‘turn’ taken by the LLM, including at the beginning of the call. For more targed fillers, consider using function_fillers.
languages[].speed
stringDefaults to None
The speed to use for the specified TTS engine. This allows the AI to speak at a different speed at different points in the conversation. The speed behavior can be defined in the prompt of the AI. Valid values:auto
Only works with Cartesia TTS engine.
languages[].params
objectDefaults to None
TTS engine-specific parameters for this language.
params.similarity
numberDefaults to 0.75
The similarity slider dictates how closely the AI should adhere to the original voice when attempting to replicate it. The higher the similarity, the closer the AI will sound to the original voice. Valid values range from 0.0 to 1.0.
Only works with the ElevenLabs TTS engine.
params.stability
numberDefaults to 0.50
The stability slider determines how stable the voice is and the randomness between each generation. Lowering this slider introduces a broader emotional range for the voice. Valid values range from 0.0 to 1.0.
Only works with the ElevenLabs TTS engine.
params.speakingRate
numberDefaults to 1.0
Adjusts how quickly the voice speaks. Values below 1.0 slow the voice down; values above 1.0 speed it up. Valid values range from 0.5 to 1.5.
Only works with the Inworld TTS engine.
params.temperature
numberDefaults to 1.0
Controls the randomness and expressiveness of the generated speech. Lower values produce a more consistent, predictable delivery; higher values introduce more variation. Valid values range from 0.0 to 2.0.
Only works with the Inworld TTS engine.
params.speed
numberDefaults to 1.0
How quickly the voice speaks. Values below 1.0 slow the voice down; values above 1.0 speed it up. Valid values range from 0.5 to 2.0.
Only works with the MiniMax TTS engine.
params.vol
numberDefaults to 1.0
The speaking volume. Lower values are quieter. Valid values range from 0.1 to 1.0.
Only works with the MiniMax TTS engine.
params.pitch
integerDefaults to 0
The pitch shift in semitones. Negative values lower the pitch; positive values raise it. Valid values range from -12 to 12.
Only works with the MiniMax TTS engine.
params.emotion
string
A fixed emotional tone for the generated speech. Valid values are happy, sad, angry, fearful, disgusted, surprised, and neutral. To vary the emotion automatically during a conversation, use languages[].emotion set to auto instead.
Only works with the MiniMax TTS engine.
languages[].fillers
string[]Defaults to NoneDeprecated
An array of strings to be used as fillers in the conversation and when the agent is calling a SWAIG function. Deprecated: Use speech_fillers and function_fillers instead.
languages[].engine
stringDefaults to gcloudDeprecated
The engine to use for the language. For example, "elevenlabs". Deprecated. Set the engine with the voice parameter.
Use voice strings
Compose the voice string using the <engine id>.<voice id> syntax.
First, select your engine using the gcloud, polly, elevenlabs, deepgram, cartesia, rime, inworld, or minimax identifier. Append a period (.), and then the specific voice ID (for example, en-US-Casual-K) from the TTS provider. Refer to SignalWire’s Supported Voices and Languages for guides on configuring voice ID strings for each provider.
Supported voices and languages
SignalWire’s cloud platform integrates with leading text-to-speech providers. For a comprehensive list of supported engines, languages, and voices, refer to our documentation on Supported Voices and Languages.
Examples
Set a single language
SWML will automatically assign the language (and other required parameters) to the defaults in the above table if left unset. This example uses ai.language to configure a specific English-speaking voice from ElevenLabs.
YAMLJSON
languages:
- name: English
code: en-US
voice: elevenlabs.rachel
speech_fillers:
- one moment please,
- hmm...
- let's see,Set multiple languages
SWML will automatically assign the language (and other required parameters) to the defaults in the above table if left unset. This example uses ai.language to configure multiple languages using different TTS engines.
YAMLJSON
languages:
- name: Mandarin
code: cmn-TW
voice: gcloud.cmn-TW-Standard-A
- name: English
code: en-US
voice: elevenlabs.rachelConfigure per-language ElevenLabs parameters
Configure different stability and similarity values for each language using languages[].params:
YAMLJSON
ai:
languages:
- name: English
code: en-US
voice: elevenlabs.josh
params:
stability: 0.6
similarity: 0.8
- name: Spanish
code: es-ES
voice: elevenlabs.maria
params:
stability: 0.4
similarity: 0.9params
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Parameters for AI that can be passed in ai.params at the top level of the ai method. These parameters control the fundamental behavior and capabilities of the AI agent, including model selection, conversation management, and advanced features like thinking and vision.
Properties
ai.params
object
An object that accepts the following properties.
params.ai_model
stringDefaults to gpt-4o-mini
The AI model that the AI Agent will use during the conversation.
params.ai_name
stringDefaults to computer
Sets the name the AI agent responds to for wake/activation purposes. When using enable_pause, start_paused, or speak_when_spoken_to, the user must say this name to get the agent’s attention. The name matching is case-insensitive.
params.app_name
stringDefaults to swml app
A custom identifier for the AI application instance. This name is included in webhook payloads (post_prompt_url, SWAIG function calls), allowing backend systems to identify which AI configuration made the request.
params.conscience
string
Sets the prompt which binds the agent to its purpose. This prompt helps reinforce the AI’s behavior after SWAIG function calls.
It is used to reinforce the AI agent’s behavior and guardrails throughout the conversation.
params.convo
object[]
Injects pre-existing conversation history into the AI session at startup. This allows you to seed the AI agent with context from a previous conversation or provide example interactions.
convo[].role
stringRequired
The role of the message sender. Valid values:
user- A message from the human caller/user interacting with the AI agent.assistant- A message from the AI agent itself.system- A system message providing instructions or context to guide the AI’s behavior.
convo[].content
stringRequired
The text content of the message.
convo[].lang
stringDefaults to en
The language code for the message. Uses standard ISO language codes such as en, en-US, es, fr, de, etc.
params.conversation_id
string
Used by check_for_input and save_conversation to identify an individual conversation.
params.conversation_sliding_window
integer
Sets the size of the sliding window for conversation history. This limits how much conversation history is sent to the AI model.
params.direction
stringDefaults to the natural direction of the call
Forces the direction of the call to the assistant. Valid values are inbound and outbound.
params.enable_inner_dialog
booleanDefaults to false
Enables the inner dialog feature, which runs a separate AI process in the background that analyzes the conversation and provides real-time insights to the main AI agent. This gives the agent a form of “internal thought process” that can help it make better decisions.
params.enable_pause
booleanDefaults to false
Enables the pause/resume functionality for the AI agent. When enabled, a pause_conversation function is automatically added that the AI can call when the user says things like “hold on”, “wait”, or “pause”. While paused, the agent stops responding until the user speaks the agent’s name (set via ai_name) to resume. Cannot be used together with speak_when_spoken_to.
params.enable_thinking
booleanDefaults to false
Enables thinking output for the AI Agent. When set to true, the AI Agent will be able to utilize thinking capabilities. This may introduce a little bit of latency as the AI will use an additional turn in the conversation to think about the query.
params.enable_turn_detection
booleanDefaults to true
Enables intelligent turn detection that monitors partial speech transcripts for sentence-ending punctuation. When detected, the system can proactively finalize the speech recognition, reducing latency before the AI responds. Works with turn_detection_timeout.
params.enable_vision
booleanDefaults to false
Enables visual input processing for the AI Agent. When set to true, the AI Agent will be able to utilize visual processing capabilities. The image used for visual processing will be gathered from the user’s camera if video is available on the call, leveraging the get_visual_input function.
params.languages_enabled
booleanDefaults to false
Allows multilingualism when true.
params.local_tz
stringDefaults to US/Central
The local timezone setting for the AI. Value should use IANA TZ ID
params.save_conversation
booleanDefaults to false
Send a summary of the conversation after the call ends. This requires post_prompt_url to be set and the conversation_id defined. This eliminates the need for a post_prompt in the ai parameters.
params.summary_mode
string
Summary generation mode. Valid values: "string", "original".
params.thinking_model
stringDefaults to Value of ai_model parameter
The AI model that the AI Agent will use when utilizing thinking capabilities.
params.transfer_summary
booleanDefaults to false
Pass a summary of a conversation from one AI agent to another. For example, transfer a call summary between support agents in two departments.
params.vision_model
stringDefaults to Value of ai_model parameter
The AI model that the AI Agent will use when utilizing vision capabilities.
params.wait_for_user
booleanDefaults to false
When false, AI agent will initialize dialogue after call is setup. When true, agent will wait for the user to speak first.
Speech Recognition
Configure how the AI agent processes and understands spoken input, including speaker identification, voice activity detection, and transcription settings.
params.asr_diarize
booleanDefaults to false
If true, enables speaker diarization in ASR (Automatic Speech Recognition). This will break up the transcript into chunks, with each chunk containing a unique identity (e.g speaker1, speaker2, etc.) and the text they spoke.
params.asr_smart_format
booleanDefaults to false
Enables smart formatting in ASR (Automatic Speech Recognition). This improves the formatting of numbers, dates, times, and other entities in the transcript.
params.enable_text_normalization
stringDefaults to both
Converts numbers, currency, dates, and similar values between their written and spoken forms so the AI understands callers more accurately and speaks its responses more naturally. For example, a caller who says “twenty three dollars” is understood as $23, and the AI’s $23 is spoken back as “twenty three dollars”. Applies in both directions by default. See accepted values below.
params.asr_speaker_affinity
booleanDefaults to false
If true, will force the AI Agent to only respond to the speaker who responds to the AI Agent first. Any other speaker will be ignored.
params.end_of_speech_timeout
integerDefaults to 700
Amount of silence, in ms, at the end of an utterance to detect end of speech. Allowed values from 0-10,000.
params.energy_level
numberDefaults to 52
Amount of energy necessary for bot to hear you (in dB). Allowed values from 0.0-100.0.
params.first_word_timeout
integerDefaults to 1000
Amount of time, in ms, to wait for the first word after speech is detected. Allowed values from 0-10,000.
params.llm_diarize_aware
booleanDefaults to false
If true, the AI Agent will be involved with the diarization process. Users can state who they are at the start of the conversation and the AI Agent will be able to correctly identify them when they are speaking later in the conversation.
params.openai_asr_engine
stringDefaults to gcloud_speech_v2_async
The ASR (Automatic Speech Recognition) engine to use. Common values include deepgram:nova-2, deepgram:nova-3, and other supported ASR engines.
Values for enable_text_normalization
| Value | Applies to | What it does |
|---|---|---|
heard | Caller input | Converts what the caller says into written form before the AI reads it, for example, “twenty three dollars” becomes $23. |
spoken | AI responses | Converts the AI’s written response into spoken form before it is read aloud, for example, $23 becomes “twenty three dollars”. |
both | Caller input and AI responses | Applies both conversions. This is the default. |
false / off / none | , | Turns text normalization off. |
true / on | Caller input and AI responses | Same as both. |
Text normalization is applied per language and adapts automatically if the conversation switches languages.
If text normalization isn’t available for the language being spoken, that direction is simply skipped and the conversation continues uninterrupted. Some languages support only one direction; in that case, both applies whichever is available.
Speech Synthesis
Customize the AI agent’s voice output, including volume control, voice characteristics, emotional range, and video avatars for visual interactions.
params.ai_volume
integerDefaults to 0
Adjust the volume of the AI. Allowed values from -50-50.
params.max_emotion
integerDefaults to 30
Maximum emotion intensity for text-to-speech. Allowed values from 1-30.
params.speech_gen_quick_stops
integerDefaults to 3
Number of quick stops for speech generation. Allowed values from 0-10.
params.tts_number_format
stringDefaults to international
The format of the number the AI will reference the phone number. Valid values: international (e.g. +12345678901) or national (e.g. (234) 567-8901).
params.video_idle_file
string
URL of a video file to play when AI is idle. Only works for calls that support video.
params.video_listening_file
string
URL of a video file to play when AI is listening to the user speak. Only works for calls that support video.
params.video_talking_file
string
URL of a video file to play when AI is talking. Only works for calls that support video.
params.eleven_labs_similarity
numberDefaults to 0.75Deprecated
The similarity slider dictates how closely the AI should adhere to the original voice when attempting to replicate it. The higher the similarity, the closer the AI will sound to the original voice. Valid values range from 0.0 to 1.0. Deprecated: Use languages[].params.similarity instead.
params.eleven_labs_stability
numberDefaults to 0.50Deprecated
The stability slider determines how stable the voice is and the randomness between each generation. Lowering this slider introduces a broader emotional range for the voice. Valid values range from 0.0 to 1.0. Deprecated: Use languages[].params.stability instead.
Interruption & Barge Control
Manage how the AI agent handles interruptions when users speak over it, including when to stop speaking, acknowledge interruptions, or continue regardless.
params.acknowledge_interruptions
boolean | numberDefaults to false
Instructs the agent to acknowledge crosstalk and confirm user input when the user speaks over the agent. Can be boolean or a positive integer specifying the maximum number of interruptions to acknowledge.
params.barge_functions
booleanDefaults to true
Allow functions to be called during barging. When false, functions are not executed if the user is speaking.
params.barge_match_string
string
Takes a string, including a regular expression, defining barge behavior. For example, this param can direct the AI to stop when the word “hippopotamus” is input.
params.barge_min_words
integer
Defines the number of words that must be input before triggering barge behavior. Allowed values from 1-99.
params.enable_barge
string
Controls when user can interrupt the AI. Valid values: "complete", "partial", "all", or boolean. Set to false to disable barging.
params.interrupt_on_noise
boolean | integerDefaults to false
When enabled, barges agent upon any sound interruption longer than 1 second. Can be boolean or a positive integer specifying the threshold.
params.interrupt_prompt
string
A prompt that is used to help the AI agent respond to interruptions.
Default: “The user didn’t wait for you to finish responding and started talking over you. As part of your next response, make a comment about how you were both talking at the same time and verify you properly understand what the user said.”
params.transparent_barge
booleanDefaults to true
When enabled, the AI will not respond to the user’s input when the user is speaking over the agent. The agent will wait for the user to finish speaking before responding. Additionally, any attempt the LLM makes to barge will be ignored and scraped from the conversation logs.
params.transparent_barge_max_time
integerDefaults to 3000
Maximum duration for transparent barge mode. Allowed values from 0-60,000 ms.
Timeouts & Delays
Set various timing parameters that control wait times, response delays, and session limits to optimize the conversation flow and prevent dead air.
params.attention_timeout
integerDefaults to 5000
Amount of time, in ms, to wait before prompting the user to respond. Allowed values: 0 (to disable) or 10,000-600,000.
params.attention_timeout_prompt
stringDefaults to The user has not responded, try to get their attention. Stay in the same language.
A custom prompt that is fed into the AI when the attention_timeout is reached.
params.digit_timeout
integerDefaults to 3000
Time, in ms, at the end of digit input to detect end of input. Allowed values from 0-30,000.
params.hard_stop_prompt
string
A final prompt that is fed into the AI when the hard_stop_time is reached.
params.hard_stop_time
string
Specifies the maximum duration for the AI Agent to remain active before it exits the session. After the timeout, the AI will stop responding, and will proceed with the next SWML instruction. Time format: 30s (seconds), 2m (minutes), 1h (hours), or combined 1h45m30s.
params.inactivity_timeout
integerDefaults to 600000
Amount of time, in ms, to wait before exiting the app due to inactivity. Allowed values: 0 (to disable) or 10,000-3,600,000.
params.initial_sleep_ms
integerDefaults to 0
Amount of time, in ms, to wait before the AI Agent starts processing. Allowed values from 0-300,000.
params.outbound_attention_timeout
integerDefaults to 120000
Sets a time duration for the outbound call recipient to respond to the AI agent before timeout. Allowed values from 10,000-600,000 ms.
params.speech_event_timeout
integerDefaults to 1400
Timeout for speech events processing. Allowed values from 0-10,000 ms.
params.speech_timeout
integerDefaults to 60000
Overall speech timeout (developer mode only). Allowed values from 0-600,000 ms.
Audio & Media
Control background audio, hold music, and greeting messages to enhance the caller experience during different phases of the conversation.
params.background_file
string
URL of audio file to play in the background while AI plays in foreground.
params.background_file_loops
integerDefaults to undefined
Maximum number of times to loop playing the background file.
params.background_file_volume
integerDefaults to 0
Defines background_file volume. Allowed values from -50 to 50.
params.hold_music
string
A URL for the hold music to play, accepting WAV, mp3, and FreeSWITCH tone_stream.
params.hold_on_process
booleanDefaults to false
Enables hold music during SWAIG processing.
params.static_greeting
string
The static greeting to play when the call is answered. This will always play at the beginning of the call.
params.static_greeting_no_barge
booleanDefaults to false
If true, the static greeting will not be interrupted by the user if they speak over the greeting. If false, the static greeting can be interrupted by the user if they speak over the greeting.
SWAIG Functions
Configure SignalWire AI Gateway (SWAIG) function capabilities, including permissions, execution timing, and data persistence across function calls.
params.function_wait_for_talking
booleanDefaults to false
If true, the AI will wait for any filler to finish playing before executing a function. If false, the AI will asynchronously execute a function while playing a filler.
params.functions_on_no_response
booleanDefaults to false
Execute functions when the user doesn’t respond (on attention timeout).
params.swaig_allow_settings
booleanDefaults to true
Allows tweaking any of the indicated settings, such as barge_match_string, using the returned SWML from the SWAIG function.
params.swaig_allow_swml
booleanDefaults to true
Allows your SWAIG to return SWML to be executed.
params.swaig_post_conversation
booleanDefaults to false
Post entire conversation to any SWAIG call.
params.swaig_set_global_data
booleanDefaults to true
Allows SWAIG functions to set global data that persists across function calls.
Input & DTMF
Handle dual-tone multi-frequency (DTMF) input and configure input polling for integrating external data sources during conversations.
params.digit_terminators
string
DTMF digit, as a string, to signal the end of input (ex: ”#”)
params.input_poll_freq
integerDefaults to 2000
Check for input function with check_for_input. Allowed values from 1,000-10,000 ms. Example use case: Feeding an inbound SMS to AI on a voice call, eg., for collecting an email address or other complex information.
Debug & Development
Enable debugging tools, logging, and performance monitoring features to help developers troubleshoot and optimize their AI agent implementations.
params.audible_debug
booleanDefaults to false
If true, the AI will announce the function that is being executed on the call.
params.audible_latency
booleanDefaults to false
Announce latency information during the call for debugging purposes.
params.cache_mode
booleanDefaults to false
Enable response caching to improve performance for repeated queries.
params.debug
boolean | integerDefaults to false
Enables debug mode for the AI session. When set to true or a positive integer, additional debug information is logged and may be included in webhook payloads. Higher integer values increase verbosity.
params.debug_webhook_level
integerDefaults to 1
Enables debugging to the set URL. Allowed values from 0-2. Level 0 disables, 1 provides basic info, 2 provides verbose info.
params.debug_webhook_url
string
Each interaction between the AI and end user is posted in real time to the established URL. Authentication can also be set in the url in the format of username:password@url.
params.enable_accounting
booleanDefaults to false
Enable usage accounting and tracking for billing and analytics purposes.
params.verbose_logs
booleanDefaults to false
Enable verbose logging (developer mode only).
Inner Dialog
Configure the inner dialog feature, which enables a secondary AI process to analyze conversations in real-time and provide insights to the main AI agent.
params.inner_dialog_model
string
Specifies the AI model to use for the inner dialog feature. If not set, the main ai_model is used. This allows you to use a different (potentially faster or cheaper) model for background analysis.
params.inner_dialog_prompt
stringDefaults to The assistant is intelligent and straightforward, does its job well and is not excessively polite.
The system prompt that guides the inner dialog AI’s behavior. This prompt shapes how the background AI analyzes the conversation and what kind of insights it provides to the main agent.
params.inner_dialog_synced
booleanDefaults to false
When enabled, synchronizes the inner dialog with the main conversation flow. This ensures the inner dialog AI waits for the main conversation turn to complete before providing its analysis, rather than running fully asynchronously.
Pause & Wake
Control the agent’s listening behavior, including pause/resume functionality and activation triggers for hands-free scenarios.
params.speak_when_spoken_to
booleanDefaults to false
When enabled, the AI agent remains silent until directly addressed by name (set via ai_name). This creates a “push-to-talk” style interaction where the agent only responds when explicitly called upon, useful for scenarios where the agent should listen but not interrupt.
params.start_paused
booleanDefaults to false
When enabled, the AI agent starts in a paused state. The agent will not respond to any input until the user speaks the agent’s name (set via ai_name) to activate it. This is useful for scenarios where you want the agent to wait for explicit activation.
params.wake_prefix
string
Specifies an additional prefix that must be spoken along with the agent’s name to wake the agent. For example, if ai_name is “assistant” and wake_prefix is “hey”, the user would need to say “hey assistant” to activate the agent.
Advanced Configuration
Fine-tune advanced AI behavior settings including response limits, data persistence, prompt formatting, and voice activity detection.
params.max_response_tokens
integer
Sets the maximum number of tokens the AI model can generate in a single response. Allowed values from 1 to 16384. This helps control response length and costs.
params.persist_global_data
booleanDefaults to true
When enabled, global_data persists across multiple AI agent invocations within the same call. This allows data set by SWAIG functions to be retained if the AI agent is invoked multiple times during a single call session.
params.pom_format
stringDefaults to markdown
Specifies the output format for structured prompts sent to the AI model. Valid values are markdown or xml. This affects how system prompts and context are formatted when sent to the underlying language model.
params.swaig_post_swml_vars
boolean | arrayDefaults to false
Controls whether SWML variables are included in SWAIG function webhook payloads. When set to true, all SWML variables are posted. When set to an array of strings, only the specified variable names are included in the payload.
params.turn_detection_timeout
integerDefaults to 250
Time in milliseconds to wait after detecting a potential end-of-turn before finalizing speech recognition. Works with enable_turn_detection. Lower values make the agent more responsive but may cut off users mid-sentence. Allowed values from 0 to 10000.
params.vad_config
string
Configures Silero Voice Activity Detection (VAD) settings. Format: threshold or threshold:frame_ms. The threshold (0-100) sets sensitivity for voice detection, and optional frame_ms (16-40) sets the analysis frame duration in milliseconds.
prompt
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Defines the AI agent’s personality, goals, behaviors, and instructions for handling conversations. The prompt establishes how the agent should interact with callers, what information it should gather, and how it should respond to various scenarios.
It is recommended to write prompts using markdown formatting as LLMs better understand structured content. Additionally it is recommended to read the Prompting Best Practices guide.
Prompt types
There are three ways to define prompt content, each suited for different use cases:
Text prompt, A single string containing the full prompt. Best for simple agents where the entire personality, instructions, and rules fit naturally into one block of text.
POM (Prompt Object Model), A structured array of sections with titles, body text, and bullet points. Best for complex prompts that benefit from clear organization. SignalWire renders the POM into a markdown document before sending it to the LLM.
Contexts, A system of named conversation flows, each with its own steps, memory settings, and transition logic. Best for multi-stage conversations where the agent needs to switch between distinct modes (e.g., greeting → support → billing). Requires a
defaultcontext as the entry point. See Contexts below.
Text and POM are mutually exclusive, use one or the other. Contexts can be combined with either a text or POM prompt to add structured conversation flows on top of the base prompt.
Properties
ai.prompt
object
An object that contains the prompt parameters.
The prompt property accepts one of the following objects:
Regular Prompt
POM Prompts
prompt.text
stringRequired
The main identity prompt for the AI. This prompt will be used to outline the agent’s personality, role, and other characteristics.
prompt.temperature
numberDefaults to 1.0
Randomness setting. Float value between 0.0 and 1.5. Closer to 0 will make the output less random.
prompt.top_p
numberDefaults to 1.0
Randomness setting. Alternative to temperature. Float value between 0.0 and 1.0. Closer to 0 will make the output less random.
prompt.confidence
numberDefaults to 0.6
Threshold to fire a speech-detect event at the end of the utterance. Float value between 0.0 and 1.0. Decreasing this value will reduce the pause after the user speaks, but may introduce false positives.
prompt.presence_penalty
numberDefaults to 0
Aversion to staying on topic. Float value between -2.0 and 2.0. Positive values increase the model’s likelihood to talk about new topics.
prompt.frequency_penalty
numberDefaults to 0
Aversion to repeating lines. Float value between -2.0 and 2.0. Positive values decrease the model’s likelihood to repeat the same line verbatim.
prompt.max_tokens
integerDefaults to 256
Limits the amount of tokens that the AI agent may generate when creating its response. Valid value range: 0 - 4096.
prompt.contexts
object
An object that defines the available contexts for the AI. Each context represents a set of steps that guide the flow of the conversation. The object must include a default key, which specifies the initial context used at the start of the conversation. Additional contexts can be added as other keys within the object.
contexts.default
objectRequired
The default context used at the beginning of the conversation.
contexts.*
object
Additional contexts for specialized conversation flows. The key is user-defined (e.g., support, sales, billing).
*.steps
object[]Required
An array of step objects that define the conversation flow for this context. Steps execute sequentially unless otherwise specified. Each step contains either a text string or a pom array to provide prompt instructions.
*.isolated
booleanDefaults to false
When true, resets conversation history to only the system prompt when entering this context. Useful for focused tasks that shouldn’t be influenced by previous conversation.
*.enter_fillers
object[]
Language-specific filler phrases played when transitioning into this context.
enter_fillers[].<language_code toc={true}>
string[]
An array of filler phrases for the specified language code. One phrase is randomly selected during transitions. Possible language codes:
default- Default language set by the user in theai.languagespropertybg- Bulgarianca- Catalancs- Czechda- Danishda-DK- Danish (Denmark)de- Germande-CH- German (Switzerland)el- Greeken- Englishen-AU- English (Australia)en-GB- English (United Kingdom)en-IN- English (India)en-NZ- English (New Zealand)en-US- English (United States)es- Spanishes-419- Spanish (Latin America)et- Estonianfi- Finnishfr- Frenchfr-CA- French (Canada)hi- Hindihu- Hungarianid- Indonesianit- Italianja- Japaneseko- Koreanko-KR- Korean (South Korea)lt- Lithuanianlv- Latvianms- Malaymulti- Multilingual (Spanish + English)nl- Dutchnl-BE- Flemish (Belgian Dutch)no- Norwegianpl- Polishpt- Portuguesept-BR- Portuguese (Brazil)pt-PT- Portuguese (Portugal)ro- Romanianru- Russiansk- Slovaksv- Swedishsv-SE- Swedish (Sweden)th- Thaith-TH- Thai (Thailand)tr- Turkishuk- Ukrainianvi- Vietnamesezh- Chinese (Simplified)zh-CN- Chinese (Simplified, China)zh-Hans- Chinese (Simplified Han)zh-Hant- Chinese (Traditional Han)zh-HK- Chinese (Traditional, Hong Kong)zh-TW- Chinese (Traditional, Taiwan)
*.exit_fillers
object[]
Language-specific filler phrases played when leaving this context. Same format as enter_fillers.
Examples
Basic prompt
YAMLJSON
version: 1.0.0
sections:
main:
- ai:
prompt:
text: |
You are a friendly customer service agent for a telecommunications company.
Your name is Alex. Always greet the caller warmly and ask how you can help.
## Rules
- Be polite and professional at all times
- If the caller asks about billing, offer to transfer them to the billing department
- If you cannot help with a request, apologize and suggest alternatives
temperature: 0.8
top_p: 0.9
confidence: 0.6POM prompt
YAMLJSON
version: 1.0.0
sections:
main:
- ai:
prompt:
text: "Prompt is defined in pom"
pom:
- title: "Agent Personality"
body: "You are a friendly and engaging assistant. Keep the conversation light and fun."
subsections:
- title: "Personal Information"
numberedBullets: true
bullets:
- "You are a AI Agent"
- "Your name is Frank"
- "You work at SignalWire"
- title: "Task"
body: "You are to ask the user a series of questions to gather information."
bullets:
- "Ask the user to provide their name"
- "Ask the user to provide their favorite color"
- "Ask the user to provide their favorite food"
- "Ask the user to provide their favorite movie"
- "Ask the user to provide their favorite TV show"
- "Ask the user to provide their favorite music"
- "Ask the user to provide their favorite sport"
- "Ask the user to provide their favorite animal"Rendered prompt
The above POM example will render the following markdown prompt:
## Agent Personality
You are a friendly and engaging assistant. Keep the conversation light and fun.
### Personal Information
1. You are a AI Agent
2. Your name is Frank
3. You work at SignalWire
## Task
You are to ask the user a series of questions to gather information.
- Ask the user to provide their name
- Ask the user to provide their favorite color
- Ask the user to provide their favorite food
- Ask the user to provide their favorite movie
- Ask the user to provide their favorite TV show
- Ask the user to provide their favorite music
- Ask the user to provide their favorite sport
- Ask the user to provide their favorite animalBasic context
YAMLJSON
version: 1.0.0
sections:
main:
- ai:
prompt:
text: You are a helpful assistant that can switch between different expertise areas.
contexts:
default:
steps:
- name: greeting
text: Greet the user and ask what they need help with. If they need technical support, transfer them to the support context.
valid_contexts:
- support
support:
isolated: true
enter_fillers:
- en-US: ["Switching to technical support", "Let me connect you with support"]
es-ES: ["Cambiando a soporte técnico", "Permítame conectarlo con soporte"]
exit_fillers:
- en-US: ["Leaving support mode", "Returning to main menu"]
es-ES: ["Saliendo del modo de soporte", "Volviendo al menú principal"]
steps:
- name: troubleshoot
text: Help the user troubleshoot their technical issue. When finished, ask if they need anything else or want to return to the main menu.
valid_contexts:
- defaultAdvanced multi-context
This example demonstrates multiple contexts with different AI personalities, voice settings, and specialized knowledge domains:
YAMLJSON
sections:
main:
- ai:
hints:
- StarWars
- StarTrek
languages:
- name: Ryan-English
voice: elevenlabs.patrick
code: en-US
- name: Luke-English
voice: elevenlabs.fin
code: en-US
- name: Spock-English
voice: elevenlabs.charlie
code: en-US
prompt:
text: Help the user transfer to the Star Wars or Star Trek expert.
contexts:
default:
steps:
- name: start
text: |+
Your name is Ryan. You are a receptionist. Your only purpose is to change the context to starwars or startrek.
step_criteria: |+
Introduce yourself as Ryan.
Ask the user if he would like to talk to a star wars or star trek expert until they provide an adequate answer.
- name: transfer
text: You will now successfully transfer the user to the Star Wars or Star Trek expert.
step_criteria: If the user has chosen a valid context, transfer them to the appropriate expert.
valid_contexts:
- starwars
- startrek
starwars:
steps:
- name: start
text: |+
The user has been transferred to the Star Wars expert.
Until told otherwise, your name is Luke. Change the language to Luke-English.
Your current goal is to get the user to tell you their name.
Unless told otherwise, refer to the user as 'Padawan {users_name}'.
step_criteria: |+
Introduce yourself as Luke, the Star Wars expert.
The user must tell you their name if they only say one word assume that is their name.
- name: question
text: |+
Your goal is to get the user to choose one of the following options.
- Jedi Order (advance to jedi_order step)
- The ways of the Force (advance to force step)
- Talk to the star trek expert. (change context to startrek)
step_criteria: +|
The user must provide a valid answer to continue.
Refer to the user as 'Padawan {users_name}' for the rest of the conversation.
valid_steps:
- jedi_order
- force
valid_contexts:
- startrek
- name: jedi_order
text: |+
Limit the topic to the Jedi Order.
Inform the user they can say they want to change the topic at any time, if they do move to the question step.
step_criteria: The user says they want to change the topic.
valid_steps:
- question
- name: force
text: |+
Limit the topic to the force.
Inform the user they can say they want to change the topic at any time, if they do move to the question step.
step_criteria: The user says they want to change the topic.
valid_steps:
- question
startrek:
steps:
- name: start
text: |+
The user has been transferred to the Star Trek expert.
Until told otherwise, your name is Spok. Change the language to Spok-English.
Your current goal is to get the user to tell you their name.
Unless told otherwise, refer to the user as 'Ensign {users_name}'.
step_criteria: |+
Introduce yourself as Spok, the Star Trek expert.
The user must tell you their name if they only say one word assume that is their name.
- name: question
text: |+
Your goal is to get the user to choose one of the following options.
- Vulcan Culture (advance to vulcan_culture step)
- Federation (advance to federation step)
- Talk to the star wars expert. (change context to starwars)
step_criteria: +|
The user must provide a valid answer to continue.
Refer to the user as 'Ensign {users_name}' for the rest of the conversation.
valid_steps:
- vulcan_culture
- federation
valid_contexts:
- starwars
- name: vulcan_culture
text: |+
Limit the topic to Vulcan Culture.
Inform the user they can say they want to change the topic at any time, if they do move to the question step.
step_criteria: The user says they want to change the topic.
valid_steps:
- question
- name: federation
text: |+
Limit the topic to the Federation of Planets.
Inform the user they can say they want to change the topic at any time, if they do move to the question step.
step_criteria: The user says they want to change the topic.
valid_steps:
- questionVariable Expansion
Use the following syntax to expand variables into your prompt.
${call_direction}
string
Inbound or outbound.
${caller_id_number}
string
The caller ID number.
${local_date}
string
The local date.
${spoken_date}
string
The spoken date.
${local_time}
string
The local time.
${time_of_day}
string
The time of day.
${supported_languages}
string
A list of supported languages.
${default_language}
string
The default language.
SWAIG
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
The SignalWire AI Gateway Interface. Allows you to create user-defined functions that can be executed during the dialogue.
Properties
ai.SWAIG
object
An object that accepts the following properties.
SWAIG.defaults
object
Default settings for all SWAIG functions. If defaults is not set, settings may be set in each function object. Default is not set.
defaults.web_hook_url
string
The default URL to send status callbacks and reports to for all SWAIG functions. If defaults is not set, web_hook_url may be set in each SWAIG function object. Authentication can also be set in the url in the format of username:password@url.
SWAIG.functions
object[]
An array of JSON objects to define functions that can be executed during the interaction with the AI. Default is not set. The fields of this object are the six following.
See functions for additional details.
SWAIG.includes
object[]
An array of objects to include remote function signatures. This allows you to include functions that are defined in a remote location.
See includes for additional details.
SWAIG.internal_fillers
object
An object that defines language-specific filler phrases for internal SWAIG functions. These fillers help break silence between responses and are played asynchronously during function execution. Each key is a function name, and each value is an object mapping language codes to arrays of filler phrases.
internal_fillers.hangup
object
Filler phrases played when the AI Agent is hanging up the call.
internal_fillers.check_time
object
Filler phrases played when the AI Agent is checking the time.
internal_fillers.wait_for_user
object
Filler phrases played when the AI Agent is waiting for user input.
internal_fillers.wait_seconds
object
Filler phrases played during deliberate pauses or wait periods.
internal_fillers.adjust_response_latency
object
Filler phrases played when the AI Agent is adjusting response timing.
internal_fillers.next_step
object
Filler phrases played when transitioning between conversation steps when utilizing prompt.contexts.
internal_fillers.change_context
object
Filler phrases played when switching between conversation contexts when utilizing prompt.contexts.
internal_fillers.get_visual_input
object
Filler phrases played when the AI Agent is processing visual input. Enabled when enable_vision is set to true in ai.params.
internal_fillers.get_ideal_strategy
object
Filler phrases played when the AI Agent is thinking or considering options. Enabled when enable_thinking is set to true in ai.params.
SWAIG.native_functions
string[]
Prebuilt functions the AI agent is able to call. The agent is already aware of these functions and can use them creatively based on prompting. For example, a prompt like “tell the user what time it is” will automatically use check_time.
Accepted values:
adjust_response_latency- Adjust how long the agent will wait for the user to stop talking.check_time- Returns the current time for the time zone set inai.local_tz.wait_for_user- Causes the AI to wait until the user speaks again. Use when the user asks to wait or hold on.wait_seconds- Waits for the given amount of time.
SWAIG.mcp_servers
object[]
An array of MCP (Model Context Protocol) servers whose tools and resources are made available to the AI. Each server’s tools are discovered at startup and registered as callable functions, so they can be invoked like any other SWAIG function.
mcp_servers[].url
stringRequired
The MCP server URL.
mcp_servers[].headers
object
HTTP headers sent to the MCP server. Authorization tokens go here, there is no separate auth field. Header values support variable expansion (e.g. Bearer ${global_data.token}).
mcp_servers[].resources
booleanDefaults to false
Whether to fetch the server’s resources into global_data, when the server advertises resource support.
mcp_servers[].resource_vars
object
Template variables passed to the MCP server when fetching resources. Used only when resources is enabled.
Filler language codes
Several SWAIG properties accept filler phrases keyed by language code, including internal_fillers and per-function fillers. The following language codes are supported across all filler configurations.
| Code | Description |
|---|---|
default | Default language set by the user in the ai.languages property |
bg | Bulgarian |
ca | Catalan |
cs | Czech |
da | Danish |
da-DK | Danish (Denmark) |
de | German |
de-CH | German (Switzerland) |
el | Greek |
en | English |
en-AU | English (Australia) |
en-GB | English (United Kingdom) |
en-IN | English (India) |
en-NZ | English (New Zealand) |
en-US | English (United States) |
es | Spanish |
es-419 | Spanish (Latin America) |
et | Estonian |
fi | Finnish |
fr | French |
fr-CA | French (Canada) |
hi | Hindi |
hu | Hungarian |
id | Indonesian |
it | Italian |
ja | Japanese |
ko | Korean |
ko-KR | Korean (South Korea) |
lt | Lithuanian |
lv | Latvian |
ms | Malay |
multi | Multilingual (Spanish + English) |
nl | Dutch |
nl-BE | Flemish (Belgian Dutch) |
no | Norwegian |
pl | Polish |
pt | Portuguese |
pt-BR | Portuguese (Brazil) |
pt-PT | Portuguese (Portugal) |
ro | Romanian |
ru | Russian |
sk | Slovak |
sv | Swedish |
sv-SE | Swedish (Sweden) |
th | Thai |
th-TH | Thai (Thailand) |
tr | Turkish |
uk | Ukrainian |
vi | Vietnamese |
zh | Chinese (Simplified) |
zh-CN | Chinese (Simplified, China) |
zh-Hans | Chinese (Simplified Han) |
zh-Hant | Chinese (Traditional Han) |
zh-HK | Chinese (Traditional, Hong Kong) |
zh-TW | Chinese (Traditional, Taiwan) |
Webhook response
When a SWAIG function is executed, the function expects the user to respond with a JSON object that contains a response key and an optional action key. This request response is used to provide the LLM with a new prompt response via the response key and to execute SWML-compatible objects that will perform new dialplan actions via the action key.
response
stringRequired
Static text that will be added to the AI agent’s context.
action
object[]
A list of SWML-compatible objects that are executed upon the execution of a SWAIG function.
action[].SWML
object
A SWML object to be executed.
action[].say
string
A message to be spoken by the AI agent.
action[].stop
boolean
Whether to stop the conversation.
action[].hangup
boolean
Whether to hang up the call. When set to true, the call will be terminated after the AI agent finishes speaking.
action[].hold
integer | object
Places the caller on hold while playing hold music (configured via the params.hold_music parameter). During hold, speech detection is paused and the AI agent will not respond to the caller.
The value specifies the hold timeout in seconds. Can be:
- An integer (e.g.,
120for 120 seconds) - An object with a
timeoutproperty
Default timeout is 300 seconds (5 minutes). Maximum timeout is 900 seconds (15 minutes).
Unholding a call
There is no unhold SWAIG action because the AI agent is inactive during hold and cannot process actions. To take a caller off hold, either:
- Let the hold timeout expire (the AI will automatically resume with a default message), or
- Use the Calling API
ai_unholdcommand to programmatically unhold the call with a custom prompt.
hold.timeout
integerDefaults to 300
The duration to hold the caller in seconds. Maximum is 900 seconds (15 minutes).
action[].change_context
string
The name of the context to switch to. The context must be defined in the AI’s prompt.contexts configuration. This action triggers an immediate context switch during the execution of a SWAIG function.
Visit the contexts documentation for details on defining contexts.
action[].change_step
string
The name of the step to switch to. The step must be defined in prompt.contexts.{context_name}.steps for the current context. This action triggers an immediate step transition during the execution of a SWAIG function.
Visit the steps documentation for details on defining steps.
action[].toggle_functions
object[]
An array of objects to toggle SWAIG functions on or off during the conversation. Each object identifies a function by name and sets its active state.
See toggle_functions for additional details.
toggle_functions[].function
stringRequired
The name of the SWAIG function to toggle.
toggle_functions[].active
booleanDefaults to true
Whether to activate or deactivate the function.
action[].set_global_data
object
A JSON object containing any global data, as a key-value map. This action sets the data in the global_data to be globally referenced.
action[].set_meta_data
object
A JSON object containing any metadata, as a key-value map. This action sets the data in the meta_data to be referenced locally in the function.
See set_meta_data for additional details.
action[].unset_global_data
string | object
The key of the global data to unset from the global_data. You can also reset the global_data by passing in a new object.
action[].unset_meta_data
string | object
The key of the metadata to unset from the meta_data. You can also reset the meta_data by passing in a new object.
action[].playback_bg
object
A JSON object containing the audio file to play.
playback_bg.file
string
URL or filepath of the audio file to play. Authentication can also be set in the url in the format of username:password@url.
playback_bg.wait
booleanDefaults to false
Whether to wait for the audio file to finish playing before continuing.
action[].stop_playback_bg
boolean
Whether to stop the background audio file.
action[].user_input
string
Used to inject text into the users queue as if they input the data themselves.
action[].context_switch
object
A JSON object containing the context to switch to.
See context_switch for additional details.
context_switch.system_prompt
string
The instructions to send to the agent.
context_switch.consolidate
booleanDefaults to false
Whether to consolidate the context.
context_switch.user_prompt
string
A string serving as simulated user input for the AI Agent. During a context_switch in the AI’s prompt, the user_prompt offers the AI pre-established context or guidance.
action[].transfer
boolean | object
Transfer the call to a new destination. Accepts two forms depending on whether it accompanies a sibling action[].SWML payload:
- Boolean, use alongside a sibling
action[].SWMLpayload in the same action object. Whentrue, ends the AI session and hard-transfers the call to that SWML. When omitted orfalse, the SWML executes inline and the AI session continues afterward. - Object, use on its own, without
SWML, to transfer the call to a specific destination configured with the fields below. A bare string is also accepted as shorthand fortransfer.dest.
transfer.dest
string
The destination to transfer to: the name of a section in the current SWML document, or a URL that returns SWML to execute.
transfer.summarize
booleanDefaults to false
Whether to include a conversation summary when transferring.
Webhook response example
{
"response": "Oh wow, it's 82.0°F in Tulsa. Bet you didn't see that coming! Humidity at 38%. Your hair is going to love this! Wind speed is 2.2 mph. Hold onto your hats, or don't, I'm not your mother! Looks like Sunny. Guess you'll survive another day.",
"action": [\
{\
"set_meta_data": {\
"temperature": 82.0,\
"humidity": 38,\
"wind_speed": 2.2,\
"weather": "Sunny"\
}\
},\
{\
"SWML": {\
"version": "1.0.0",\
"sections": {\
"main": [\
{\
"play": {\
"url": "https://example.com/twister.mp3"\
}\
}\
]\
}\
}\
}\
]
}Callback Request for web_hook_url
SignalWire will make a request to the web_hook_url of a SWAIG function with the following parameters:
call_id
string
The unique identifier for the current call.
ai_session_id
string
The unique identifier for the AI session.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
caller_id_name
string
Name of the caller.
caller_id_num
string
Number of the caller.
global_data
object
Global data set via the set_global_data action, as a key-value map.
content_disposition
string
Content disposition identifier (e.g., "SWAIG Function").
channel_active
boolean
Whether the channel is currently active.
channel_offhook
boolean
Whether the channel is off-hook.
channel_ready
boolean
Whether the channel is ready.
content_type
string
Type of content. The value will be text/swaig.
app_name
string
Name of the application that originated the request.
function
string
Name of the function that was invoked.
meta_data
object
A JSON object containing any user metadata, as a key-value map.
SWMLVars
object
A collection of variables related to SWML.
purpose
string
The purpose of the function being invoked. The value will be the functions.purpose value you provided in the SWML Function properties.
argument_desc
string | object
The description of the argument being passed. This value comes from the argument you provided in the SWML Function properties.
argument
object
The argument the AI agent is providing to the function. The object contains the three following fields.
argument.parsed
object
If a JSON object is detected within the argument, it is parsed and provided here.
argument.raw
string
The raw argument provided by the AI agent.
argument.substituted
string
The argument provided by the AI agent, excluding any JSON.
version
string
Version number.
Webhook request example
Below is a json example of the callback request that is sent to the web_hook_url:
{
"app_name": "swml app",
"global_data": {
"caller_id_name": "",
"caller_id_number": "sip:guest-246dd851-ba60-4762-b0c8-edfe22bc5344@46e10b6d-e5d6-421f-b6b3-e2e22b8934ed.call.signalwire.com;context=guest"
},
"project_id": "46e10b6d-e5d6-421f-b6b3-e2e22b8934ed",
"space_id": "5bb2200d-3662-4f4d-8a8b-d7806946711c",
"caller_id_name": "",
"caller_id_num": "sip:guest-246dd851-ba60-4762-b0c8-edfe22bc5344@46e10b6d-e5d6-421f-b6b3-e2e22b8934ed.call.signalwire.com;context=guest",
"channel_active": true,
"channel_offhook": true,
"channel_ready": true,
"content_type": "text/swaig",
"version": "2.0",
"content_disposition": "SWAIG Function",
"function": "get_weather",
"argument": {
"parsed": [\
{\
"city": "Tulsa",\
"state": "Oklahoma"\
}\
],
"raw": "{\"city\":\"Tulsa\",\"state\":\"Oklahoma\"}"
},
"call_id": "6e0f2f68-f600-4228-ab27-3dfba2b75da7",
"ai_session_id": "9af20f15-7051-4496-a48a-6e712f22daa5",
"argument_desc": {
"properties": {
"city": {
"description": "Name of the city",
"type": "string"
},
"country": {
"description": "Name of the country",
"type": "string"
},
"state": {
"description": "Name of the state",
"type": "string"
}
},
"required": [],
"type": "object"
},
"purpose": "Get weather with sarcasm"
}Variables
- ai_result: (out)
success|failed - return_value: (out)
success|failed
Examples
internal_fillers
YAMLJSON
SWAIG:
internal_fillers:
hangup:
en-US:
- 'Goodbye!'
- 'Thank you for calling.'
- 'Have a great day!'
es-ES:
- '¡Adiós!'
- 'Gracias por llamar.'
- '¡Que tengas un buen día!'
check_time:
default:
- 'Let me check the time.'
- 'One moment while I get the time.'
- 'Just checking the current time.'mcp_servers
YAMLJSON
SWAIG:
mcp_servers:
- url: "https://crm.example.com/mcp"
headers:
Authorization: "Bearer ${global_data.crm_token}"
resources: true
resource_vars:
customer_id: "${global_data.customer_id}"functions
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
An array of JSON objects to define functions that can be executed during the interaction with the AI.
Properties
SWAIG.functions
object[]
An array of JSON objects that accept the following properties.
functions[].description
stringRequired
A description of the context and purpose of the function, to explain to the agent when to use it.
functions[].function
stringRequired
A unique name for the function. This can be any user-defined string or can reference a reserved function. Reserved functions are SignalWire functions that will be executed at certain points in the conversation. To learn more about reserved functions, see Reserved Functions.
functions[].active
booleanDefaults to true
Whether the function is active.
functions[].data_map
object
An object that processes function inputs and executes operations through expressions, webhooks, or direct output. Properties are evaluated in strict priority order: (1) expressions, (2) webhooks, (3) output. Evaluation stops at the first property that returns a valid output result, similar to a return statement in a function.
See data_map for additional details.
functions[].parameters
object
A JSON object that defines the expected user input parameters and their validation rules for the function.
See parameters for additional details.
functions[].fillers
object
An object containing language-specific arrays of filler phrases that are played when calling a SWAIG function. These fillers help break silence between responses and are played asynchronously during the function call. Each key is a language code and each value is an array of filler phrases selected from randomly.
functions[].skip_fillers
booleanDefaults to false
Skips the top-level fillers specified in ai.languages (which includes speech_fillers and function_fillers). When set to true, only function-specific fillers defined directly on SWAIG.functions.fillers will play.
functions[].meta_data
object
A powerful and flexible environmental variable which can accept arbitrary data that is set initially in the SWML script or from the SWML set_meta_data action. This data can be referenced locally to the function. All contained information can be accessed and expanded within the prompt - for example, by using a template string.
functions[].meta_data_token
stringDefaults to Set by SignalWire
Scoping token for meta_data. If not supplied, metadata will be scoped to function’s web_hook_url.
functions[].wait_file
string
A file to play while the function is running. wait_file_loops can specify the amount of times that files should continously play.
functions[].wait_file_loops
string | integer
The amount of times that wait_file should continuously play/loop.
functions[].wait_for_fillers
booleanDefaults to false
Whether to wait for fillers to finish playing before continuing with the function.
functions[].web_hook_url
string
Function-specific URL to send status callbacks and reports to. Takes precedence over a default setting. Authentication can also be set in the url in the format of username:password@url.
functions[].purpose
stringDeprecated
Deprecated. Use description instead.
functions[].argument
objectDeprecated
Deprecated. Use parameters instead.
Webhook response
When a SWAIG function is executed, the function expects the user to respond with a JSON object that contains a response key and an optional action key. This request response is used to provide the LLM with a new prompt response via the response key and to execute SWML-compatible objects that will perform new dialplan actions via the action key.
response
stringRequired
Static text that will be added to the AI agent’s context.
action
object[]
A list of SWML-compatible objects that are executed upon the execution of a SWAIG function.
action[].SWML
object
A SWML object to be executed.
action[].say
string
A message to be spoken by the AI agent.
action[].stop
boolean
Whether to stop the conversation.
action[].hangup
boolean
Whether to hang up the call. When set to true, the call will be terminated after the AI agent finishes speaking.
action[].hold
integer | object
Places the caller on hold while playing hold music (configured via the params.hold_music parameter). During hold, speech detection is paused and the AI agent will not respond to the caller.
The value specifies the hold timeout in seconds. Can be:
- An integer (e.g.,
120for 120 seconds) - An object with a
timeoutproperty
Default timeout is 300 seconds (5 minutes). Maximum timeout is 900 seconds (15 minutes).
Unholding a call
There is no unhold SWAIG action because the AI agent is inactive during hold and cannot process actions. To take a caller off hold, either:
- Let the hold timeout expire (the AI will automatically resume with a default message), or
- Use the Calling API
ai_unholdcommand to programmatically unhold the call with a custom prompt.
hold.timeout
integerDefaults to 300
The duration to hold the caller in seconds. Maximum is 900 seconds (15 minutes).
action[].change_context
string
The name of the context to switch to. The context must be defined in the AI’s prompt.contexts configuration. This action triggers an immediate context switch during the execution of a SWAIG function.
Visit the contexts documentation for details on defining contexts.
action[].change_step
string
The name of the step to switch to. The step must be defined in prompt.contexts.{context_name}.steps for the current context. This action triggers an immediate step transition during the execution of a SWAIG function.
Visit the steps documentation for details on defining steps.
action[].toggle_functions
object[]
An array of objects to toggle SWAIG functions on or off during the conversation. Each object identifies a function by name and sets its active state.
See toggle_functions for additional details.
toggle_functions[].function
stringRequired
The name of the SWAIG function to toggle.
toggle_functions[].active
booleanDefaults to true
Whether to activate or deactivate the function.
action[].set_global_data
object
A JSON object containing any global data, as a key-value map. This action sets the data in the global_data to be globally referenced.
action[].set_meta_data
object
A JSON object containing any metadata, as a key-value map. This action sets the data in the meta_data to be referenced locally in the function.
See set_meta_data for additional details.
action[].unset_global_data
string | object
The key of the global data to unset from the global_data. You can also reset the global_data by passing in a new object.
action[].unset_meta_data
string | object
The key of the metadata to unset from the meta_data. You can also reset the meta_data by passing in a new object.
action[].playback_bg
object
A JSON object containing the audio file to play.
playback_bg.file
string
URL or filepath of the audio file to play. Authentication can also be set in the url in the format of username:password@url.
playback_bg.wait
booleanDefaults to false
Whether to wait for the audio file to finish playing before continuing.
action[].stop_playback_bg
boolean
Whether to stop the background audio file.
action[].user_input
string
Used to inject text into the users queue as if they input the data themselves.
action[].context_switch
object
A JSON object containing the context to switch to.
See context_switch for additional details.
context_switch.system_prompt
string
The instructions to send to the agent.
context_switch.consolidate
booleanDefaults to false
Whether to consolidate the context.
context_switch.user_prompt
string
A string serving as simulated user input for the AI Agent. During a context_switch in the AI’s prompt, the user_prompt offers the AI pre-established context or guidance.
action[].transfer
boolean | object
Transfer the call to a new destination. Accepts two forms depending on whether it accompanies a sibling action[].SWML payload:
- Boolean, use alongside a sibling
action[].SWMLpayload in the same action object. Whentrue, ends the AI session and hard-transfers the call to that SWML. When omitted orfalse, the SWML executes inline and the AI session continues afterward. - Object, use on its own, without
SWML, to transfer the call to a specific destination configured with the fields below. A bare string is also accepted as shorthand fortransfer.dest.
transfer.dest
string
The destination to transfer to: the name of a section in the current SWML document, or a URL that returns SWML to execute.
transfer.summarize
booleanDefaults to false
Whether to include a conversation summary when transferring.
Webhook response example
{
"response": "Oh wow, it's 82.0°F in Tulsa. Bet you didn't see that coming! Humidity at 38%. Your hair is going to love this! Wind speed is 2.2 mph. Hold onto your hats, or don't, I'm not your mother! Looks like Sunny. Guess you'll survive another day.",
"action": [\
{\
"set_meta_data": {\
"temperature": 82.0,\
"humidity": 38,\
"wind_speed": 2.2,\
"weather": "Sunny"\
}\
},\
{\
"SWML": {\
"version": "1.0.0",\
"sections": {\
"main": [\
{\
"play": {\
"url": "https://example.com/twister.mp3"\
}\
}\
]\
}\
}\
}\
]
}Callback Request for web_hook_url
SignalWire will make a request to the web_hook_url of a SWAIG function with the following parameters:
call_id
string
The unique identifier for the current call.
ai_session_id
string
The unique identifier for the AI session.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
caller_id_name
string
Name of the caller.
caller_id_num
string
Number of the caller.
global_data
object
Global data set via the set_global_data action, as a key-value map.
content_disposition
string
Content disposition identifier (e.g., "SWAIG Function").
channel_active
boolean
Whether the channel is currently active.
channel_offhook
boolean
Whether the channel is off-hook.
channel_ready
boolean
Whether the channel is ready.
content_type
string
Type of content. The value will be text/swaig.
app_name
string
Name of the application that originated the request.
function
string
Name of the function that was invoked.
meta_data
object
A JSON object containing any user metadata, as a key-value map.
SWMLVars
object
A collection of variables related to SWML.
purpose
string
The purpose of the function being invoked. The value will be the functions.purpose value you provided in the SWML Function properties.
argument_desc
string | object
The description of the argument being passed. This value comes from the argument you provided in the SWML Function properties.
argument
object
The argument the AI agent is providing to the function. The object contains the three following fields.
argument.parsed
object
If a JSON object is detected within the argument, it is parsed and provided here.
argument.raw
string
The raw argument provided by the AI agent.
argument.substituted
string
The argument provided by the AI agent, excluding any JSON.
version
string
Version number.
Webhook request example
Below is a json example of the callback request that is sent to the web_hook_url:
{
"app_name": "swml app",
"global_data": {
"caller_id_name": "",
"caller_id_number": "sip:guest-246dd851-ba60-4762-b0c8-edfe22bc5344@46e10b6d-e5d6-421f-b6b3-e2e22b8934ed.call.signalwire.com;context=guest"
},
"project_id": "46e10b6d-e5d6-421f-b6b3-e2e22b8934ed",
"space_id": "5bb2200d-3662-4f4d-8a8b-d7806946711c",
"caller_id_name": "",
"caller_id_num": "sip:guest-246dd851-ba60-4762-b0c8-edfe22bc5344@46e10b6d-e5d6-421f-b6b3-e2e22b8934ed.call.signalwire.com;context=guest",
"channel_active": true,
"channel_offhook": true,
"channel_ready": true,
"content_type": "text/swaig",
"version": "2.0",
"content_disposition": "SWAIG Function",
"function": "get_weather",
"argument": {
"parsed": [\
{\
"city": "Tulsa",\
"state": "Oklahoma"\
}\
],
"raw": "{\"city\":\"Tulsa\",\"state\":\"Oklahoma\"}"
},
"call_id": "6e0f2f68-f600-4228-ab27-3dfba2b75da7",
"ai_session_id": "9af20f15-7051-4496-a48a-6e712f22daa5",
"argument_desc": {
"properties": {
"city": {
"description": "Name of the city",
"type": "string"
},
"country": {
"description": "Name of the country",
"type": "string"
},
"state": {
"description": "Name of the state",
"type": "string"
}
},
"required": [],
"type": "object"
},
"purpose": "Get weather with sarcasm"
}Variables
- ai_result: (out)
success|failed - return_value: (out)
success|failed
Tool webhook
When the agent calls one of your SWAIG functions, the platform sends an HTTP POST to that function’s web_hook_url (or the SWAIG defaults.web_hook_url). Your endpoint runs the function and returns a JSON object with a response string (the result the AI reads next) and, optionally, an action, a single object or an array, telling the agent what to do.
See the AI SWAIG tool webhook webhook page for the full field reference.
Reserved Functions
Reserved functions are special SignalWire functions that are automatically triggered at specific points during a conversation. You define them just like any other SWAIG function, but their names correspond to built-in logic on the SignalWire platform, allowing them to perform specific actions at the appropriate time.
Function name conflicts
Do not use reserved function names for your own SWAIG functions unless you want to use the reserved function’s built-in behavior. Otherwise, your function may not work as expected.
List of Reserved Functions
start_hook
function
Triggered when the call is answered. Sends the set properties of the function to the defined web_hook_url.
stop_hook
function
Triggered when the call is ended. Sends the set properties of the function to the defined web_hook_url.
summarize_conversation
function
Triggered when the call is ended. The post_prompt must be defined for this function to be triggered. Provides a summary of the conversation and any set properties to the defined web_hook_url.
Where are my function properties?
If the AI is not returning the properties you set in your SWAIG function, it may be because a reserved function was triggered before those properties were available. To ensure your function receives all necessary information, make sure the AI has access to the required property values before the reserved function is called. Any property missing at the time the reserved function runs will not be included in the data sent back.
Diagram examples
SWML Examples
Using SWAIG Functions
YAMLJSON
version: 1.0.0
sections:
main:
- ai:
post_prompt_url: "https://example.com/my-api"
prompt:
text: |
You are a helpful assistant that can provide information to users about a destination.
At the start of the conversation, always ask the user for their name.
You can use the appropriate function to get the phone number, address,
or weather information.
post_prompt:
text: "Summarize the conversation."
SWAIG:
includes:
- functions:
- get_phone_number
- get_address
url: https://example.com/functions
user: me
pass: secret
defaults:
web_hook_url: https://example.com/my-webhook
web_hook_auth_user: me
web_hook_auth_pass: secret
functions:
- function: get_weather
parameters:
properties:
location:
type: string
type: object
- function: summarize_conversation
parameters:
type: object
properties:
name:
type: stringdata_map
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
functions[].data_map defines how a SWAIG function should process and respond to the user’s input data.
functions[].data_map
object
An object that processes function inputs and executes operations through expressions, webhooks, or direct output.
Processing order
The components are processed in the following sequence:
expressions- Processes data using pattern matching (includes its ownoutput)webhooks- Makes external API calls (includes its ownoutputandexpressions)output- Returns a direct response and actions to perform
Similar to a return statement in conventional programming languages, when a valid output is encountered within any component, it immediately terminates function execution. The output provides:
- A
responseobject: Contains static text for the AI agent’s context - An optional
actionobject: Defines executable actions to be triggered
If no component produces a valid output, the system continues processing in sequence:
- First attempts
expressions - If unsuccessful, tries
webhooks - If still unsuccessful, attempts top-level
output - If all fail, returns a generic fallback error message
Properties
data_map.expressions
object[]
An array of objects that define plain string or regex patterns to match against the user’s input. When a match is found, the output object is returned.
expressions[].string
stringRequired
The actual input or value from the user or system.
expressions[].pattern
stringRequired
A regular expression pattern to validate or match the string.
expressions[].output
objectRequired
Defines the response or action to be taken when the pattern matches. See output for details.
data_map.webhooks
object[]
An array of objects that define external API calls. If a webhook defines foreach, expressions, and output, they are evaluated in that order.
webhooks[].url
stringRequired
The endpoint for the external service or API. Authentication can also be set in the url in the format of username:password@url. See webhook runtime request for details on template variable substitution and request behavior.
webhooks[].method
stringRequired
The HTTP method (GET, POST, etc.) for the API call.
webhooks[].headers
object
Any necessary headers for the API call.
webhooks[].params
object
An object of any necessary parameters for the API call. The key is the parameter name and the value is the parameter value.
webhooks[].input_args_as_params
booleanDefaults to false
A boolean to determine if the input parameters should be passed as parameters.
webhooks[].required_args
string | string[]
A string or array of strings that represent the parameters that are required to make the webhook request.
webhooks[].error_keys
string | string[]
A string or array of strings that represent the keys to be used for error handling.
webhooks[].expressions
object
A list of expressions to be evaluated upon matching. See expressions for details.
webhooks[].foreach
object
Iterates over an array of objects and processes an output based on each element in the array. Works similarly to JavaScript’s forEach method.
foreach.input_key
stringRequired
The key to be used to access the current element in the array.
foreach.output_key
stringRequired
The key that can be referenced in the output of the foreach iteration. The values that are stored from append will be stored in this key.
foreach.append
stringRequired
The values to append to the output_key. Properties from the object can be referenced and added to the output_key by using the following syntax: ${this.property_name}. The this keyword is used to reference the current object in the array.
foreach.max
number
The max amount of elements that are iterated over in the array. This will start at the beginning of the array.
webhooks[].output
objectRequired
Defines the response or action to be taken when the webhook is successfully triggered. See output for details.
data_map.output
object
Similar to a return statement in conventional programming languages, the data_map.output object immediately terminates function execution and returns control to the caller.
output.response
stringRequired
Static text that will be added to the AI agent’s context.
output.action
object[]
A list of SWML-compatible objects that are executed upon the execution of a SWAIG function. See list of valid actions for details.
List of valid actions
action[].SWML
object
A SWML object to be executed.
action[].say
string
A message to be spoken by the AI agent.
action[].stop
boolean
Whether to stop the conversation.
action[].hangup
boolean
Whether to hang up the call. When set to true, the call will be terminated after the AI agent finishes speaking.
action[].hold
integer | object
Places the caller on hold while playing hold music (configured via the params.hold_music parameter). During hold, speech detection is paused and the AI agent will not respond to the caller.
The value specifies the hold timeout in seconds. Can be:
- An integer (e.g.,
120for 120 seconds) - An object with a
timeoutproperty
Default timeout is 300 seconds (5 minutes). Maximum timeout is 900 seconds (15 minutes).
Unholding a call
There is no unhold SWAIG action because the AI agent is inactive during hold and cannot process actions. To take a caller off hold, either:
- Let the hold timeout expire (the AI will automatically resume with a default message), or
- Use the Calling API
ai_unholdcommand to programmatically unhold the call with a custom prompt.
hold.timeout
integerDefaults to 300
The duration to hold the caller in seconds. Maximum is 900 seconds (15 minutes).
action[].change_context
string
The name of the context to switch to. The context must be defined in the AI’s prompt.contexts configuration. This action triggers an immediate context switch during the execution of a SWAIG function.
Visit the contexts documentation for details on defining contexts.
action[].change_step
string
The name of the step to switch to. The step must be defined in prompt.contexts.{context_name}.steps for the current context. This action triggers an immediate step transition during the execution of a SWAIG function.
Visit the steps documentation for details on defining steps.
action[].toggle_functions
object[]
An array of objects to toggle SWAIG functions on or off during the conversation. Each object identifies a function by name and sets its active state.
See toggle_functions for additional details.
toggle_functions[].function
stringRequired
The name of the SWAIG function to toggle.
toggle_functions[].active
booleanDefaults to true
Whether to activate or deactivate the function.
action[].set_global_data
object
A JSON object containing any global data, as a key-value map. This action sets the data in the global_data to be globally referenced.
action[].set_meta_data
object
A JSON object containing any metadata, as a key-value map. This action sets the data in the meta_data to be referenced locally in the function.
See set_meta_data for additional details.
action[].unset_global_data
string | object
The key of the global data to unset from the global_data. You can also reset the global_data by passing in a new object.
action[].unset_meta_data
string | object
The key of the metadata to unset from the meta_data. You can also reset the meta_data by passing in a new object.
action[].playback_bg
object
A JSON object containing the audio file to play.
playback_bg.file
string
URL or filepath of the audio file to play. Authentication can also be set in the url in the format of username:password@url.
playback_bg.wait
booleanDefaults to false
Whether to wait for the audio file to finish playing before continuing.
action[].stop_playback_bg
boolean
Whether to stop the background audio file.
action[].user_input
string
Used to inject text into the users queue as if they input the data themselves.
action[].context_switch
object
A JSON object containing the context to switch to.
See context_switch for additional details.
context_switch.system_prompt
string
The instructions to send to the agent.
context_switch.consolidate
booleanDefaults to false
Whether to consolidate the context.
context_switch.user_prompt
string
A string serving as simulated user input for the AI Agent. During a context_switch in the AI’s prompt, the user_prompt offers the AI pre-established context or guidance.
action[].transfer
boolean | object
Transfer the call to a new destination. Accepts two forms depending on whether it accompanies a sibling action[].SWML payload:
- Boolean, use alongside a sibling
action[].SWMLpayload in the same action object. Whentrue, ends the AI session and hard-transfers the call to that SWML. When omitted orfalse, the SWML executes inline and the AI session continues afterward. - Object, use on its own, without
SWML, to transfer the call to a specific destination configured with the fields below. A bare string is also accepted as shorthand fortransfer.dest.
transfer.dest
string
The destination to transfer to: the name of a section in the current SWML document, or a URL that returns SWML to execute.
transfer.summarize
booleanDefaults to false
Whether to include a conversation summary when transferring.
Webhook runtime request
When the AI triggers a function that uses data_map.webhooks, SignalWire sends a request to each configured url.
Template variables
The url and params fields support %{variable} substitution. Nested properties use dot notation, for example, https://api.example.com/weather?city=%{args.location} substitutes the value the AI extracted for location. For more on variables and scopes, see the Variables reference.
args
object
Function argument values extracted by the AI, keyed by argument name.
args.*
any
Individual argument value. The key matches an argument name from the function’s parameters schema.
call_id
string
Unique identifier for the current call.
ai_session_id
string
AI session identifier.
conversation_id
string
Conversation identifier.
function
string
Name of the function being executed.
caller_id_name
string
Caller’s display name.
caller_id_num
string
Caller’s phone number.
project_id
string
SignalWire project ID.
space_id
string
SignalWire space ID.
app_name
string
AI application name.
global_data
object
The application’s global data.
global_data.*
any
User-defined property.
meta_data
object
Function metadata (when meta_data_token is set).
meta_data.*
any
User-defined property.
Request body
When params is defined (or method is POST), SignalWire sends the params object as the JSON request body. Template variables in params values are expanded before sending.
If no params are defined and method is not POST, the request is sent without a body.
If input_args_as_params is true, the function arguments extracted by the AI are merged into params. If no params are defined, the arguments become the entire request body.
Response processing
The JSON response from the webhook is processed through the output template. Fields from the response can be referenced using %{key} syntax in the output’s response string. For example, if the webhook returns {"temp": 72, "conditions": "sunny"}, an output of "The weather is %{temp}°F with %{conditions}" will produce "The weather is 72°F with sunny".
Examples
expressions
YAMLJSON
data_map:
expressions:
- string: "starwars"
pattern: "(?i)star\\s*wars"
output:
response: "May the Force be with you!"
- string: "startrek"
pattern: "(?i)star\\s*trek"
output:
response: "Live long and prosper!"webhooks with explicit params
YAMLJSON
data_map:
webhooks:
- url: https://api.example.com/weather
method: POST
params:
call_id: "%{call_id}"
city: "%{args.location}"
output:
response: "The weather in %{city} is %{temp}°F and %{conditions}."Sends the following request body to https://api.example.com/weather:
{
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"city": "New York"
}webhooks with input_args_as_params
YAMLJSON
data_map:
webhooks:
- url: https://api.example.com/weather
method: POST
input_args_as_params: true
output:
response: "The weather is %{temp}°F and %{conditions}."Sends the AI-extracted arguments directly as the request body:
{
"location": "New York"
}output with action
YAMLJSON
sections:
main:
- ai:
prompt:
text: You are a helpful SignalWire assistant.
SWAIG:
functions:
- function: test_function
parameters:
type: object
properties:
name:
type: string
required:
- name
data_map:
output:
response: We are testing the function.
action:
- SWML:
sections:
main:
- play:
url: 'say:We are testing the function.'Related guides
- Executing SWML from a SWAIG function
parameters
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
The parameters object is used to define the input data that will be passed to the function.
Properties
functions[].parameters
object
An object that accepts the following properties.
parameters.type
stringRequired
Defines the top-level type of the parameters. Must be set to "object"
parameters.properties
objectRequired
An object containing the properties definitions to be passed to the function
properties.{property_name}
objectRequired
The properties object defines the input data that will be passed to the function. It supports different types of parameters, each with their own set of configuration options. The property name is a key in the properties object that is user-defined. An object with dynamic property names, where:
- Keys: User-defined strings, that set the property name.
- Values: Must be one of the valid schema types. Learn more about valid schema types from the JSON Schema documentation
Schema Types
Each property in the properties object must use one of the following schema types:
string
integer
number
boolean
array
object
oneOf
allOf
anyOf
const
{property_name}.type
stringRequired
The type of property the AI is passing to the function. Must be set to "string"
{property_name}.description
string
A description of the property
{property_name}.enum
string[]
An array of strings that are the possible values
{property_name}.default
string
The default string value
{property_name}.pattern
string
Regular expression pattern for the string value to match
{property_name}.nullable
booleanDefaults to false
Whether the property can be null
YAMLJSON
parameters:
type: object
properties:
property_name:
type: string
pattern: ^[a-z]+$parameters.required
string[]
Array of required property names from the properties object
includes
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Remote function signatures to include in SWAIG functions. Will allow you to include functions that are defined in a remote location that can be executed during the interaction with the AI. To learn more about how includes works see the request flow section.
Properties
SWAIG.includes
object[]
An array of objects that accept the following properties.
includes[].url
stringRequired
URL where the remote functions are defined. Authentication can also be set in the url in the format of username:password@url.
includes[].function
string[]Required
An array of the function names to be included.
includes[].meta_data
object
Metadata to be passed to the remote function. These are key-value pairs defined by the user.
SWML usage
YAMLJSON
version: 1.0.0
sections:
main:
- ai:
prompt:
text: "You are a helpful assistant that can check weather."
SWAIG:
includes:
- url: "https://example.com/swaig"
function: ["get_weather"]
meta_data:
user_id: "12345"Request flow
SWAIG includes creates a bridge between AI agents and external functions. When a SWML script initializes, it follows this two-phase process:
Initialization Phase: SWAIG discovers available functions from configured endpoints and requests their signatures to understand what each function can do.
Runtime Phase: The AI agent analyzes conversations, determines when functions match user intent, and executes them with full context.
Signature request
During SWML script initialization, SWAIG acts as a function discovery service. It examines your includes configuration, identifies the remote functions you’ve declared, then systematically contacts each endpoint to gather function definitions.
How it works: Looking at our SWML configuration example, SWAIG sends a targeted request to https://example.com/swaig specifically asking for the get_weather function definition. Along with this request, it forwards any meta_data you’ve configured, giving your server the context it needs to respond appropriately.
The discovery request:
{
"version": "2.0",
"action": "get_signature",
"content_type": "text/swaig",
"content_disposition": "function signature request",
"functions": ["get_weather"]
}What your server should return: Your endpoint must respond with complete function definitions that tell SWAIG everything it needs to know. Each function signature follows the SWAIG functions structure and describes the function’s purpose and required parameters:
[\
{\
"function": "function_name1",\
"description": "Description of what this function does",\
"parameters": {\
"type": "object",\
"properties": {\
"param1": {\
"type": "string",\
"description": "Parameter description"\
}\
},\
"required": ["param1"]\
},\
"web_hook_url": "https://example.com/swaig",\
"web_hook_auth_user": "optional_username",\
"web_hook_auth_password": "optional_password"\
}\
]Your server can optionally include web_hook_auth_user and web_hook_auth_password in each function definition to set HTTP basic authentication credentials for the function’s web_hook_url.
Function execution request
When the AI agent determines that a function call matches user intent, such as when a user requests weather information SWAIG packages the required information and sends it to the configured endpoint. The full details of the request can be found in the web_hook_url documentation.
Example request format:
{
"content_type": "text/swaig",
"function": "function_name1",
"argument": {
"parsed": [{"city": "New York"}],
"raw": "{\"city\":\"New York\"}",
"substituted": "{\"city\":\"New York\"}"
},
"meta_data": {
"custom_key": "custom_value"
},
"meta_data_token": "optional_token",
"app_name": "swml app",
"version": "2.0"
}SWAIG provides arguments in multiple formats, parsed for direct access, raw for the original text, and substituted with variable replacements applied. This flexibility supports edge cases and complex parsing scenarios.
Response formats:
When your function completes, it needs to send a response back to SWAIG. You have three main options depending on what you want to accomplish:
Simple Response
Response + Actions
Error Handling
Use this when: Your function just needs to return information to the AI agent.
{
"response": "The weather in New York is sunny and 75°F"
}The AI agent will receive this information and incorporate it naturally into the conversation with the user.
More information about the response format can be found in the web_hook_url documentation.
Flow diagram
The following diagram illustrates the complete SWAIG includes process from initialization to function execution:
Reference implementation
The following implementations demonstrate the essential pattern: define functions, map them to actual code, and handle both signature requests and function executions.
Python/Flask
JavaScript/Express
from flask import Flask, request, jsonify
app = Flask(__name__)
FUNCTIONS = {
"get_weather": {
"function": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "The city name"}
},
"required": ["city"]
},
"web_hook_url": "https://example.com/swaig"
}
}
def get_weather(city, meta_data=None, **kwargs):
# Logic to get weather data
# ...
temperature = 75
result = f"The weather in {city} is sunny and {temperature}°F"
# Return both a response AND an action
actions = [{"say": result}]
return result, actions
# Connect function names to actual functions
<Badge type="tip" text="Fresh" />
FUNCTION_MAP = {
"get_weather": get_weather
}
@app.route('/swaig', methods=['POST'])
def handle_swaig():
data = request.json
# SWAIG is asking what we can do
if data.get('action') == 'get_signature':
requested = data.get('functions', list(FUNCTIONS.keys()))
return jsonify([FUNCTIONS[name] for name in requested if name in FUNCTIONS])
# SWAIG wants us to actually do something
function_name = data.get('function')
if function_name not in FUNCTION_MAP:
return jsonify({"response": "Function not found"}), 200
params = data.get('argument', {}).get('parsed', [{}])[0]
meta_data = data.get('meta_data', {})
# Call the function and get results
result, actions = FUNCTION_MAP[function_name](meta_data=meta_data, **params)
return jsonify({"response": result, "action": actions})
if __name__ == '__main__':
app.run(debug=True)Testing the implementation
To test the implementation, start the server and simulate SWAIG requesting function signatures. This command requests signatures from the endpoint:
curl -X POST http://localhost:5000/swaig \
-H "Content-Type: application/json" \
-d '{"action": "get_signature"}'Expected response: A successful response returns function definitions in this format:
[\
{\
"description": "Get current weather for a city",\
"function": "get_weather",\
"parameters": {\
"properties": {\
"city": {\
"description": "The city name",\
"type": "string"\
}\
},\
"required": [\
"city"\
],\
"type": "object"\
},\
"web_hook_url": "https://example.com/swaig"\
}\
]amazon_bedrock
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Create an Amazon Bedrock agent with a prompt. Since the text prompt is central to getting great results out of the AI, it is highly recommended that you also read the Prompting Best Practices guide.
Properties
amazon_bedrock
objectRequired
An object that accepts the following properties.
amazon_bedrock.global_data
object
A powerful and flexible environmental variable which can accept arbitrary data that is set initially in the SWML script or from the SWML set_global_data action. This data can be referenced globally. All contained information can be accessed and expanded within the prompt - for example, by using a template string.
amazon_bedrock.params
object
A JSON object containing parameters as key-value pairs.
amazon_bedrock.post_prompt
object
The final set of instructions and configuration settings to send to the agent. Accepts either a text string or a pom object array for structured prompts, plus optional tuning parameters. See post_prompt details below.
amazon_bedrock.post_prompt_url
string
The URL to which to send status callbacks and reports. Authentication can also be set in the url in the format of username:password@url. See post_prompt_url callback below.
amazon_bedrock.prompt
objectRequired
Establishes the initial set of instructions and settings to configure the agent.
See prompt for additional details.
amazon_bedrock.SWAIG
object
An array of JSON objects to create user-defined functions/endpoints that can be executed during the dialogue.
See SWAIG for additional details.
post_prompt
The post_prompt object accepts either a plain text prompt or a structured POM prompt, plus optional tuning parameters.
Regular prompt
POM prompt
post_prompt.text
stringRequired
The main identity prompt for the AI. This prompt will be used to outline the agent’s personality, role, and other characteristics.
post_prompt.temperature
number
Controls the randomness of responses. Higher values (e.g., 0.8) make output more random and creative, while lower values (e.g., 0.2) make it more focused and deterministic. Range: 0.0 to 1.0.
post_prompt.top_p
number
Controls diversity via nucleus sampling. Only tokens with cumulative probability up to top_p are considered. Lower values make output more focused. Range: 0.0 to 1.0.
post_prompt.confidence
number
Minimum confidence threshold for AI responses. Responses below this threshold may be filtered or flagged. Range: 0.0 to 1.0.
post_prompt.presence_penalty
number
Penalizes tokens based on whether they appear in the text so far. Positive values encourage the model to talk about new topics.
post_prompt.frequency_penalty
number
Penalizes tokens based on their frequency in the text so far. Positive values decrease the likelihood of repeating the same line verbatim.
post_prompt_url callback
SignalWire will make a request to the post_prompt_url with the following parameters:
action
string
Action that prompted this request. The value will be “post_conversation”.
ai_end_date
integer
Timestamp indicating when the AI session ended.
ai_session_id
string
A unique identifier for the AI session.
ai_start_date
integer
Timestamp indicating when the AI session started.
app_name
string
Name of the application that originated the request.
call_answer_date
integer
Timestamp indicating when the call was answered.
call_end_date
integer
Timestamp indicating when the call ended.
call_id
string
ID of the call.
call_log
object
The complete log of the call, as a JSON object.
call_log.content
string
Content of the call log entry.
call_log.role
string
Role associated with the call log entry (e.g., “system”, “assistant”, “user”).
call_start_date
integer
Timestamp indicating when the call started.
caller_id_name
string
Name associated with the caller ID.
caller_id_num
string
Number associated with the caller ID.
content_disposition
string
Disposition of the content.
content_type
string
Type of content. The value will be text/swaig.
conversation_id
string
A unique identifier for the conversation thread, if configured via the AI parameters.
post_prompt_data
object
The answer from the AI agent to the post_prompt. The object contains the three following fields.
post_prompt_data.parsed
object
If a JSON object is detected within the answer, it is parsed and provided here.
post_prompt_data.raw
string
The raw data answer from the AI agent.
post_prompt_data.substituted
string
The answer from the AI agent, excluding any JSON.
project_id
string
ID of the Project.
space_id
string
ID of the Space.
SWMLVars
object
A collection of variables related to SWML.
swaig_log
object
A log related to SWAIG functions.
total_input_tokens
integer
Represents the total number of input tokens.
total_output_tokens
integer
Represents the total number of output tokens.
version
string
Version number.
Post prompt callback request example
Below is a json example of the callback request that is sent to the post_prompt_url:
{
"total_output_tokens": 119,
"caller_id_name": "[CALLER_NAME]",
"SWMLVars": {
"ai_result": "success",
"answer_result": "success"
},
"call_start_date": 1694541295773508,
"project_id": "[PROJECT_ID]",
"call_log": [\
{\
"content": "[AI INITIAL PROMPT/INSTRUCTIONS]",\
"role": "system"\
},\
{\
"content": "[AI RESPONSE]",\
"role": "assistant"\
},\
{\
"content": "[USER RESPONSE]",\
"role": "user"\
}\
],
"ai_start_date": 1694541297950440,
"call_answer_date": 1694541296799504,
"version": "2.0",
"content_disposition": "Conversation Log",
"conversation_id": "[CONVERSATION_ID]",
"space_id": "[SPACE_ID]",
"app_name": "swml app",
"swaig_log": [\
{\
"post_data": {\
"content_disposition": "SWAIG Function",\
"conversation_id": "[CONVERSATION_ID]",\
"space_id": "[SPACE_ID]",\
"meta_data_token": "[META_DATA_TOKEN]",\
"app_name": "swml app",\
"meta_data": {},\
"argument": {\
"raw": "{\n \"target\": \"[TRANSFER_TARGET]\"\n}",\
"substituted": "",\
"parsed": [\
{\
"target": "[TRANSFER_TARGET]"\
}\
]\
},\
"call_id": "[CALL_ID]",\
"content_type": "text/swaig",\
"ai_session_id": "[AI_SESSION_ID]",\
"caller_id_num": "[CALLER_NUMBER]",\
"caller_id_name": "[CALLER_NAME]",\
"project_id": "[PROJECT_ID]",\
"purpose": "Use to transfer to a target",\
"argument_desc": {\
"type": "object",\
"properties": {\
"target": {\
"description": "the target to transfer to",\
"type": "string"\
}\
}\
},\
"function": "transfer",\
"version": "2.0"\
},\
"command_name": "transfer",\
"epoch_time": 1694541334,\
"command_arg": "{\n \"target\": \"[TRANSFER_TARGET]\"\n}",\
"url": "https://example.com/here",\
"post_response": {\
"action": [\
{\
"say": "This is a say message!"\
},\
{\
"SWML": {\
"sections": {\
"main": [\
{\
"connect": {\
"to": "+1XXXXXXXXXX"\
}\
}\
]\
},\
"version": "1.0.0"\
}\
},\
{\
"stop": true\
}\
],\
"response": "transferred to [TRANSFER_TARGET], the call has ended"\
}\
}\
],
"total_input_tokens": 5627,
"caller_id_num": "[CALLER_NUMBER]",
"call_id": "[CALL_ID]",
"call_end_date": 1694541335435503,
"content_type": "text/swaig",
"action": "post_conversation",
"post_prompt_data": {
"substituted": "[SUMMARY_MESSAGE_PLACEHOLDER]",
"parsed": [],
"raw": "[SUMMARY_MESSAGE_PLACEHOLDER]"
},
"ai_end_date": 1694541335425164,
"ai_session_id": "[AI_SESSION_ID]"
}Responding to post prompt requests
The response to the callback request should be a JSON object with the following parameters:
{
"response": "ok"
}Amazon Bedrock example
The following example selects Bedrock’s Tiffany voice using the voice_id parameter in the prompt. It includes scaffolding for a post_prompt_url as well as several remote and inline functions using SWAIG.
YAMLJSON
---
version: 1.0.0
sections:
main:
- amazon_bedrock:
post_prompt_url: https://example.com/my-api
prompt:
voice_id: tiffany
text: |
You are a helpful assistant that can provide information to users about a destination.
At the start of the conversation, always ask the user for their name.
You can use the appropriate function to get the phone number, address,
or weather information.
post_prompt:
text: Summarize the conversation.
SWAIG:
includes:
- functions:
- get_phone_number
- get_address
url: https://example.com/functions
defaults:
web_hook_url: https://example.com/my-webhook
functions:
- function: get_weather
parameters:
properties:
location:
type: string
type: object
- function: summarize_conversation
parameters:
type: object
properties:
name:
type: stringparams
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Parameters for AI that can be passed in amazon_bedrock.params at the top level of the amazon_bedrock Method.
Properties
amazon_bedrock.params
object
An object that accepts the following properties.
params.attention_timeout
integerDefaults to 5000 ms
Amount of time, in ms, to wait before prompting the user to respond. Allowed values: 0 (to disable) or 10,000-600,000.
params.inactivity_timeout
integerDefaults to 600000 ms
Amount of time, in ms, to wait before exiting the app due to inactivity. Allowed values: 0 (to disable) or 10,000-3,600,000.
params.hard_stop_time
string
Specifies the maximum duration for the AI Agent to remain active before it exits the session. After the timeout, the AI will stop responding, and will proceed with the next SWML instruction.
Time Format
- Seconds Format:
30s - Minutes Format:
2m - Hours Format:
1h - Combined Format:
1h45m30s
params.hard_stop_prompt
string
A final prompt that is fed into the AI when the hard_stop_time is reached.
params.video_talking_file
string
URL of a video file to play when AI is talking. Only works for calls that support video.
params.video_idle_file
string
URL of a video file to play when AI is idle. Only works for calls that support video.
params.video_listening_file
string
URL of a video file to play when AI is listening to the user speak. Only works for calls that support video.
prompt
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Properties
amazon_bedrock.prompt
objectRequired
An object that accepts the prompt properties.
The prompt property accepts one of the following objects:
Regular Prompt
POM Prompts
prompt.text
stringRequired
The instructions to send to the agent.
prompt.temperature
numberDefaults to 1.0
Randomness setting. Float value between 0.0 and 1.5. Closer to 0 will make the output less random.
prompt.top_p
numberDefaults to 1.0
Randomness setting. Alternative to temperature. Float value between 0.0 and 1.0.
prompt.confidence
numberDefaults to 0.6
Threshold to fire a speech-detect event at the end of the utterance.
voice_id
stringDefaults to matthew
The voice the Amazon Bedrock agent will use during the interaction. Possible Values: tiffany, matthew, amy, lupe, carlos
Variable Expansion
Use the following syntax to expand variables into your prompt.
${call_direction}
string
Inbound or outbound.
${caller_id_number}
string
The caller ID number.
${local_date}
string
The local date.
${spoken_date}
string
The spoken date.
${local_time}
string
The local time.
${time_of_day}
string
The time of day.
${supported_languages}
string
A list of supported languages.
${default_language}
string
The default language.
SWAIG
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
The SignalWire AI Gateway Interface. Allows you to create user-defined functions that can be executed during the dialogue.
Properties
amazon_bedrock.SWAIG
object
An object that accepts the following properties.
SWAIG.defaults
object
Default settings for all SWAIG functions. If defaults is not set, settings may be set in each function object. Default is not set.
defaults.web_hook_url
string
The default URL to send status callbacks and reports to for all SWAIG functions. If defaults is not set, web_hook_url may be set in each SWAIG function object. Authentication can also be set in the url in the format of username:password@url.
SWAIG.functions
object[]
An array of JSON objects to define functions that can be executed during the interaction with the AI. Default is not set. The fields of this object are the six following.
See functions for additional details.
SWAIG.includes
object[]
An array of objects to include remote function signatures. This allows you to include functions that are defined in a remote location.
See includes for additional details.
SWAIG.native_functions
string[]
Prebuilt functions the AI agent is able to call. The agent is already aware of these functions and can use them creatively based on prompting. For example, a prompt like “tell the user what time it is” will automatically use check_time.
Accepted values:
adjust_response_latency- Adjust how long the agent will wait for the user to stop talking.check_time- Returns the current time for the time zone set inai.local_tz.wait_for_user- Causes the AI to wait until the user speaks again. Use when the user asks to wait or hold on.wait_seconds- Waits for the given amount of time.
Webhook response
When a SWAIG function is executed, the function expects the user to respond with a JSON object that contains a response key and an optional action key. This request response is used to provide the LLM with a new prompt response via the response key and to execute SWML-compatible objects that will perform new dialplan actions via the action key.
response
stringRequired
Static text that will be added to the AI agent’s context.
action
object[]
A list of SWML-compatible objects that are executed upon the execution of a SWAIG function.
action[].SWML
object
A SWML object to be executed.
action[].say
string
A message to be spoken by the AI agent.
action[].stop
boolean
Whether to stop the conversation.
action[].hangup
boolean
Whether to hang up the call. When set to true, the call will be terminated after the AI agent finishes speaking.
action[].hold
integer | object
Places the caller on hold while playing hold music (configured via the params.hold_music parameter). During hold, speech detection is paused and the AI agent will not respond to the caller.
The value specifies the hold timeout in seconds. Can be:
- An integer (e.g.,
120for 120 seconds) - An object with a
timeoutproperty
Default timeout is 300 seconds (5 minutes). Maximum timeout is 900 seconds (15 minutes).
Unholding a call
There is no unhold SWAIG action because the AI agent is inactive during hold and cannot process actions. To take a caller off hold, either:
- Let the hold timeout expire (the AI will automatically resume with a default message), or
- Use the Calling API
ai_unholdcommand to programmatically unhold the call with a custom prompt.
hold.timeout
integerDefaults to 300
The duration to hold the caller in seconds. Maximum is 900 seconds (15 minutes).
action[].change_context
string
The name of the context to switch to. The context must be defined in the AI’s prompt.contexts configuration. This action triggers an immediate context switch during the execution of a SWAIG function.
Visit the contexts documentation for details on defining contexts.
action[].change_step
string
The name of the step to switch to. The step must be defined in prompt.contexts.{context_name}.steps for the current context. This action triggers an immediate step transition during the execution of a SWAIG function.
Visit the steps documentation for details on defining steps.
action[].toggle_functions
object[]
An array of objects to toggle SWAIG functions on or off during the conversation. Each object identifies a function by name and sets its active state.
See toggle_functions for additional details.
toggle_functions[].function
stringRequired
The name of the SWAIG function to toggle.
toggle_functions[].active
booleanDefaults to true
Whether to activate or deactivate the function.
action[].set_global_data
object
A JSON object containing any global data, as a key-value map. This action sets the data in the global_data to be globally referenced.
action[].set_meta_data
object
A JSON object containing any metadata, as a key-value map. This action sets the data in the meta_data to be referenced locally in the function.
See set_meta_data for additional details.
action[].unset_global_data
string | object
The key of the global data to unset from the global_data. You can also reset the global_data by passing in a new object.
action[].unset_meta_data
string | object
The key of the metadata to unset from the meta_data. You can also reset the meta_data by passing in a new object.
action[].playback_bg
object
A JSON object containing the audio file to play.
playback_bg.file
string
URL or filepath of the audio file to play. Authentication can also be set in the url in the format of username:password@url.
playback_bg.wait
booleanDefaults to false
Whether to wait for the audio file to finish playing before continuing.
action[].stop_playback_bg
boolean
Whether to stop the background audio file.
action[].user_input
string
Used to inject text into the users queue as if they input the data themselves.
action[].context_switch
object
A JSON object containing the context to switch to.
See context_switch for additional details.
context_switch.system_prompt
string
The instructions to send to the agent.
context_switch.consolidate
booleanDefaults to false
Whether to consolidate the context.
context_switch.user_prompt
string
A string serving as simulated user input for the AI Agent. During a context_switch in the AI’s prompt, the user_prompt offers the AI pre-established context or guidance.
action[].transfer
boolean | object
Transfer the call to a new destination. Accepts two forms depending on whether it accompanies a sibling action[].SWML payload:
- Boolean, use alongside a sibling
action[].SWMLpayload in the same action object. Whentrue, ends the AI session and hard-transfers the call to that SWML. When omitted orfalse, the SWML executes inline and the AI session continues afterward. - Object, use on its own, without
SWML, to transfer the call to a specific destination configured with the fields below. A bare string is also accepted as shorthand fortransfer.dest.
transfer.dest
string
The destination to transfer to: the name of a section in the current SWML document, or a URL that returns SWML to execute.
transfer.summarize
booleanDefaults to false
Whether to include a conversation summary when transferring.
Webhook response example
{
"response": "Oh wow, it's 82.0°F in Tulsa. Bet you didn't see that coming! Humidity at 38%. Your hair is going to love this! Wind speed is 2.2 mph. Hold onto your hats, or don't, I'm not your mother! Looks like Sunny. Guess you'll survive another day.",
"action": [\
{\
"set_meta_data": {\
"temperature": 82.0,\
"humidity": 38,\
"wind_speed": 2.2,\
"weather": "Sunny"\
}\
},\
{\
"SWML": {\
"version": "1.0.0",\
"sections": {\
"main": [\
{\
"play": {\
"url": "https://example.com/twister.mp3"\
}\
}\
]\
}\
}\
}\
]
}Callback Request for web_hook_url
SignalWire will make a request to the web_hook_url of a SWAIG function with the following parameters:
call_id
string
The unique identifier for the current call.
ai_session_id
string
The unique identifier for the AI session.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
caller_id_name
string
Name of the caller.
caller_id_num
string
Number of the caller.
global_data
object
Global data set via the set_global_data action, as a key-value map.
content_disposition
string
Content disposition identifier (e.g., "SWAIG Function").
channel_active
boolean
Whether the channel is currently active.
channel_offhook
boolean
Whether the channel is off-hook.
channel_ready
boolean
Whether the channel is ready.
content_type
string
Type of content. The value will be text/swaig.
app_name
string
Name of the application that originated the request.
function
string
Name of the function that was invoked.
meta_data
object
A JSON object containing any user metadata, as a key-value map.
SWMLVars
object
A collection of variables related to SWML.
purpose
string
The purpose of the function being invoked. The value will be the functions.purpose value you provided in the SWML Function properties.
argument_desc
string | object
The description of the argument being passed. This value comes from the argument you provided in the SWML Function properties.
argument
object
The argument the AI agent is providing to the function. The object contains the three following fields.
argument.parsed
object
If a JSON object is detected within the argument, it is parsed and provided here.
argument.raw
string
The raw argument provided by the AI agent.
argument.substituted
string
The argument provided by the AI agent, excluding any JSON.
version
string
Version number.
Webhook request example
Below is a json example of the callback request that is sent to the web_hook_url:
{
"app_name": "swml app",
"global_data": {
"caller_id_name": "",
"caller_id_number": "sip:guest-246dd851-ba60-4762-b0c8-edfe22bc5344@46e10b6d-e5d6-421f-b6b3-e2e22b8934ed.call.signalwire.com;context=guest"
},
"project_id": "46e10b6d-e5d6-421f-b6b3-e2e22b8934ed",
"space_id": "5bb2200d-3662-4f4d-8a8b-d7806946711c",
"caller_id_name": "",
"caller_id_num": "sip:guest-246dd851-ba60-4762-b0c8-edfe22bc5344@46e10b6d-e5d6-421f-b6b3-e2e22b8934ed.call.signalwire.com;context=guest",
"channel_active": true,
"channel_offhook": true,
"channel_ready": true,
"content_type": "text/swaig",
"version": "2.0",
"content_disposition": "SWAIG Function",
"function": "get_weather",
"argument": {
"parsed": [\
{\
"city": "Tulsa",\
"state": "Oklahoma"\
}\
],
"raw": "{\"city\":\"Tulsa\",\"state\":\"Oklahoma\"}"
},
"call_id": "6e0f2f68-f600-4228-ab27-3dfba2b75da7",
"ai_session_id": "9af20f15-7051-4496-a48a-6e712f22daa5",
"argument_desc": {
"properties": {
"city": {
"description": "Name of the city",
"type": "string"
},
"country": {
"description": "Name of the country",
"type": "string"
},
"state": {
"description": "Name of the state",
"type": "string"
}
},
"required": [],
"type": "object"
},
"purpose": "Get weather with sarcasm"
}Variables
- ai_result: (out)
success|failed - return_value: (out)
success|failed
functions
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
An array of JSON objects to define functions that can be executed during the interaction with the Amazon Bedrock agent.
Properties
SWAIG.functions
object[]
An array of JSON objects that accept the following properties.
functions[].description
stringRequired
A description of the context and purpose of the function, to explain to the agent when to use it.
functions[].function
stringRequired
A unique name for the function. This can be any user-defined string or can reference a reserved function. Reserved functoins are SignalWire functions that will be executed at certain points in the conversation. To learn more about reserved functions, see Reserved Functions.
functions[].active
booleanDefaults to true
Whether the function is active.
functions[].data_map
object
An object containing properties to process or validate the input, perform actions based on the input, or connect to external APIs or services in a serverless fashion.
See data_map for additional details.
functions[].parameters
object
A JSON object that defines the expected user input parameters and their validation rules for the function.
See parameters for additional details.
functions[].meta_data
object
A powerful and flexible environmental variable which can accept arbitrary data that is set initially in the SWML script or from the SWML set_meta_data action. This data can be referenced locally to the function. All contained information can be accessed and expanded within the prompt - for example, by using a template string.
functions[].meta_data_token
stringDefaults to Set by SignalWire
Scoping token for meta_data. If not supplied, metadata will be scoped to function’s web_hook_url.
functions[].web_hook_url
string
Function-specific URL to send status callbacks and reports to. Takes precedence over a default setting. Authentication can also be set in the url in the format of username:password@url.
Webhook response
When a SWAIG function is executed, the function expects the user to respond with a JSON object that contains a response key and an optional action key. This request response is used to provide the LLM with a new prompt response via the response key and to execute SWML-compatible objects that will perform new dialplan actions via the action key.
response
stringRequired
Static text that will be added to the AI agent’s context.
action
object[]
A list of SWML-compatible objects that are executed upon the execution of a SWAIG function.
action[].SWML
object
A SWML object to be executed.
action[].say
string
A message to be spoken by the AI agent.
action[].stop
boolean
Whether to stop the conversation.
action[].hangup
boolean
Whether to hang up the call. When set to true, the call will be terminated after the AI agent finishes speaking.
action[].hold
integer | object
Places the caller on hold while playing hold music (configured via the params.hold_music parameter). During hold, speech detection is paused and the AI agent will not respond to the caller.
The value specifies the hold timeout in seconds. Can be:
- An integer (e.g.,
120for 120 seconds) - An object with a
timeoutproperty
Default timeout is 300 seconds (5 minutes). Maximum timeout is 900 seconds (15 minutes).
Unholding a call
There is no unhold SWAIG action because the AI agent is inactive during hold and cannot process actions. To take a caller off hold, either:
- Let the hold timeout expire (the AI will automatically resume with a default message), or
- Use the Calling API
ai_unholdcommand to programmatically unhold the call with a custom prompt.
hold.timeout
integerDefaults to 300
The duration to hold the caller in seconds. Maximum is 900 seconds (15 minutes).
action[].change_context
string
The name of the context to switch to. The context must be defined in the AI’s prompt.contexts configuration. This action triggers an immediate context switch during the execution of a SWAIG function.
Visit the contexts documentation for details on defining contexts.
action[].change_step
string
The name of the step to switch to. The step must be defined in prompt.contexts.{context_name}.steps for the current context. This action triggers an immediate step transition during the execution of a SWAIG function.
Visit the steps documentation for details on defining steps.
action[].toggle_functions
object[]
An array of objects to toggle SWAIG functions on or off during the conversation. Each object identifies a function by name and sets its active state.
See toggle_functions for additional details.
toggle_functions[].function
stringRequired
The name of the SWAIG function to toggle.
toggle_functions[].active
booleanDefaults to true
Whether to activate or deactivate the function.
action[].set_global_data
object
A JSON object containing any global data, as a key-value map. This action sets the data in the global_data to be globally referenced.
action[].set_meta_data
object
A JSON object containing any metadata, as a key-value map. This action sets the data in the meta_data to be referenced locally in the function.
See set_meta_data for additional details.
action[].unset_global_data
string | object
The key of the global data to unset from the global_data. You can also reset the global_data by passing in a new object.
action[].unset_meta_data
string | object
The key of the metadata to unset from the meta_data. You can also reset the meta_data by passing in a new object.
action[].playback_bg
object
A JSON object containing the audio file to play.
playback_bg.file
string
URL or filepath of the audio file to play. Authentication can also be set in the url in the format of username:password@url.
playback_bg.wait
booleanDefaults to false
Whether to wait for the audio file to finish playing before continuing.
action[].stop_playback_bg
boolean
Whether to stop the background audio file.
action[].user_input
string
Used to inject text into the users queue as if they input the data themselves.
action[].context_switch
object
A JSON object containing the context to switch to.
See context_switch for additional details.
context_switch.system_prompt
string
The instructions to send to the agent.
context_switch.consolidate
booleanDefaults to false
Whether to consolidate the context.
context_switch.user_prompt
string
A string serving as simulated user input for the AI Agent. During a context_switch in the AI’s prompt, the user_prompt offers the AI pre-established context or guidance.
action[].transfer
boolean | object
Transfer the call to a new destination. Accepts two forms depending on whether it accompanies a sibling action[].SWML payload:
- Boolean, use alongside a sibling
action[].SWMLpayload in the same action object. Whentrue, ends the AI session and hard-transfers the call to that SWML. When omitted orfalse, the SWML executes inline and the AI session continues afterward. - Object, use on its own, without
SWML, to transfer the call to a specific destination configured with the fields below. A bare string is also accepted as shorthand fortransfer.dest.
transfer.dest
string
The destination to transfer to: the name of a section in the current SWML document, or a URL that returns SWML to execute.
transfer.summarize
booleanDefaults to false
Whether to include a conversation summary when transferring.
Webhook response example
{
"response": "Oh wow, it's 82.0°F in Tulsa. Bet you didn't see that coming! Humidity at 38%. Your hair is going to love this! Wind speed is 2.2 mph. Hold onto your hats, or don't, I'm not your mother! Looks like Sunny. Guess you'll survive another day.",
"action": [\
{\
"set_meta_data": {\
"temperature": 82.0,\
"humidity": 38,\
"wind_speed": 2.2,\
"weather": "Sunny"\
}\
},\
{\
"SWML": {\
"version": "1.0.0",\
"sections": {\
"main": [\
{\
"play": {\
"url": "https://example.com/twister.mp3"\
}\
}\
]\
}\
}\
}\
]
}Callback Request for web_hook_url
SignalWire will make a request to the web_hook_url of a SWAIG function with the following parameters:
call_id
string
The unique identifier for the current call.
ai_session_id
string
The unique identifier for the AI session.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
caller_id_name
string
Name of the caller.
caller_id_num
string
Number of the caller.
global_data
object
Global data set via the set_global_data action, as a key-value map.
content_disposition
string
Content disposition identifier (e.g., "SWAIG Function").
channel_active
boolean
Whether the channel is currently active.
channel_offhook
boolean
Whether the channel is off-hook.
channel_ready
boolean
Whether the channel is ready.
content_type
string
Type of content. The value will be text/swaig.
app_name
string
Name of the application that originated the request.
function
string
Name of the function that was invoked.
meta_data
object
A JSON object containing any user metadata, as a key-value map.
SWMLVars
object
A collection of variables related to SWML.
purpose
string
The purpose of the function being invoked. The value will be the functions.purpose value you provided in the SWML Function properties.
argument_desc
string | object
The description of the argument being passed. This value comes from the argument you provided in the SWML Function properties.
argument
object
The argument the AI agent is providing to the function. The object contains the three following fields.
argument.parsed
object
If a JSON object is detected within the argument, it is parsed and provided here.
argument.raw
string
The raw argument provided by the AI agent.
argument.substituted
string
The argument provided by the AI agent, excluding any JSON.
version
string
Version number.
Webhook request example
Below is a json example of the callback request that is sent to the web_hook_url:
{
"app_name": "swml app",
"global_data": {
"caller_id_name": "",
"caller_id_number": "sip:guest-246dd851-ba60-4762-b0c8-edfe22bc5344@46e10b6d-e5d6-421f-b6b3-e2e22b8934ed.call.signalwire.com;context=guest"
},
"project_id": "46e10b6d-e5d6-421f-b6b3-e2e22b8934ed",
"space_id": "5bb2200d-3662-4f4d-8a8b-d7806946711c",
"caller_id_name": "",
"caller_id_num": "sip:guest-246dd851-ba60-4762-b0c8-edfe22bc5344@46e10b6d-e5d6-421f-b6b3-e2e22b8934ed.call.signalwire.com;context=guest",
"channel_active": true,
"channel_offhook": true,
"channel_ready": true,
"content_type": "text/swaig",
"version": "2.0",
"content_disposition": "SWAIG Function",
"function": "get_weather",
"argument": {
"parsed": [\
{\
"city": "Tulsa",\
"state": "Oklahoma"\
}\
],
"raw": "{\"city\":\"Tulsa\",\"state\":\"Oklahoma\"}"
},
"call_id": "6e0f2f68-f600-4228-ab27-3dfba2b75da7",
"ai_session_id": "9af20f15-7051-4496-a48a-6e712f22daa5",
"argument_desc": {
"properties": {
"city": {
"description": "Name of the city",
"type": "string"
},
"country": {
"description": "Name of the country",
"type": "string"
},
"state": {
"description": "Name of the state",
"type": "string"
}
},
"required": [],
"type": "object"
},
"purpose": "Get weather with sarcasm"
}Variables
- ai_result: (out)
success|failed - return_value: (out)
success|failed
Reserved Functions
Reserved functions are special SignalWire functions that are automatically triggered at specific points during a conversation. You define them just like any other SWAIG function, but their names correspond to built-in logic on the SignalWire platform, allowing them to perform specific actions at the appropriate time.
Function name conflicts
Do not use reserved function names for your own SWAIG functions unless you want to use the reserved function’s built-in behavior. Otherwise, your function may not work as expected.
List of Reserved Functions
start_hook
string
Triggered when the call is answered. Sends the set properties of the function to the defined web_hook_url.
stop_hook
string
Triggered when the call is ended. Sends the set properties of the function to the defined web_hook_url.
summarize_conversation
string
Triggered when the call is ended. The post_prompt must be defined for this function to be triggered. Provides a summary of the conversation and any set properties to the defined web_hook_url.
Where are my function properties?
If the AI is not returning the properties you set in your SWAIG function, it may be because a reserved function was triggered before those properties were available. To ensure your function receives all necessary information, make sure the AI has access to the required property values before the reserved function is called. Any property missing at the time the reserved function runs will not be included in the data sent back.
Diagram examples
SWML Examples
Using SWAIG Functions
YAMLJSON
version: 1.0.0
sections:
main:
- amazon_bedrock:
post_prompt_url: "https://example.com/my-api"
prompt:
text: |
You are a helpful assistant that can provide information to users about a destination.
At the start of the conversation, always ask the user for their name.
You can use the appropriate function to get the phone number, address,
or weather information.
post_prompt:
text: "Summarize the conversation."
SWAIG:
includes:
- functions:
- get_phone_number
- get_address
url: https://example.com/functions
user: me
pass: secret
defaults:
web_hook_url: https://example.com/my-webhook
web_hook_auth_user: me
web_hook_auth_pass: secret
functions:
- function: get_weather
parameters:
properties:
location:
type: string
type: object
- function: summarize_conversation
parameters:
type: object
properties:
name:
type: stringdata_map
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
functions[].data_map defines how a SWAIG function should process and respond to the user’s input data.
functions[].data_map
object
An object that processes function inputs and executes operations through expressions, webhooks, or direct output.
Processing order
The components are processed in the following sequence:
expressions- Processes data using pattern matching (includes its ownoutput)webhooks- Makes external API calls (includes its ownoutputandexpressions)output- Returns a direct response and actions to perform
Similar to a return statement in conventional programming languages, when a valid output is encountered within any component, it immediately terminates function execution. The output provides:
- A
responseobject: Contains static text for the AI agent’s context - An optional
actionobject: Defines executable actions to be triggered
If no component produces a valid output, the system continues processing in sequence:
- First attempts
expressions - If unsuccessful, tries
webhooks - If still unsuccessful, attempts top-level
output - If all fail, returns a generic fallback error message
Properties
data_map.expressions
object[]
An array of objects that define plain string or regex patterns to match against the user’s input. When a match is found, the output object is returned.
expressions[].string
stringRequired
The actual input or value from the user or system.
expressions[].pattern
stringRequired
A regular expression pattern to validate or match the string.
expressions[].output
objectRequired
Defines the response or action to be taken when the pattern matches. See output for details.
data_map.webhooks
object[]
An array of objects that define external API calls. If a webhook defines foreach, expressions, and output, they are evaluated in that order.
webhooks[].url
stringRequired
The endpoint for the external service or API. Authentication can also be set in the url in the format of username:password@url. See webhook runtime request for details on template variable substitution and request behavior.
webhooks[].method
stringRequired
The HTTP method (GET, POST, etc.) for the API call.
webhooks[].headers
object
Any necessary headers for the API call.
webhooks[].params
object
An object of any necessary parameters for the API call. The key is the parameter name and the value is the parameter value.
webhooks[].input_args_as_params
booleanDefaults to false
A boolean to determine if the input parameters should be passed as parameters.
webhooks[].required_args
string | string[]
A string or array of strings that represent the parameters that are required to make the webhook request.
webhooks[].error_keys
string | string[]
A string or array of strings that represent the keys to be used for error handling.
webhooks[].expressions
object
A list of expressions to be evaluated upon matching. See expressions for details.
webhooks[].foreach
object
Iterates over an array of objects and processes an output based on each element in the array. Works similarly to JavaScript’s forEach method.
foreach.input_key
stringRequired
The key to be used to access the current element in the array.
foreach.output_key
stringRequired
The key that can be referenced in the output of the foreach iteration. The values that are stored from append will be stored in this key.
foreach.append
stringRequired
The values to append to the output_key. Properties from the object can be referenced and added to the output_key by using the following syntax: ${this.property_name}. The this keyword is used to reference the current object in the array.
foreach.max
number
The max amount of elements that are iterated over in the array. This will start at the beginning of the array.
webhooks[].output
objectRequired
Defines the response or action to be taken when the webhook is successfully triggered. See output for details.
data_map.output
object
Similar to a return statement in conventional programming languages, the data_map.output object immediately terminates function execution and returns control to the caller.
output.response
stringRequired
Static text that will be added to the AI agent’s context.
output.action
object[]
A list of SWML-compatible objects that are executed upon the execution of a SWAIG function. See list of valid actions for details.
List of valid actions
action[].SWML
object
A SWML object to be executed.
action[].say
string
A message to be spoken by the AI agent.
action[].stop
boolean
Whether to stop the conversation.
action[].hangup
boolean
Whether to hang up the call. When set to true, the call will be terminated after the AI agent finishes speaking.
action[].hold
integer | object
Places the caller on hold while playing hold music (configured via the params.hold_music parameter). During hold, speech detection is paused and the AI agent will not respond to the caller.
The value specifies the hold timeout in seconds. Can be:
- An integer (e.g.,
120for 120 seconds) - An object with a
timeoutproperty
Default timeout is 300 seconds (5 minutes). Maximum timeout is 900 seconds (15 minutes).
Unholding a call
There is no unhold SWAIG action because the AI agent is inactive during hold and cannot process actions. To take a caller off hold, either:
- Let the hold timeout expire (the AI will automatically resume with a default message), or
- Use the Calling API
ai_unholdcommand to programmatically unhold the call with a custom prompt.
hold.timeout
integerDefaults to 300
The duration to hold the caller in seconds. Maximum is 900 seconds (15 minutes).
action[].change_context
string
The name of the context to switch to. The context must be defined in the AI’s prompt.contexts configuration. This action triggers an immediate context switch during the execution of a SWAIG function.
Visit the contexts documentation for details on defining contexts.
action[].change_step
string
The name of the step to switch to. The step must be defined in prompt.contexts.{context_name}.steps for the current context. This action triggers an immediate step transition during the execution of a SWAIG function.
Visit the steps documentation for details on defining steps.
action[].toggle_functions
object[]
An array of objects to toggle SWAIG functions on or off during the conversation. Each object identifies a function by name and sets its active state.
See toggle_functions for additional details.
toggle_functions[].function
stringRequired
The name of the SWAIG function to toggle.
toggle_functions[].active
booleanDefaults to true
Whether to activate or deactivate the function.
action[].set_global_data
object
A JSON object containing any global data, as a key-value map. This action sets the data in the global_data to be globally referenced.
action[].set_meta_data
object
A JSON object containing any metadata, as a key-value map. This action sets the data in the meta_data to be referenced locally in the function.
See set_meta_data for additional details.
action[].unset_global_data
string | object
The key of the global data to unset from the global_data. You can also reset the global_data by passing in a new object.
action[].unset_meta_data
string | object
The key of the metadata to unset from the meta_data. You can also reset the meta_data by passing in a new object.
action[].playback_bg
object
A JSON object containing the audio file to play.
playback_bg.file
string
URL or filepath of the audio file to play. Authentication can also be set in the url in the format of username:password@url.
playback_bg.wait
booleanDefaults to false
Whether to wait for the audio file to finish playing before continuing.
action[].stop_playback_bg
boolean
Whether to stop the background audio file.
action[].user_input
string
Used to inject text into the users queue as if they input the data themselves.
action[].context_switch
object
A JSON object containing the context to switch to.
See context_switch for additional details.
context_switch.system_prompt
string
The instructions to send to the agent.
context_switch.consolidate
booleanDefaults to false
Whether to consolidate the context.
context_switch.user_prompt
string
A string serving as simulated user input for the AI Agent. During a context_switch in the AI’s prompt, the user_prompt offers the AI pre-established context or guidance.
action[].transfer
boolean | object
Transfer the call to a new destination. Accepts two forms depending on whether it accompanies a sibling action[].SWML payload:
- Boolean, use alongside a sibling
action[].SWMLpayload in the same action object. Whentrue, ends the AI session and hard-transfers the call to that SWML. When omitted orfalse, the SWML executes inline and the AI session continues afterward. - Object, use on its own, without
SWML, to transfer the call to a specific destination configured with the fields below. A bare string is also accepted as shorthand fortransfer.dest.
transfer.dest
string
The destination to transfer to: the name of a section in the current SWML document, or a URL that returns SWML to execute.
transfer.summarize
booleanDefaults to false
Whether to include a conversation summary when transferring.
Webhook runtime request
When the AI triggers a function that uses data_map.webhooks, SignalWire sends a request to each configured url.
Template variables
The url and params fields support %{variable} substitution. Nested properties use dot notation, for example, https://api.example.com/weather?city=%{args.location} substitutes the value the AI extracted for location. For more on variables and scopes, see the Variables reference.
args
object
Function argument values extracted by the AI, keyed by argument name.
args.*
any
Individual argument value. The key matches an argument name from the function’s parameters schema.
call_id
string
Unique identifier for the current call.
ai_session_id
string
AI session identifier.
conversation_id
string
Conversation identifier.
function
string
Name of the function being executed.
caller_id_name
string
Caller’s display name.
caller_id_num
string
Caller’s phone number.
project_id
string
SignalWire project ID.
space_id
string
SignalWire space ID.
app_name
string
AI application name.
global_data
object
The application’s global data.
global_data.*
any
User-defined property.
meta_data
object
Function metadata (when meta_data_token is set).
meta_data.*
any
User-defined property.
Request body
When params is defined (or method is POST), SignalWire sends the params object as the JSON request body. Template variables in params values are expanded before sending.
If no params are defined and method is not POST, the request is sent without a body.
If input_args_as_params is true, the function arguments extracted by the AI are merged into params. If no params are defined, the arguments become the entire request body.
Response processing
The JSON response from the webhook is processed through the output template. Fields from the response can be referenced using %{key} syntax in the output’s response string. For example, if the webhook returns {"temp": 72, "conditions": "sunny"}, an output of "The weather is %{temp}°F with %{conditions}" will produce "The weather is 72°F with sunny".
Examples
expressions
YAMLJSON
data_map:
expressions:
- string: "starwars"
pattern: "(?i)star\\s*wars"
output:
response: "May the Force be with you!"
- string: "startrek"
pattern: "(?i)star\\s*trek"
output:
response: "Live long and prosper!"webhooks with explicit params
YAMLJSON
data_map:
webhooks:
- url: https://api.example.com/weather
method: POST
params:
call_id: "%{call_id}"
city: "%{args.location}"
output:
response: "The weather in %{city} is %{temp}°F and %{conditions}."Sends the following request body to https://api.example.com/weather:
{
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"city": "New York"
}webhooks with input_args_as_params
YAMLJSON
data_map:
webhooks:
- url: https://api.example.com/weather
method: POST
input_args_as_params: true
output:
response: "The weather is %{temp}°F and %{conditions}."Sends the AI-extracted arguments directly as the request body:
{
"location": "New York"
}output with action
YAMLJSON
sections:
main:
- amazon_bedrock:
prompt:
text: You are a helpful SignalWire assistant.
SWAIG:
functions:
- function: test_function
parameters:
type: object
properties:
name:
type: string
required:
- name
data_map:
output:
response: We are testing the function.
action:
- SWML:
sections:
main:
- play:
url: 'say:We are testing the function.'parameters
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
The parameters object is used to define the input data that will be passed to the function.
Properties
functions[].parameters
object
An object that accepts the following properties.
parameters.type
stringRequired
Defines the top-level type of the parameters. Must be set to "object"
parameters.properties
objectRequired
An object containing the properties definitions to be passed to the function
properties.{property_name}
objectRequired
The properties object defines the input data that will be passed to the function. It supports different types of parameters, each with their own set of configuration options. The property name is a key in the properties object that is user-defined. An object with dynamic property names, where:
- Keys: User-defined strings, that set the property name.
- Values: Must be one of the valid schema types. Learn more about valid schema types from the JSON Schema documentation
Schema Types
Each property in the properties object must use one of the following schema types:
string
integer
number
boolean
array
object
oneOf
allOf
anyOf
const
{property_name}.type
stringRequired
The type of property the AI is passing to the function. Must be set to "string"
{property_name}.description
string
A description of the property
{property_name}.enum
string[]
An array of strings that are the possible values
{property_name}.default
string
The default string value
{property_name}.pattern
string
Regular expression pattern for the string value to match
{property_name}.nullable
booleanDefaults to false
Whether the property can be null
YAMLJSON
parameters:
type: object
properties:
property_name:
type: string
pattern: ^[a-z]+$parameters.required
string[]
Array of required property names from the properties object
Includes
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Remote function signatures to include in SWAIG functions. Will allow you to include functions that are defined in a remote location that can be executed during the interaction with the Amazon Bedrock agent. To learn more about how includes works see the request flow section.
Properties
SWAIG.includes
object[]
An array of objects that accept the following properties.
includes[].url
stringRequired
URL where the remote functions are defined. Authentication can also be set in the url in the format of username:password@url.
includes[].function
string[]Required
An array of the function names to be included.
includes[].meta_data
object
Metadata to be passed to the remote function. These are key-value pairs defined by the user.
SWML usage
YAMLJSON
version: 1.0.0
sections:
main:
- amazon_bedrock:
prompt:
text: "You are a helpful assistant that can check weather."
SWAIG:
includes:
- url: "https://example.com/swaig"
function: ["get_weather"]
meta_data:
user_id: "12345"Request flow
SWAIG includes creates a bridge between AI agents and external functions. When a SWML script initializes, it follows this two-phase process:
Initialization Phase: SWAIG discovers available functions from configured endpoints and requests their signatures to understand what each function can do.
Runtime Phase: The AI agent analyzes conversations, determines when functions match user intent, and executes them with full context.
Signature request
During SWML script initialization, SWAIG acts as a function discovery service. It examines your includes configuration, identifies the remote functions you’ve declared, then systematically contacts each endpoint to gather function definitions.
How it works: Looking at our SWML configuration example, SWAIG sends a targeted request to https://example.com/swaig specifically asking for the get_weather function definition. Along with this request, it forwards any meta_data you’ve configured, giving your server the context it needs to respond appropriately.
The discovery request:
{
"version": "2.0",
"action": "get_signature",
"content_type": "text/swaig",
"content_disposition": "function signature request",
"functions": ["get_weather"]
}What your server should return: Your endpoint must respond with complete function definitions that tell SWAIG everything it needs to know. Each function signature follows the SWAIG functions structure and describes the function’s purpose and required parameters:
[\
{\
"function": "function_name1",\
"description": "Description of what this function does",\
"parameters": {\
"type": "object",\
"properties": {\
"param1": {\
"type": "string",\
"description": "Parameter description"\
}\
},\
"required": ["param1"]\
},\
"web_hook_url": "https://example.com/swaig",\
"web_hook_auth_user": "optional_username",\
"web_hook_auth_password": "optional_password"\
}\
]Your server can optionally include web_hook_auth_user and web_hook_auth_password in each function definition to set HTTP basic authentication credentials for the function’s web_hook_url.
Function execution request
When the AI agent determines that a function call matches user intent, such as when a user requests weather information SWAIG packages the required information and sends it to the configured endpoint. The full details of the request can be found in the web_hook_url documentation.
Example request format:
{
"content_type": "text/swaig",
"function": "function_name1",
"argument": {
"parsed": [{"city": "New York"}],
"raw": "{\"city\":\"New York\"}",
"substituted": "{\"city\":\"New York\"}"
},
"meta_data": {
"custom_key": "custom_value"
},
"meta_data_token": "optional_token",
"app_name": "swml app",
"version": "2.0"
}SWAIG provides arguments in multiple formats, parsed for direct access, raw for the original text, and substituted with variable replacements applied. This flexibility supports edge cases and complex parsing scenarios.
Response formats:
When your function completes, it needs to send a response back to SWAIG. You have three main options depending on what you want to accomplish:
Simple Response
Response + Actions
Error Handling
Use this when: Your function just needs to return information to the AI agent.
{
"response": "The weather in New York is sunny and 75°F"
}The AI agent will receive this information and incorporate it naturally into the conversation with the user.
More information about the response format can be found in the web_hook_url documentation.
Flow diagram
The following diagram illustrates the complete SWAIG includes process from initialization to function execution:
Reference implementation
The following implementations demonstrate the essential pattern: define functions, map them to actual code, and handle both signature requests and function executions.
Python/Flask
JavaScript/Express
from flask import Flask, request, jsonify
app = Flask(__name__)
FUNCTIONS = {
"get_weather": {
"function": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "The city name"}
},
"required": ["city"]
},
"web_hook_url": "https://example.com/swaig"
}
}
def get_weather(city, meta_data=None, **kwargs):
# Logic to get weather data
# ...
temperature = 75
result = f"The weather in {city} is sunny and {temperature}°F"
# Return both a response AND an action
actions = [{"say": result}]
return result, actions
# Connect function names to actual functions
FUNCTION_MAP = {
"get_weather": get_weather
}
@app.route('/swaig', methods=['POST'])
def handle_swaig():
data = request.json
# SWAIG is asking what we can do
if data.get('action') == 'get_signature':
requested = data.get('functions', list(FUNCTIONS.keys()))
return jsonify([FUNCTIONS[name] for name in requested if name in FUNCTIONS])
# SWAIG wants us to actually do something
function_name = data.get('function')
if function_name not in FUNCTION_MAP:
return jsonify({"response": "Function not found"}), 200
params = data.get('argument', {}).get('parsed', [{}])[0]
meta_data = data.get('meta_data', {})
# Call the function and get results
result, actions = FUNCTION_MAP[function_name](meta_data=meta_data, **params)
return jsonify({"response": result, "action": actions})
if __name__ == '__main__':
app.run(debug=True)Testing the implementation
To test the implementation, start the server and simulate SWAIG requesting function signatures. This command requests signatures from the endpoint:
curl -X POST http://localhost:5000/swaig \
-H "Content-Type: application/json" \
-d '{"action": "get_signature"}'Expected response: A successful response returns function definitions in this format:
[\
{\
"description": "Get current weather for a city",\
"function": "get_weather",\
"parameters": {\
"properties": {\
"city": {\
"description": "The city name",\
"type": "string"\
}\
},\
"required": [\
"city"\
],\
"type": "object"\
},\
"web_hook_url": "https://example.com/swaig"\
}\
]answer
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Answer incoming call and set an optional maximum duration.
Properties
answer
object
An object that accepts the following properties.
answer.max_duration
integerDefaults to 14400 seconds (4 hours)
Maximum duration in seconds for the call.
answer.codecs
string
Comma-separated string of codecs to offer. Valid codecs are: PCMU, PCMA, G722, G729, AMR-WB, OPUS, VP8, H264.
answer.username
string
Username to use for SIP authentication.
answer.password
string
Password to use for SIP authentication.
Examples
No parameters
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}Named parameter
YAMLJSON
version: 1.0.0
sections:
main:
- answer:
max_duration: 60cond
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Execute a sequence of instructions depending on the value of a JavaScript condition.
The cond statement expects an array of conditions. Each condition is an object with a when and a then property, with the exception of a single, optional condition with just an else property.
Properties
cond
object[]Required
Array of when-then and else conditions
Properties for when-then conditions
cond[].when
stringRequired
The JavaScript condition to act on
cond[].then
object[]Required
Sequence of SWML Methods to execute when the condition evaluates to true
Properties for else condition
cond[].else
object[]
Sequence of SWML Methods to execute when none of the other conditions evaluate to true
The JavaScript condition string already has access to all the document variables. Using the variable substitution operator (${var}) inside this string might result in inconsistent behavior.
❌ when: "${call.type.toLowerCase() == 'sip'}"
❌ when: "${prompt_value} == 1"
✅ when: "call.type.toLowerCase() == 'sip'"Examples
Tell the caller what he’s calling from
YAMLJSON
version: 1.0.0
sections:
main:
- cond:
- when: call.type.toLowerCase() == 'sip'
then:
- play:
url: "say: You're calling from SIP."
- when: call.type.toLowerCase() == 'phone'
then:
- play:
url: "say: You're calling from phone."Perform tasks based on user input
YAMLJSON
version: 1.0.0
sections:
main:
- prompt:
play: >-
say: Press 1 to listen to music; 2 to hear your phone number; and
anything else to hang up
- cond:
- when: '${prompt_value} == 1'
then:
- play:
url: 'https://cdn.signalwire.com/swml/April_Kisses.mp3'
- execute:
dest: main
- when: call.type.toLowerCase() == 'phone'
then:
- transfer:
dest: say_phone_number
- execute:
dest: main
- else:
- hangup: {}
say_phone_number:
# The `.split('').join(' ')`` adds a space between each digit of the phone number,
# making sure the TTS spells out each digit one by one
- play:
url: "say: ${call.from.split('').join(' ')}"See Also
- Variables and Expressions: Complete reference for SWML variables, scopes, and using variables in conditional logic
- switch: Alternative conditional logic method
connect
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Connect to a phone number, SIP URI, Resource Address, queue, or WebSocket stream.
Properties
connect
objectRequired
Connects the current call to a destination, a phone number, SIP URI, Resource Address, queue, or WebSocket stream. The object shape depends on the connection type, select a tab below to see the full property schema for each mode.
Single
Parallel
Serial
Serial Parallel
Dial a single destination directly using the to property.
connect.to
stringRequired
Single destination to dial. The value format determines the destination type:
- Phone number, E.164 format (e.g.,
+15552345678) - SIP URI, (e.g.,
sip:alice@example.com) - Resource Address, address path (e.g.,
/public/test_room) - Queue,
queue:prefix (e.g.,queue:support) - WebSocket stream,
stream:wss://prefix (e.g.,stream:wss://example.com/audio)
connect.answer_on_bridge
booleanDefaults to false
Delay answer until the B-leg answers.
connect.call_state_events
string[]Defaults to ['ended']
An array of call state event names to be notified about. Allowed event names are created, ringing, answered, and ended.
connect.call_state_url
string
Webhook url to send call status change notifications to. Authentication can also be set in the url in the format of username:password@url. Learn more about status callbacks.
connect.codecs
stringDefaults to Based on SignalWire settings
Comma-separated string of codecs to offer. Has no effect on calls to phone numbers.
connect.confirm
string | object[]
Confirmation to execute when the call is connected. Can be either:
- A URL (string) that returns a SWML document
- An array of SWML methods to execute inline
connect.confirm_timeout
integerDefaults to Inherits from timeout
The amount of time, in seconds, to wait for the confirm script to execute.
connect.encryption
stringDefaults to optional
The encryption method to use for the call. Possible values: mandatory, optional, forbidden.
connect.from
stringDefaults to Calling party's caller ID number
Caller ID number. Optional.
connect.from_name
string
The caller ID name shown to the person you’re calling, displayed alongside the from number (sometimes called CNAM). Applies to SIP calls only, it has no effect on calls to phone numbers.
connect.headers
object[]
Custom SIP headers to add to INVITE. Has no effect on calls to phone numbers.
headers[].name
stringRequired
The name of the header.
headers[].value
stringRequired
The value of the header.
connect.max_duration
integerDefaults to 14400 seconds (4 hours)
Maximum duration, in seconds, allowed for the call.
connect.password
string
SIP authentication password (sip_auth_password) for the outbound leg. Only applies to SIP URI targets, ignored for phone, Resource Address, queue, and stream destinations.
connect.result
object | object[]
Action to take based on the result of the call. This will run once the peer leg of the call has ended.
Will use the switch properties when the return_value is a object, and will use the cond properties method when the return_value is an array. See Variables for details.
connect.ringback
string[]Defaults to Plays audio from the provider
Array of play URIs to play as ringback tone.
connect.session_timeout
integerDefaults to Based on SignalWire settings
Time, in seconds, to set the SIP Session-Expires header in INVITE. Must be a positive, non-zero number. Has no effect on calls to phone numbers.
connect.status_url
string
Webhook URL to deliver status events. For phone, SIP, and Resource Address destinations, reports the connect operation status (connecting, connected, failed, disconnected). See Connect Status Callbacks. For stream destinations, reports stream status notifications. See Stream Status Callbacks.
connect.status_url_method
stringDefaults to POST
HTTP method for the status webhook. Possible values: GET, POST. Stream destinations only.
connect.timeout
integerDefaults to 60 seconds
Maximum time, in seconds, to wait for an answer.
connect.transfer_after_bridge
string
SWML to execute after the bridge completes. This defines what should happen after the call is connected and the bridge ends.
Can be either:
- A URL (http or https) that returns a SWML document
- An inline SWML document (as a JSON string)
Required when connecting to a queue (when to starts with queue:).
connect.username
string
SIP authentication username (sip_auth_username) for the outbound leg. Only applies to SIP URI targets, ignored for phone, Resource Address, queue, and stream destinations.
connect.webrtc_media
booleanDefaults to false
If true, WebRTC media is offered to the SIP endpoint. Has no effect on calls to phone numbers.
Stream-specific properties
The following properties apply only when to starts with stream:wss://.
connect.authorization_bearer_token
string
Bearer token sent as an Authorization header during the WebSocket handshake.
connect.codec
stringDefaults to PCMU
Audio codec for the stream. Supported values: PCMU, PCMA, G722, L16. Codec can include rate and ptime modifiers (e.g., PCMU@40i, L16@24000h@40i).
connect.custom_parameters
object
Custom key-value pairs sent in the WebSocket start message.
connect.name
string
Stream name identifier.
connect.realtime
booleanDefaults to false
Enable realtime mode for bidirectional audio.
Example
YAMLJSON
version: 1.0.0
sections:
main:
- connect:
to: "sip:alice@example.com"
from: "+15551112222"
username: "sipuser"
password: "s3cret"Variables
Set by the method:
- connect_result: (out)
connected|failed. - connect_failed_reason: (out) Detailed reason for failure.
- return_value: (out) Same value as
connect_result.
StatusCallbacks
A POST request will be sent to call_state_url with a JSON payload when the call state changes. Only events listed in call_state_events will be sent (default: ended).
event_type
string
The type of event. Always calling.call.state for this method.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing call state parameters.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.call_state
string
The current call state. Valid values:created, ringing, answered, ended.
params.direction
string
The direction of the call leg (e.g., outbound).
params.device
object
Details about the device involved in the call.
device.type
string
The type of device (e.g., phone, sip).
device.params.from_number
string
The originating phone number.
device.params.to_number
string
The destination phone number.
params.end_reason
string
The reason the call ended (only present when call_state is ended). Valid values:hangup, busy, no_answer, cancel, declined, error.
Raw JSON example
{
"event_type": "calling.call.state",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"call_state": "answered",
"direction": "outbound",
"device": {
"type": "phone",
"params": {
"from_number": "+15551231234",
"to_number": "+15553214321"
}
},
"end_reason": null
}
}Connect Status Callbacks
When you provide a top-level status_url, SignalWire sends HTTP POST requests reporting the overall status of the connect operation.
event_type
string
The type of event. Always calling.call.connect for connect status events.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing connect status parameters.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.segment_id
string
The segment ID for the call leg. Present when a segment ID has been assigned.
params.tag
string
The tag associated with the call. Present when a tag has been set.
params.connect_state
string
The current connect state. Possible values:
connecting, Attempting to connectconnected, Successfully connectedfailed, Connection faileddisconnected, Connection ended
params.failed_reason
string
The reason the connection failed. Only present when connect_state is failed.
params.peer
object
Details about the connected peer. Present when connect_state is connected.
peer.call_id
string
The peer’s call ID.
peer.tag
string
The tag associated with the peer call. Present when a tag has been set on the peer.
peer.node_id
string
The node ID of the node handling this call.
peer.queue_id
string
The queue ID when the peer was connected via a queue. Only present for queue-based connections.
peer.queue_name
string
The queue name when the peer was connected via a queue. Only present for queue-based connections.
peer.device
object
Details about the peer’s device.
Raw JSON example
{
"event_type": "calling.call.connect",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"connect_state": "connected",
"peer": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"device": {
"type": "phone",
"params": {
"from_number": "+15551231234",
"to_number": "+15553214321"
}
}
}
}
}Failed state example
{
"event_type": "calling.call.connect",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"connect_state": "failed",
"failed_reason": "no_answer"
}
}Stream Status Callbacks
When connecting to a WebSocket stream destination with a status_url, SignalWire sends HTTP requests reporting the stream status.
event_type
string
The type of event. Always calling.call.stream for stream status events.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing stream status parameters.
params.control_id
string
The control identifier for the stream.
params.state
string
The current stream state. Possible values:
streaming, Stream is activefinished, Stream has ended
params.url
string
The WebSocket URL of the stream.
params.name
string
The stream name, if one was provided.
Raw JSON example
{
"event_type": "calling.call.stream",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"control_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"state": "streaming",
"url": "wss://example.com/audio",
"name": "my-stream"
}
}Examples
Use connect with a Resource Address
Connect to a Resource by using its Address as the to value.
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- play:
volume: 10
urls:
- 'silence:1.0'
- 'say:Hello, connecting to a fabric Resource that is a room'
- connect:
to: /public/test_roomDial a single phone number
YAMLJSON
version: 1.0.0
sections:
main:
- connect:
from: "+15553214321"
to: "+15551231234"Dial numbers in parallel
YAMLJSON
version: 1.0.0
sections:
main:
- connect:
parallel:
- to: "+15551231234"
- to: "+15553214321"Dial SIP serially with a timeout
YAMLJSON
version: 1.0.0
sections:
main:
- connect:
timeout: 20
serial:
- from: "sip:chris@example.com"
to: "sip:alice@example.com"
- to: "sip:bob@example.com"
codecs: PCMUSet the caller ID name on SIP legs
Set from_name at the top level so every device inherits it, then override it on a single destination. agent1 sees the caller ID name “Support Team” (inherited); agent2 sees “Billing Dept” (overridden).
YAMLJSON
version: 1.0.0
sections:
main:
- connect:
from: "+15551000001"
from_name: "Support Team"
serial:
- to: "sip:agent1@pbx.example.com"
- to: "sip:agent2@pbx.example.com"
from_name: "Billing Dept"Connect to a queue with transfer after bridge
YAMLJSON
version: 1.0.0
sections:
main:
- connect:
to: "queue:support"
transfer_after_bridge: "https://example.com/post-call-swml"Connect to a WebSocket stream
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- connect:
to: "stream:wss://example.com/audio"
codec: PCMU
realtime: true
name: my-stream
status_url: "https://example.com/stream-status"denoise
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Start noise reduction. You can stop it at any time using stop_denoise.
denoise
objectRequired
An empty object that accepts no parameters.
Variables
Set by the method:
- denoise_result: (out)
on|failed
Examples
Start denoise
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- denoise: {}
- play:
url: 'say: Denoising ${denoise_result}'detect_machine
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
A detection method that combines AMD (Answering Machine Detection) and fax detection. Detect whether the user on the other end of the call is a machine (fax, voicemail, etc.) or a human. The detection event(s) will be sent to the specified status_url as a POST request, and the current detection state or final result will also be saved in the detect_result variable.
Properties
detect_machine
objectRequired
An object that accepts the following properties.
detect_machine.detect_message_end
booleanDefaults to false
If true, stops detection on beep / end of voicemail greeting.
detect_machine.detectors
stringDefaults to amd,fax
Comma-separated string of detectors to enable. Valid Values:amd, fax
detect_machine.end_silence_timeout
numberDefaults to 1.0
How long to wait for voice activity to finish (in seconds).
detect_machine.initial_timeout
numberDefaults to 4.5
How long to wait for initial voice activity before giving up (in seconds).
detect_machine.machine_ready_timeout
numberDefaults to value of the end_silence_timeout parameter
How long to wait for voice activity to finish before firing the READY event (in seconds).
detect_machine.machine_voice_threshold
numberDefaults to 1.25
The number of seconds of ongoing voice activity required to classify as MACHINE.
detect_machine.machine_words_threshold
integerDefaults to 6
The minimum number of words that must be detected in a single utterance before classifying the call as MACHINE.
detect_machine.status_url
string
The HTTP(S) URL to deliver detector events to. Learn more about status callbacks.
detect_machine.timeout
numberDefaults to 30.0
The maximum time to run the detector (in seconds).
detect_machine.tone
stringDefaults to CED
The tone to detect. Only the remote side tone will be received. (CED or CNG) Used for fax detection.
detect_machine.wait
booleanDefaults to true
If false, the detector will run asynchronously and status_url must be set. If true, the detector will wait for detection to complete before moving to the next SWML instruction.
Variables
The following variables are available after the detect_machine method is executed and detection is complete. You can reference these variables in your SWML script utilizing the ${variable} syntax.
detect_result
machine | human | fax | unknown | detecting | error
The lowercase SWML variable value for the current detection state or final result. Callback lifecycle events such as READY, NOT_READY, and finished are never assigned to this variable.
detect_machine_beep
true | false
Whether a beep was detected. true if detected.
detect_ms
integer
The number of milliseconds the detection took.
StatusCallbacks
A POST request will be sent to status_url with a JSON payload like the following:
event_type
string
The type of event, always calling.call.detect for this method.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing detection-specific parameters.
params.control_id
string
The control ID for this detect operation.
params.detect
object
Detection result details (see subfields below).
detect.type
string
The type of detection. Valid values:machine or fax.
detect.params.event
string
The detector event value in the status callback payload.
Detection outcome values are HUMAN, MACHINE, and UNKNOWN. Lifecycle marker values are READY, NOT_READY, and finished. READY, NOT_READY, and finished only appear in callback payloads and are not valid ${detect_result} values. The lowercase finished value is intentional.
detect.params.beep
boolean
Present and set to true when a beep was detected. Absent when no beep has been detected.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.segment_id
string
The segment ID for this part of the call.
Raw JSON example
{
"event_type": "calling.call.detect",
"event_channel": "swml:be38xxxx-8xxx-4xxxx-9fxx-bxxxxxxxxx",
"timestamp": 1745332535.668522,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"control_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"detect": {
"type": "machine",
"params": {
"event": "MACHINE",
"beep": true
}
},
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"segment_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}Examples
Play the detection result
YAMLJSON
version: 1.0.0
sections:
main:
- detect_machine:
status_url: 'https://example.com/detect-events'
timeout: 20
- play:
url: 'say:Detection result: ${detect_result}'Conditional actions based on the detection result
YAMLJSON
version: 1.0.0
sections:
main:
- play:
url: "say: Welcome to the machine detection test."
- detect_machine:
status_url: "https://webhook.site/5c8abf82-b8c7-41c8-b5d6-b32a40068109"
detectors: "amd,fax"
wait: true
- cond:
- when: detect_result == 'machine'
then:
- play:
url: "say: You are a machine, goodbye."
- hangup: {}
- when: detect_result == 'human'
then:
- play:
url: "say: You are a human, hello."
- hangup: {}
- when: detect_result == 'fax'
then:
- play:
url: "say: You are a fax, goodbye."
- hangup: {}
- else:
- play:
url: "say: Unable to determine if you are a human, machine, or fax, goodbye. Result was ${detect_result}"
- hangup: {}enter_queue
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Place the current call in a named queue where it will wait to be connected to an available agent or resource. While waiting, callers will hear music or custom audio. When an agent connects to the queue (using the connect method), the caller and agent are bridged together. After the bridge completes (when the agent or caller hangs up), execution continues with the SWML script specified in transfer_after_bridge.
Properties
enter_queue
objectRequired
An object that accepts the following properties.
enter_queue.queue_name
stringRequired
Name of the queue to enter. If a queue with this name does not exist, it will be automatically created.
enter_queue.transfer_after_bridge
stringRequired
SWML to execute after the bridge completes (when the agent or caller hangs up). This defines what should happen after the call is connected to an agent and the bridge ends.
Can be either:
- A URL (http or https) that returns a SWML document
- An inline SWML document (as a JSON string)
enter_queue.status_url
string
HTTP or HTTPS URL to deliver queue status events. Status events will be sent via HTTP POST requests. See Queue Status Callbacks for event details.
enter_queue.wait_url
string
URL for media to play while waiting in the queue. The file will be fetched using an HTTP GET request. Supported audio formats include:
WAV(audio/wav, audio/wave, audio/x-wav)MP3(audio/mpeg)AIFF(audio/aiff, audio/x-aifc, audio/x-aiff)GSM(audio/x-gsm, audio/gsm)μ-law(audio/ulaw)
Default hold music will be played if not set.
enter_queue.wait_time
integerDefaults to 3600
Maximum time in seconds to wait in the queue before timeout.
Queue Status Callbacks
When you provide a status_url, SignalWire will send HTTP POST requests to that URL for the following queue events.
Event Object Structure
event_type
string
The type of event that is being reported. Will always be calling.call.queue for queue events.
event_channel
string
The SWML channel identifier for the call (format: swml:{uuid}).
timestamp
number
Unix timestamp with microsecond precision indicating when the event occurred.
project_id
string
The SignalWire project ID (UUID format).
space_id
string
The SignalWire Space ID (UUID format).
params
object
An object containing the event-specific parameters.
params.status
string
The event type identifier.
Possible Values:
enqueue- Caller added to queueleave- Caller left without being bridgeddequeue- Caller pulled from queue and bridged
params.id
string
Unique queue entry identifier (UUID format).
params.name
string
The name of the queue.
params.position
integer
The caller’s position in the queue. Set to 0 when dequeued.
params.size
integer
The total number of callers in the queue. Set to 0 when dequeued.
params.avg_time
integer
Average wait time in the queue (in seconds).
params.enqueue_ts
integer
Unix timestamp in microseconds when the caller entered the queue. Set to 0 in dequeue events.
params.dequeue_ts
integer
Unix timestamp in microseconds when the caller was dequeued. Set to 0 in enqueue and leave events, populated in dequeue events.
params.leave_ts
integer
Unix timestamp in microseconds when the caller left the queue. Set to 0 in enqueue and dequeue events, populated in leave events.
params.status_url
string
The callback URL that was configured for status events.
params.control_id
string
Control identifier (UUID format). Present in enqueue and leave events. May be null in dequeue events.
params.call_id
string
The call identifier (UUID format).
params.node_id
string
The node identifier where the call is being processed (format: {uuid}@{region}).
Event Examples
enqueue Event
Sent when a caller is added to the queue.
{
"event_type": "calling.call.queue",
"event_channel": "swml:a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"timestamp": 1762966696.218623,
"project_id": "f8e7d6c5-b4a3-4210-9876-543210fedcba",
"space_id": "1a2b3c4d-5e6f-4789-abcd-ef0123456789",
"params": {
"status": "enqueue",
"id": "9f8e7d6c-5b4a-4321-9876-543210fedcba",
"name": "support_queue",
"position": 1,
"size": 1,
"avg_time": 0,
"enqueue_ts": 1762966696203260,
"dequeue_ts": 0,
"leave_ts": 0,
"status_url": "https://example.com/queue-status",
"control_id": "7a6b5c4d-3e2f-4123-8765-432109876543",
"call_id": "5d4c3b2a-1f0e-4321-9abc-def012345678",
"node_id": "2b3c4d5e-6f7a-4890-bcde-f01234567890@us-east"
}
}leave Event
Sent when a caller leaves the queue without being bridged to another call (e.g., timeout, hangup).
{
"event_type": "calling.call.queue",
"event_channel": "swml:3c4d5e6f-7a8b-4910-cdef-012345678901",
"timestamp": 1762966720.978854,
"project_id": "f8e7d6c5-b4a3-4210-9876-543210fedcba",
"space_id": "1a2b3c4d-5e6f-4789-abcd-ef0123456789",
"params": {
"status": "leave",
"id": "9f8e7d6c-5b4a-4321-9876-543210fedcba",
"name": "support_queue",
"position": 1,
"size": 1,
"avg_time": 0,
"enqueue_ts": 1762966719450020,
"dequeue_ts": 0,
"leave_ts": 1762966720943789,
"status_url": "https://example.com/queue-status",
"control_id": "8b7a6c5d-4e3f-4234-9876-543210987654",
"call_id": "6e5d4c3b-2a1f-4432-abcd-ef0123456789",
"node_id": "4d5e6f7a-8b9c-4a01-def0-123456789012@us-east"
}
}dequeue Event
Sent when a caller is pulled out of the queue and bridged with another caller.
{
"event_type": "calling.call.queue",
"event_channel": "swml:a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"timestamp": 1762966703.409084,
"project_id": "f8e7d6c5-b4a3-4210-9876-543210fedcba",
"space_id": "1a2b3c4d-5e6f-4789-abcd-ef0123456789",
"params": {
"status": "dequeue",
"id": "9f8e7d6c-5b4a-4321-9876-543210fedcba",
"name": "support_queue",
"position": 0,
"size": 0,
"avg_time": 0,
"enqueue_ts": 0,
"dequeue_ts": 1762966703217168,
"leave_ts": 0,
"status_url": "https://example.com/queue-status",
"control_id": null,
"call_id": "5d4c3b2a-1f0e-4321-9abc-def012345678",
"node_id": "2b3c4d5e-6f7a-4890-bcde-f01234567890@us-east"
}
}Variables
Set by the method:
queue_result: (out) The result of the queue operation. Possible Values:
entering- Call is entering the queueconnecting- Call is in the process of connecting to an agentconnected- Successfully connected to an agentleaving- Call is leaving the queuetimeout- Waited too long and timed outhangup- Caller hung up while waitingfailed- Queue operation failed due to an error
wait_time: (out) Time in seconds the caller waited in the queue. Set to -1 if not available.
entry_position: (out) The caller’s position in the queue when they entered. Set to -1 if not available.
entry_size: (out) The total size of the queue when the caller entered. Set to -1 if not available.
Examples
Basic Queue
YAMLJSON
version: 1.0.0
sections:
main:
- enter_queue:
queue_name: "my_queue"
transfer_after_bridge: "https://example.com/post-call-swml"Queue with Status Callback
YAMLJSON
version: 1.0.0
sections:
main:
- enter_queue:
queue_name: "sales_queue"
status_url: "https://example.com/queue-status"
wait_time: 1800
transfer_after_bridge: "https://example.com/post-call-swml"execute
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Execute a specified section or URL as a subroutine, and upon completion, return to the current document. Use the return statement to pass any return values or objects back to the current document.
Properties
execute
objectRequired
An object that accepts the following properties.
execute.dest
stringRequired
Accepts any valid destination
execute.params
object
Named parameters to send to section or URL
execute.meta
object
User-defined metadata. This data is ignored by SignalWire and can be used for your own tracking purposes.
execute.on_return
object[]
Array of SWML methods to execute when the executed section or URL returns.
execute.result
object | object[]
Action to take based on the result of the call. This will run once the peer leg of the call has ended.
Will use the switch method when the return_value is a object, and will use the cond method when the return_value is an array.
Valid Destinations
The destination string can be one of:
"section_name"- section in the current document to execute. (For example:main)- A URL (http or https) - URL pointing to the document to execute. An HTTP POST request will be sent to the URL. The
paramsobject is passed, along with the variables and thecallobject. Authentication can also be set in the url in the format ofusername:password@url. - An inline SWML document (as a JSON string) - SWML document provided directly as a JSON string.
Examples
Executing a subroutine
YAMLJSON
version: 1.0.0
sections:
main:
- execute:
dest: subroutine
params:
to_play: 'https://cdn.signalwire.com/swml/April_Kisses.mp3'
subroutine:
- answer: {}
- play:
url: '${params.to_play}'Executing a subroutine and branching on return
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- execute:
dest: my_arithmetic
params:
a: 2
b: 3
on_return:
- switch:
variable: return_value
case:
'5':
- play:
url: 'say: Math works!'
'23':
- play:
url: 'say: Wrong'
default:
- play:
url: 'say: Bad robot! ${return_value}'
my_arithmetic:
- return: '${parseInt(params.a) + parseInt(params.b)}'Execute a SWML script hosted on a server
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- execute:
dest: 'https://<YOUR_NGROK_UUID>.ngrok-free.app'
params:
some_info: 12345A minimal server for this SWML script can be written as follows:
Python/Flask
JavaScript/Express
from flask import Flask, request
from waitress import serve
app = Flask(__name__)
@app.route("/", methods=['POST'])
def swml():
content = request.get_json(silent=True)
print(content)
return '''
version: 1.0.0
sections:
main:
- answer: {}
- play:
url: "say: The call type is {}"
'''.format(content['call']['type'])
if __name__ == "__main__":
serve(app, host='0.0.0.0', port=6000)This server (running on localhost) can be made accessible to the wider web (and thus this SWML script) using forwarding tools like ngrok. Visit ngrok.com to learn how.
The server will be sent the following payload:
{
"call": {
"call_id": "<call_id>",
"node_id": "<node_id>",
"segment_id": "<segment_id>",
"call_state": "answered",
"direction": "inbound",
"type": "phone",
"from": "<address>",
"to": "<address>",
"from_number": "<address>",
"to_number": "<address>",
"headers": [],
"project_id": "<your Project UUID>",
"space_id": "<your Space UUID>"
},
"vars": {
"answer_result": "success"
},
"params": {
"some_info": "12345"
}
}The call object is described in detail in the Calling overview. All variables created within the SWML document are passed inside vars, and the params object contains the parameters defined in the params parameter of execute.
goto
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Jump to a label within the current section, optionally based on a condition. The goto method will only navigate to a label within the same section.
Properties
goto
objectRequired
An object that accepts the following properties.
goto.label
stringRequired
The label in section to jump to.
goto.when
string
A JavaScript condition that determines whether to perform the jump. If the condition evaluates to true, the jump is executed. If omitted, the jump is unconditional.
goto.max
integerDefaults to 100
The maximum number of times to jump, from the minimum of 1 to max 100 jumps.
Examples
Loop with max
YAMLJSON
version: 1.0.0
sections:
main:
- label: foo
- play:
url: 'say: This speech will be repeated 4 times.'
- goto:
label: foo
max: 3Loop if a condition is satisfied
YAMLJSON
version: 1.0.0
sections:
main:
- label: foo
- play:
url: 'say: This is some text that will be repeated 4 times.'
- set:
do_loop: true
- goto:
label: foo
when: do_loop === true
max: 3hangup
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
End the call with an optional reason.
Properties
hangup
objectRequired
An object that accepts the following properties.
hangup.reason The reason for hanging up the call.
Examples
No parameters
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- hangup: {}Set a hangup reason
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- hangup:
reason: "busy"join_conference
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Join an ad-hoc audio conference started on either the SignalWire or Compatibility API. This method allows you to connect the current call to a named conference where multiple participants can communicate simultaneously.
Properties
join_conference
objectRequired
An object that accepts the following properties.
join_conference.name
stringRequired
Name of conference.
join_conference.muted
booleanDefaults to false
Whether to join the conference in a muted state. If set to true, the participant will be muted upon joining.
join_conference.beep
stringDefaults to true
Sets the behavior of the beep sound when joining or leaving the conference.
Possible Values: true, false, onEnter, onExit
join_conference.start_on_enter
booleanDefaults to true
Starts the conference when the main participant joins. This means the start action will not wait on more participants to join before starting.
join_conference.end_on_exit
booleanDefaults to false
Ends the conference when the main participant leaves. This means the end action will not wait on more participants to leave before ending.
join_conference.wait_url
string
A URL to fetch SWML while waiting for the conference to start (before a start_on_enter participant joins). SignalWire sends a POST request with the standard document-fetching webhook body. The response should be a SWML document containing audio to play (e.g., hold music). Default hold music will be played if not set.
join_conference.max_participants
integerDefaults to 100000
The maximum number of participants allowed in the conference. If the limit is reached, new participants will not be able to join.
join_conference.record
stringDefaults to do-not-record
Enables or disables recording of the conference.
Possible Values: do-not-record, record-from-start
join_conference.region
string
Specifies the geographical region where the conference will be hosted.
Possible Values: global, us, eu, ch
join_conference.trim
stringDefaults to trim-silence
If set to trim-silence, it will remove silence from the start of the recording. If set to do-not-trim, it will keep the silence.
Possible Values: trim-silence, do-not-trim
join_conference.coach
string
Coach accepts a call SID of a call that is currently connected to an in-progress conference. Specifying a call SID that does not exist or is no longer connected will result in a failure.
join_conference.status_callback_event
string
A space-separated list of one or more events to listen for and send to the status callback URL.
Possible Values: start, end, join, leave, mute, hold, modify, speaker, announcement
join_conference.status_callback_event_type
string
The content type used when sending status events to the status callback URL.
Possible Values: cxml, laml, relay
join_conference.status_callback
string
The URL to which status events will be sent. This URL must be publicly accessible and able to handle HTTP requests. Learn more about status callbacks.
join_conference.status_callback_method
stringDefaults to POST
The HTTP method to use when sending status events to the status callback URL.
Possible Values: GET, POST
join_conference.recording_status_callback
string
The URL to which recording status events will be sent. This URL must be publicly accessible and able to handle HTTP requests. Learn more about status callbacks.
join_conference.recording_status_callback_method
stringDefaults to POST
The HTTP method to use when sending recording status events to the recording status callback URL.
Possible Values: GET, POST
join_conference.recording_status_callback_event
string
A space-separated list of one or more events to listen for and send to the recording status callback URL.
Possible Values: in-progress, completed, absent
join_conference.recording_status_callback_event_type
string
The content type used when sending recording status events to the recording status callback URL.
Possible Values: cxml, laml, relay
join_conference.result
object
Allows the user to specify a custom action to be executed when the conference result is returned (typically when it has ended). The actions can a switch object or a cond array. The switch object allows for conditional execution based on the result of the conference, while the cond array allows for multiple conditions to be checked in sequence. If neither is provided, the default action will be to end the conference.
join_conference.stream
object
Attach a bidirectional WebSocket stream to the conference. Conference audio is streamed to the url, enabling real-time audio processing, transcription, or AI agents that listen to the conference. Uses the same stream schema as the stream device type in connect.
join_conference.stream.url
stringRequired
Secure WebSocket URL (must start with wss://) that the conference audio is streamed to. Plain ws:// is not supported.
join_conference.stream.name
string
A friendly name to identify the stream at the WebSocket endpoint.
join_conference.stream.codec
string
Audio codec for the streamed audio. Supported values: PCMU, PCMA, G722, L16. Codec can include rate and ptime modifiers (e.g., PCMU@40i, L16@24000h@40i).
join_conference.stream.status_url
string
HTTP or HTTPS URL to which stream status events will be sent.
join_conference.stream.status_url_method
stringDefaults to POST
The HTTP method to use when sending stream status events to the status URL.
Possible Values: GET, POST
join_conference.stream.realtime
booleanDefaults to false
When true, enables bidirectional audio so your endpoint can stream audio back into the conference (not just receive it).
join_conference.stream.authorization_bearer_token
string
Bearer token sent in the Authorization header when the WebSocket connection is opened, so your endpoint can authenticate the request.
join_conference.stream.custom_parameters
object
Custom key-value pairs delivered to your WebSocket endpoint when the stream connects. Use them to pass context such as a session or customer ID.
Variables
join_conference_result
string
The result of the conference join attempt. Possible values: completed (successfully joined and left the conference), answered (successfully joined the conference), no-answer (failed to join due to no answer), failed (failed to join due to an error), canceled (join attempt was canceled).
return_value
string
Contains the same value as join_conference_result for use in conditional logic.
StatusCallbacks
A POST request will be sent to status_callback with a JSON payload for events specified in status_callback_event. Both conference and recording events share the same calling.conference event type; the specific event is identified by params.status.
event_type
string
The type of event. Always calling.conference.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing conference-specific parameters.
params.call_id
string
The call ID of the participant.
params.name
string
The name of the conference.
params.conference_id
string
The unique ID of the conference.
params.status
string
The conference event. Valid values:conference-start, conference-end, participant-join, participant-leave, participant-mute, participant-unmute, participant-hold, participant-unhold, participant-speech-start, participant-speech-stop, participant-modify, record-start, record-pause, record-resume, record-stop.
params.size
number
The number of participants currently in the conference.
params.node_id
string
The node identifier.
params.segment_id
string
The segment ID for the call. Present when available.
params.region
string
The geographical region of the conference.
params.tag
string
The tag associated with the call. Present when set.
params.muted
boolean
Whether the participant is muted. Present on participant events.
params.hold
boolean
Whether the participant is on hold. Present on participant events.
params.start_on_join
boolean
Whether the participant starts the conference on join.
params.end_on_leave
boolean
Whether the participant ends the conference on leave.
params.coaching
boolean
Whether the participant is in coaching mode. Present on participant events.
params.recording_url
string
URL to the conference recording. Present on conference-end and record-stop events when a recording exists.
params.recording_file_size
number
Recording file size in bytes. Present on conference-end and record-stop events.
params.recording_duration
number
Recording duration in seconds. Present on conference-end and record-stop events.
params.reason_ended
string
The reason the conference ended. Present on conference-end events.
params.call_id_ending_conf
string
The call ID of the participant that ended the conference. Present on conference-end events.
Participant join event example
{
"event_type": "calling.conference",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"name": "my_conference",
"conference_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"status": "participant-join",
"size": 3,
"muted": false,
"hold": false,
"start_on_join": true,
"end_on_leave": false,
"coaching": false
}
}Conference end event example
{
"event_type": "calling.conference",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.456,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"name": "my_conference",
"conference_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"status": "conference-end",
"size": 0,
"reason_ended": "last-participant-left",
"call_id_ending_conf": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"recording_url": "https://your-space.signalwire.com/api/v1/recordings/rec-uuid/download",
"recording_duration": 300,
"recording_file_size": 4800000
}
}Examples
Basic Conference Join
YAMLJSON
version: 1.0.0
sections:
main:
- join_conference:
name: "team_meeting"Conference with Custom Settings
YAMLJSON
version: 1.0.0
sections:
main:
- join_conference:
name: "team_meeting"
muted: false
beep: "onEnter"
start_on_enter: true
max_participants: 10
record: "record-from-start"Conference with Status Callbacks
YAMLJSON
version: 1.0.0
sections:
main:
- join_conference:
name: "support_call"
status_callback_event: "join"
status_callback: "https://example.com/conference-status"
status_callback_method: "POST"
recording_status_callback: "https://example.com/recording-status"
recording_status_callback_event: "completed"Conference with a stream attached
YAMLJSON
version: 1.0.0
sections:
main:
- join_conference:
name: "team_meeting"
stream:
url: "wss://example.com/conference-audio"
codec: "PCMU"
realtime: true
status_url: "https://example.com/stream-status"join_room
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Join a RELAY room. If the room doesn’t exist, it creates a new room.
join_room
objectRequired
An object that accepts the following properties.
Properties
join_room.name
stringRequired
Name of the room to join. Allowed characters: A-Z | a-z | 0-9_-
You can create a room via out REST API here
Variables
Set by the method:
- join_room_result: (out)
joined|failed
Examples
Joining a room
YAMLJSON
version: 1.0.0
sections:
main:
- join_room:
name: my_roomlabel
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Mark any point of the SWML section with a label so that goto can jump to it.
Properties
label
stringRequired
Mark any point of the SWML section with a label so that goto can jump to it.
Examples
YAMLJSON
version: 1.0.0
sections:
main:
- label: foo
- play:
url: 'say: This speech will be repeated 4 times.'
- goto:
label: foo
max: 3live_transcribe
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Start live transcription of the call. The transcription will be sent to the specified webhook URL.
For whole-call transcription delivered after the call ends, see transcribe.
Properties
live_transcribe
objectRequired
An object that accepts the following properties.
live_transcribe.action
string | objectRequired
The action to perform. See actions below.
Actions
The action property controls the transcription session. Use start to begin transcribing with configuration options, stop to end an active session, or summarize to request an on-demand AI summary mid-session.
start
stop
summarize
action.start
objectRequired
Start a live transcription session.
start.webhook
string
The URL to receive transcription events via HTTP POST. When live_events is enabled, partial results are sent as they occur. When ai_summary is enabled, a summary is sent when the session ends. Authentication can also be set in the URL in the format of username:password@url.
start.lang
stringRequired
The language to transcribe. See supported voices & languages.
start.live_events
booleanDefaults to false
Whether to enable live events.
start.ai_summary
booleanDefaults to false
Whether to enable automatic AI summarization. When enabled, an AI-generated summary of the conversation will be sent to your webhook when the transcription session ends.
start.speech_timeout
integerDefaults to 60000
The timeout for speech recognition in milliseconds. Minimum value: 1500.
start.vad_silence_ms
integerDefaults to 300 | 500
Voice activity detection silence time in milliseconds. Default depends on the speech engine: 300 for Deepgram, 500 for Google. Minimum value: 1.
start.vad_thresh
integerDefaults to 400
Voice activity detection threshold. Range: 0 to 1800.
start.debug_level
integerDefaults to 0
Debug level for logging.
start.direction
string[]Required
The direction of the call that should be transcribed. Possible values: remote-caller, local-caller.
start.speech_engine
stringDefaults to deepgram
The speech recognition engine to use. Possible values: deepgram, google.
start.ai_summary_prompt
string
The AI prompt that instructs how to summarize the conversation when ai_summary is enabled. This prompt is sent to an AI model to guide how it generates the summary.
Example: “Summarize the key points and action items from this conversation.”
Examples
Start
Stop
Summarize
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- live_transcribe:
action:
start:
webhook: 'https://example.com/webhook'
lang: en
live_events: true
direction:
- remote-caller
- local-caller
speech_engine: deepgramlive_translate
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Start live translation of the call. The translation will be sent to the specified webhook URL.
Properties
live_translate
objectRequired
An object that accepts the following properties.
live_translate.action
string | objectRequired
The action to perform. See actions below.
Actions
The action property controls the translation session. Use start to begin translating with configuration options, stop to end an active session, summarize to request an on-demand AI summary mid-session, or inject to insert a translated message into the conversation.
start
stop
summarize
inject
action.start
objectRequired
Start a live translation session.
start.webhook
string
The URL to receive translation events via HTTP POST. When live_events is enabled, partial results are sent as they occur. When ai_summary is enabled, summaries in both languages are sent when the session ends. Authentication can also be set in the URL in the format of username:password@url.
start.from_lang
stringRequired
The language to translate from. See supported voices & languages.
start.to_lang
stringRequired
The language to translate to. See supported voices & languages.
start.from_voice
stringDefaults to elevenlabs.josh
The TTS voice to use for the source language. See supported voices & languages.
start.to_voice
stringDefaults to elevenlabs.josh
The TTS voice to use for the target language. See supported voices & languages.
start.filter_from
string
Translation filter to apply to the source language direction. Adjusts the tone or style of translated speech.
Preset values: polite (removes insults, maintains sentiment), rude (adds insults, maintains sentiment), professional (removes slang), shakespeare (iambic pentameter), gen-z (Gen-Z slang and expressions).
For custom filters, use the prompt: prefix (e.g., prompt:Use formal business language).
start.filter_to
string
Translation filter to apply to the target language direction. Adjusts the tone or style of translated speech.
Preset values: polite, rude, professional, shakespeare, gen-z.
For custom filters, use the prompt: prefix.
start.live_events
booleanDefaults to false
Whether to enable live events.
start.ai_summary
booleanDefaults to false
Whether to enable automatic AI summarization. When enabled, AI-generated summaries in both languages will be sent to your webhook when the translation session ends.
start.speech_timeout
integerDefaults to 60000
The timeout for speech recognition in milliseconds. Minimum value: 1500.
start.vad_silence_ms
integerDefaults to 300 | 500
Voice activity detection silence time in milliseconds. Default depends on the speech engine: 300 for Deepgram, 500 for Google. Minimum value: 1.
start.vad_thresh
integerDefaults to 400
Voice activity detection threshold. Range: 0 to 1800.
start.debug_level
integerDefaults to 0
Debug level for logging.
start.direction
string[]Required
The direction of the call that should be translated. Possible values: remote-caller, local-caller.
start.speech_engine
stringDefaults to deepgram
The speech recognition engine to use. Possible values: deepgram, google.
start.ai_summary_prompt
string
The AI prompt that instructs how to summarize the conversation when ai_summary is enabled. This prompt is sent to an AI model to guide how it generates the summary.
Action usage context
| Action | Call start | Live call |
|---|---|---|
start | ✅ Primary use | ✅ Can start mid-call |
stop | ❌ No session to stop | ✅ Designed for this |
summarize | ❌ No content to summarize | ✅ Designed for this |
inject | ❌ No session exists | ✅ Designed for this |
Call start: The initial SWML document returned when a call first arrives.
Live call: Actions sent to active calls via the Call Commands REST API or SWML sections executed via transfer or execute during a call.
ai_summary vs summarize action
ai_summary: true(instart): Automatically generates summary when session endssummarizeaction: On-demand summary during an active session
Examples
Start
Stop
Summarize
Inject
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- live_translate:
action:
start:
webhook: 'https://example.com/webhook'
from_lang: en-US
to_lang: es-ES
from_voice: elevenlabs.josh
to_voice: elevenlabs.josh
live_events: true
direction:
- remote-caller
- local-caller
speech_engine: deepgrampay
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Enable secure payment processing during voice calls. When implemented in your voice application, it manages the entire payment flow, collecting card details from the caller via DTMF, then POSTing them to a payment_connector_url you host. Your server is responsible for charging the card through your payment processor (Stripe, Braintree, etc.) and returning the result to SignalWire.
Transaction Types
The pay method supports two primary transaction types: charges and tokenization.
Charges
When you need to process a payment right away, use a charge transaction. This collects the payment details and processes the transaction in real-time.
YAMLJSON
version: 1.0.0
sections:
main:
- pay:
charge_amount: "25.00"
payment_connector_url: "https://example.com/process"Setting any positive value for charge_amount initiates a charge transaction.
Tokenization
Tokenization allows you to securely store payment information for future use. Instead of processing a payment immediately, it generates a secure token that represents the payment method. To initiate a tokenization transaction, either pass charge_amount as 0 or omit the charge_amount attribute entirely.
The token is provided and stored by your payment processor and can be used for future transactions without requiring customers to re-enter their payment details. Note that this behavior may vary depending on the payment processor you are using.
YAMLJSON
version: 1.0.0
sections:
main:
- pay:
charge_amount: "0"
payment_connector_url: "https://example.com/process"Properties
pay
objectRequired
An object that accepts the following properties.
pay.payment_connector_url
stringRequired
The URL to make POST requests with all the gathered payment details. This URL processes the final payment transaction and returns the results in the response. See payment_connector_url details below.
pay.charge_amount
string
The amount to charge against payment method passed in the request. Float value with no currency prefix passed as string.
pay.currency
stringDefaults to usd
Uses the ISO 4217 currency code of the charge amount.
pay.description
string
Custom description of the payment provided in the request.
pay.input
stringDefaults to dtmf
The method of how to collect the payment details. Currently only dtmf mode is supported.
While entering a value (card number, expiration date, security code, or postal code), the caller can press # to submit the entry immediately instead of waiting for the timeout. Pressing * cancels the payment, and pay_result becomes caller-interrupted-with-star.
pay.language
stringDefaults to en-US
Language to use for prompts being played to the caller by the pay method. Supported languages are listed in the Voice and Languages page.
pay.max_attempts
integerDefaults to 1
Number of times the pay method will retry to collect payment details.
pay.min_postal_code_length
integerDefaults to 0
The minimum length of the postal code the user must enter.
pay.parameters
object[]
Array of parameter objects to pass to your payment processor. Enables you to pass custom parameters or include additional payment details not covered by the standard pay attributes.
parameters[].name
stringRequired
The identifier for your custom parameter. This will be the key in the parameters object.
parameters[].value
stringRequired
The value associated with the parameter. This will be the value in the parameters object.
pay.payment_method
string
Indicates the payment method which is going to be used in this payment request. Currently only credit-card is supported.
pay.postal_code
boolean|stringDefaults to true
Takes true, false or real postcode (if it’s known beforehand) to let pay method know whether to prompt for postal code.
pay.prompts
object[]
Array of prompt objects for customizing the audio prompts played during different stages of the payment process. If no custom prompts are provided, default prompts will be used. If custom prompts are provided but certain payment steps are omitted, the system will fall back to the default prompts for those steps.
prompts[].for
stringRequired
The payment step this prompt is for. Possible values:
payment-card-number- Collect the payment card number. Default: “Please enter your credit card number”expiration-date- Collect the expiration date. Default: “Please enter your credit card’s expiration date. 2 digits for the month and 2 digits for the year”security-code- Collect the security code. Default: “Please enter your credit card’s security code. It’s the 3 digits located on the back of your card”postal-code- Collect the postal code. Default: “Please enter your billing postal code”payment-processing- Played during payment processing. Default: “Payment processing. Please wait”payment-completed- Played when payment succeeds. Default: “Payment completed. Thank you”payment-failed- Played when payment fails. Default: “Payment failed”payment-canceled- Played when payment is cancelled. Default: “Payment canceled”
prompts[].actions
object[]Required
Array of action objects to execute for this prompt. Each action can either play an audio file or speak a phrase using text-to-speech.
actions[].type
stringRequired
The action to perform. Allowed values: Say (text-to-speech), Play (play an audio file).
actions[].phrase
stringRequired
When type is Say, the text to be spoken. When type is Play, the URL to the audio file.
prompts[].attempts
string
Which payment attempt(s) this prompt applies to. The value increments when a payment fails. Use a single number (e.g., "1") or space-separated numbers (e.g., "2 3") to target specific attempts.
prompts[].card_type
string
Space-separated list of card types this prompt applies to. Allowed values: visa, mastercard, amex, maestro, discover, optima, jcb, diners-club.
prompts[].error_type
string
Space-separated list of error types this prompt applies to. Possible values:
timeout- User input timeoutinvalid-card-number- Failed card validationinvalid-card-type- Unsupported card typeinvalid-date- Invalid expiration dateinvalid-security-code- Invalid CVV formatinvalid-postal-code- Invalid postal code formatsession-in-progress- Concurrent session attemptinvalid-bank-routing-number- Invalid bank routing numberinvalid-bank-account-number- Invalid bank account numberinput-matching-failed- Input matching failedcard-declined- Payment declined
pay.security_code
booleanDefaults to true
Takes true or false to let pay method know whether to prompt for security code.
pay.status_url
string
The URL to send requests for each status change during the payment process. See the status_url request body section for more details.
pay.timeout
integerDefaults to 5
Limit in seconds that pay method waits for the caller to press another digit before moving on to validate the digits captured. The caller can press # to finish an entry immediately rather than waiting for this timeout.
pay.token_type
stringDefaults to reusable
Whether the payment is a one off payment or re-occurring. Allowed values: one-time, reusable.
pay.valid_card_types
stringDefaults to visa mastercard amex
List of payment cards allowed to use in the requested payment process, separated by a space. Allowed values: visa, mastercard, amex, maestro, discover, jcb, diners-club.
pay.voice
stringDefaults to woman
Text-to-speech voice to use. Supported voices are listed in the Voice and Languages page.
status_url request body
The status_url parameter is used to send requests for each status change during the payment process.
event_type
string
The type of event that is being reported. Will always be calling.call.pay.
event_channel
string
The channel that the event is being reported from.
timestamp
number
The timestamp of the event in the format of unix timestamp.
project_id
string
The project ID the event is being reported from.
space_id
string
The Space ID the event is being reported from.
params
object
An object containing the parameters of the event.
params.status_url
string
The URL to send requests to for each status change during the payment process.
params.status_url_method
string
The method to use for the requests to the status_url.
params.for
string
The status of the payment process.
params.error_type
string
The error type of the payment process.
params.payment_method
string
The payment method of the payment process.
params.payment_card_number
string
The payment card number of the payment process.
params.payment_card_type
string
The payment card type of the payment process.
params.security_code
string
The security code of the payment process.
params.expiration_date
string
The expiration date of the payment process.
params.payment_card_postal_code
string
The payment card postal code of the payment process.
params.control_id
string
The control ID of the payment process.
params.call_id
string
The call ID of the payment process.
params.node_id
string
The node ID of the payment process.
Request format
Below is an example of the request body that will be sent to the status_url.
{
"event_type": "calling.call.pay",
"event_channel": "swml:XXXX-XXXX-XXXX-XXXX-XXXX",
"timestamp": 1743707517.12267,
"project_id": "XXXX-XXXX-XXXX-XXXX-XXXX",
"space_id": "XXXX-XXXX-XXXX-XXXX-XXXX",
"params": {
"status_url": "https://example.com/status",
"status_url_method": "POST",
"for": "payment-completed",
"error_type": "",
"payment_method": "credit-card",
"payment_card_number": "************1234",
"payment_card_type": "visa",
"security_code": "***",
"expiration_date": "1225",
"payment_card_postal_code": "23112",
"control_id": "XXXX-XXXX-XXXX-XXXX-XXXX",
"call_id": "XXXX-XXXX-XXXX-XXXX-XXXX",
"node_id": "XXXX-XXXX-XXXX-XXXX-XXXX"
}
}payment_connector_url
SignalWire sends a POST request to the payment_connector_url once all required payment information has been collected from the caller. Your endpoint processes the payment and returns the result.
Request body
transaction_id
string
Unique identifier for the transaction.
method
string
The payment method (e.g., credit-card).
cardnumber
string
The card number collected from the caller.
cvv
string
The card security code.
expiry_month
string
The card expiry month (e.g., 12).
expiry_year
string
The card expiry year (e.g., 99).
postal_code
string
The billing postal code.
chargeAmount
string
The amount to charge.
currency_code
string
The ISO 4217 currency code.
token_type
string
The token type (one-time or reusable).
description
string
The payment description provided in the pay method.
Request example
{
"transaction_id": "8c9d14d5-52ae-4e2e-b880-a14e6e1cda7d",
"method": "credit-card",
"cardnumber": "************1234",
"cvv": "***",
"postal_code": "123456",
"description": "Payment description",
"chargeAmount": "10.55",
"token_type": "reusable",
"expiry_month": "12",
"expiry_year": "99",
"currency_code": "usd"
}Response format
Your endpoint must respond with JSON. The format varies depending on the transaction type.
Successful charge
Successful tokenization
Failed charge
Failed tokenization
Return a 200 HTTP status code with:
charge_id
string
A unique identifier for the successful transaction.
error_code
null
Must be null for successful transactions.
error_message
null
Must be null for successful transactions.
{
"charge_id": "ch_123456789",
"error_code": null,
"error_message": null
}Error responses will trigger the payment-failed prompt in your SWML application.
Variables
When the payment process completes, the following variables are set in the vars scope. Access them in subsequent SWML instructions using the ${variable} syntax (e.g., ${pay_result}).
pay_result
string
The overall outcome of the payment process. Possible values:
success- The payment was successful.too-many-failed-attempts- The caller exceeded themax_attemptslimit.payment-connector-error- The payment connector returned an error.caller-interrupted-with-star- The caller pressed the*key to cancel.relay-pay-stop- The payment was stopped via theSTOPcommand.caller-hung-up- The caller hung up before completing payment.validation-error- Card details failed validation.internal-error- An internal system error occurred.
pay_payment_results
object
Detailed payment results returned by the payment processor, including card details, tokens, and any error information. Access nested properties with dot notation (e.g., ${pay_payment_results.payment_token}).
pay_payment_results.payment_token
string
Token generated by the payment processor. Use this for future transactions when using tokenization (charge_amount: 0).
pay_payment_results.payment_confirmation_code
string
Confirmation code returned by the payment processor for a successful charge.
pay_payment_results.payment_card_number
string
Redacted card number (e.g., ************1234).
pay_payment_results.payment_card_type
string
Type of card used (e.g., visa, mastercard, amex).
pay_payment_results.payment_card_expiration_date
string
Card expiration date (e.g., 1225 for December 2025).
pay_payment_results.payment_card_security_code
string
Redacted security code (e.g., ***).
pay_payment_results.payment_card_postal_code
string
Postal code entered by the caller.
pay_payment_results.payment_error
string
Error description if the payment failed. Empty on success.
pay_payment_results.payment_error_code
string
Error code if the payment failed. Empty on success.
pay_payment_results.connector_error
object
Error object from the payment connector. Only present when the connector returns an error.
connector_error.code
string
Connector-specific error code.
connector_error.message
string
Connector-specific error message.
Examples
Simple payment collection
YAMLJSON
version: 1.0.0
sections:
main:
- pay:
charge_amount: '20.45'
payment_connector_url: "https://example.com/process"
status_url: "https://example.com/status"Basic tokenization
YAMLJSON
version: 1.0.0
sections:
main:
- pay:
token_type: "reusable"
charge_amount: '0'
payment_connector_url: "https://example.com/tokenize"Retry logic
YAMLJSON
version: 1.0.0
sections:
main:
- pay:
charge_amount: '75.00'
payment_connector_url: "https://example.com/process"
max_attempts: 3
timeout: 10Custom parameters
YAMLJSON
version: 1.0.0
sections:
main:
- pay:
charge_amount: "10.00"
payment_connector_url: "https://example.com/process"
parameters:
- name: "my_custom_parameter_1"
value: "my_custom_value_1"International payment with custom prompts
YAMLJSON
version: 1.0.0
sections:
main:
- pay:
charge_amount: '100.00'
payment_connector_url: "https://example.com/process"
currency: "pln"
language: "pl-PL"
prompts:
- for: "payment-card-number"
actions:
- type: "Say"
phrase: "Witamy w telefonicznym systemie płatności"
- type: "Say"
phrase: "Proszę wprowadzić numer karty płatniczej"
- for: "payment-card-number"
error_type: "invalid-card-number timeout invalid-card-type"
actions:
- type: "Say"
phrase: "Wprowadziłeś błędny numer karty płatniczej. Proszę spróbować ponownie"
- for: "payment-completed"
actions:
- type: "Say"
phrase: "Płatność zakończona powodzeniem"Handling payment results
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- pay:
charge_amount: '25.00'
payment_connector_url: "https://example.com/process"
- cond:
- when: "pay_result == 'success'"
then:
- play:
url: 'say: Payment successful. Your confirmation code is ${pay_payment_results.payment_confirmation_code}.'
- else:
- play:
url: 'say: Payment was not completed. Please try again later.'play
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Play file(s), ringtones, speech or silence.
Properties
play
objectRequired
An object that accepts the following properties. Accepts either a single URL or multiple URLs. See audio source below.
play.status_url
string
HTTP or HTTPS URL to deliver play status events. Learn more about status callbacks.
Audio source
The play object accepts one of the following properties to specify the audio source:
Single URL (url)
Multiple URLs (urls)
play.url
stringRequired
A single playable sound. Authentication can also be set in the url in the format of username:password@url.
Playable sounds
Audio file from a URL
To play an audio file from the web, simply list that audio’s URL. Specified audio file should be accessible with an HTTP GET request. HTTP and HTTPS URLs are supported. Authentication can also be set in the url in the format of username:password@url.
Example: https://cdn.signalwire.com/swml/audio.mp3
Ring
To play the standard ringtone of a certain country, use ring:[duration:]<country code>.
The total duration can be specified in seconds as an optional second parameter. When left unspecified, it will ring just once. The country code must be specified. It has values like us for United States, it for Italy. For the list of available country codes, refer to the supported ringtones section below. For example:
ring:us - ring with the US ringtone once ring:3.2:uk - ring with the UK ringtone for 3.2 seconds
Speak using a TTS
To speak using a TTS, use say:<text to speak>. When using say, you can optionally set say_voice, say_language and say_gender in the play or prompt properties. For the list of useable voices and languages, refer to the supported voices and languages section below.
Silence
To be silent for a certain duration, use silence:<duration>. The duration is in seconds.
Variables
Read by the method:
say_voice:(in) - Optional voice to use for text to speech.say_language:(in) - Optional language to use for text to speech.say_gender:(in) - Optional gender to use for text to speech.
Possible values for voice, language, and ringtone
Supported voices and languages
To learn more about the supported voices and languages, please visit the Supported Voices and Languages Documentation.
Supported ring tones
| Parameter | |
|---|---|
urls.ring | Available values are the following ISO 3166-1 alpha-2 country codes: at, au, bg, br, be, ch, cl, cn, cz, de, dk, ee, es, fi, fr, gr, hu, il, in, it, lt, jp, mx, my, nl, no, nz, ph, pl, pt, ru, se, sg, th, uk, us, us-old, tw, ve, za. |
StatusCallbacks
A POST request will be sent to status_url with a JSON payload like the following:
event_type
string
The type of event. Always calling.call.play for this method.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing playback-specific parameters.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.control_id
string
The control ID for this play operation.
params.state
string
The current playback state. Valid values:playing, paused, finished, error.
Raw JSON example
{
"event_type": "calling.call.play",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"control_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"state": "finished"
}
}Examples
Playing a single URL
YAMLJSON
version: 1.0.0
sections:
main:
- play:
url: 'https://cdn.signalwire.com/swml/audio.mp3'Playing multiple URLs
YAMLJSON
version: 1.0.0
sections:
main:
- play:
urls:
- 'https://cdn.signalwire.com/swml/audio.mp3'
- 'say: this is something to say'
- 'silence: 3.0'
- 'ring:10.0:us'Playing multiple URLs with volume adjusted
YAMLJSON
version: 1.0.0
sections:
main:
- play:
volume: 20
urls:
- 'https://cdn.signalwire.com/swml/audio.mp3'
- 'say: this is something to say'
- 'silence: 3.0'
- 'ring:10.0:us'Specifying a voice to use for speaking
Globally
YAMLJSON
version: 1.0.0
sections:
main:
- set:
say_voice: gcloud.en-US-Neural2-A
- play:
url: 'say:Hi, do I sound different?'
- play:
url: 'say:I don''t, do I?'For just one instance
YAMLJSON
version: 1.0.0
sections:
main:
- play:
url: 'say:Hi, do I sound different?'
say_voice: gcloud.en-US-Neural2-A
- play:
url: 'say:I was down with the flu'prompt
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Play a prompt and wait for input. The input can be received either as digits from the keypad, or from speech, or both depending on what properties are set.
Properties
prompt
objectRequired
An object that accepts the following properties.
prompt.play
string | string[]Required
Either a playable sound or an array of playable sounds
prompt.volume
numberDefaults to 0
Volume gain to apply to played URLs. Allowed values from -40.0 to 40.0.
prompt.say_voice
stringDefaults to Polly.Salli
Voice to use with say: for text to speech
prompt.say_language
stringDefaults to en-US
Language to use with say: for text to speech
prompt.say_gender
stringDefaults to female
Gender to use with say: for text to speech
prompt.max_digits
integerDefaults to 1
Number of digits to collect
prompt.terminators
string
Digits that terminate digit collection
prompt.digit_timeout
numberDefaults to 5.0 seconds
Time in seconds to wait for next digit
prompt.initial_timeout
numberDefaults to 5.0 seconds
Time in seconds to wait for start of input
prompt.speech_timeout
number
Max time in seconds to wait for speech result
prompt.speech_end_timeout
number
Time in seconds to wait for end of speech utterance
prompt.speech_language
string
Language to detect speech in
prompt.speech_hints
string[]
Expected words to match
prompt.speech_engine
string
The engine selected for speech recognition. The engine must support the specified language. Valid values: Google, Google.V2, Deepgram. Default is not set (SignalWire picks the engine).
prompt.status_url
string
HTTP or HTTPS URL to deliver prompt status events. Learn more about status callbacks.
By default, only digit input via keypad is enabled. When at least one speech input based parameter is set (speech_timeout, speech_end_timeout, speech_language or speech_hints), speech input is enabled and digit input is disabled.
To enable speech and digit based input collection at once, set at least one speech input parameter and at least one digit input based parameter (max_digits, terminators, digit_timeout, and initial_timeout).
Playable sounds
Audio file from a URL
To play an audio file from the web, simply list that audio’s URL. Specified audio file should be accessible with an HTTP GET request. HTTP and HTTPS URLs are supported. Authentication can also be set in the url in the format of username:password@url.
Example: https://cdn.signalwire.com/swml/audio.mp3
Ring
To play the standard ringtone of a certain country, use ring:[duration:]<country code>.
The total duration can be specified in seconds as an optional second parameter. When left unspecified, it will ring just once. The country code must be specified. It has values like us for United States, it for Italy. For the list of available country codes, refer to the supported ringtones section below. For example:
ring:us - ring with the US ringtone once ring:3.2:uk - ring with the UK ringtone for 3.2 seconds
Speak using a TTS
To speak using a TTS, use say:<text to speak>. When using say, you can optionally set say_voice, say_language and say_gender in the play or prompt properties. For the list of useable voices and languages, refer to the supported voices and languages section below.
Silence
To be silent for a certain duration, use silence:<duration>. The duration is in seconds.
Variables
Read by the method:
- say_voice: (in) - optional voice to use for text to speech.
- say_language: (in) - optional language to use for text to speech.
- say_gender: (in) - optional gender to use for text to speech.
Possible values for voice, language, and ringtone
Supported voices and languages
To learn more about the supported voices and languages, please visit the Supported Voices and Languages Documentation.
Supported ring tones
| Parameter | |
|---|---|
urls.ring | Available values are the following ISO 3166-1 alpha-2 country codes: at, au, bg, br, be, ch, cl, cn, cz, de, dk, ee, es, fi, fr, gr, hu, il, in, it, lt, jp, mx, my, nl, no, nz, ph, pl, pt, ru, se, sg, th, uk, us, us-old, tw, ve, za. |
Set by the method
- prompt_result: (out) -
failed,no_input,match_speech,match_digits, orno_match. - prompt_value: (out) - the digits or utterance collected.
- prompt_digit_terminator: (out) - digit terminator collected, if any.
- prompt_speech_confidence: (out) - speech confidence measured, if any.
StatusCallbacks
A POST request will be sent to status_url with a JSON payload like the following:
event_type
string
The type of event. Always calling.call.collect for this method.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing prompt-specific parameters.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.control_id
string
The control ID for this prompt operation.
params.result
object
The collection result details.
result.type
string
The type of input collected. Valid values:digit, speech, no_input, no_match, start_of_input, finished, error.
result.params.digits
string
The DTMF digits collected (when type is digit).
result.params.terminator
string
The terminator digit that ended collection (when type is digit).
result.params.text
string
The recognized speech text (when type is speech).
result.params.confidence
number
The speech recognition confidence score (when type is speech).
params.final
boolean
Whether this is the final result in a continuous collect session. Only present when partial_results is enabled. true indicates collection has ended; false indicates more results may follow.
params.state
string
The current collection state. Only present when continuous collect is enabled. Valid values:collecting, finished, error.
Raw JSON example
Digit input:
{
"event_type": "calling.call.collect",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"control_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"result": {
"type": "digit",
"params": {
"digits": "1234",
"terminator": "#"
}
}
}
}Speech input:
{
"event_type": "calling.call.collect",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"control_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"result": {
"type": "speech",
"params": {
"text": "one",
"confidence": 0.95
}
}
}
}Examples
The play method also has examples related to playing sounds from URLs. The interface for playing sounds for play and prompt is identical.
Play prompt and wait for digit press
YAMLJSON
version: 1.0.0
sections:
main:
- prompt:
play: 'say:Input a number'
- switch:
variable: prompt_value
default:
- play:
url: 'say:You didn''t press one'
- transfer:
dest: main
case:
'1':
- play:
url: 'say:You pressed one'Using terminators
YAMLJSON
version: 1.0.0
sections:
main:
- prompt:
play: 'say:PIN number please'
max_digits: 10
terminators: '*#5'
- play:
url: 'say: ${prompt_value} was terminated by ${prompt_digit_terminator}'Play prompt and wait for digit or speech
YAMLJSON
version: 1.0.0
sections:
main:
- prompt:
play: 'https://example.com/press_or_say_one.wav'
speech_language: en-US
max_digits: 1
speech_hints:
- one
- two
- three
- four
- five
- six
- seven
- eight
- nine
- switch:
variable: prompt_value
default:
- play:
url: 'https://example.com/bad_input.wav'
- transfer:
dest: main
case:
'1':
- transfer:
dest: 'https://example.com/sales.swml'
one:
- transfer:
dest: 'https://example.com/sales.swml'Play prompt and collect digits, then pass the data to an external action
YAMLJSON
version: 1.0.0
sections:
main:
- prompt:
play: 'https://example.com/menu.wav'
- transfer:
dest: 'https://example.com/post_next_menu'In this case, the URL listed in transfer will be sent an HTTP POST request with all the out variables (like prompt_value) already set. For more details on this behavior, refer to transfer statement’s documentation.
receive_fax
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Receive a fax being delivered to this call.
Properties
receive_fax
objectRequired
An object that accepts the following properties.
receive_fax.status_url
string
HTTP or HTTPS URL to deliver receive fax status events. Learn more about status callbacks.
Variables
Set by the method:
- receive_fax_document: (out) URL of received document.
- receive_fax_identity: (out) identity of this fax station.
- receive_fax_remote_identity: (out) identity of the sending fax station.
- receive_fax_pages: (out) number of pages received.
- receive_fax_result_code: (out) fax status code.
- receive_fax_result_text: (out) description of fax status code.
- receive_fax_result: (out)
success|failed.
StatusCallbacks
A POST request will be sent to status_url with a JSON payload like the following:
event_type
string
The type of event. Always calling.call.fax for this method.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing fax-specific parameters.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.control_id
string
The control ID for this fax operation.
params.fax
object
Fax result details.
fax.type
string
The type of fax operation. Always finished.
fax.params.direction
string
The direction of the fax (receive).
fax.params.identity
string
The identity of this fax station.
fax.params.remote_identity
string
The identity of the sending fax station.
fax.params.document
string
URL of the received fax document.
fax.params.pages
number
Number of pages received.
fax.params.success
boolean
Whether the fax was received successfully.
fax.params.result
number
The numeric result code of the fax operation (e.g., 0 for success).
fax.params.result_text
string
A description of the fax result (e.g., OK).
fax.params.format
string
The format of the fax document. Always "pdf".
Page progress events
A separate callback is sent for each page as the fax progresses:
fax.type
string
Always "page" for page progress events.
fax.params.direction
string
The direction of the fax.
fax.params.number
number
The page number that was just processed.
Raw JSON example
{
"event_type": "calling.call.fax",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"control_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"fax": {
"type": "finished",
"params": {
"direction": "receive",
"identity": "+15551231234",
"remote_identity": "+15553214321",
"document": "https://your-space.signalwire.com/api/v1/faxes/fax-uuid/download",
"pages": 3,
"success": true,
"result": 0,
"result_text": "OK",
"format": "pdf"
}
}
}
}Examples
Receive a fax and post a result to a webhook
YAMLJSON
version: 1.0.0
sections:
main:
- receive_fax: {}
- execute:
dest: 'https://<NGROK UUID>.ngrok-free.app'In this example, when a fax is received, a POST request will be sent to the URL with all the fax related variables (like receive_fax_document) already set. Refer to the execute statement’s documentation for more details on this behavior.
record
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Record the call audio in the foreground pausing further SWML execution until recording ends. Use this, for example, to record voicemails. To record calls in the background in a non-blocking fashion, use the record_call
Properties
record
objectRequired
An object that accepts the following properties.
record.stereo
booleanDefaults to false
Whether to record in stereo mode
record.format
stringDefaults to wav
Format ("wav", "mp3", or "mp4")
record.direction
stringDefaults to speak
Direction of the audio to record: "speak" for what party says, "listen" for what party hears
record.terminators
stringDefaults to #
String of digits that will stop the recording when pressed
record.beep
booleanDefaults to false
Whether to play a beep before recording
record.input_sensitivity
numberDefaults to 44.0
How sensitive the recording voice activity detector is to background noise. A larger value is more sensitive. Allowed values from 0.0 to 100.0.
record.initial_timeout
numberDefaults to 4.0 seconds
How long, in seconds, to wait for speech to start?
record.end_silence_timeout
numberDefaults to 5.0 seconds
How much silence, in seconds, will end the recording?
record.max_length
number
Maximum length of the recording in seconds.
record.status_url
string
HTTP or HTTPS URL to deliver record status events. Learn more about status callbacks.
Variables
Set by the method:
- record_url: (out) the URL of the newly created recording.
- record_result: (out)
success|failed.
StatusCallbacks
A POST request will be sent to status_url with a JSON payload like the following:
event_type
string
The type of event. Always calling.call.record for this method.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing recording-specific parameters.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.control_id
string
The control ID for this record operation.
params.state
string
The current recording state. Valid values:recording, paused, finished, no_input, error.
params.url
string
URL to download the recording.
params.duration
number
Recording duration in seconds. Present when state is finished or no_input.
params.size
number
Recording file size in bytes. Present when state is finished or no_input.
params.recording_id
string
The unique identifier for the recording. Present when available.
params.start_time
number
Unix timestamp (seconds, float) when the recording started. Present when the recording has ended.
params.end_time
number
Unix timestamp (seconds, float) when the recording ended. Present when the recording has ended.
params.pause_behavior
string
How paused recording handles audio. Only present when state is paused. Valid values:silence, skip.
params.record
object
Recording configuration details.
record.audio.format
string
Recording format. Valid values:wav, mp3.
record.audio.direction
string
Direction of the audio recorded: speak or listen.
record.audio.stereo
boolean
Whether the recording was made in stereo mode.
Raw JSON example
{
"event_type": "calling.call.record",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"state": "finished",
"control_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"url": "https://your-space.signalwire.com/api/v1/recordings/rec-uuid/download",
"duration": 15,
"size": 248320,
"recording_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"start_time": 1640000000.123,
"end_time": 1640000015.623,
"record": {
"audio": {
"format": "wav",
"direction": "speak",
"stereo": false
}
}
}
}Examples
Record some audio and play it back
YAMLJSON
version: 1.0.0
sections:
main:
- play:
url: 'say:Start speaking after the beep. Press hash to end recording.'
- record:
end_silence_timeout: 3
beep: true
- play:
url: 'say:Recording ${record_result}. Playing back recording:'
- play:
url: '${record_url}'record_call
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Record call in the background. Unlike the record method, the record_call method will start the recording and continue executing the SWML script while allowing the recording to happen in the background. To stop call recordings started with record_call, use the stop_call_record method.
Properties
record_call
objectRequired
An object that accepts the following properties.
record_call.control_id
stringDefaults to Auto-generated, saved to record_control_id variable
Identifier for this recording, to use with stop_record_call
record_call.stereo
booleanDefaults to false
Whether to record in stereo mode
record_call.format
stringDefaults to wav
Format ("wav", "mp3", or "mp4")
record_call.direction
stringDefaults to both
Direction of the audio to record: "speak" for what party says, "listen" for what party hears, "both" for what the party hears and says
record_call.terminators
string
String of digits that will stop the recording when pressed. Default is empty (no terminators).
record_call.beep
booleanDefaults to false
Whether to play a beep before recording
record_call.input_sensitivity
numberDefaults to 44.0
How sensitive the recording voice activity detector is to background noise? A larger value is more sensitive. Allowed values from 0.0 to 100.0.
record_call.initial_timeout
numberDefaults to 0
How long, in seconds, to wait for speech to start?
record_call.end_silence_timeout
numberDefaults to 0
How much silence, in seconds, will end the recording?
record_call.max_length
number
Maximum length of the recording in seconds.
record_call.status_url
string
HTTP or HTTPS URL to deliver record status events. Learn more about status callbacks.
Variables
Set by the method:
- record_call_url: (out) the URL of the newly started recording.
- record_call_result: (out)
success|failed. - record_control_id: (out) control ID of this recording.
StatusCallbacks
A POST request will be sent to status_url with a JSON payload like the following:
event_type
string
The type of event. Always calling.call.record for this method.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing recording-specific parameters.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.control_id
string
The control ID for this record operation.
params.state
string
The current recording state. Valid values:recording, paused, finished, no_input, error.
params.record
object
Recording result details (present when state is finished).
record.url
string
URL to download the recording.
record.duration
number
Recording duration in seconds.
record.size
number
Recording file size in bytes.
record.format
string
Recording format. Valid values:wav, mp3.
Raw JSON example
{
"event_type": "calling.call.record",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"control_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"state": "finished",
"record": {
"url": "https://your-space.signalwire.com/api/v1/recordings/rec-uuid/download",
"duration": 15.5,
"size": 248320,
"format": "wav"
}
}
}Examples
Start an MP3 recording of the call
YAMLJSON
version: 1.0.0
sections:
main:
- record_call:
format: mp3Record and play back
Record both sides of the conversation:
YAMLJSON
version: 1.0.0
sections:
main:
- record_call:
beep: true
terminators: '#'
- play:
urls:
- 'say:Leave your message now'
- 'silence:10'
- stop_record_call: {}
- play:
urls:
- 'say:Playing back'
- '${record_call_url}'Record only the speaker’s side
YAMLJSON
version: 1.0.0
sections:
main:
- record_call:
beep: true
direction: speak
- play:
urls:
- 'say:Leave your message now'
- 'silence:10'
- stop_record_call: {}
- play:
urls:
- 'say:Playing back'
- '${record_call_url}'request
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Send a GET, POST, PUT, or DELETE request to a remote URL.
Properties
request
objectRequired
An object containing the following properties.
request.url
stringRequired
URL to send the HTTPS request to. Authentication can also be set in the url in the format of username:password@url.
request.method
stringRequired
Request type. GET|POST|PUT|DELETE
request.headers
object
Object containing HTTP headers to set. Valid header values are Accept, Authorization, Content-Type, Range, and custom X- headers
request.body
string | object
Request body. Content-Type header should be explicitly set, but if not set, the most likely type will be set based on the first non-whitespace character.
request.connect_timeout
numberDefaults to 0
Maximum time in seconds to wait for a connection. Default is 0 (no timeout).
request.timeout
numberDefaults to 0
Maximum time in seconds to wait for a response. Default is 0 (no timeout).
request.save_variables
booleanDefaults to false
Store parsed JSON response as variables
Variables
Set by the method:
- request_url: (out) URL the request was sent to.
- request_result: (out)
success|failed. - return_value: (out) The same value as the
request_result. - request_response_code: (out) HTTP response code from the request.
- request_response_headers.
<header name lowercase>: (out) HTTP response headers. Header names should be normalized to lowercase and trimmed of whitespace. A maximum of 64 headers are saved. Ex:${request_response_headers.content-type}. - request_response_body: (out) Raw HTTP response body. This is limited to 64KB.
- request_response.
<object_field>: (out) Variables saved from the response ifsave_variablesis true and parsed as JSON.
For example, if the server responds with the following JSON:
{ "status": "created", "time": "2 seconds ago", "number": { "home": "n/a" } }The variables request_response.status, request_response.time, and request_response.number.home are set.
Examples
Making a GET Request
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- request:
url: 'https://jsonplaceholder.typicode.com/todos/1'
method: GET
save_variables: true
timeout: 10
- play:
url: 'say: the title is: ${request_response.title}'return
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Return from execute or exit script.
return
anyRequired
The return value.
Properties
No specific parameters. The value can be set to any type.
Variables
Set by the method:
- return_value:(out) Optional return value.
Examples
Return with optional value
YAMLJSON
version: 1.0.0
sections:
main:
- return: 1Return with multiple values
YAMLJSON
version: 1.0.0
sections:
main:
- execute:
dest: fn_that_returns
- play:
url: 'say: returned ${return_value[0].a}'
fn_that_returns:
- return:
- a: 1
- b: 2using the on_return parameter
YAMLJSON
version: 1.0.0
sections:
main:
- execute:
dest: fn_that_returns
on_return:
- play:
url: 'say: returned ${return_value}'
fn_that_returns:
- return: helloReturn with no value
YAMLJSON
version: 1.0.0
sections:
main:
- return: {}Additional examples are available in the introduction.
send_digits
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Send digit presses as DTMF tones.
send_digits
objectRequired
An object that accepts the following properties.
Properties
send_digits.digits
stringRequired
The digits to send. Valid values are 0123456789*#ABCDWw. Character W is a 1 second delay, and w is a 500 ms delay.
Variables
Set by the method:
- send_digits_result: (out)
success|failed
Examples
Send digits
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- send_digits:
digits: '012345'
- play:
url: 'say: ${send_digits_result}'send_fax
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Send a fax.
Properties
send_fax
objectRequired
An object that accepts the following properties.
send_fax.document
stringRequired
URL to the PDF document to fax
send_fax.header_info
string
Text to add to the fax header
send_fax.identity
stringDefaults to Calling party's caller ID number
Station identity to report
send_fax.status_url
string
HTTP or HTTPS URL to deliver send fax status events. Learn more about status callbacks.
Variables
Set by the method:
- send_fax_document: (out) URL of sent document.
- send_fax_identity: (out) identity of this fax station.
- send_fax_remote_identity: (out) identity of the receiving fax station.
- send_fax_pages: (out) number of pages sent.
- send_fax_result_code: (out) fax status code.
- send_fax_result_text: (out) description of fax status code.
- send_fax_result: (out)
success|failed.
StatusCallbacks
A POST request will be sent to status_url with a JSON payload like the following:
event_type
string
The type of event. Always calling.call.fax for this method.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing fax-specific parameters.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.control_id
string
The control ID for this fax operation.
params.fax
object
Fax result details.
fax.type
string
The type of fax operation. Always finished.
fax.params.direction
string
The direction of the fax (send).
fax.params.identity
string
The identity of this fax station.
fax.params.remote_identity
string
The identity of the receiving fax station.
fax.params.document
string
URL of the sent fax document.
fax.params.pages
number
Number of pages sent.
fax.params.success
boolean
Whether the fax was sent successfully.
fax.params.result
number
The numeric result code of the fax operation (e.g., 0 for success).
fax.params.result_text
string
A description of the fax result (e.g., OK).
fax.params.format
string
The format of the fax document. Always "pdf".
Page progress events
A separate callback is sent for each page as the fax progresses:
fax.type
string
Always "page" for page progress events.
fax.params.direction
string
The direction of the fax.
fax.params.number
number
The page number that was just processed.
Raw JSON example
{
"event_type": "calling.call.fax",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"control_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"fax": {
"type": "finished",
"params": {
"direction": "send",
"identity": "+15551231234",
"remote_identity": "+15553214321",
"document": "https://example.com/fax_to_send.pdf",
"pages": 3,
"success": true,
"result": 0,
"result_text": "OK",
"format": "pdf"
}
}
}
}Examples
Send a fax and post a result to a webhook
YAMLJSON
version: 1.0.0
sections:
main:
- send_fax:
document: https://example.com/fax_to_send.pdf
- execute:
dest: 'https://example.com/handle_outgoing_fax_result'send_sms
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Send an outbound message to a PSTN phone number.
Properties
send_sms
objectRequired
An object that accepts the following properties. Supports both SMS and MMS messages. See message types below for the properties specific to each type.
Message types
The send_sms object accepts the following properties depending on the message type:
SMS
MMS
send_sms.to_number
stringRequired
Phone number to send SMS message to in e.164 format
send_sms.from_number
stringRequired
Phone number SMS message will be sent from
send_sms.body
stringRequired
Body of the text message
send_sms.region
stringDefaults to Chosen based on account preferences or device location
Region of the world to originate the message from
send_sms.tags
string[]
Array of tags to associate with the message to facilitate log searches
send_sms.status_callback
string
URL to receive delivery status callbacks for the outbound message (e.g., queued, sent, delivered, failed). Default is not set. See Status callbacks below.
Variables
Set by the method:
- send_sms_result: (out)
success|failed.
Status callbacks
When status_callback is set, SignalWire sends an HTTP POST to that URL each time the outbound message transitions to a new state. Callback delivery is independent of SWML execution: the document continues as soon as the message is accepted, and delivery-state callbacks fire afterwards.
The callback uses the same payload as other outbound messages sent through SignalWire:
See the Message status callback webhook page for the full field reference and the list of possible status values.
Examples
SMS
MMS
Status callbacks
Send a text-only message:
YAMLJSON
version: 1.0.0
sections:
main:
- send_sms:
from_number: "+155512312345"
to_number: "+15555554321"
body: "Hi, I hope you're well."set
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Set script variables to the specified values. Variables set using set can be removed using unset.
set
objectRequired
An object that accepts user-defined key-value pairs.
Variables
Any variable can be set by this method.
Examples
Setting variables
YAMLJSON
version: 1.0.0
sections:
main:
- set:
num_var: 1
- play:
url: 'say: ${num_var}'
- set:
num_var: 2
- play:
url: 'say: ${num_var}'Setting multiple variables
YAMLJSON
version: 1.0.0
sections:
main:
- set:
items:
- drill bit
- drill
person: handyman
systems:
ventilation:
- inlet
- outlet
- fans
hr:
- lucy
- liam
- luke
- play:
url: 'say: The items ${items} will be used by ${person} to fix ${systems.ventilation}.'See Also
- Variables and Expressions: Complete reference for SWML variables, scopes, and syntax
- unset: Remove variables from the script
sip_refer
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Send SIP REFER to a SIP call.
Properties
sip_refer
objectRequired
An object that accepts the following properties.
sip_refer.to_uri
stringRequired
SIP URI to REFER to.
sip_refer.status_url
string
HTTP or HTTPS URL to deliver SIP REFER status events. Learn more about status callbacks.
sip_refer.username
string
Username to use for SIP authentication.
sip_refer.password
string
Password to use for SIP authentication.
Variables
Set by the method:
- sip_refer_to: (out) The SIP URI the recipient is to INVITE.
- sip_refer_result: (out) Overall SIP REFER result.
- return_value: (out) Same value as
sip_refer_result. - sip_refer_response_code: (out) Recipient response to the REFER request.
- sip_refer_to_response_code: (out) INVITE response to the recipient.
StatusCallbacks
A POST request will be sent to status_url with a JSON payload like the following:
event_type
string
The type of event. Always calling.call.refer for this method.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing SIP REFER-specific parameters.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.sip_refer_to
string
The SIP URI the recipient is being referred to.
params.state
string
The overall result of the SIP REFER operation (e.g., success).
params.sip_refer_response_code
string
The SIP response code for the REFER request itself (e.g., "202"). Only present when a response has been received.
params.sip_notify_response_code
string
The SIP response code for the INVITE sent by the recipient to the refer target (e.g., "200"). Only present when a response has been received.
params.segment_id
string
The segment ID for the call leg. Present when available.
params.tag
string
The tag associated with the call. Present when set.
Raw JSON example
{
"event_type": "calling.call.refer",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"sip_refer_to": "sip:alice@example.com",
"state": "success",
"sip_refer_response_code": "202",
"sip_notify_response_code": "200"
}
}Examples
Send SIP REFER and post result
YAMLJSON
version: 1.0.0
sections:
main:
- sip_refer:
to_uri: 'sip:alice@example.com'
- play:
url: 'say: Connected. The SIP refer result is ${sip_refer_result}'
- execute:
dest: 'https://example.com/handle_sip_refer_result'sleep
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Set the amount of time for the current application to sleep for in milliseconds before continuing to the next action.
sleep
object | integerRequired
An object that accepts the following properties, or an integer value directly.
Properties
sleep.duration
integerRequired
The amount of time to sleep in milliseconds. Must be a positive number. Can also be set to a -1 integer for the sleep to never end.
Possible Values:-1 or any positive number
Examples
Timed Sleep Example
YAMLJSON
version: 1.0.0
sections:
main:
- sleep: 5000Forever Sleep Example
YAMLJSON
version: 1.0.0
sections:
main:
- sleep: -1stop_denoise
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Stop noise reduction (which was started with denoise).
stop_denoise
objectRequired
An empty object that accepts no parameters.
Variables
Set by the method:
- denoise_result: (out)
off
Examples
Stop denoise
YAMLJSON
version: 1.0.0
sections:
main:
- stop_denoise: {}
- play:
url: 'say: Denoising ${denoise_result}'stop_record_call
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Stop an active background recording.
stop_record_call
objectRequired
An object that accepts the following properties.
Properties
stop_record_call.control_id
stringDefaults to The last started recording will be stopped
Identifier for the recording to stop
Variables
Read by the method:
- record_control_id: (in) control ID of last recording started.
Set by the method:
- stop_record_call_result: (out)
success|failed
Examples
Stop last call recording
YAMLJSON
version: 1.0.0
sections:
main:
- stop_record_call: {}Stop a specific call recording
YAMLJSON
version: 1.0.0
sections:
main:
- stop_record_call:
control_id: my-recording-idstop_stream
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Stop an audio stream started with stream. By default it stops the most recently started stream; pass a control_id to stop a specific one.
Properties
stop_stream
object
An object that accepts the following properties.
stop_stream.control_id
stringDefaults to The most recently started stream is stopped
The control ID of the stream to stop, as assigned when you started it with stream.
Variables
stream_control_id
string
Read by the method. Control ID of the most recently started stream.
stop_stream_result
success | failed
Set by the method. Whether the stream stopped successfully.
Examples
Stop the last stream
YAMLJSON
version: 1.0.0
sections:
main:
- stop_stream: {}Stop a specific stream
YAMLJSON
version: 1.0.0
sections:
main:
- stop_stream:
control_id: my-stream-idstop_tap
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Stop an active tap stream.
stop_tap
objectRequired
An object that accepts the following properties.
Properties
stop_tap.control_id
stringDefaults to The last tap started will be stopped
ID of the tap to stop
Variables
Read by the method:
- tap_control_id: (in) Control ID of last tap stream started.
Set by the method:
- stop_tap_result: (out) Success or failed.
Examples
Stop the last call tap
YAMLJSON
version: 1.0.0
sections:
main:
- stop_tap: {}Stop a specific call tap
YAMLJSON
version: 1.0.0
sections:
main:
- stop_tap:
control_id: my-tap-idstream
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Stream the call’s audio to a WebSocket endpoint you control. The stream runs in the background: execution continues to the next instruction while audio is delivered to your endpoint in real time, which is useful for live transcription, voice analytics, or other custom media processing.
The stream keeps running until you stop it with stop_stream or the call ends. You can run more than one stream at once by giving each its own control_id.
Properties
stream
objectRequired
An object that accepts the following properties.
stream.url
stringRequired
The secure WebSocket URI (wss://) to stream the call’s audio to.
stream.control_id
stringDefaults to Auto-generated, stored in the stream_control_id variable
Identifier for this stream, used to stop it later with stop_stream. Must be unique among the active streams on the call.
stream.name
string
A friendly name to identify this stream. Included in the stream’s status events.
stream.track
stringDefaults to inbound_track
Which side of the call’s audio to stream: inbound_track for what the caller says, outbound_track for what the caller hears, or both_tracks for both.
stream.codec
string
Codec to use for the streamed audio. Freeform and endpoint-specific; common values include PCMU, PCMA, and OPUS.
stream.status_url
string
HTTP or HTTPS URL to deliver stream status events. Learn more about status callbacks.
stream.status_url_method
stringDefaults to POST
HTTP method used to deliver stream status events to status_url. Possible values:GET, POST.
stream.authorization_bearer_token
string
Bearer token sent in the Authorization header when connecting to the WebSocket endpoint.
stream.custom_parameters
object
Custom key-value pairs included in the first message sent to your WebSocket endpoint when the stream connects.
Variables
stream_result
success | failed
Whether the stream started successfully.
stream_control_id
string
Identifier assigned to this stream. stop_stream uses it to stop the right one.
StatusCallbacks
When you set status_url, SignalWire POSTs a calling.call.stream event to it whenever the stream changes state: params.state is streaming when the stream starts and finished when it ends.
See the Stream status callback webhook page for the full field reference.
Examples
Stream to a WebSocket endpoint
YAMLJSON
version: 1.0.0
sections:
main:
- stream:
url: wss://example.com/audio-streamStream both tracks with status callbacks
YAMLJSON
version: 1.0.0
sections:
main:
- stream:
url: wss://example.com/audio-stream
name: live-transcription
track: both_tracks
status_url: https://example.com/stream-status
custom_parameters:
customer_tier: goldswitch
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Execute different instructions based on a variable’s value
Properties
switch
objectRequired
An object that accepts the following properties.
switch.variable
stringRequired
Name of the variable whose value needs to be compared.
switch.case
objectRequired
Case_params object of key-mapped values to array of SWML Methods to execute.
switch.default
[]
Array of SWML Methods to execute if no cases match.
case_params
The case_params object serves as a dictionary where each key is a string identifier, and the associated value is an array of SWML Method objects.
case.property_name
[]objectRequired
Name of the variable whose value needs to be compared.
Examples
YAMLJSON
version: 1.0.0
sections:
main:
- switch:
variable: call.type
case:
sip:
- play:
url: "say: You're calling from SIP."
phone:
- play:
url: "say: You're calling from phone."
default:
- play:
url: 'say: Unexpected error'YAMLJSON
version: 1.0.0
sections:
main:
- set:
foo: 5
- execute:
dest: example_fn
params:
foo: '${foo}'
example_fn:
- switch:
variable: params.foo
default:
- play:
url: 'say: nothing matches'
case:
'5':
- play:
url: 'say: yup, math works!'See Also
- Variables and Expressions: Complete reference for SWML variables, scopes, and using variables in conditional logic
- cond: Alternative conditional logic method
tap
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Start background call tap. Media is streamed over Websocket or RTP to customer controlled URI.
Properties
tap
objectRequired
An object that accepts the following properties.
tap.uri
stringRequired
Destination of the tap media stream: rtp://IP:port, ws://example.com, or wss://example.com
tap.control_id
stringDefaults to Auto-generated, stored in the tap_control_id variable
Identifier for this tap to use with stop_tap
tap.direction
string
speak“ Direction of the audio to tap: speak for what party says, listen for what party hears, both for what party hears and says
tap.codec
string
PCMU“ PCMU or PCMA
tap.rtp_ptime
integerDefaults to 20 ms
If using a rtp:// URI, this optional parameter can set the packetization time of the media in milliseconds. Optional. Default 20 ms.
tap.status_url
string
HTTP or HTTPS URL to deliver tap status events. Learn more about status callbacks.
Variables
Set by the method:
- tap_uri: (out) The destination URI of the newly started tap.
- tap_result: (out)
success|failed. - tap_control_id: (out) Control ID of this tap.
- tap_rtp_src_addr: (out) If RTP, source address of the tap stream.
- tap_rtp_src_port: (out) If RTP, source port of the tap stream.
- tap_ptime: (out) Packetization time of the tap stream.
- tap_codec: (out) Codec in the tap stream.
- tap_rate: (out) Sample rate in the tap stream.
StatusCallbacks
A POST request will be sent to status_url with a JSON payload like the following:
event_type
string
The type of event. Always calling.call.tap for this method.
event_channel
string
The channel for the event, includes the SWML session ID.
timestamp
number
Unix timestamp (float) when the event was generated.
project_id
string
The project ID associated with the call.
space_id
string
The Space ID associated with the call.
params
object
An object containing tap-specific parameters.
params.call_id
string
The call ID.
params.node_id
string
The node handling the call.
params.segment_id
string
The segment ID for the call leg. Present when available.
params.tag
string
The tag associated with the call. Present when set.
params.control_id
string
The control ID for this tap operation.
params.state
string
The current tap state. Valid values:tapping, finished.
params.tap
object
Details about the tap media stream.
tap.type
string
The type of media being tapped (e.g., audio).
tap.params.direction
string
The direction of audio being tapped.
params.device
object
Details about the destination device receiving the tap stream.
device.type
string
The type of device (e.g., rtp, ws).
device.params.addr
string
The destination address for the tap stream.
device.params.port
number
The destination port for the tap stream.
device.params.codec
string
The audio codec used for the tap stream (e.g., PCMU, PCMA).
device.params.ptime
number
The packetization time in milliseconds. Present for RTP taps only.
device.params.uri
string
The WebSocket destination URI. Present for WebSocket taps only.
Raw JSON example
{
"event_type": "calling.call.tap",
"event_channel": "swml:xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"timestamp": 1640000000.123,
"project_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"space_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"params": {
"call_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"node_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"segment_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"control_id": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"state": "tapping",
"tap": {
"type": "audio",
"params": {
"direction": "both"
}
},
"device": {
"type": "rtp",
"params": {
"addr": "192.168.1.100",
"port": 12345,
"codec": "PCMU",
"ptime": 20
}
}
}
}Examples
Start WSS tap
YAMLJSON
version: 1.0.0
sections:
main:
- tap:
uri: wss://example.com/taptranscribe
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Transcribe the entire call in the background. Execution continues to the next instruction while the call proceeds; the transcription covers the whole call and completes when the call ends. To stop it early, use the transcribe_stop method.
For real-time transcription delivered as the call happens, use live_transcribe instead.
Only one transcription can be active on a call at a time. Starting another while one is already running will fail.
Properties
transcribe
object
An object that accepts the following properties.
transcribe.status_url
string
An HTTP or HTTPS URL that receives the status callback when the transcription finishes. Learn more about status callbacks.
Variables
transcribe_result
success | failed
Whether transcription started successfully.
transcribe_control_id
string
Identifier assigned to this transcription. transcribe_stop uses it to stop the right one.
StatusCallbacks
When you set status_url, SignalWire POSTs a transcript event to it when the call’s transcription finishes: calling.transcript.completed includes the transcribed text when speech was captured, or calling.transcript.failed if the call could not be transcribed.
See the Transcript status callback webhook page for the full field reference.
Example
YAMLJSON
version: 1.0.0
sections:
main:
- transcribe:
status_url: https://example.com/transcribe-statustranscribe_stop
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Stop the transcription currently running on the call, started with transcribe. This method accepts no parameters.
Properties
transcribe_stop
object
An empty object.
Variables
transcribe_stop_result
success | failed
Whether the transcription stopped successfully.
Example
YAMLJSON
version: 1.0.0
sections:
main:
- transcribe_stop: {}transfer
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Transfer the execution of the script to a different SWML section, URL, or RELAY application. Once the transfer is complete, the script will continue executing SWML from the new location.
Properties
transfer
objectRequired
An object that accepts the following properties.
transfer.dest
stringRequired
Specifies where to transfer to. The value can be one of:
"<section_name>"- section in the SWML document to jump to- A URL (http or https) - URL to fetch next document from. Sends HTTP POST. Authentication can also be set in the url in the format of
username:password@url. - An inline SWML document (as a JSON string) - SWML document provided directly as a JSON string
transfer.params
object
Named parameters to send to a section, URL, or application.
transfer.meta
object
User data, ignored by SignalWire. Accepts an object mapping variable names to values.
Valid Destination Values
The destination string can be one of:
"section_name"- section in the current document to execute. (For example:execute: main)"relay:<relay application>"- relay application to notify (currently not implemented)"https://example.com/sub-swml.yaml"- URL pointing to the document to execute. An HTTP POST request will be sent to the URL. Authentication can also be set in the url in the format ofusername:password@url. Theparamsobject is passed, along with the variables and thecallobject.
Examples
Basic transfer to a URL
YAMLJSON
version: 1.0.0
sections:
main:
- transfer:
dest: "https://example.com/next"Basic transfer to a section
YAMLJSON
version: 1.0.0
sections:
main:
- play:
url: 'say:Transferring you to another section'
- transfer:
dest: subsection
- play:
url: 'say:Back!'
subsection:
- play:
url: 'say:inside a subsection'Named parameter with sub-parameters
YAMLJSON
version: 1.0.0
sections:
main:
- transfer:
- dest: "https://example.com/next"
- params:
- foo: "bar"Transfer to a SWML script hosted on a server
YAMLJSON
version: 1.0.0
sections:
main:
- prompt:
play: >-
say: Press 1 to be transfered to the Sales department, 2 for marketing
department or anything else to listen to some music.
- switch:
variable: prompt_value
case:
'1':
- transfer:
dest: 'https://<YOUR_NGROK_UUID>.ngrok-free.app'
params:
where: sales
'2':
- transfer:
dest: 'https://<YOUR_NGROK_UUID>.ngrok-free.app'
params:
where: marketing
- play:
url: 'https://cdn.signalwire.com/swml/April_Kisses.mp3'A minimal server for this SWML script can be written as follows:
Python/Flask
JavaScript/Express
from flask import Flask, request
from waitress import serve
app = Flask(__name__)
@app.route("/", methods=['POST'])
def swml():
content = request.get_json(silent=True)
print(content)
return '''
version: 1.0.0
sections:
main:
- answer: {}
- play:
url: 'say: Welcome to the {} department.'
'''.format(content['params']['where'])
if __name__ == "__main__":
serve(app, host='0.0.0.0', port=6000)This server (running on localhost) can be made accessible to the wider web (and thus this SWML script) using forwarding tools like ngrok. Visit ngrok.com to learn how.
The server will be sent the payload in the following format:
{
"call": {
"call_id": "<call_id>",
"node_id": "<node_id>",
"segment_id": "<segment_id>",
"call_state": "answered",
"direction": "inbound",
"type": "phone",
"from": "<address>",
"to": "<address>",
"from_number": "<address>",
"to_number": "<address>",
"headers": [],
"project_id": "<your Project UUID>",
"space_id": "<your Space UUID>"
},
"vars": {
"answer_result": "success",
"prompt_result": "match_digits",
"prompt_value_raw": "2",
"prompt_value": "2"
},
"params": { "where": "marketing" }
}The call object is described in detail in the introduction. All variables created within the SWML document are passed inside vars, and the params object contains the parameters defined in the params parameter of transfer.
unset
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Unset specified variables. The variables have been set either using the set command or as a byproduct of some other statements or methods (like record)
unset
string | string[]Required
The name of the variable to unset (as a string) or an array of variable names to unset.
Variable
Any variable can be unset by this method.
Examples
Unset a single variable
YAMLJSON
version: 1.0.0
sections:
main:
- set:
num_var: 1
- play:
url: 'say: The value of num_var is: ${num_var}.'
- unset: num_var
- play:
url: 'say: The value of num_var is ${num_var}.'Unset multiple variables
YAMLJSON
version: 1.0.0
sections:
main:
- set:
systems:
hr:
- tracy
- luke
engineering:
john: absent
name: john
- play:
url: 'say: ${systems.hr}'
- unset:
- systems
- name
# this play statement emits an error because `systems` is undefined
# at this point so there's nothing for `play` to say.
- play:
url: 'say: ${systems}'See Also
- Variables and Expressions: Complete reference for SWML variables, scopes, and syntax
- set: Set variables in the script
user_event
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Allows the user to set and send events to the connected client on the call. This is useful for triggering actions on the client side. Commonly used with the browser-sdk. Accepts an object mapping event names to values. The event object can be any valid JSON object.
user_event
objectRequired
An object that accepts the following properties.
Properties
user_event.event
anyRequired
An object mapping event names to values. The event object can be any valid JSON object.
Event Object
The event parameter can be any valid JSON object. Any key-value pair in the object is sent to the client as an event type called: user_event.
The client can listen for these events using the on-method.
Examples
Send a custom event to the client
YAMLJSON
version: 1.0.0
sections:
main:
- user_event:
event:
myCustomEvent: 'Hello, world!'
- play:
url: 'say: Custom event sent.'Send multiple events with different payloads
YAMLJSON
version: 1.0.0
sections:
main:
- user_event:
event:
eventA:
foo: bar
eventB:
count: 42
active: true
- play:
url: 'say: Multiple events sent.'Errors
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Reference for the error codes that SWML reports when a document fails to fetch, parse, or run. Calling and messaging SWML use different code namespaces:
- Calling errors start with
relay_script_*and surface on the call session as thescript_errorvariable and ascalling.script.warningevents. - Messaging errors include the
swml_*codes for messaging-specific failures plus a handful of document-level codes. They appear on the inbound message in the Messaging logs and on any status callbacks you’ve configured.
Calling errors
Errors raised while executing a calling SWML document. Each error is reported with a contextual message describing the offending method, parameter, or condition. You can read the code from the script_error variable on the call session or from the payload of the calling.script.warning event.
relay_script_parse_error
string
The fetched document could not be parsed as valid JSON or YAML, or the dest URL of a transfer was malformed.
relay_script_parse_internal_error
string
An internal parsing error occurred while reading the document. Verify the document is valid YAML or JSON and retry.
relay_script_version_invalid
string
The document’s version value is not a supported SWML version.
relay_script_sections_missing
string
The document has no sections element.
relay_script_main_section_missing
string
The document’s sections is missing the required main section.
relay_script_section_code_missing
string
A section is defined but contains no executable steps.
relay_script_section_parameter_undefined
string
An execute step references a section that does not exist in the document.
relay_script_element_undefined
string
An unrecognized top-level element appears in the document.
relay_script_element_wrong_type
string
A document element has the wrong JSON type for its position (for example, an array where an object was expected).
relay_script_element_invalid_value
string
A document element has an invalid value (for example, an enum-valued field set to an unrecognized string).
relay_script_element_duplicated
string
A document element that may appear at most once was provided multiple times.
relay_script_method_missing_name
string
A step in a section does not have a method name (the step entry is malformed).
relay_script_method_undefined
string
A step references a method that is not a recognized SWML calling method.
relay_script_method_parameter_missing
string
A required parameter for the method is missing, for example, transfer without dest, or request without url.
relay_script_method_parameter_invalid_value
string
A method parameter has an invalid value, for example, a request.method that is not one of the supported HTTP verbs, or a switch.variable that does not resolve to a valid variable name.
relay_script_method_parameter_undefined
string
A method received a parameter name it does not recognize.
relay_script_method_parameter_conflict
string
Two mutually-exclusive parameters were provided on the same method.
relay_script_method_no_matching_condition
string
A switch step matched no case and no default was provided.
relay_script_method_execute_failed
string
A method failed while running, for example, a media playback failure, a transfer that couldn’t dial, or a tap or stream that couldn’t be set up. The accompanying message provides the specific cause.
relay_script_js_eval_error
string
A JavaScript expression in a cond, switch, eval, or when clause raised an error.
relay_script_nested_too_deep
string
A document or one of its sections is nested beyond the maximum depth.
relay_script_too_many_transfers
string
The chain of transfer and goto steps exceeded the platform maximum (32 transfers per call).
relay_script_internal_error
string
An internal server error occurred during script execution.
Messaging errors
Errors emitted when an inbound message’s SWML document fails to fetch, parse, or execute. Each inbound message is marked failed with the listed error_code and a corresponding error_message, visible in the Messaging logs.
Document fetch / route
unrouteable_message
string
Unrouteable message received, no SWML handler is assigned to the inbound number.
insufficient_balance
string
Insufficient account balance to receive the message.
message_filtered
string
Message filtered (e.g. spam detection or carrier-level filtering).
http_retrieval_error
string
The attempt to retrieve the SWML document timed out or failed.
url_failed_to_parse
string
The configured SWML URL could not be parsed.
Document parse
json_or_yaml_required
string
The document must be valid JSON or YAML.
swml_invalid_document
string
Document may contain only one of reply, receive, or sections at the top level.
swml_missing_entry_point
string
Document must contain reply, receive, or sections.
swml_invalid_section_format
string
Section main must be an array of steps.
swml_unsupported_method
string
The document references an unsupported SWML messaging method.
reply method
swml_reply_failed
string
Failed to create the reply message (general fallback for reply persistence errors).
swml_reply_media_limit_exceeded
string
The reply exceeds the maximum of 8 media attachments.
swml_reply_body_or_media_required
string
The reply must include a body or media.
swml_reply_invalid_from_number
string
The reply from number is not a valid PhoneRoute or ShortCode in this project.
swml_reply_invalid_to_number
string
The reply to number has an invalid format.
swml_reply_missing_messaging_capability
string
The reply from number is not SMS- or MMS-capable for the kind of message being sent.
swml_reply_character_limit_exceeded
string
The reply body exceeds the character limit for the destination.
swml_reply_inactive_campaign
string
The reply from number must belong to an active 10DLC campaign.
switch method
swml_switch_no_match
string
switch matched no case and no default was provided.
swml_switch_invalid_transform
string
switch.transform is not one of lowercase, uppercase, trim, lowercase_trim, uppercase_trim.
execute method
swml_section_not_found
string
The section named by execute.dest is not defined in the current document.
transfer method
swml_transfer_failed
string
transfer.dest is required and was missing or empty.
swml_transfer_fetch_failed
string
Failed to fetch the transferred SWML document from the destination URL.
swml_transfer_document_invalid
string
The transferred SWML document is not a valid messaging document.
goto method
swml_goto_label_not_found
string
goto.label does not match any label step in the current section.
request method
swml_request_url_required
string
request.url is required and was missing or empty.
Expressions
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Expressions allow you to use JavaScript within SWML variables to transform data, perform calculations, and implement logic. Instead of static values, you can dynamically construct values based on call data, user input, and calculations.
Calling SWML only
Expressions (${...}) are a Calling SWML feature. Messaging SWML supports only pure variable substitution via %{path.to.value}, no JavaScript, no method calls, no operators. For dynamic behavior in a messaging document, use switch for branching and request for fetching computed values from your server.
For information about variable scopes and basic access patterns, see the Variables Reference. For template transformation functions, see the Template Functions Reference.
What are expressions?
Expressions use the ${...} syntax and support JavaScript for dynamic value construction. Any JavaScript that evaluates to a value can be used inside these delimiters. Both syntaxes work identically.
SWML uses the Google V8 JavaScript engine (version 6 and later) to evaluate expressions. For detailed JavaScript feature support, refer to the V8 documentation.
YAMLJSON
version: 1.0.0
sections:
main:
- prompt:
play: 'say: Please enter your order quantity'
speech_hints:
- one
- two
- three
- set:
# Set the prompt value
quantity: '${prompt_value}'
# Set the unit price
unit_price: 5
# Extract area code from caller
area_code: '${call.from.substring(0, 3)}'
# Calculate total with tax
subtotal: '${vars.unit_price * parseInt(vars.quantity)}'
tax: '${subtotal * 0.08}'
total: '${subtotal + tax}'
# Determine shipping message
shipping_msg: '${total > 50 ? "with free shipping" : "plus shipping"}'
- play:
url: 'say: Your total is ${total.toFixed(2)} dollars ${shipping_msg}'Expressions are evaluated at runtime and replaced with their computed values.
Variable access in expressions
All SWML variables are accessible within JavaScript expressions. You can reference them with or without scope prefixes:
- set:
# With prefix (explicit)
caller: '${call.from}'
value: '${vars.my_variable}'
setting: '${envs.api_key}'
# Without prefix (automatic)
formatted: '${my_variable.toUpperCase()}'When you access a variable without a prefix, the expression engine checks scopes in this order: vars, then envs, then call. Using explicit prefixes like vars. or call. is recommended for clarity, especially when variable names might exist in multiple scopes.
When to use expressions vs. server-side logic
Expressions are evaluated at runtime within SWML and work well for simple transformations like formatting phone numbers or calculating totals. The question of when to use expressions versus server-side logic depends largely on your deployment model.
Serverless (dashboard-hosted) SWML
When hosting SWML directly in the SignalWire Dashboard, expressions become your primary tool for dynamic behavior. You can use them to transform call data like extracting area codes with ${call.from.substring(0, 3)}, perform calculations such as ${vars.unit_price * parseInt(vars.quantity)}, or make simple decisions with ternary operators.
YAMLJSON
version: 1.0.0
sections:
main:
- prompt:
play: 'say: Please enter your order quantity'
speech_hints:
- one
- two
- three
- set:
# Set the prompt value
quantity: '${prompt_value}'
# Set the unit price
unit_price: 5
# Extract area code from caller
area_code: '${call.from.substring(0, 3)}'
# Calculate total with tax
subtotal: '${vars.unit_price * parseInt(vars.quantity)}'
tax: '${subtotal * 0.08}'
total: '${subtotal + tax}'
# Determine shipping message
shipping_msg: '${total > 50 ? "with free shipping" : "plus shipping"}'
- play:
url: 'say: Your total is ${total.toFixed(2)} dollars ${shipping_msg}'If you need complex logic in serverless mode, use the request method to fetch data from a server during call execution. The response data becomes available as variables that you can then manipulate with expressions.
Server-based (external URL) SWML
Serving SWML from your own web server opens up more architectural options. This is where you should handle database queries, external API calls to your business systems, and any complex business logic that requires authentication or heavy data processing.
The general pattern is to do the heavy lifting server-side before generating the SWML response, then use expressions for runtime transformations. For example, you might query your database to fetch customer information, call your internal billing service to get their account status, and insert that data directly into the SWML. Then expressions handle runtime concerns like formatting that data or calculating values based on user input collected during the call.
app.post('/swml-handler', async (req, res) => {
const { call, params } = req.body;
// Server-side: Query database
const customer = await db.query(
'SELECT * FROM customers WHERE phone = ?',
[call.from]
);
// Server-side: Call internal billing API
const billing = await fetch(`https://billing.yourcompany.com/api/account/${customer.id}`);
const accountData = await billing.json();
// Return SWML with data inserted
const swml = {
version: '1.0.0',
sections: {
main: [\
{\
play: {\
// Expression: Simple transformation at runtime\
url: `say: Hello ${customer.name}, your account status is ${accountData.status}`\
}\
},\
{\
set: {\
// Expression: Calculate with fetched data\
discount: '${params.base_price * 0.1}'\
}\
}\
]
}
};
res.json(swml);
});The key principle is to use server-side logic to prepare and fetch data, then use expressions for transformations and dynamic behavior that happen during the call itself.
Common expression patterns
String operations
Transform and manipulate text using JavaScript string methods:
YAMLJSON
version: 1.0.0
sections:
main:
- set:
first_name: 'John'
last_name: 'Doe'
# Extract part of a string
area_code: '${call.from.substring(0, 3)}'
# Change case
uppercase: '${call.type.toUpperCase()}'
# Combine strings
full_name: '${vars.first_name + " " + vars.last_name}'
- play:
url: 'say: Hello ${full_name}. Your area code is ${area_code}. Call type: ${uppercase}'Common methods: substring(), toUpperCase(), toLowerCase(), trim(), replace(), split(), join()
Arithmetic and math
Perform calculations using standard JavaScript operators and Math functions:
YAMLJSON
version: 1.0.0
sections:
main:
- set:
# Calculate total
total: '${params.price * params.quantity}'
# Format currency (2 decimal places)
formatted: '${total.toFixed(2)}'
# Round to nearest integer
rounded: '${Math.round(params.rating)}'Use operators: +, -, *, /, % and Math functions: Math.round(), Math.ceil(), Math.floor(), Math.max(), Math.min()
Conditional logic
Use ternary operators and comparisons to make decisions:
YAMLJSON
version: 1.0.0
sections:
main:
- set:
# Conditional greeting based on call direction
greeting: '${call.direction == "inbound" ? "Welcome" : "Calling"}'
# Fallback to "unknown" if call.type is null
call_label: '${call.type != null ? call.type : "unknown"}'
# Compound condition checking both type and direction
status: '${call.type == "phone" && call.direction == "inbound" ? "valid" : "invalid"}'
- play:
url: 'say: ${greeting}! Your call type is ${call_label} and status is ${status}'Use comparisons: ==, !=, >, <, >=, <= and logical operators: &&, ||
Array operations
Work with arrays using JavaScript array methods:
version: 1.0.0
sections:
main:
- set:
# Define the array first
items:
- apple
- banana
- set:
# Get array length
count: '${(items.length)}'
# Join array into string
list: '${vars.items.join(", ")}'
# Check if array contains item
has_item: '${vars.items.includes("apple")}'
# Get last item
last: '${vars.items[vars.items.length - 1]}'
- play:
url: 'say: You have ${count} items: ${list}. Last item is ${last}.'Common methods: .length, .join(), .includes(), bracket notation for access
Type conversions
Convert between strings, numbers, and booleans:
YAMLJSON
version: 1.0.0
sections:
main:
- set:
quantity: ${parseInt("42")}
count: 100
text: "${count.toString()}"
is_active: "${Boolean(1)}"
- play:
url: 'say: The quantity is ${quantity}. The count variable is ${text}. Active is set to ${is_active}'Use: parseInt(), parseFloat(), .toString(), Boolean()
Expression limitations
Expressions are designed for quick data transformations during calls. They work great for formatting strings, performing calculations, and making simple decisions, but they’re intentionally constrained to keep your calls running smoothly.
You can’t create custom functions with the function keyword or arrow syntax. Instead, rely on JavaScript’s built-in methods like string operations, Math functions, and array methods:
- set:
calculator: '${function(x) { return x * 2; }}'
# Do this instead
- set:
doubled: '${value * 2}'Loops like for and while aren’t available, but you can use array methods for most transformation needs. Methods like .map(), .filter(), and .reduce() handle common iteration patterns:
# Loops aren't supported
- set:
result: '${for(let i=0; i<10; i++) { sum += i; }}'
# Array methods work well
- set:
sum: '${[1,2,3,4,5].reduce((a,b) => a+b, 0)}'Simple property access like .length, .name, .value, etc. on arrays or strings require parentheses to evaluate correctly. Without them, the expression is treated as a variable lookup rather than JavaScript. Method Calls with parentheses work directly:
# Property access needs parentheses
- set:
count: '${(items.length)}'
name_length: '${(user.name.length)}'
# Method calls work without extra syntax
- set:
list: '${items.join(", ")}'
upper: '${name.toUpperCase()}'Expressions execute synchronously, so you can’t use async, await, or make API calls directly. For operations that need external data, use the request method to fetch data first, then transform the results with expressions.
Keep expressions under 1,024 characters and expect them to complete within 150ms. If you’re hitting these limits, it’s usually a sign that the logic belongs in your server code rather than inline in SWML.
Messaging SWML overview
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Messaging SWML is the flavor of SWML used to handle inbound SMS and MMS messages. When a message arrives on a phone number configured with a SWML message handler, SignalWire fetches and processes the SWML document, optionally sending an outbound reply.
For handling voice calls, see the Calling SWML overview.
Document structure
A Messaging SWML document follows the standard SWML document structure, a top-level sections map with sections.main as the entry point. Each section contains an array of messaging methods that run sequentially. A document can execute up to 100 methodsteps per inbound message; once that ceiling is hit, execution stops.
Webhook and variable payload
When SignalWire fetches a Messaging SWML document from an external URL, it POSTs the inbound message webhook payload to your server, on the initial inbound-message fetch and on every fetch triggered by a transfer step. Your server must respond with a valid SWML document using one of these content types: application/json, application/yaml, or text/x-yaml.
Inside the executing document, the same message and params fields are available for %{...} variable expansion (for example, %{message.from}). As the script runs, methods also populate the vars.* runtime scope, those values are not in the initial inbound payload, but they are propagated across transfer boundaries and delivered on transfer-driven fetches.
message
object
The inbound message that triggered the SWML document.
message.message_id
string
Unique identifier for the inbound message segment.
message.project_id
string
The Project ID this message belongs to.
message.space_id
string
The Space ID this message belongs to.
message.direction
string
The direction of the message. Always inbound for messages that trigger a Messaging SWML document.
message.type
string
The message type. Possible values: sms, mms.
message.from
string
Sender phone number in E.164 format.
message.to
string
Recipient phone number in E.164 format (the SignalWire number that received the message).
message.body
string
The text content of the inbound message.
message.media
object[]
Media attachments on the inbound message. Empty array when no media is attached.
message.media[].url
string
URL where the media file is stored.
message.media[].content_type
string
MIME type of the media file (e.g., image/jpeg, image/png).
message.media[].size
integer
Size of the media file in bytes.
message.segments
integer
Number of SMS segments the inbound message was split into.
message.timestamp
string
ISO 8601 timestamp of when the inbound message was received.
params
object
Parameters passed by the calling transfer or execute step. Empty {} on the initial inbound fetch. Section-scoped, restored to the caller’s value when an execute returns.
vars
object
Runtime variable scope, populated by methods as the script executes. Not part of theinitial inbound payload, values appear here only after a method that sets them has run. The full vars object is propagated across transfer boundaries and delivered as a top-level vars field on the transfer-driven webhook payload.
The standard runtime entries are listed below. Methods may also write additional keys; see each method’s reference page for what it sets.
vars.reply_result
string
Result of the most recent reply step. Set after the step completes. Possible values: queued, failed.
vars.reply_message_id
string
Message segment ID of the most recent successful reply. Set after the step completes.
vars.request_result
string
Result of the most recent request step. Set after the step completes. Possible values: success, failed, timeout, limit_exceeded.
vars.request_response
object
Parsed JSON response from the most recent request. Set after the step completes when save_variables: true was set on the request step. Access nested fields with dot notation, e.g., %{vars.request_response.field_name}.
vars.request_response_code
integer
HTTP response code from the most recent request. Set after the step completes.
vars.request_response_body
string
Raw response body from the most recent request. Set after the step completes. Truncated to 64 KB.
See Variables for variable-expansion syntax, deployment-mode differences, and tips on accessing nested fields and array elements.
Methods
A method is a single step in a full-mode SWML document, each item in a sections.<name> array invokes one method. Each method’s reference page documents its parameters, defaults, and any output variables it sets. Methods below are grouped by what they do.
Message handling
Decide what to do with the inbound message, send an outbound reply, or accept it silently.
reply\ \ Send an SMS or MMS back to the sender of the inbound message. Use for auto-replies, confirmations, and keyword responses. receive\ \ Accept the inbound message without sending a reply. Use to acknowledge the message without an outbound response.
Control flow
Direct execution within the document, reuse blocks of logic, repeat steps, choose between branches, or hand off the message to another document entirely.
execute\ \ Run another section of the current document, then resume when it finishes. Use to reuse a sequence of steps from more than one place. return\ \ Hand control back to the section that called the current one, optionally passing a value the caller can read. transfer\ \ Hand off the rest of the conversation to a different SWML document hosted on an external server. The current document stops; the new one takes over. goto\ \ Restart from a named point earlier or later in the current section. Use for retry loops that repeat a step until it succeeds. label\ \ Mark a place in the section that goto can jump to. Labels perform no action; they serve as navigation anchors. switch\ \ Choose what to do next based on a value from the inbound message or a variable. Use for keyword routing, different replies for different inbound message bodies.
External integration
Reach out to your own backend during message handling, so the reply can depend on data only your systems know.
request\ \ Call an external API while handling the message, for example, to look up a customer record before replying.
execute
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Call a named section as a subroutine. Execution continues in the called section, then returns to the caller when the section completes (via return or by reaching the end of the section).
The destination must be the name of a section defined in the current document, execute does not accept URLs or inline documents in the messaging context.
Properties
execute
objectRequired
An object that accepts the following properties.
execute.dest
stringRequired
Name of the section to execute. Must reference a section defined in the current document.
execute.params
object
Parameters accessible as params.* in the called section. Replaces (does not merge with) any outer params from the caller.
Variables
After the called section completes, execute exposes the following variable in the caller’s context. Variables that the subroutine itself set via reply or request, reply_result, reply_message_id, request_result, request_response, request_response_code, request_response_body, are also propagated back to the caller automatically; see those methods for details.
return_value
any
The value supplied to return inside the called section. Set only when the subroutine called return with an argument. Absent when the subroutine ran to completion without return.
Examples
Calling a subroutine
YAMLJSON
version: 1.0.0
sections:
main:
- execute:
dest: greet
params:
name: "%{message.from}"
- reply:
body: "%{return_value}"
greet:
- return: "Hello, %{params.name}!"Branch on the subroutine return value
YAMLJSON
version: 1.0.0
sections:
main:
- execute:
dest: classify
params:
body: "%{message.body}"
- switch:
variable: return_value
case:
opt_out:
- reply:
body: "You've been unsubscribed."
help:
- reply:
body: "Reply STOP to unsubscribe."
default:
- reply:
body: "Thanks for your message!"
classify:
- switch:
variable: params.body
transform: lowercase_trim
case:
stop:
- return: "opt_out"
help:
- return: "help"
default:
- return: "other"goto
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Jump to a label within the current section. Used for retry loops and conditional repetition.
goto does not cross subroutine boundaries, it can only jump within the section that contains the matching label.
Properties
goto
objectRequired
An object that accepts the following properties.
goto.label
stringRequired
Label to jump to. Must reference a label step earlier or later in the current section.
goto.max
integerDefaults to 100
Maximum number of times this goto can jump to its label. Once the limit is reached, the section ends without running any further steps.
Examples
Retry a request up to three times
YAMLJSON
version: 1.0.0
sections:
main:
- label: try_lookup
- request:
url: "https://api.example.com/lookup"
body:
phone: "%{message.from}"
save_variables: true
- switch:
variable: request_result
case:
success:
- reply:
body: "Hi %{request_response.name}!"
timeout:
- goto:
label: try_lookup
max: 3
default:
- reply:
body: "Sorry, we couldn't look up your account."label
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Mark any point of the current SWML section with a label so that goto can jump to it.
Properties
label
stringRequired
The label name. Must be unique within the section.
Examples
Label paired with goto for retry
YAMLJSON
version: 1.0.0
sections:
main:
- label: try_lookup
- request:
url: "https://api.example.com/lookup"
save_variables: true
- switch:
variable: request_result
case:
timeout:
- goto:
label: try_lookup
max: 3
default:
- reply:
body: "Lookup complete."receive
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Accept the inbound message without sending a reply. receive is a no-op step, it acknowledges the inbound message and does nothing else.
Properties
receive
objectRequired
An empty object. receive takes no parameters.
Example
YAMLJSON
version: 1.0.0
sections:
main:
- receive: {}reply
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Create and send an outbound message in response to the inbound message. reply accepts three shapes: a string shorthand, an object with body/media/routing fields, or an inline switch that branches the reply body on a variable’s value.
reply does not end execution, subsequent steps in the section continue to run after the reply is queued.
Properties
reply accepts one of three shapes, use whichever fits the document shape:
String shorthand
Object
Inline switch
A single string used as the reply body. The reply is sent to the inbound message’s from number, using the inbound to as the sender.
reply
stringRequired
The body of the reply message.
Variables
reply writes these variables into the script context after it runs. Read them with the %{variable} syntax in subsequent steps. When reply is called multiple times in a single document, both variables reflect the most recent reply.
reply_result
string
Outcome of the reply attempt. queued when the outbound message was accepted for delivery, failed when validation or delivery rejected it (invalid from/to, missing body and media, character limit exceeded, missing messaging capability, inactive campaign, etc.).
reply_message_id
string
ID of the outbound message created by the successful reply. Absent when reply_result is failed.
Status callbacks
The status_url on reply registers a delivery status callback for the outbound reply message, not for the inbound message that triggered the SWML document. It behaves the same way as the status callback on any other outbound message sent through SignalWire.
- Fires as the outbound reply moves through delivery states.
- Callback delivery is independent of SWML execution: the SWML document completes as soon as the reply is accepted (
reply_result: "queued"); delivery-state callbacks fire afterwards. - If
replyis called multiple times in a single document, each reply’sstatus_urlis registered independently for its own outbound message.
When status_url is set, SignalWire sends an HTTP POST to that URL each time the outbound reply transitions to a new state. The callback uses the same payload as other outbound messages sent through SignalWire:
See the Message status callback webhook page for the full field reference and the list of possible status values.
Examples
Reply with body
YAMLJSON
version: 1.0.0
sections:
main:
- reply:
body: "Thanks for your message!"Reply with media (MMS)
YAMLJSON
version: 1.0.0
sections:
main:
- reply:
body: "Here's the document you requested"
media:
- "https://example.com/document.pdf"Reply with a status callback URL
YAMLJSON
version: 1.0.0
sections:
main:
- reply:
body: "Your order is confirmed"
status_url: "https://example.com/status"Keyword-driven reply with inline switch
The inline switch form branches the reply body on a variable’s value, typically the inbound message.body.
YAMLJSON
version: 1.0.0
sections:
main:
- reply:
switch:
variable: message.body
transform: lowercase_trim
case:
help: "Reply STOP to unsubscribe, or visit https://example.com/help."
stop: "You've been unsubscribed."
start: "Welcome back!"
default: "Thanks for your message!"Per-case media and routing with inline switch
When a case needs more than a body string, different media, a different destination, or a per-branch status_url, supply a full reply object for that case instead of a bare string.
YAMLJSON
version: 1.0.0
sections:
main:
- reply:
switch:
variable: message.body
transform: lowercase_trim
case:
menu:
body: "Here's our menu."
media:
- "https://example.com/menu.pdf"
directions:
body: "Tap below for directions."
media:
- "https://example.com/map.jpg"
agent:
body: "Connecting you with a human, they'll text from a different number."
from: "+15559876543"
default: "Reply MENU, DIRECTIONS, or AGENT."Forward an inbound message to another number
YAMLJSON
version: 1.0.0
sections:
main:
- reply:
to: "+12223334444"
from: "+15559876543"
body: "Your number %{message.to} got a message from %{message.from}! The body was: %{message.body}"request
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Make an HTTP request to an external URL. The response can optionally be parsed and stored as variables for use in subsequent steps.
Request failures are soft, they set request_result but do not stop execution, so the document can branch on the outcome without failing the inbound message.
Properties
request
objectRequired
An object containing the following properties.
request.url
stringRequired
Endpoint to call. Must be a publicly reachable URL.
request.method
stringDefaults to POST
HTTP method. One of GET, POST, PUT, PATCH, or DELETE.
request.headers
object
HTTP headers to include with the request, as a map of header name to value. Each value must be a string.
request.body
string | object
Request body. Objects are JSON-encoded automatically.
request.timeout
numberDefaults to 5.0
Timeout in seconds. Clamped to a maximum of 5.0.
request.save_variables
booleanDefaults to false
If true, parse the JSON response into request_response.* variables.
Variables
request writes these variables into the script context after the HTTP call completes (or is skipped). Read them with the %{variable} syntax in subsequent steps.
request_result
string
Outcome of the request. Always set. One of success (request completed with a 2xx response), failed (network error or non-2xx response), timeout (request exceeded timeout, or the 5-second platform maximum), or limit_exceeded (the document already used the maximum of 10 request calls).
request_response_code
integer
HTTP status code from the response. Set when the request was actually sent. Absent when request_result is limit_exceeded.
request_response_body
string
Raw response body, truncated to 64 KB. Set when the response had a body. Absent when request_result is limit_exceeded.
request_response.<field>
any
Variables saved from the parsed JSON response when save_variables is true. Each top-level key of the JSON body becomes a request_response.<key> path, with dotted paths into nested objects.
For example, if the server responds with:
{ "status": "created", "time": "2 seconds ago", "number": { "home": "n/a" } }the variables request_response.status, request_response.time, and request_response.number.home are set.
Examples
Look up the inbound sender and reply with the result
YAMLJSON
version: 1.0.0
sections:
main:
- request:
url: "https://api.example.com/lookup"
method: POST
body:
phone: "%{message.from}"
save_variables: true
timeout: 3
- reply:
body: "Hi %{request_response.name}, thanks for reaching out!"Branch on request_result
YAMLJSON
version: 1.0.0
sections:
main:
- request:
url: "https://api.example.com/lookup"
save_variables: true
- switch:
variable: request_result
case:
success:
- reply:
body: "Found you in our system."
failed:
- reply:
body: "Sorry, we couldn't reach the lookup service."
timeout:
- reply:
body: "Lookup timed out, please try again later."
default:
- reply:
body: "Unable to look up your account."return
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Return from the current section. Inside a subroutine called via execute, control returns to the caller and the value is accessible as return_value in the caller’s context. In main, return stops execution entirely (its value is discarded).
To return without a value, use return: null.
Properties
return
anyRequired
The value to return. Accepts any type. Use null to return no value.
Variables
When called from a section invoked via execute, return provides the variable below to the caller’s context once execution resumes. When called from main, return stops execution immediately and no variable is set anywhere.
return_value
any
The value supplied to return. Available in the caller’s context after the execute step that invoked this section completes. String values are expanded for %{...} placeholders before storage; objects and arrays are stored as-is.
Examples
Return a string from a subroutine
YAMLJSON
version: 1.0.0
sections:
main:
- execute:
dest: greet
- reply:
body: "%{return_value}"
greet:
- return: "Hello there!"Return with no value (exit a section without setting return_value)
YAMLJSON
version: 1.0.0
sections:
main:
- execute:
dest: maybe_reply
- reply:
body: "Done."
maybe_reply:
- switch:
variable: message.body
transform: lowercase_trim
case:
stop:
- reply:
body: "You've been unsubscribed."
- return: null
default:
- return: nullReturn from main to stop execution
YAMLJSON
version: 1.0.0
sections:
main:
- reply:
body: "Got it."
- return: nullswitch
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Branch on a variable’s value, with optional text transforms applied before matching. Useful for keyword-driven inbound message handling.
Properties
switch
objectRequired
An object that accepts the following properties.
switch.variable
stringRequired
Variable path to match. Specified without the %{} wrapper (e.g. message.body).
switch.transform
string
Transform to apply to the value before matching. One of lowercase, uppercase, trim, lowercase_trim, or uppercase_trim.
switch.case
objectRequired
Map of values to arrays of SWML methods to execute. The key is the value to compare against variable (after applying transform); the value is the array of methods to run on match.
switch.default
object[]
Array of SWML methods to execute if no case matches. If omitted and no case matches, execution stops with an error.
Examples
Keyword-based reply
YAMLJSON
version: 1.0.0
sections:
main:
- switch:
variable: message.body
transform: lowercase_trim
case:
help:
- reply:
body: "Reply STOP to unsubscribe, or visit https://example.com/help."
stop:
- reply:
body: "You've been unsubscribed."
start:
- reply:
body: "Welcome back!"
default:
- reply:
body: "Sorry, I didn't understand that. Reply HELP for assistance."Branch on a saved request response
YAMLJSON
version: 1.0.0
sections:
main:
- request:
url: "https://api.example.com/customer"
body:
phone: "%{message.from}"
save_variables: true
- switch:
variable: request_response.tier
case:
gold:
- reply:
body: "Welcome back, valued customer!"
silver:
- reply:
body: "Thanks for being a member."
default:
- reply:
body: "Thanks for your message."transfer
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Fetch and execute a new SWML document from a URL. This is a tail call, it replaces the current document and does not return. Steps after transfer, including steps in calling sections, are skipped.
In the messaging context, transfer.dest must be a URL, it does not accept a section name or an inline document.
Properties
transfer
objectRequired
An object that accepts the following properties.
transfer.dest
stringRequired
URL (http or https) to fetch the new SWML document from. Authentication can be set in the URL in the format username:password@url.
transfer.method
stringDefaults to POST
HTTP method for the fetch request. One of GET, POST, PUT, PATCH, or DELETE.
transfer.params
object
Parameters to include in the request body of the fetch. Available as params.* in the transferred document.
Webhook payload sent to dest
When transfer fetches an external document, SignalWire POSTs the inbound message webhook payload to dest:
message, the original inbound message that triggered this SWML document.params, the values supplied to thistransferstep.vars, runtime variables propagated from the current document (request_result,reply_result,request_response,request_response_code,request_response_body,reply_message_id). Present on transfer-driven fetches; absent on the initial inbound fetch.
Examples
Transfer to an external SWML handler
YAMLJSON
version: 1.0.0
sections:
main:
- transfer:
dest: "https://example.com/messaging-handler"
params:
reason: "escalation"Route to different handlers based on keyword
YAMLJSON
version: 1.0.0
sections:
main:
- switch:
variable: message.body
transform: lowercase_trim
case:
sales:
- transfer:
dest: "https://example.com/sales-handler"
params:
source: "sms"
support:
- transfer:
dest: "https://example.com/support-handler"
params:
source: "sms"
default:
- reply:
body: "Reply SALES or SUPPORT to be routed to the right team."Template functions
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Template functions provide simple text transformations for common operations like converting to lowercase, URL encoding, and date formatting. They complement JavaScript expressions by handling specific formatting tasks that don’t require complex logic.
For information about variable scopes, see the Variables Reference. For JavaScript expressions and data manipulation, see the Expressions Reference.
Template functions are only available in SWAIG (SignalWire AI Gateway) contexts, specifically within:
- AI function
data_mapprocessing (expressions, webhooks, output) - Webhook responses to SWAIG functions
- AI prompt variable expansion
They are not available in regular SWML methods or general variable contexts. For regular SWML variable manipulation, use JavaScript expressions with the ${expression} syntax instead.
Reference
lc
string
Converts a string to lowercase. Commonly used to normalize user input for case-insensitive comparisons or ensure consistent casing when accessing object properties dynamically.
Syntax:${lc:<value>}
Example:
YAMLJSON
SWAIG:
functions:
- function: lookup
parameters:
type: object
properties:
department:
type: string
data_map:
expressions:
- string: '${meta_data.contacts.${lc:args.department}}'
pattern: '\w+'
output:
response: "Found contact for ${args.department}"
meta_data:
contacts:
sales: '+12025551234'
support: '+12025555678'enc:url
string
Encodes a string for safe use in URLs by converting special characters to percent-encoded equivalents. Always use this when including variables in URL query parameters or paths to prevent special characters from breaking URLs or causing unexpected behavior.
Syntax:${enc:url:<value>}
Example:
YAMLJSON
SWAIG:
functions:
- function: search
parameters:
type: object
properties:
query:
type: string
data_map:
webhooks:
- url: 'https://api.example.com/search?q=${enc:url:args.query}'
method: GET
output:
response: "Found ${results.total} results for ${args.query}"strftime_tz
string
Formats the current date and time using standard strftime format codes with timezone support. This generates timestamps at the moment the template is evaluated, not when the SWML script was created.
Syntax:@{strftime_tz <timezone> <format>}
Common format codes:
| Code | Description | Example |
|---|---|---|
%Y-%m-%d | ISO date | 2025-01-15 |
%H:%M:%S | 24-hour time | 14:30:45 |
%I:%M %p | 12-hour time | 02:30 PM |
%A, %B %d, %Y | Full readable date | Monday, January 15, 2025 |
Example:
YAMLJSON
SWAIG:
functions:
- function: log_call
data_map:
webhooks:
- url: 'https://api.example.com/logs'
method: POST
params:
timestamp: '@{strftime_tz America/Chicago %Y-%m-%d %H:%M:%S}'
call_id: '${call.call_id}'
from: '${call.from}'
output:
response: "Call logged successfully"fmt_ph
string
Formats a phone number using specified international format standards. Supports multiple format types for different use cases, with optional separators for improved text-to-speech pronunciation.
Syntax:@{fmt_ph <format> <phone_number>} or @{fmt_ph <format>:sep:<separator> <phone_number>}
Available formats:
national- National format (default)international- International format with country codeRFC3966- RFC 3966 format (tel: URI)e164- E.164 format (+1234567890)
Example:
YAMLJSON
SWAIG:
functions:
- function: format_number
data_map:
output:
response: |
International format: @{fmt_ph international ${call.from}}
Spaced format: @{fmt_ph national:sep:- ${call.from}}expr
string
Evaluates simple arithmetic expressions with literal numbers. Supports addition, subtraction, multiplication, division, and parentheses for grouping. Only works with literal numbers and cannot reference variables.
Syntax:@{expr <expression>}
Example:
YAMLJSON
SWAIG:
functions:
- function: calculate_discount
data_map:
output:
response: "The discount is @{expr (100 - 25) / 5} dollars"echo
string
Returns the argument unchanged. Primarily useful for debugging template evaluation or forcing explicit variable expansion in complex nested scenarios.
Syntax:@{echo <text>}
Example:
YAMLJSON
SWAIG:
functions:
- function: debug_value
parameters:
type: object
properties:
input:
type: string
data_map:
output:
response: "Debug value: @{echo ${args.input}}"separate
string
Inserts spaces between each character in a string to improve text-to-speech pronunciation. Particularly useful for spelling out confirmation codes, license plates, serial numbers, or any text that should be read character-by-character.
Syntax:@{separate <text>}
Example:
YAMLJSON
SWAIG:
functions:
- function: spell_code
parameters:
type: object
properties:
code:
type: string
data_map:
output:
response: "Your code is @{separate ${args.code}}"In this example, if code is “ABC123”, the AI will pronounce “A B C 1 2 3” instead of trying to say “ABC123” as a word.
sleep
string
Pauses execution for the specified number of seconds. Can be used for rate limiting, timing coordination, or testing purposes.
Syntax:@{sleep <seconds>}
Use sparingly in production environments. Excessive delays can cause timeouts, impact call quality, and degrade user experience. Best suited for development, testing, or specific rate-limiting scenarios.
Example:
YAMLJSON
SWAIG:
functions:
- function: delayed_task
data_map:
output:
response: "Executed after @{sleep 2} second delay"Function chaining
Prefix functions (using ${...} syntax) can be chained together to apply multiple transformations in sequence. The transformations are applied from left to right.
Syntax:${func1:func2:func3:<value>}
Example:
YAMLJSON
SWAIG:
functions:
- function: search
parameters:
type: object
properties:
query:
type: string
data_map:
webhooks:
# First converts to lowercase, then URL encodes
- url: 'https://api.example.com/search?q=${lc:enc:url:args.query}'
method: GET
output:
response: "Found results for ${args.query}"Full example
YAMLJSON
version: 1.0.0
sections:
main:
- answer: {}
- ai:
prompt:
text: |
You help users access department resources.
When they specify a department, use the lookup function.
SWAIG:
functions:
- function: lookup
parameters:
type: object
properties:
department:
type: string
data_map:
expressions:
- string: '${meta_data.contacts.${lc:args.department}}'
pattern: '\w+'
output:
response: "Found contact for ${args.department}"
meta_data:
contacts:
sales: '+12025551234'
support: '+12025555678'Variables
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
SWML provides a variable system for accessing call or message information, storing intermediate state, and passing data between sections. This page covers how to use variables: syntax, scopes, accessing nested fields, and deployment-mode differences.
For the authoritative field-by-field reference of what each scope contains, see the per-flavor overviews:
- Calling webhook and variable payload,
call,params,vars,envs - Messaging webhook and variable payload,
message,params,vars
For JavaScript expressions on top of variables, see Expressions. For template transformation functions, see Template Functions.
Syntax
Wrap a variable name in ${...} or %{...} anywhere inside a string value, and SignalWire substitutes the current value when the script runs. Use it to personalize a greeting with the caller’s number, pass a request body through to your backend, or pick a reply based on the inbound message body.
The two flavors of SWML accept slightly different forms.
Calling
In a Calling document, ${...} and %{...} are interchangeable, pick whichever reads more naturally in your YAML or JSON.
Reference a value. Use a plain path like ${call.from} or %{vars.user_choice}. Works for any field on call, params, envs, or vars. If the path is valid but the value isn’t set, the placeholder resolves to an empty string.
If the placeholder body isn’t a plain path, for example, it includes operators, method calls, or other JavaScript, it’s evaluated as a JavaScript expression instead. See Expressions.
YAMLJSON
version: 1.0.0
sections:
main:
- play:
url: 'say: This call is from ${call.from}'Messaging
A Messaging document uses %{...} only.
Reference a value. Use a plain path like %{message.from} or %{vars.reply_message_id}. Works for any field on message, params, or vars. If the path is valid but the value isn’t set, the placeholder resolves to an empty string.
YAMLJSON
version: 1.0.0
sections:
main:
- reply:
body: 'Received message from %{message.from}: %{message.body}'Variable scopes
The variables available at runtime are the same fields delivered on the inbound webhook payload for each SWML flavor. See the Calling webhook and variable payload and the Messaging webhook and variable payload for the authoritative list of scopes (call / message, params, vars, envs) and every field inside them.
Accessing nested data
Variables can hold simple values, nested objects, or arrays. Use dot notation (.) for object properties and bracket notation ([], zero-based) for array elements. The patterns below work identically inside ${...} and %{...}; the examples use calling syntax and the set method to seed the data.
YAMLJSON
version: 1.0.0
sections:
main:
- set:
user:
name: Alice
address:
city: Seattle
employees:
- name: Alice
role: Engineer
- name: Bob
role: Manager
- play:
url: 'say: ${user.name} lives in ${user.address.city}'
- play:
url: 'say: ${employees[0].name} is an ${employees[0].role}'
- play:
url: 'say: ${employees[1].name} is a ${employees[1].role}'The same patterns apply in messaging, for example, %{message.media[0].url} accesses the first media attachment’s URL.
Deployment modes
SWML can be hosted in two places, which affects how variable values get into your script.
Serverless (Dashboard-hosted)
The SWML document lives in the SignalWire Dashboard. SignalWire evaluates the placeholders against the live runtime context, no HTTP fetch is involved.
YAMLJSON
version: 1.0.0
sections:
main:
- set:
department: sales
- play:
url: 'say: You are calling from ${call.from}'
- play:
url: 'say: Department is ${vars.department}'Server-based (external URL)
SignalWire POSTs the runtime context to your server and your server returns the SWML document in response (see the Calling or Messaging payload reference for the request shape). You have two ways to use the variables:
1. Return SWML with placeholders. SignalWire substitutes at runtime, exactly the same syntax used in serverless mode. Best when you just need to interpolate values into otherwise-static SWML.
2. Substitute server-side before responding. Read variables from the request body in your server code, then build a SWML document with the values already filled in. Best when you need logic, transformations, or external lookups that can’t be expressed as a placeholder.
The ${...} in the example below is JavaScript template-literal syntax, not SWML variable expansion, it’s interpolated by Node.js before the response is sent.
// Example: Node.js / Express server
app.post('/swml-handler', (req, res) => {
const { call, vars, envs, params } = req.body;
// Pull values out of the request and apply your own logic
const department = params.department || 'support';
const callerNumber = call.from;
// Build SWML with concrete values already substituted
res.json({
version: '1.0.0',
sections: {
main: [\
{ play: { url: `say: Welcome to ${department}` } },\
{ play: { url: `say: Calling from ${callerNumber}` } },\
],
},
});
});See the Deployment Guide for complete server setup instructions.
