0.0
The project is in a healthy, maintained state
A Ruby framework for building, deploying, and managing AI agents as microservices that interact with the SignalWire platform.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

>= 5.0
>= 2.0
>= 13.0

Runtime

 Project Readme

SignalWire SDK for Ruby

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

Documentation · Report an Issue · RubyGems

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 the full set of API namespaces REST docs
gem install signalwire-sdk

Published as signalwire-sdk on RubyGems. The require path is still signalwire, so require 'signalwire' works unchanged.


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.

require 'signalwire'

AGENT = SignalWire::AgentBase.new(name: 'my-agent', route: '/')

AGENT.add_language('English', 'en-US', 'elevenlabs.rachel')
AGENT.prompt_add_section('Role', 'You are a helpful assistant.')

AGENT.define_tool(
  name:        'get_time',
  description: 'Get the current time',
  parameters:  {}
) do |_args, _raw_data|
  SignalWire::Swaig::FunctionResult.new("The time is #{Time.now.strftime('%H:%M:%S')}")
end

AGENT.run if __FILE__ == $PROGRAM_NAME

Exposing the agent as the AGENT constant lets swaig-test discover it, and guarding AGENT.run keeps loading the file for a test from starting a server.

Test locally without running a server:

swaig-test quickstart_agent.rb --simulate-serverless lambda --list-tools
swaig-test quickstart_agent.rb --simulate-serverless lambda --dump-swml
swaig-test quickstart_agent.rb --simulate-serverless lambda --exec get_time

--exec NAME runs a tool. Pass each argument as its own --param KEY=VALUE (values are parsed as JSON — numbers, true/false, and null are typed; anything else is a string). For a tool get_weather(location):

swaig-test my_agent.rb --simulate-serverless lambda \
  --exec get_weather --param location="San Francisco" --param units=metric

Agent Features

  • Prompt Object Model (POM) -- structured prompt composition via prompt_add_section
  • SWAIG tools -- define functions with define_tool and a block that the AI calls mid-conversation, with native access to the call's media stack
  • Skills system -- add capabilities with one-liners: agent.add_skill('datetime')
  • Contexts and steps -- structured multi-step workflows with navigation control
  • DataMap tools -- tools that execute on SignalWire's servers, calling REST APIs without your own webhook
  • Dynamic configuration -- per-request agent customization for multi-tenant deployments
  • Call flow control -- pre-answer, post-answer, and post-AI verb insertion
  • Prefab agents -- ready-to-use archetypes (InfoGatherer, Survey, FAQ, Receptionist, Concierge)
  • Multi-agent hosting -- serve multiple agents on a single server with AgentServer
  • Document search -- vector/keyword search over a remote index via the native_vector_search skill (remote HTTP mode; the Ruby port does not ship the offline/embedded backend)
  • SIP routing -- route SIP calls to agents based on usernames
  • Session state -- persistent conversation state with global data and post-prompt summaries
  • Security -- auto-generated basic auth, function-specific HMAC tokens, SSL support
  • Rack compatible -- run standalone or mount in Rails, Sinatra, or any Rack app
  • Serverless -- auto-detects Lambda, CGI, Google Cloud Functions, Azure Functions

Agent Examples

The examples/ directory contains 56 working examples:

Example What it demonstrates
simple_agent.rb POM prompts, SWAIG tools, hints, language config, LLM tuning
contexts_demo.rb Multi-step workflow with context switching and step navigation
datamap_demo.rb Server-side API tools without webhooks
skills_demo.rb Loading built-in skills (datetime, math, joke)
call_flow_and_actions_demo.rb Call flow verbs, debug events, FunctionResult actions
session_and_state_demo.rb Global data, post-prompt analysis, on_summary callback
multi_agent_server.rb Multiple agents on one server with AgentServer
lambda_agent.rb Serverless deployment with exportable Rack app
comprehensive_dynamic_agent.rb 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 threaded, imperative control over live phone calls and SMS/MMS.

require 'signalwire'
require 'signalwire/relay/client'

client = SignalWire::Relay::Client.new(
  project:  'your-project-id',
  token:    'your-api-token',
  space:    'example.signalwire.com',
  contexts: ['default']
)

client.on_call do |call|
  call.answer
  action = call.play([{ 'type' => 'tts', 'params' => { 'text' => 'Welcome!' } }])
  action.wait
  call.hangup
end

