Skip to content

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: SWML

Pronounce

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: jif

ai_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:

  1. 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.
  2. It sends the running transcript to the model, along with your operator prompt and your SWAIG tools.
  3. The model returns a single line of agent-facing advice (an insight), or calls the built-in sidecar_skip tool to stay silent when no advice is needed.
  4. Any tools the model calls (lookups, alerts, intent triggers) run through your SWAIG functions and MCP servers.
  5. 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 topiccalling.ai.sidecar, always fires. Subscribe with the SignalWire RELAY or browser SDK to consume callbacks in real time.
  • Webhook, fires only when url is set, as an HTTP POST to that URL with the callback body wrapped under sidecar_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.

typeWhenKey fields
startThe sidecar attached to the callmodel, tools (the tool names available), global_data
turnThe customer finished a turn (an evaluation is about to run)transcript_delta, customer_text, agent_text
requestThe sidecar called the modelmodel, iter, messages_count, messages_token_count, tool_choice
thoughtThe model produced text while still working, for example alongside a tool calltext, iter
insightThe sidecar’s advice for the agentraw (the advice text), iter, total_iters
skipThe model called sidecar_skip to stay silent for this turnreason?
tool_callThe model called one of your toolsname, arguments?, iter
tool_resultOne of your tools returned a resultname, response, iter
actionA SWAIG action was returned (and, if enabled, executed)action, source_function?, executed
global_data_changeA set_global_data / unset_global_data action changed global_datakey, old_value?, new_value?
history_prunedThe conversation history was trimmed to fit the token budgetdropped_count, kept_count, tokens_before, tokens_after
errorSomething failed, or an anti-loop guard trippederror_reason, detail?
ask_requestAn ai_sidecar.ask was queuedquestion, ask_id
ask_answerThe answer to an ai_sidecar.askraw, iter, total_iters, ask_id, triggered_by
stopThe sidecar is shutting downstop_reason
finalThe last callback before the sidecar stops, a full snapshot of the sessionstop_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_reasonTrigger
transcribe_closeThe call ended normally
transferredA SWAIG transfer action terminated the call
hung_upA SWAIG hangup action terminated the call
stop_actionA SWAIG stop action stopped the sidecar (transcription continues)
api_stopThe sidecar was stopped programmatically

Error reasons

The error callback carries an error_reason describing the failure.

error_reasonTrigger
tool_loopAn 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_allowedAn SWML action was requested but swaig_allow_swml is false
llm_errorThe model call returned an error. detail carries the provider’s error message
webhook_http_failureA tool’s webhook request failed. Carries the function name, the http_code returned, and the curl_code
event_log_truncatedThe 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_sidecar and plain live_transcribe cannot 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, only remote-caller) is rejected.
  • Turn detection is tuned for Deepgram.deepgram is the default speech engine, and turn-end detection is calibrated for it.
  • say doesn’t speak. The sidecar has no voice on the call, so a say action 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 final callback fires and it stops.
  • sidecar_skip is 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 error callback with error_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 a text field. 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.rachel

Configure 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.9

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.

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

ValueApplies toWhat it does
heardCaller inputConverts what the caller says into written form before the AI reads it, for example, “twenty three dollars” becomes $23.
spokenAI responsesConverts the AI’s written response into spoken form before it is read aloud, for example, $23 becomes “twenty three dollars”.
bothCaller input and AI responsesApplies both conversions. This is the default.
false / off / none,Turns text normalization off.
true / onCaller input and AI responsesSame 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 default context 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 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)
*.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.6

POM 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 animal

Basic 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:
                    - default

Advanced 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:
                    - question

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

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 in ai.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.

CodeDescription
defaultDefault language set by the user in the ai.languages property
bgBulgarian
caCatalan
csCzech
daDanish
da-DKDanish (Denmark)
deGerman
de-CHGerman (Switzerland)
elGreek
enEnglish
en-AUEnglish (Australia)
en-GBEnglish (United Kingdom)
en-INEnglish (India)
en-NZEnglish (New Zealand)
en-USEnglish (United States)
esSpanish
es-419Spanish (Latin America)
etEstonian
fiFinnish
frFrench
fr-CAFrench (Canada)
hiHindi
huHungarian
idIndonesian
itItalian
jaJapanese
koKorean
ko-KRKorean (South Korea)
ltLithuanian
lvLatvian
msMalay
multiMultilingual (Spanish + English)
nlDutch
nl-BEFlemish (Belgian Dutch)
noNorwegian
plPolish
ptPortuguese
pt-BRPortuguese (Brazil)
pt-PTPortuguese (Portugal)
roRomanian
ruRussian
skSlovak
svSwedish
sv-SESwedish (Sweden)
thThai
th-THThai (Thailand)
trTurkish
ukUkrainian
viVietnamese
zhChinese (Simplified)
zh-CNChinese (Simplified, China)
zh-HansChinese (Simplified Han)
zh-HantChinese (Traditional Han)
zh-HKChinese (Traditional, Hong Kong)
zh-TWChinese (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., 120 for 120 seconds)
  • An object with a timeout property

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_unhold command 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[].SWML payload in the same action object. When true, ends the AI session and hard-transfers the call to that SWML. When omitted or false, 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 for transfer.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., 120 for 120 seconds)
  • An object with a timeout property

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_unhold command 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[].SWML payload in the same action object. When true, ends the AI session and hard-transfers the call to that SWML. When omitted or false, 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 for transfer.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: string

