Skip to main content

Swml

SWML (SignalWire Markup Language)

Summary: SWML is the JSON format that tells SignalWire how to handle calls. Your agent generates SWML automatically - you configure the agent, and it produces the right SWML.

What is SWML?

SWML (SignalWire Markup Language) is a document that instructs SignalWire how to handle a phone call. SWML can be written in JSON or YAML format - this guide uses JSON throughout. When a call comes in, SignalWire requests SWML from your agent, then executes the instructions.

┌─────────────────────────────────────────────────────────────────────────────┐
│ SWML Flow │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Call Arrives │
│ │ │
│ ▼ │
│ 2. SignalWire requests: POST https://your-agent.com/ │
│ │ │
│ ▼ │
│ 3. Your agent returns SWML JSON │
│ │ │
│ ▼ │
│ 4. SignalWire executes the SWML instructions │
│ │ │
│ ▼ │
│ 5. AI conversation begins based on SWML config │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

SWML Document Structure

Every SWML document has this structure:

{
"version": "1.0.0",
"sections": {
"main": [
{ "verb1": { ...config } },
{ "verb2": { ...config } },
{ "verb3": { ...config } }
]
}
}

Key parts:

  • version: Always "1.0.0"
  • sections: Contains named sections (usually just main)
  • Each section is an array of verbs (instructions)

Common Verbs

VerbPurposeExample
answerAnswer the incoming call{"answer": {}}
aiStart AI conversation{"ai": {...config}}
connectTransfer to another number{"connect": {"to": "+1..."}}
playPlay audio file{"play": {"url": "..."}}
record_callRecord the call{"record_call": {"format": "mp4"}}
hangupEnd the call{"hangup": {}}

A Complete SWML Example

Here's what your agent generates:

{
"version": "1.0.0",
"sections": {
"main": [
{
"answer": {}
},
{
"ai": {
"prompt": {
"text": "# Role\nYou are a helpful customer service agent.\n\n# Guidelines\n- Be professional\n- Be concise"
},
"post_prompt": "Summarize what was discussed",
"post_prompt_url": "https://your-agent.com/post_prompt",
"SWAIG": {
"defaults": {
"web_hook_url": "https://your-agent.com/swaig"
},
"functions": [
{
"function": "get_balance",
"description": "Get the customer's account balance",
"parameters": {
"type": "object",
"properties": {
"account_id": {
"type": "string",
"description": "The account ID"
}
},
"required": ["account_id"]
}
}
]
},
"hints": ["account", "balance", "payment"],
"languages": [
{
"name": "English",
"code": "en-US",
"voice": "rime.spore"
}
],
"params": {
"end_of_speech_timeout": 500,
"attention_timeout": 15000
}
}
}
]
}
}

The ai Verb in Detail

The ai verb is the heart of voice AI agents. Here's what each part does:

{
"ai": {
"prompt": {}, // What the AI should do (system prompt)
"post_prompt": "...", // Instructions for summarizing the call
"post_prompt_url": "...",// Where to send the summary
"SWAIG": {}, // Functions the AI can call
"hints": [], // Words to help speech recognition
"languages": [], // Voice and language settings
"params": {}, // AI behavior parameters
"global_data": {} // Data available throughout the call
}
}

prompt

The AI's system prompt - its personality and instructions:

{
"prompt": {
"text": "You are a helpful assistant..."
}
}

Or using POM (Prompt Object Model):

{
"prompt": {
"pom": [
{
"section": "Role",
"body": "You are a customer service agent"
},
{
"section": "Rules",
"bullets": ["Be concise", "Be helpful"]
}
]
}
}

SWAIG

Defines functions the AI can call:

{
"SWAIG": {
"defaults": {
"web_hook_url": "https://your-agent.com/swaig"
},
"functions": [
{
"function": "check_order",
"description": "Check order status",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string"}
}
}
}
]
}
}

hints

Words that help speech recognition accuracy:

{
"hints": ["SignalWire", "SWML", "account number", "order ID"]
}

languages

Voice and language configuration:

{
"languages": [
{
"name": "English",
"code": "en-US",
"voice": "rime.spore"
}
]
}

params

AI behavior settings:

{
"params": {
"end_of_speech_timeout": 500,
"attention_timeout": 15000,
"barge_match_string": "stop|cancel|quit"
}
}

How Your Agent Generates SWML

You don't write SWML by hand. Your agent configuration becomes SWML:

from signalwire_agents import AgentBase


class MyAgent(AgentBase):
def __init__(self):
super().__init__(name="my-agent")

# This becomes languages in SWML
self.add_language("English", "en-US", "rime.spore")

# This becomes prompt in SWML
self.prompt_add_section("Role", "You are helpful.")

# This becomes hints in SWML
self.add_hints(["help", "support"])

# This becomes params in SWML
self.set_params({"end_of_speech_timeout": 500})

# This becomes SWAIG.functions in SWML
self.define_tool(
name="get_help",
description="Get help information",
parameters={},
handler=self.get_help
)

When SignalWire requests SWML, the agent's _render_swml() method:

  1. Collects all configuration (prompts, languages, hints, params)
  2. Builds the SWAIG functions array with webhook URLs
  3. Assembles the complete SWML document
  4. Returns JSON to SignalWire

SWML Rendering Pipeline

┌─────────────────────────────────────────────────────────────────────────────┐
│ SWML Rendering Pipeline │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Request Arrives (GET /) │
│ │ │
│ ▼ │
│ 2. _render_swml() called │
│ │ │
│ ├───► Get prompt (text or POM) │
│ ├───► Get post-prompt │
│ ├───► Collect SWAIG functions │
│ ├───► Generate security tokens │
│ ├───► Build webhook URLs │
│ ├───► Collect hints, languages, params │
│ │ │
│ ▼ │
│ 3. Assemble AI verb │
│ │ │
│ ▼ │
│ 4. Build document: answer + ai verbs │
│ │ │
│ ▼ │
│ 5. Return SWML JSON │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Viewing Your SWML

You can see the SWML your agent generates:

## Using curl
curl http://localhost:3000/

## Using swaig-test CLI
swaig-test my_agent.py --dump-swml

## Pretty-printed
swaig-test my_agent.py --dump-swml --raw | jq '.'

SWML Schema Validation

The SDK validates SWML against the official schema:

  • Located at signalwire_agents/core/schema.json
  • Catches invalid configurations before sending to SignalWire
  • Provides helpful error messages

Common SWML Patterns

Auto-Answer with AI

{
"version": "1.0.0",
"sections": {
"main": [
{"answer": {}},
{"ai": {...}}
]
}
}

Record the Call

{
"version": "1.0.0",
"sections": {
"main": [
{"answer": {}},
{"record_call": {"format": "mp4", "stereo": true}},
{"ai": {...}}
]
}
}

Transfer After AI

When a SWAIG function returns a transfer action, the SWML for transfer is embedded in the response:

{
"response": "Transferring you now",
"action": [
{"transfer": true},
{
"swml": {
"version": "1.0.0",
"sections": {
"main": [
{"connect": {"to": "+15551234567", "from": "+15559876543"}}
]
}
}
}
]
}

Next Steps

Now that you understand SWML structure, let's look at SWAIG - how AI calls your functions.