From Small Biz to Smart Biz with AI
β‘οΈ LIVEWire Developer Docs
Deploy an AI-powered voice agent with server logic to a phone number
The companion developer guide to the LIVEWire event Wednesday May 8th, 2024 11:00am PT / 2:00pm ET
This demo guides you through installing and setting up the WireStarter Docker container, configuring it with SWSH (the SignalWire Interactive Shell), and connecting a SWML Script to a Python application running a local server to handle logic. The server is Flask and itβs exposed to the SWML Script via an ngrok tunnel.
At the end of the demo, you'll be able to call your SignalWire phone number and speak with an AI agent that communicates back and forth with your new server to make decisions.
π Definitionsβ
- WireStarter: A Docker container that simplifies the setup of SignalWire SDKs and development environments.
- SWSH (SignalWire interactive SHell): A command line utility built in to WireStarter that interfaces with SignalWire APIs.
- SWML (SignalWire Markup Language): A hybrid markup and scripting language for writing RELAY applications (realtime interacative communication applications using Websockets) using simple statements in YAML or JSON.
- SWML Script: A cloud execution solution for hosting and running SWML in "bins" on your SignalWire Dashboard.
- Flask: A Python web application framework for Python, used here for our server.
- ngrok: A tunneling service used here to create a secure tunnel from our local Flask server to the SWML Script.
ποΈ Application Structureβ
π Prerequisitesβ
Before getting started, please make sure you have the following prerequisites.
- Sign up for a free SignalWire Space
- Install Docker Desktop
- Buy a SignalWire Phone Number
- Create a free ngrok account
Everything else you need is built into WireStarter.
Ask SignalWire staff for a promo code to elevate your account out of Trial status and add extra credit to your account.
1. π Set up WireStarterβ
WireStarter is a Docker container which sets up the SignalWire SDKs and builds a development and testing environment for new developers.
WireStarter has been updated recently. If you've used WireStarter before, be sure to delete the previous version and reinstall the latest version of the container.
- Open Docker Desktop
Docker Desktop must be running at the start of the process.
- Install and Run WireStarter
Run the following command from your system terminal to download and install the WireStarter Docker Container.
docker run -it -d --rm --name wirestarter briankwest/wirestarter:latest
If you already have the latest version of WireStarter installed, you can also start it from the Images window in Docker Desktop.
- Start and Configure SWSH
Now that WireStarter is installed and running, we will start SWSH (the SignalWire Interactive Shell) in the Container.
SWSH will ask for your SignalWire Space ID, SignalWire Project ID, SignalWire Project Token, ngrok Token, and ngrok Args (most users should leave ngrok Args blank). Make sure you have that information handy by opening the SignalWire 'tokens' page and the ngrok 'Your Authtoken' page.
Switch over to Docker Desktop, and open the running WireStarter container.
Click on the Exec
tab to open the integrated terminal.

In that tab, run the following command to start SWSH:
exec bash
After you enter your authentication information, SWSH will automatically open an NGROK Tunnel and display the NGROK Tunnel URL in the integrated terminal output. Save this URL - we'll need it in the next step!

If the WireStarter container is stopped and restarted, NGROK will generate a new tunnel URL. To avoid reentering this URL in the SWML script (as shown in the following step), keep the WireStarter container running throughout the demo.
2. π Create the SWML Scriptβ
The call flow will be handled by a SWML (SignalWire Markup Language) Script, which itself seeks logic from the websocket we will host locally using Flask.
To create a SWML Script, navigate to the Relay / SWML page of your SignalWire Dashboard.
On that page, select the SWML Scripts tab as shown in the below screenshot.