client.run
  • 57+ calling methods (play, record, collect, detect, tap, stream, AI, conferencing, and more)
  • SMS/MMS messaging with delivery tracking
  • Action objects with wait, stop, pause, resume
  • Thread-safe with auto-reconnect and exponential backoff

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.

require 'signalwire'
require 'signalwire/rest/rest_client'

client = SignalWire::REST::RestClient.new(
  project: 'your-project-id',
  token:   'your-api-token',
  host:    'example.signalwire.com'
)

client.fabric.ai_agents.create(name: 'Support Bot', prompt: { 'text' => 'You are helpful.' })
client.calling.play(call_id, play: [{ 'type' => 'tts', 'params' => { 'text' => 'Hello!' } }])
client.phone_numbers.search(areacode: '512')
client.datasphere.documents.search(query_string: 'billing policy')
  • Full namespaced API surface: Fabric (13 resource types), Calling (37 commands), Video, Datasphere, Phone Numbers, SIP, Queues, Recordings, and more
  • Hash returns -- raw JSON, no wrapper objects to learn
  • Single RestClient with namespaced sub-objects for every API

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


Installation

# From RubyGems
gem install signalwire-sdk

# Or in your Gemfile
gem 'signalwire-sdk', require: 'signalwire'

Published as signalwire-sdk on RubyGems (the bare signalwire name belongs to the unrelated legacy SignalWire Ruby client). The require: hint keeps require 'signalwire' working unchanged.

Requires Ruby >= 3.2.

Documentation

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

Guides are also available in the docs/ directory:

Getting Started

  • Agent Guide -- creating agents, prompt configuration, dynamic setup
  • Architecture -- SDK architecture and core concepts
  • SDK Features -- feature overview, SDK vs raw SWML comparison

Core Features

Skills and Extensions

Deployment

Reference

Environment Variables

Your Project ID, API Token, and Space come from the SignalWire dashboard: sign in at my.signalwire.comAPI (Project ID + Space URL) and APITokens (create an API token).

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)
SIGNALWIRE_REST_BASE_URL REST Override the derived REST endpoint (point at a mock/dev server without a code change)
SIGNALWIRE_REST_CA_FILE REST Path to a custom CA bundle to trust for the REST transport (private-CA deployments)
SIGNALWIRE_RELAY_CA_FILE RELAY Path to a custom CA bundle to trust for the RELAY WebSocket transport
SIGNALWIRE_SIGNING_KEY Agents HMAC key for inbound webhook signature validation (validation is off until set)
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_DOMAIN Agents External domain used to build absolute webhook/SSL URLs
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
SWML_ALLOW_PRIVATE_URLS Agents Allow webhook/tool URLs pointing at private/loopback IPs (1/true/yes); off by default (SSRF guard)
SWML_SKIP_SCHEMA_VALIDATION Agents Skip SWML schema validation (1/true/yes)
SIGNALWIRE_SKILL_PATHS Skills Extra skill search directories (colon-separated)
SIGNALWIRE_RELAY_HOST RELAY Override the RELAY WebSocket host (testing / self-hosted)
SIGNALWIRE_RELAY_SCHEME RELAY Override the RELAY WebSocket scheme (ws/wss)
SIGNALWIRE_RELAY_CA_FILE RELAY Custom CA bundle for the RELAY TLS (wss://) connection
SIGNALWIRE_REST_CA_FILE REST Custom CA bundle for the REST HTTPS connection
SIGNALWIRE_LOG_LEVEL All Logging level (debug, info, warn, error)
SIGNALWIRE_LOG_MODE All Set to off to suppress all logging

A ready-to-copy .env.example at the repo root lists every environment variable the SDK reads, including the skill *_BASE_URL overrides used for testing.

Testing

Tests, formatting, and linting go through the canonical scripts/run-*.sh entry points. They self-bootstrap their tool environment (bundle install on a missing gem) and run from any directory — prefer them over raw rake test / rubocop.

# Run the full test suite (self-bootstraps, any CWD)
bash scripts/run-tests.sh

# Run a subset — pass a test file (or glob)
bash scripts/run-tests.sh tests/function_result_test.rb

# Coverage
COVERAGE=1 bash scripts/run-tests.sh

# Format (rubocop): apply in place, or --check for verify-only
bash scripts/run-format.sh
bash scripts/run-format.sh --check

# Lint (rubocop, zero offenses); --fix applies safe autocorrect first
bash scripts/run-lint.sh

License

MIT -- see LICENSE for details.