data_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:

  1. expressions - Processes data using pattern matching (includes its own output)
  2. webhooks - Makes external API calls (includes its own output and expressions)
  3. 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:

  1. A response object: Contains static text for the AI agent’s context
  2. An optional action object: 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., 120 for 120 seconds)
  • An object with a timeout property

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_unhold command 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[].SWML payload in the same action object. When true, ends the AI session and hard-transfers the call to that SWML. When omitted or false, 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 for transfer.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.'
  • 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: string

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.

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 in ai.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., 120 for 120 seconds)
  • An object with a timeout property

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_unhold command 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[].SWML payload in the same action object. When true, ends the AI session and hard-transfers the call to that SWML. When omitted or false, 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 for transfer.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., 120 for 120 seconds)
  • An object with a timeout property

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_unhold command 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[].SWML payload in the same action object. When true, ends the AI session and hard-transfers the call to that SWML. When omitted or false, 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 for transfer.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: string

data_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:

  1. expressions - Processes data using pattern matching (includes its own output)
  2. webhooks - Makes external API calls (includes its own output and expressions)
  3. 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:

  1. A response object: Contains static text for the AI agent’s context
  2. An optional action object: 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., 120 for 120 seconds)
  • An object with a timeout property

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_unhold command 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[].SWML payload in the same action object. When true, ends the AI session and hard-transfers the call to that SWML. When omitted or false, 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 for transfer.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: 60

cond

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 connect
  • connected, Successfully connected
  • failed, Connection failed
  • disconnected, 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 active
  • finished, 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_room

Dial 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: PCMU

Set 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 queue
  • leave - Caller left without being bridged
  • dequeue - 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 queue
    • connecting - Call is in the process of connecting to an agent
    • connected - Successfully connected to an agent
    • leaving - Call is leaving the queue
    • timeout - Waited too long and timed out
    • hangup - Caller hung up while waiting
    • failed - 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 params object is passed, along with the variables and the call object. 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.

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: 12345

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: 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: 3

Loop 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: 3

hangup

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_room

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 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: 3

live_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: deepgram

live_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

ActionCall startLive 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 (in start): Automatically generates summary when session ends
  • summarize action: 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: deepgram

pay

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 timeout
  • invalid-card-number - Failed card validation
  • invalid-card-type - Unsupported card type
  • invalid-date - Invalid expiration date
  • invalid-security-code - Invalid CVV format
  • invalid-postal-code - Invalid postal code format
  • session-in-progress - Concurrent session attempt
  • invalid-bank-routing-number - Invalid bank routing number
  • invalid-bank-account-number - Invalid bank account number
  • input-matching-failed - Input matching failed
  • card-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 the max_attempts limit.
  • 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 the STOP command.
  • 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: 10

Custom 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.ringAvailable 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.ringAvailable 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, or no_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: mp3

Record 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 if save_variables is 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: 1

Return 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: 2

using 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: hello

Return 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: 5000

Forever Sleep Example

YAMLJSON

version: 1.0.0
sections:
  main:
    - sleep: -1

stop_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-id

stop_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-id

stop_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-id

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.

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-stream

Stream 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: gold

switch

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/tap

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.

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-status

transcribe_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 of username:password@url. The params object is passed, along with the variables and the call object.

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 the script_error variable and as calling.script.warning events.
  • 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 reply is called multiple times in a single document, each reply’s status_url is 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: null

Return from main to stop execution

YAMLJSON

version: 1.0.0
sections:
  main:
    - reply:
        body: "Got it."
    - return: null

switch

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 this transfer step.
  • 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_map processing (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:

CodeDescriptionExample
%Y-%m-%dISO date2025-01-15
%H:%M:%S24-hour time14:30:45
%I:%M %p12-hour time02:30 PM
%A, %B %d, %YFull readable dateMonday, 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 code
  • RFC3966 - 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.

SignalWire Developer Documentation