Click Create a SWML Script.
Name the Script "vicky
", and
copy and paste the following SWML into the text box labeled SWML
.
{
"version" : "1.0.0",
"sections" : {
"main" : [
{
"ai" : {
"prompt" : {
"top_p" : 0.3,
"text" : "Hello, I'm Vickey a virtual assistant.",
"temperature" : 0.3
},
"post_prompt" : {
"text" : "Summarize the conversation"
},
"SWAIG" : {
"functions" : [
{
"argument" : {
"type" : "object",
"properties" : {
"phone" : {
"description" : "The users phone number in e164 format",
"type" : "string"
},
}
},
"function" : "whats_up",
"purpose" : "When users ask what's up brother"
},
{
"argument" : {
"type" : "object",
"properties" : {
"phone" : {
"description" : "The users phone number in e164 format",
"type" : "string"
},
}
},
"function" : "whats_day",
"purpose" : "When users ask what day it is"
}
],
"defaults" : {
"web_hook_url" : [NGROK_TUNNEL_HOST]/swaig
}
},
"languages" : [
{
"voice" : "nova",
"name" : "English",
"code" : "en-US",
"engine" : "openai"
}
]
}
}
]
}
}
Replace [NGROK_TUNNEL_HOST]
with the actual NGROK Tunnel URL generated in the previous step.
Append /swaig
to the end of the URL.
The complete `web_hook_url" should look like this:
...
"defaults" : {
"web_hook_url" : "https://1234-56-78-901-23.ngrok-free.app/swaig"
}
...
After saving the SWML Script, navigate to the Phone Numbers page of your SignalWire Dashboard. Select the number you wish to use for this demo.
Click Edit Settings. Set "Handle Calls Using" to "a SWML Script", and select the "vicky" SWML Script using the drop-down menu.
3. π Create project directories and copy in the Python appβ
In this step, we will download our server Python application and set it up to run within the WireStarter container. This app includes logic which our SWML Script will trigger via HTTP requests to its websocket connection. The Python app uses Flask to create a local server on the WireStarter container, which WireStarter in turn exposes to the NGROK Tunnel URL.
Copy the below Python code and save it as app.py
in your Downloads folder.
Alternatively, download app.py
directly using the button below.
from flask import Flask, jsonify, request
import json
app = Flask(__name__)
@app.route('/swaig', methods=['POST'])
def swaig():
request_data = request.get_json()
print("Received request data:\n", json.dumps(request_data, indent=4))
response_message = {"response": "Tell the user: special teams, special plays, special players" }
print("Response data:\n", json.dumps(response_message, indent=4))
return jsonify(response_message)
if __name__ == '__main__':
app.run(debug=True)
Return to the integrated terminal in the running WireStarter Docker Container.
Enter exit
once to exit SWSH.
Navigate to the root of the container using cd /
.
Then, run the following command to create a folder named livewire
within workdir
in the container:
mkdir /workdir/livewire
Return to your system terminal, and navigate to your Downloads folder.
Copy the container ID from the Containers view in Docker Desktop.

Finally, run the following command in your system terminal to copy app.py
into /workdir/livewire/
within the WireStarter container.
Replace [container-id]
with the WireStarter container ID from Docker Desktop.
docker cp app.py [container-id]:/workdir/livewire/

app.py
into /workdir/livewire/
in the WireStarter container using the Docker CLI.4. π Run and test the applicationβ
- Run
app.py
Return to the Docker integrated terminal. From the root of the container filesystem, run the Python application using the below command:
python3 /workdir/livewire/app.py
Alternatively, you can navigate to /workdir/livewire/
and run python3 app.py
.

app.py
running inside the WireStarter container. Flask has started and is running on a local address.- Dial the phone number
We did it!
The application should now be ready to test. Using your cell phone or softphone, dial the phone number you assigned to the SWML Script back in Step 2. Vicky will answer.
- Test the server logic
Our demo Python app is set up with very minimal logic - that's where your creativity comes in!
To make sure the SWML Script is correctly contacting our server, ask Vicky "what day is it?" or "what's up, brother?"
If Vicky responds, "special teams, special plays, special players," you know the demo is working.
Congratulations!
π§° Troubleshootingβ
- Vicky says something isn't available and nothing shows up in the Docker integrated terminal logs
This occurs when the SWML Script is unable to reach the websocket.
This often occurs when the NGROK url is incorrect, so first,
check it for typos.
If you have stopped and restarted the WireStarter container,
you'll need to update the "web_hook_url"
in the SWML Script with the new NGROK Tunnel URL,
as this regenerated on container restart.
- The Python app sends 404 responses (seen in the Docker logs) when Vicky contacts the Python app
This occurs when the NGROK tunnel URL is correctly set in the SWML script, but it is missing the /swaig
path.
Made with β€οΈ by SignalWire's DevEx teamβ
Have feedback on this site? Drop us a line at devex@signalwire.com or say hi on the Community Discord.