Skip to main content

AI-Zen

AI Zen is a tier 1 Digital Employee at the cable company Livewire


On this page, you'll find a full breakdown of the prompts used, along with all the functions. The functions are written in Perl. To quickly access all relevant files, please visit the GitHub repository.

Try it out!

Live demo coming soon.

Zen logo.

GitHub Repository

View the project and clone it to your development environment from the GitHub repository.


Server OS/applications used:

Prompt Used


# Your name is Zen. You speak English.

# Personality and Introduction

You are a witty assistant who likes to make light of every situation but is very dedicated to helping people. You are Zen and work for the local cable company Livewire. Greet the user with that information.

# Your Skills, Knowledge, and Behavior

## Reboot Modem

This will reboot the modem.

## Check Modem

Check if the modem is online or offline.

## Modem Speed Test

This will perform a speed test from the modem to a speed test site with speed_test function.

## Modem Speed Subscription

The customer subscribes to 1 gigabit download and 75 megabits upload.

## Modem Signal

The upstream can be between 40db and 50db. The downstream can be between -10db and +10db.

## SNR

SNR is signal-to-noise ratio. A good SNR is 30db to 40db.

## Swap Modem

Be sure to ask for new mac address. Read back to the provided mac address to verify it's accuracy. If the user verifies it is correct then use swap_modem function.

## Transfer Calls

You are able to transfer calls to the following destinations: Sales, Supervisor, Freeswitch, External.

## Customer Verification

You are able to verify customer first name, last name, cpni, account number and phone number with verify_customer function.

# Conversation Flow

These are the steps you need to follow during this conversation. Ensure you are strictly following the steps below in order.

## Step 1

Ask the user for their account number and CPNI, Then use verify_customer function to verify the customer . If the account number and CPNI are incorrect after 4 attempts, continue.

## Step 2

Perform a speed test and give the results from speed_test function then give the results.

## Step 3

Check modem levels with modem_diagnostics function and give the results.

## Step 4

Check modem SNR with modem_diagnostics function and give the results.

## Step 5

Ask the customer if there is anything else you can help them with.

## Step 6

End all calls with saying "Thank you for choosing Livewire."

Functions

Functions in this example will connect to a database and pull data with json output. In this example, once the function verify_customer is executed by the user verifing the account_number and cpni then the record for that customer can be used later. The prompt for this example won't allow any further steps to happen unless verify_customer is validated.

verify_customer

  • Name:verify_customer
  • Purpose:Verify customer account number, cpni first, last name and phone number
  • Argument:account_number|7 digit number,cpni|4 digit number

my $env = shift;
my $req = Plack::Request->new( $env );
my $swml = SignalWire::ML->new;
my $post_data = decode_json( $req->raw_body );
my $data = $post_data->{argument}->{parsed}->[0];
my $res = Plack::Response->new( 200 );
my $agent = $req->param( 'agent_id' );

my $dbh = DBI->connect(
"dbi:Pg:dbname=$database;host=$host;port=$port",
$dbusername,
$dbpassword,
{ AutoCommit => 1, RaiseError => 1 } ) or die "Couldn't execute statement: $DBI::errstr\n";
my $sql = "SELECT * FROM customers WHERE account_number = ? AND cpni = ? LIMIT 1";

my $sth = $dbh->prepare( $sql );
$sth->bind_param(1,$data->{account_number});
$sth->bind_param(2,$data->{cpni});
$sth->execute() or die "Couldn't execute statement: $DBI::errstr";

my $agents = $sth->fetchrow_hashref;


if ($data->{account_number} eq $agents->{account_number} && $data->{cpni} eq $agents->{cpni}) {
$res->body( $swml->swaig_response_json( { response => "Account verified, proceed", action => [ { set_meta_data => { customer => $agents } } ] } ) );
} else {
# This is the failure
$res->body( $swml->swaig_response_json( { response => "Account invalid try again" } ) ) ;
}

return $res->finalize;

Meta_Data Functions

Meta_Data Functions access the output of an already executed function. In this example once the function verify_customer is executed by the user by verifing account_number and CPNI (customer proprietary network information). That customer's record is then accessable via JSON for any meta_data functions.

modem_swap

  • Name:modem_swap
  • Purpose:Swap the users modem
  • Argument:mac_address|new modem MAC Address in lowercase hex 12 characters

my $env = shift;
my $req = Plack::Request->new( $env );
my $swml = SignalWire::ML->new;
my $post_data = decode_json( $req->raw_body );
my $data = $post_data->{argument}->{parsed}->[0];
my $res = Plack::Response->new( 200 );
my $agent = $req->param( 'agent_id' );
my $customer = $post_data->{meta_data}->{customer};

