Duration 2 hours
Day 1 of 2

Learning Objectives

By the end of this module, students will be able to:

  • Explain the structure of SWML documents
  • Identify key SWML verbs and their purposes
  • Understand how SignalWire processes SWML
  • Trace the request/response lifecycle

Topics

1. What is SWML? (20 min)

SignalWire Markup Language

SWML (SignalWire Markup Language) is a JSON-based document format that tells SignalWire how to handle calls.

Key Concept

Your Agent creates SWML → SignalWire executes SWML → Caller experiences the result

Why SWML?

Benefit Description
Declarative Describe what, not how
Portable Works across deployments
Cacheable Can be pre-generated
Debuggable JSON is easy to inspect

SWML vs Code

Traditional approach:

# Pseudo-code - handling each event
on_call_start:
    say("Hello")
on_speech_detected:
    process(speech)
    generate_response()
    say(response)

SWML approach:

{
  "ai": {
    "prompt": { "text": "You are helpful..." }
  }
}

SignalWire handles all the event processing!


2. SWML Document Structure (30 min)

Basic Structure

{
  "version": "1.0.0",
  "sections": {
    "main": [
      { "verb": { "parameters": "..." } }
    ]
  }
}

Required Elements

Element Purpose
version SWML spec version (always “1.0.0”)
sections Container for call flows
main Default entry point

Sections

Sections are named flows. main always executes first:

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

Verbs

Verbs are actions within sections:

{
  "sections": {
    "main": [
      { "answer": {} },
      { "play": { "url": "greeting.mp3" } },
      { "ai": { "prompt": { "text": "..." } } }
    ]
  }
}

3. The AI Verb (30 min)

Core of Voice AI

The ai verb creates an AI-powered conversation:

{
  "ai": {
    "prompt": {
      "text": "You are a helpful assistant."
    },
    "languages": [
      {
        "name": "English",
        "code": "en-US",
        "voice": "rime.spore"
      }
    ]
  }
}

AI Verb Components

{
  "ai": {
    "prompt": { },           // System instructions
    "languages": [ ],        // Voice configuration
    "params": { },           // AI behavior settings
    "SWAIG": { },            // Function definitions
    "hints": [ ],            // Speech recognition hints
    "post_prompt": { }       // Call summary instructions
  }
}

Prompt Structure

{
  "prompt": {
    "text": "Main prompt text",
    "temperature": 0.7,
    "top_p": 0.9
  }
}

Language Configuration

{
  "languages": [
    {
      "name": "English",
      "code": "en-US",
      "voice": "rime.spore",
      "speech_fillers": ["One moment...", "Let me check..."]
    }
  ]
}

SWAIG Functions

{
  "SWAIG": {
    "functions": [
      {
        "function": "get_weather",
        "description": "Get current weather",
        "parameters": {
          "type": "object",
          "properties": {
            "city": { "type": "string" }
          }
        }
      }
    ],
    "defaults": {
      "web_hook_url": "https://your-agent.com/swaig"
    }
  }
}

4. Common SWML Verbs (25 min)

Answer

Pick up the call:

{ "answer": { "max_duration": 3600 } }

Play

Play audio file:

{ "play": { "url": "https://example.com/greeting.mp3" } }

Say (TTS)

Text-to-speech:

{ "say": { "text": "Hello, welcome to our service." } }

Connect

Transfer to another destination:

{
  "connect": {
    "to": "+15551234567",
    "from": "+15559876543"
  }
}

Hangup

End the call:

{ "hangup": { "reason": "completed" } }

Verb Reference Table

Verb Purpose Key Parameters
answer Answer incoming call max_duration
hangup End call reason
play Play audio url, volume
say Text-to-speech text, voice
ai AI conversation prompt, languages, SWAIG
connect Transfer call to, from
record Record audio format, stereo

5. Request/Response Flow (15 min)

Initial Request

When a call arrives, SignalWire sends:

POST /your-agent HTTP/1.1
Content-Type: application/json

{
  "call": {
    "call_id": "abc123",
    "from": "+15551234567",
    "to": "+15559876543",
    "direction": "inbound"
  }
}

Your Response

Your agent returns SWML:

HTTP/1.1 200 OK
Content-Type: application/json

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

Function Calls

During conversation, SignalWire calls your SWAIG endpoint:

POST /your-agent/swaig HTTP/1.1
Content-Type: application/json

{
  "function": "get_weather",
  "argument": {
    "parsed": [{ "city": "Seattle" }]
  }
}

Your response:

{
  "response": "The weather in Seattle is 65°F and cloudy."
}

SDK Abstraction

What You Write

agent = AgentBase(name="my-agent")

agent.prompt_add_section("Role", "You are helpful.")
agent.add_language("English", "en-US", "rime.spore")

@agent.tool(
    description="Get weather",
    parameters={
        "type": "object",
        "properties": {
            "city": {"type": "string", "description": "The city to get weather for"}
        },
        "required": ["city"]
    }
)
def get_weather(args: dict, raw_data: dict = None) -> SwaigFunctionResult:
    city = args.get("city", "")
    return f"Weather in {city}: 65°F"

What Gets Generated

{
  "version": "1.0.0",
  "sections": {
    "main": [
      {
        "ai": {
          "prompt": {
            "text": "# Role\nYou are helpful."
          },
          "languages": [{
            "name": "English",
            "code": "en-US",
            "voice": "rime.spore"
          }],
          "SWAIG": {
            "functions": [{
              "function": "get_weather",
              "description": "Get weather",
              "parameters": {
                "type": "object",
                "properties": {
                  "city": { "type": "string" }
                }
              }
            }]
          }
        }
      }
    ]
  }
}

The SDK handles all the JSON generation!


Key Takeaways

  1. SWML is declarative - Describe the experience, not the implementation
  2. JSON structure is fixed - version, sections, main
  3. AI verb is the core - Most voice AI uses this
  4. SDK generates SWML - You write Python, it creates JSON
  5. Inspect with swaig-test - Always verify generated output

Common Mistakes

1. Invalid JSON

SWML must be valid JSON. Use swaig-test --dump-swml to validate.

2. Missing Main Section

Every SWML needs a main section in sections.

3. Wrong Verb Order

Verbs execute sequentially. answer should come before ai.

Preparation for Lab 1.3

  • Have a working agent from Lab 1.2
  • swaig-test ready
  • Text editor for JSON inspection

Lab Preview

In Lab 1.3, you will:

  1. Generate SWML from your agent
  2. Modify AI parameters
  3. Trace the call flow
  4. Understand function registration

Back to top

SignalWire AI Agents Certification Program