Build AI voice agents, control live calls over WebSocket, and manage every SignalWire resource over REST, all from one package.
export {}; // treat each example as a module (top-level await)
declare global {
const callId: string;
const signingKey: string;
const signatureHeader: string;
const fullUrl: string;
const rawBodyString: string;
const requestParams: Record<string, string>;
}| Capability | What it does | Quick link |
|---|---|---|
| AI Agents | Build voice agents that handle calls on their own. The platform runs the AI pipeline, and 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 other REST API namespaces | REST docs |
Install the SDK from npm:
npm install @signalwire/sdkThe package installs its own documentation. npx sw-tsdocs prints a map of the SDK for the installed version, with the docs and examples on disk, and npx sw-tsdocs api <name> reads signatures and JSDoc from the installed declarations. If you're a coding agent working with the SDK, start there:
npx sw-tsdocs # the map: what the SDK does and where to start
npx sw-tsdocs agents # one topic: concepts, files to read, examples, API
npx sw-tsdocs api AgentBase # a signature, JSDoc and membersEach 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), and your agent defines the behavior.
import { AgentBase, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({
name: 'my-agent',
route: '/agent',
});
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'inworld.Mark' });
agent.promptAddSection('Role', { body: 'You are a helpful assistant.' });
agent.defineTool({
name: 'get_time',
description: 'Get the current time',
parameters: {},
handler: () => new FunctionResult(`The time is ${new Date().toLocaleTimeString()}`),
});
agent.run(); // Starts HTTP server on port 3000In a clone of this repository, swaig-test checks an agent without running a server. These commands list the example agent's tools, print its SWML, and call its get_time tool:
npx tsx src/cli/swaig-test.ts examples/simple-agent.ts --list-tools
npx tsx src/cli/swaig-test.ts examples/simple-agent.ts --dump-swml
npx tsx src/cli/swaig-test.ts examples/simple-agent.ts --exec get_timeAn agent built on AgentBase gets these features:
- Prompt Object Model (POM): structured prompt composition with
promptAddSection() - SWAIG tools: functions defined with
defineTool()that the AI calls mid-conversation. A tool's result is context for the model, and its actions can control the call. - Skills system: capabilities added in one line, such as
await agent.addSkill(new DateTimeSkill()) - Contexts and steps: structured multi-step workflows with navigation control
- DataMap tools: tools that run on SignalWire's servers, calling REST APIs without your own webhook
- Dynamic configuration: a per-request copy of the agent, configured for each call, 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: multiple agents on a single server with
AgentServer - SIP routing: SIP calls routed to agents by username
- Session state: global data for the call, and post-prompt summaries when it ends
- Security: auto-generated basic auth, per-call tool tokens, webhook signature validation, and TLS support
- Serverless: automatic detection of Lambda, CGI, Google Cloud Functions, and Azure Functions
The examples/ directory contains more than 50 working examples. These show the main features:
| Example | What it demonstrates |
|---|---|
| simple-agent.ts | POM prompts, SWAIG tools, multilingual support, LLM tuning |
| contexts-steps.ts | Multi-step workflow with context switching and step navigation |
| datamap-tools.ts | Server-side API tools without webhooks |
| skills-demo.ts | Loading built-in skills (datetime, math) |
| call-flow.ts | Call flow verbs, debug events, FunctionResult actions |
| session-state.ts | onSummary, global data, post-prompt summaries |
| multi-agent.ts | Multiple agents on one server |
| serverless-lambda.ts | AWS Lambda deployment |
| dynamic-config.ts | Per-request dynamic configuration, multi-tenant routing |
See examples/README.md for the full list organized by category.
Real-time call control and messaging over WebSocket. The RELAY client connects to SignalWire via the Blade protocol and gives you imperative, async control over live phone calls and SMS/MMS.
The RELAY client connects with SIGNALWIRE_PROJECT_ID, SIGNALWIRE_API_TOKEN and SIGNALWIRE_SPACE from the environment. This client answers each call on the default context, plays a greeting, and hangs up:
import { RelayClient, Call } from '@signalwire/sdk';
const client = new RelayClient({
contexts: ['default'],
});
client.onCall(async (call: Call) => {
await call.answer();
const action = await call.play([{ type: 'tts', text: 'Welcome to SignalWire!' }]);
await action.wait();
await call.hangup();
});
client.run();The RELAY client provides:
- Calling methods for play, record, collect, detect, tap, stream, AI, conferencing, and more
- SMS/MMS messaging with delivery tracking
- Action objects with
wait(),stop(),pause(),resume() - Auto-reconnect with exponential backoff
See the RELAY documentation for the full guide, API reference, and examples.
Typed HTTP client for managing SignalWire resources and controlling calls over HTTP. It sends standard fetch requests, with no WebSocket.
This client creates a Fabric AI agent, plays text on a live call, searches for phone numbers and searches Datasphere documents:
import { RestClient } from '@signalwire/sdk';
const client = new RestClient({
project: '...',
token: '...',
host: 'example.signalwire.com',
});
await client.fabric.aiAgents.create({ name: 'Support Bot', prompt: { text: 'You are helpful.' } });
await client.calling.play(callId, [{ type: 'tts', params: { text: 'Hello!' } }]);
await client.phoneNumbers.search({ areacode: '512' });
await client.datasphere.documents.search('billing policy');The REST client provides:
- Namespaced API surfaces: Fabric, Calling, Video, Datasphere, Phone Numbers, SIP, Queues, Recordings, and more
- Node's built-in
fetch, with no HTTP client dependency - Plain object returns: the raw JSON, with no wrapper objects
See the REST documentation for the full guide, API reference, and examples.
Your Signing Key verifies that an inbound webhook (a status callback, a
messaging callback, or a SWML or SWAIG request) came from SignalWire.
validateRequest replaces the Compatibility API's RestClient.validateRequest()
and validateRequestWithBody(). It's a top-level export of @signalwire/sdk, so
you don't need the separate @signalwire/compatibility-api package.
This fragment checks a form-encoded webhook, then a JSON one:
import { validateRequest } from '@signalwire/sdk';
// Parsed form params, from a cXML (Compatibility API) webhook.
const ok = validateRequest(signingKey, signatureHeader, fullUrl, requestParams);
// The raw request body, for JSON and SWML webhooks, or a cXML body that
// carries bodySHA256.
const okBody = validateRequest(signingKey, signatureHeader, fullUrl, rawBodyString);validateRequest folds both Compatibility API methods into one call: pass a
parsed params object / Map / array of tuples for form-encoded webhooks, or
the raw body string to additionally verify the bodySHA256 the platform
includes for JSON/SWML payloads. It returns true on a match, false
otherwise, and throws if the Signing Key is missing.
validateWebhookSignature(signingKey, signature, url, rawBody) is the
lower-level check of one signature over a raw body.
SignalWire also sends an HMAC-SHA256 signature in the
X-SignalWire-Sha256-Signature header on JSON and SWML webhooks. It signs the
same message, the URL followed by the raw body, and you can check it with
validateWebhookSignatureSha256(signingKey, signature, url, rawBody). An
agent's built-in validation, and webhookValidationMiddleware, check that
header first when it's present and fall back to X-SignalWire-Signature.
One package covers agents, RELAY and REST. It requires Node.js 22 or later:
npm install @signalwire/sdkThe reference documentation is at developer.signalwire.com/sdks/agents-sdk.
The docs/ directory has these guides. They're installed with the package, with the examples: npx sw-tsdocs path prints where.
- Agent Guide: creating agents, prompt configuration, dynamic setup
- Architecture: SDK architecture and core concepts
- SDK Features: feature overview, SDK vs raw SWML comparison
- Programmatically Governed Inference: why code, not the model, owns the rules of a call
- PGI Implementation Guide: building a governed agent, with a tested reference implementation
- Developer Pain Points: common problems in voice AI, and the SDK features that address them
- SWAIG Reference: function results, actions, post_data lifecycle
- Contexts and Steps: structured workflows, navigation, gather mode
- DataMap Guide: serverless API tools without webhooks
- LLM Parameters: temperature, top_p, barge settings
- SWML Service Guide: low-level construction of SWML documents
- Skills System: built-in skills and the modular framework
- Third-Party Skills: creating and publishing custom skills
- MCP Gateway: Model Context Protocol integration
- MCP Integration: MCP agent setup and configuration
- AI Chat: the AI Chat client, and the gateway and handoff routes for a browser chat widget
- CLI Guide:
swaig-testcommand reference - Cloud Functions: Lambda, Cloud Functions, Azure deployment
- Serverless Guide: deploy to AWS Lambda, Google Cloud Functions, Azure Functions, CGI
- Configuration: environment variables, SSL, proxy setup
- Security: authentication and security model
- API Reference: complete class and method reference
- Web Service: HTTP server and endpoint details
- Skills Parameter Schema: skill parameter definitions
- Prefabs Guide: pre-built agents: InfoGatherer, Survey, FAQ, Concierge, Receptionist
- Bedrock Agent: an agent that runs on Amazon Bedrock through the
amazon_bedrockverb
| 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 REST base URL with a full http(s):// URL (local mock / private space / proxy). Precedence: host option > SIGNALWIRE_REST_BASE_URL > SIGNALWIRE_SPACE. |
SIGNALWIRE_REST_CA_FILE |
REST | Path to a PEM CA bundle to trust for HTTPS REST requests (private/self-signed certificates). |
SIGNALWIRE_RELAY_HOST |
RELAY | Override the RELAY WebSocket host (advanced/testing). Precedence: host option > SIGNALWIRE_RELAY_HOST > SIGNALWIRE_SPACE > built-in default. |
SIGNALWIRE_RELAY_SCHEME |
RELAY | Override the RELAY WebSocket scheme (ws/wss; default wss). Precedence: scheme option > SIGNALWIRE_RELAY_SCHEME > wss; any value other than ws/wss falls back to wss. |
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 |
The scripts under scripts/ lint, format and test the SDK. They install their
dependencies on first run and work from any directory:
# Run the test suite (optional filter passed through to vitest)
bash scripts/run-tests.sh
bash scripts/run-tests.sh AgentBase
# Format the tree (or --check to verify without writing)
bash scripts/run-format.sh
bash scripts/run-format.sh --check
# Lint (tsc + eslint; --fix to autofix)
bash scripts/run-lint.shThese npm scripts build the SDK and watch for changes:
# Build
npm run build
# Dev mode (watch + rebuild)
npm run dev
# Watch-mode tests
npm run test:watchMIT. See LICENSE for details.