sub is_valid_mac_address {
my ($mac) = @_;

# Regular expression for a MAC address with optional colons or dashes
my $mac_regex = qr/^([0-9A-Fa-f]{2}(:|-)?){5}[0-9A-Fa-f]{2}$/;

return $mac =~ $mac_regex;
}

my $dbh = DBI->connect(
"dbi:Pg:dbname=$database;host=$host;port=$port",
$dbusername,
$dbpassword,
{ AutoCommit => 1, RaiseError => 1 } ) or die "Couldn't execute statement: $DBI::errstr\n";

if ( is_valid_mac_address($data->{mac_address}) ) {
# Add a SQL update statement (modify this to match your actual table and field names)
my $update_sql = "UPDATE customers SET mac_address = ? WHERE account_number = ?";
my $update_sth = $dbh->prepare( $update_sql );
$update_sth->bind_param(1, $data->{mac_address});
$update_sth->bind_param(2, $customer->{account_number});
$update_sth->execute() or die "Couldn't execute statement: $DBI::errstr";

$update_sth->finish;

# Your existing SELECT query
my $select_sql = "SELECT * FROM customers WHERE account_number = ? LIMIT 1";
my $select_sth = $dbh->prepare( $select_sql );
$select_sth->bind_param(1, $customer->{account_number} );
$select_sth->execute() or die "Couldn't execute statement: $DBI::errstr";

my $agents = $select_sth->fetchrow_hashref;

$select_sth->finish;

if (lc $agents->{mac_address} eq lc $data->{mac_address} ) {
$res->body( $swml->swaig_response_json( { response => "Customers modem mac address updated, please allow 5 minutes for all systems to update and plug in your new modem.", action => [ { set_meta_data => { customer => $agents } } ] } ) );
broadcast_by_agent_id( $agent, $agents );

} else {
$res->body( $swml->swaig_response_json( { response => "Error swapping modem, mac address may be invalid, try again. #1" } ) );
}
} else {
$res->body( $swml->swaig_response_json( { response => "Error swapping modem, mac address may be invalid, try again later. #2" } ) );
}

return $res->finalize;

speed_test

  • Name:speed_test
  • Purpose:Test upload and download speed from the modem
  • Argument:account_number|7 digit number,cpni|4 digit number

my $env = shift;
my $req = Plack::Request->new( $env );
my $swml = SignalWire::ML->new;
my $post_data = decode_json( $req->raw_body );
my $data = $post_data->{argument}->{parsed}->[0];
my $res = Plack::Response->new( 200 );
my $agent = $req->param( 'agent_id' );
my $customer = $post_data->{meta_data}->{customer};

if ($customer->{modem_speed_upload} && $customer->{modem_speed_download}) {
$res->body( $swml->swaig_response_json( { response => "Tell the user here are the test results. Download speed: $customer->{modem_speed_download}, Upload speed: $customer->{modem_speed_upload}" } ) );
} else {
$res->body( $swml->swaig_response_json( { response => "Invalid try again speed_test" } ) );
}

return $res->finalize;

modem_diagnostics

  • Name:modem_diagnostics
  • Purpose:customer modem upstream downstream and snr levels
  • Argument:account_number|7 digit number,cpni|4 digit number

my $env = shift;
my $req = Plack::Request->new( $env );
my $swml = SignalWire::ML->new;
my $post_data = decode_json( $req->raw_body );
my $data = $post_data->{argument}->{parsed}->[0];
my $res = Plack::Response->new( 200 );
my $agent = $req->param( 'agent_id' );
my $customer = $post_data->{meta_data}->{customer};

if ($customer) {
$res->body( $swml->swaig_response_json( { response => "Tell the user here are the test results. Downstream level: $customer->{modem_downstream_level}, Upstream level: $customer->{modem_upstream_level}, Modem SNR: $customer->{modem_snr}" } ) );
} else {
$res->body( $swml->swaig_response_json( { response => "Invalid try again. Use modem-diagnostics-function" } ) );
}

return $res->finalize;

GitHub

Check out the full project repository for the Zen demo on GitHub.


SignalWire

SignalWire’s AI Agent for Voice allows you to build and deploy your own digital employee. Powered by advanced natural language processing (NLP) capabilities, your digital employee will understand caller intent, retain context, and generally behave in a way that feels “human-like”.
In fact, you may find that it behaves exactly like your best employee, elevating the customer experience through efficient, intelligent, and personalized interactions.

Made with ❤️ by SignalWire's DevEx team

Have feedback on this site? Drop us a line at devex@signalwire.com or visit the Community Slack.