SignalWire SDK for Perl

Build AI voice agents, control live calls over WebSocket, and manage every SignalWire resource over REST -- all from one package.

Documentation · Report an Issue · CPAN

Discord MIT License GitHub Stars

Open in GitHub Codespaces Run on Replit

What's in this SDK

| Capability | What it does | Quick link | |-----------|-------------|------------| | AI Agents | Build voice agents that handle calls autonomously -- the platform runs the AI pipeline, your code defines the persona, tools, and call flow | Agent Guide | | RELAY Client | Control live calls and SMS/MMS in real time over WebSocket -- answer, play, record, collect DTMF, conference, transfer, and more | RELAY docs | | REST Client | Manage SignalWire resources over HTTP -- phone numbers, SIP endpoints, Fabric AI agents, video rooms, messaging, and 18+ API namespaces | REST docs |

cpanm SignalWire

AI Agents

Each agent is a self-contained microservice that generates SWML (SignalWire Markup Language) and handles SWAIG (SignalWire AI Gateway) tool calls. The SignalWire platform runs the entire AI pipeline (STT, LLM, TTS) -- your agent just defines the behavior.

use strict;
use warnings;
use SignalWire;
use SignalWire::Agent::AgentBase;
use SignalWire::SWAIG::FunctionResult;
use POSIX qw(strftime);

my $agent = SignalWire::Agent::AgentBase->new(
    name  => 'my-agent',
    route => '/agent',
);

$agent->add_language(name => 'English', code => 'en-US', voice => 'inworld.Mark');
$agent->prompt_add_section('Role', 'You are a helpful assistant.');

$agent->define_tool(
    name        => 'get_time',
    description => 'Get the current time',
    parameters  => {},
    handler     => sub {
        my ($args, $raw_data) = @_;
        return SignalWire::SWAIG::FunctionResult->new(
            response => 'The time is ' . strftime('%H:%M:%S', localtime),
        );
    },
);

$agent->run;

Test locally without running a server:

swaig-test my_agent.pl --list-tools
swaig-test my_agent.pl --dump-swml
swaig-test my_agent.pl --exec get_time

Agent Features

Agent Examples

The examples/ directory contains 39 working examples:

| Example | What it demonstrates | |---------|---------------------| | simple_agent.pl | POM prompts, SWAIG tools, multilingual support, LLM tuning | | contexts_demo.pl | Multi-persona workflow with context switching and step navigation | | datamap_demo.pl | Server-side API tools without webhooks | | skills_demo.pl | Loading built-in skills (datetime, math) | | call_flow.pl | Call flow verbs, debug events, FunctionResult actions | | session_state.pl | on_summary, global data, post-prompt summaries | | multi_agent_server.pl | Multiple agents on one server | | lambda_agent.pl | AWS Lambda deployment | | comprehensive_dynamic.pl | Per-request dynamic configuration, multi-tenant routing |

See examples/README.md for the full list organized by category.

RELAY Client

Real-time call control and messaging over WebSocket. The RELAY client connects to SignalWire via the Blade protocol and gives you imperative control over live phone calls and SMS/MMS.

use strict;
use warnings;
use SignalWire::Relay::Client;

my $client = SignalWire::Relay::Client->new(
    project  => $ENV{SIGNALWIRE_PROJECT_ID},
    token    => $ENV{SIGNALWIRE_API_TOKEN},
    host     => $ENV{SIGNALWIRE_SPACE} // 'relay.signalwire.com',
    contexts => ['default'],
);

$client->on_call(sub {
    my ($call) = @_;
    $call->answer;
    my $action = $call->play(
        media => [{ type => 'tts', params => { text => 'Welcome!' } }],
    );
    $action->wait;
    $call->hangup;
});

$client->run;

See the RELAY documentation for the full guide, API reference, and examples.

REST Client

Synchronous REST client for managing SignalWire resources and controlling calls over HTTP. No WebSocket required.

use strict;
use warnings;
use SignalWire::REST::RestClient;

my $client = SignalWire::REST::RestClient->new(
    project => $ENV{SIGNALWIRE_PROJECT_ID},
    token   => $ENV{SIGNALWIRE_API_TOKEN},
    host    => $ENV{SIGNALWIRE_SPACE},
);

$client->fabric->ai_agents->create(name => 'Support Bot', prompt => { text => 'You are helpful.' });
$client->calling->play($call_id, play => [{ type => 'tts', text => 'Hello!' }]);
$client->phone_numbers->search(area_code => '512');
$client->datasphere->documents->search(query_string => 'billing policy');

See the REST documentation for the full guide, API reference, and examples.

Installation

# From CPAN
cpanm SignalWire

# From source
cpanm --installdeps .
perl Makefile.PL
make test
make install

Documentation

Full reference documentation is available at developer.signalwire.com/sdks/agents-sdk.

Guides are also available in the docs/ directory:

Getting Started

Core Features

Skills and Extensions

Deployment

Reference

Environment Variables

| Variable | Used by | Description | |----------|---------|-------------| | SIGNALWIRE_PROJECT_ID | RELAY, REST | Project identifier | | SIGNALWIRE_API_TOKEN | RELAY, REST | API token | | SIGNALWIRE_SPACE | RELAY, REST | Space hostname (e.g. example.signalwire.com) | | SWML_BASIC_AUTH_USER | Agents | Basic auth username (default: auto-generated) | | SWML_BASIC_AUTH_PASSWORD | Agents | Basic auth password (default: auto-generated) | | SWML_PROXY_URL_BASE | Agents | Base URL when behind a reverse proxy | | SWML_SSL_ENABLED | Agents | Enable HTTPS (true, 1, yes) | | SWML_SSL_CERT_PATH | Agents | Path to SSL certificate | | SWML_SSL_KEY_PATH | Agents | Path to SSL private key | | SIGNALWIRE_LOG_LEVEL | All | Logging level (debug, info, warn, error) | | SIGNALWIRE_LOG_MODE | All | Set to off to suppress all logging |

Testing

# Install dependencies
cpanm --installdeps .

# Run the full test suite
prove -lv t/

# Run a single test
prove -lv t/06_agent.t

# Coverage
cover -test -report html

License

MIT -- see LICENSE for details.