diff --git a/fern/docs.yml b/fern/docs.yml
index 103466556..f5550017c 100644
--- a/fern/docs.yml
+++ b/fern/docs.yml
@@ -184,13 +184,6 @@ redirects:
destination: /docs/server-sdks
- source: /docs/server-sdk/:slug*
destination: /docs/server-sdks
- # Temporary: TypeScript SDK reference is hidden; redirect to Python equivalent.
- - source: /docs/server-sdks/reference/typescript
- destination: /docs/server-sdks/reference/python
- permanent: false
- - source: /docs/server-sdks/reference/typescript/:slug*
- destination: /docs/server-sdks/reference/python/:slug*
- permanent: false
check:
rules:
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/adding-skills.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/adding-skills.mdx
index 75f380101..66a255968 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/adding-skills.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/adding-skills.mdx
@@ -45,7 +45,7 @@ Pass parameters as a dictionary (or map/hash depending on language):
| Language | Syntax |
|----------|--------|
| Python | `self.add_skill("web_search", {"api_key": "KEY", "num_results": 5})` |
-| TypeScript | `await agent.addSkill(new WebSearchSkill({ apiKey: 'KEY', numResults: 5 }))` |
+| TypeScript | `await agent.addSkill(new WebSearchSkill({ api_key: 'KEY', num_results: 5 }))` |
{/*
| Go | `a.AddSkill("web_search", map[string]any{"api_key": "KEY", "num_results": 5})` |
| Ruby | `agent.add_skill('web_search', api_key: 'KEY', num_results: 5)` |
@@ -166,7 +166,7 @@ Some skills support multiple instances. Give each instance a unique `tool_name`:
| Language | Two instances of web_search |
|----------|----------------------------|
| Python | `self.add_skill("web_search", {"tool_name": "search_news", ...})` |
-| TypeScript | `await agent.addSkill(new WebSearchSkill({ toolName: 'search_news', ... }))` |
+| TypeScript | `await agent.addSkill(new WebSearchSkill({ tool_name: 'search_news', ... }))` |
{/*
| Go | `a.AddSkill("web_search", map[string]any{"tool_name": "search_news", ...})` |
| Ruby | `agent.add_skill('web_search', tool_name: 'search_news', ...)` |
@@ -296,10 +296,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase, DateTimeSkill, MathSkill } from 'signalwire-agents';
+import { AgentBase, DateTimeSkill, MathSkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'full-featured' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -314,10 +313,9 @@ agent.promptAddSection('Capabilities', {
bullets: ['Current date and time', 'Math calculations'],
});
-agent.run();
+await agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/agent-base.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/agent-base.mdx
index 98bfecc19..2538f2c1c 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/agent-base.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/agent-base.mdx
@@ -129,10 +129,9 @@ if __name__ == "__main__":
agent.run(host="0.0.0.0", port=3000)
```
-{/*
```typescript
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({
name: "customer-support",
@@ -141,16 +140,15 @@ const agent = new AgentBase({
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
agent.setParams({ end_of_speech_timeout: 500, attention_timeout: 15000, inactivity_timeout: 30000 });
-agent.promptAddSection('Role', 'You are Alex, a friendly customer support agent for Acme Inc.');
+agent.promptAddSection('Role', { body: 'You are Alex, a friendly customer support agent for Acme Inc.' });
agent.promptAddSection('Guidelines', { body: 'Follow these guidelines:', bullets: ['Be helpful and professional', 'Ask clarifying questions when needed', 'Keep responses concise for voice', 'Offer to transfer if you cannot help'] });
agent.addHints(['Acme', 'account number', 'order status', 'refund', 'billing', 'representative']);
-agent.defineTool({ name: 'check_order', description: 'Look up an order by order number', parameters: { type: 'object', properties: { order_number: { type: 'string', description: 'The order number to look up' } }, required: ['order_number'] }, handler: async (args) => new FunctionResult(`Order ${args.order_number}: Shipped on Monday, arriving Thursday`) });
-agent.addSkill('datetime');
+agent.defineTool({ name: 'check_order', description: 'Look up an order by order number', parameters: { type: 'object', properties: { order_number: { type: 'string', description: 'The order number to look up' } }, required: ['order_number'] }, handler: async (args) => new FunctionResult(`Order ${args['order_number']}: Shipped on Monday, arriving Thursday`) });
+await agent.addSkillByName('datetime');
agent.setPostPrompt('Summarize: issue type, resolution, customer satisfaction');
agent.run({ host: '0.0.0.0', port: 3000 });
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/ai-parameters.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/ai-parameters.mdx
index c76590922..80ab2ddff 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/ai-parameters.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/ai-parameters.mdx
@@ -216,10 +216,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'configured-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
agent.setParams({ end_of_speech_timeout: 600, attention_timeout: 15000, inactivity_timeout: 45000 });
@@ -227,7 +226,6 @@ agent.promptAddSection('Role', { body: 'You are a helpful customer service agent
agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/architecture.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/architecture.mdx
index 84157246b..60a1ce257 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/architecture.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/architecture.mdx
@@ -365,10 +365,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'customer-service' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -378,18 +377,23 @@ agent.promptAddSection('Role', { body: 'You are a helpful agent.' });
agent.defineTool({
name: 'lookup_order',
description: 'Look up an order by ID',
- parameters: { order_id: { type: 'string', description: 'Order ID' } },
+ parameters: {
+ type: 'object',
+ properties: {
+ order_id: { type: 'string', description: 'Order ID' },
+ },
+ required: ['order_id'],
+ },
handler: (args) => {
- const result = new FunctionResult(`Order ${args.order_id}: Shipped, arrives tomorrow`);
+ const result = new FunctionResult(`Order ${args['order_id']}: Shipped, arrives tomorrow`);
return result;
},
});
-agent.addSkill('datetime');
+await agent.addSkillByName('datetime');
agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/builtin-skills.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/builtin-skills.mdx
index 1abe9e4a3..b09439ab8 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/builtin-skills.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/builtin-skills.mdx
@@ -23,6 +23,11 @@ max-toc-depth: 3
| `google_maps` | Address validation & routing | Google Maps API key |
| `info_gatherer` | Structured question collection | (none) |
| `claude_skills` | Load SKILL.md files as tools | PyYAML |
+| `api_ninjas_trivia` | Trivia questions from API Ninjas | API key |
+| `ask_claude` | Anthropic Claude reasoning / sub-queries | `ANTHROPIC_API_KEY` |
+| `custom_skills` | Register one-off SWAIG tools from config | (none) |
+| `datasphere_serverless` | DataSphere search via DataMap (no server callback) | API credentials |
+| `spider` | Web scraping & crawling | `cheerio` (TS) / `lxml` (Python) |
### datetime
@@ -37,11 +42,7 @@ Get current date and time information with timezone support. This is one of the
**Parameters:**
-| Parameter | Type | Description | Default |
-|-----------|------|-------------|---------|
-| `default_timezone` | string | Default timezone if none specified | "UTC" |
-| `tool_name_time` | string | Custom name for time function | "get_current_time" |
-| `tool_name_date` | string | Custom name for date function | "get_current_date" |
+This skill takes no configuration parameters. Timezone is specified per call via the `timezone` argument on `get_current_time`; UTC is the default when omitted.
**Output format:**
@@ -61,18 +62,18 @@ Get current date and time information with timezone support. This is one of the
- Doesn't do time math or calculate durations
- Doesn't handle historical dates
-| Language | Adding datetime with config |
-|----------|----------------------------|
-| Python | `self.add_skill("datetime", {"default_timezone": "America/New_York"})` |
-| TypeScript | `agent.addSkill('datetime', { defaultTimezone: 'America/New_York' })` |
+| Language | Adding datetime |
+|----------|-----------------|
+| Python | `self.add_skill("datetime")` |
+| TypeScript | `await agent.addSkillByName('datetime')` |
{/*
-| Go | `a.AddSkill("datetime", map[string]any{"default_timezone": "America/New_York"})` |
-| Ruby | `agent.add_skill('datetime', default_timezone: 'America/New_York')` |
-| Java | `agent.addSkill("datetime", Map.of("default_timezone", "America/New_York"))` |
-| Perl | `$agent->add_skill('datetime', { default_timezone => 'America/New_York' })` |
-| C++ | `agent.add_skill("datetime", {{"default_timezone", "America/New_York"}})` |
-| PHP | `$agent->addSkill('datetime', ['default_timezone' => 'America/New_York'])` |
+| Go | `a.AddSkill("datetime", nil)` |
+| Ruby | `agent.add_skill('datetime')` |
+| Java | `agent.addSkill("datetime")` |
+| Perl | `$agent->add_skill('datetime')` |
+| C++ | `agent.add_skill("datetime")` |
+| PHP | `$agent->addSkill('datetime')` |
*/}
@@ -84,9 +85,7 @@ class TimeAgent(AgentBase):
super().__init__(name="time-agent")
self.add_language("English", "en-US", "rime.spore")
- self.add_skill("datetime", {
- "default_timezone": "America/New_York"
- })
+ self.add_skill("datetime")
self.prompt_add_section(
"Role",
@@ -106,10 +105,7 @@ Perform mathematical calculations safely. The skill uses a secure expression eva
**Parameters:**
-| Parameter | Type | Description | Default |
-|-----------|------|-------------|---------|
-| `tool_name` | string | Custom function name | "calculate" |
-| `tool_description` | string | Custom description | "Perform calculations" |
+This skill takes no configuration parameters. The registered tool is always named `calculate`.
**Supported operations:**
@@ -172,14 +168,18 @@ Search the web using Google Custom Search API. Results are filtered for quality
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
-| `api_key` | string | Google API key | Required |
-| `search_engine_id` | string | Search engine ID | Required |
+| `api_key` | string | Google API key (falls back to `GOOGLE_SEARCH_API_KEY`) | Required |
+| `search_engine_id` | string | Search engine ID (falls back to `GOOGLE_SEARCH_ENGINE_ID`) | Required |
+| `tool_name` | string | Custom function name (set per instance) | "web_search" |
| `num_results` | integer | Results to return | 3 |
+| `delay` | number | Seconds between requests | 0.5 |
+| `max_content_length` | integer | Max characters of scraped page content | 32768 |
+| `oversample_factor` | number | Fetch extra results then re-rank | 2.5 |
| `min_quality_score` | number | Quality threshold (0-1) | 0.3 |
-| `tool_name` | string | Custom function name | "web_search" |
-| `tool_description` | string | Custom description | "Search the web" |
+| `no_results_message` | string | Message returned when nothing matches | default |
+| `safe_search` | string | `"off"`, `"medium"`, or `"high"` | "medium" |
-**Multi-instance support:** Yes - add multiple instances for different search engines (news, docs, etc.)
+**Multi-instance support:** Yes - add multiple instances with unique `tool_name` values (e.g. `search_news`, `search_docs`).
```python
from signalwire import AgentBase
@@ -215,9 +215,8 @@ Search Wikipedia for information. A free, no-API-key alternative to web search f
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
-| `language` | string | Wikipedia language code | "en" |
-| `sentences` | integer | Sentences to return per result | 3 |
-| `tool_name` | string | Custom function name | "search_wikipedia" |
+| `num_results` | integer | Max articles returned (1-5) | 1 |
+| `no_results_message` | string | Message returned when nothing matches | default template |
```python
from signalwire import AgentBase
@@ -228,7 +227,7 @@ class WikiAgent(AgentBase):
self.add_language("English", "en-US", "rime.spore")
self.add_skill("wikipedia_search", {
- "sentences": 5 # More detailed summaries
+ "num_results": 3 # Return up to three articles
})
self.prompt_add_section(
@@ -257,9 +256,9 @@ Get current weather information for locations worldwide. Commonly used for small
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
-| `api_key` | string | WeatherAPI.com API key | Required |
+| `api_key` | string | WeatherAPI.com API key (falls back to `WEATHER_API_KEY`) | Required |
| `tool_name` | string | Custom function name | "get_weather" |
-| `tool_description` | string | Custom description | "Get weather" |
+| `units` | string | `"metric"`, `"imperial"`, `"standard"`, `"celsius"`, or `"fahrenheit"` | "fahrenheit" |
```python
from signalwire import AgentBase
@@ -293,7 +292,6 @@ Tell jokes to lighten the mood or entertain callers. Uses a curated joke databas
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
-| `category` | string | Joke category filter | None (random) |
| `tool_name` | string | Custom function name | "tell_joke" |
```python
@@ -325,13 +323,21 @@ Play audio files in the background during calls. Audio plays while conversation
**Parameters:**
+This skill supports two configuration styles:
+
+- **Catalog mode** — preload named files via `files`, caller selects by `key`:
+
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
-| `audio_url` | string | URL of audio file to play | Required |
-| `volume` | number | Playback volume (0.0-1.0) | 0.5 |
-| `loop` | boolean | Loop the audio | false |
-| `tool_name_play` | string | Custom play function name | "play_background_file" |
-| `tool_name_stop` | string | Custom stop function name | "stop_background_file" |
+| `tool_name` | string | Custom play function name | "play_background_file" |
+| `files` | array | List of `{ key, description, url, wait? }` entries | Required |
+
+- **Free-form mode** — caller supplies a URL at call time (gated by `allowed_domains`):
+
+| Parameter | Type | Description | Default |
+|-----------|------|-------------|---------|
+| `default_file_url` | string | URL played when no argument is provided | Required |
+| `allowed_domains` | array | Whitelisted domains for caller-supplied URLs | Required |
**Supported formats:** MP3, WAV, OGG
@@ -344,9 +350,13 @@ class MusicAgent(AgentBase):
self.add_language("English", "en-US", "rime.spore")
self.add_skill("play_background_file", {
- "audio_url": "https://example.com/hold-music.mp3",
- "volume": 0.3, # Lower volume for background
- "loop": True
+ "files": [
+ {
+ "key": "hold_music",
+ "description": "Looping hold music",
+ "url": "https://example.com/hold-music.mp3",
+ }
+ ]
})
```
@@ -356,10 +366,25 @@ Transfer calls to another SWML endpoint.
**Functions:**
-- `transfer_to_swml` - Transfer to SWML URL
+- `transfer_call` (default name) - Transfer based on matched pattern
**Requirements:** None
+**Parameters:**
+
+| Parameter | Type | Description | Default |
+|-----------|------|-------------|---------|
+| `transfers` | object | Pattern → `{ url \| address, message?, return_message?, post_process?, final?, from_addr? }` | Required (or use `patterns`) |
+| `patterns` | array | Alternative shape: list of pattern entries | Required (or use `transfers`) |
+| `allow_arbitrary` | boolean | Accept caller-supplied URL instead of matching a pattern | false |
+| `tool_name` | string | Custom function name | "transfer_call" |
+| `description` | string | Tool description | default |
+| `parameter_name` | string | Argument name the LLM supplies | "transfer_type" |
+| `parameter_description` | string | Argument description | default |
+| `default_message` | string | Message when no pattern matches | default |
+| `default_post_process` | boolean | Default for transferred calls returning to the agent | false |
+| `required_fields` | object | Extra per-pattern required fields | `{}` |
+
```python
from signalwire import AgentBase
@@ -369,8 +394,12 @@ class TransferAgent(AgentBase):
self.add_language("English", "en-US", "rime.spore")
self.add_skill("swml_transfer", {
- "swml_url": "https://your-server.com/other-agent",
- "description": "Transfer to specialist"
+ "transfers": {
+ "specialist": {
+ "url": "https://your-server.com/other-agent",
+ "message": "Transferring you to a specialist."
+ }
+ }
})
```
@@ -380,10 +409,27 @@ Search SignalWire DataSphere documents.
**Functions:**
-- `search_datasphere` - Search uploaded documents
+- `search_knowledge` (default name) - Search uploaded documents
**Requirements:** DataSphere API credentials
+**Parameters:**
+
+| Parameter | Type | Description | Default |
+|-----------|------|-------------|---------|
+| `space_name` | string | DataSphere space name | Required |
+| `project_id` | string | Project ID (falls back to `SIGNALWIRE_PROJECT_ID`) | Required |
+| `token` | string | API token (falls back to `SIGNALWIRE_TOKEN`) | Required |
+| `document_id` | string | Document ID to search within | Required |
+| `tool_name` | string | Custom function name | "search_knowledge" |
+| `count` | integer | Results to return (1-10) | 1 |
+| `distance` | number | Distance threshold (0-10) | 3.0 |
+| `tags` | array | Filter by document tags | — |
+| `language` | string | Language filter | — |
+| `pos_to_expand` | array | POS tags to expand (`NOUN`, `VERB`, `ADJ`, `ADV`) | — |
+| `max_synonyms` | integer | Synonym expansion limit (1-10) | — |
+| `no_results_message` | string | Message when nothing matches | default |
+
```python
from signalwire import AgentBase
@@ -395,7 +441,8 @@ class KnowledgeAgent(AgentBase):
self.add_skill("datasphere", {
"space_name": "your-space",
"project_id": "YOUR_PROJECT_ID",
- "api_token": "YOUR_API_TOKEN"
+ "token": "YOUR_API_TOKEN",
+ "document_id": "your-document-id"
})
```
@@ -405,10 +452,35 @@ Local vector search using .swsearch index files.
**Functions:**
-- `search_knowledge` - Search local vector index
+- Dynamic name (default `search_knowledge`) - Search a local vector index
**Requirements:** Search extras installed (`pip install "signalwire-sdk[search]"`)
+**Parameters:**
+
+| Parameter | Type | Description | Default |
+|-----------|------|-------------|---------|
+| `tool_name` | string | Custom function name | "search_knowledge" |
+| `index_file` | string | SQLite `.swsearch` path (SQLite backend) | — |
+| `backend` | string | `"sqlite"` or `"pgvector"` | "sqlite" |
+| `connection_string` | string | PostgreSQL URL (pgvector backend) | — |
+| `collection_name` | string | Table/collection name (pgvector backend) | — |
+| `build_index` | boolean | Rebuild index on startup | false |
+| `source_dir` | string | Source directory when building | — |
+| `remote_url` | string | Remote search-server URL (alternative to local index) | — |
+| `index_name` | string | Named index on remote server | "default" |
+| `count` | integer | Results to return (1-20) | 5 |
+| `similarity_threshold` | number | Minimum score (0.0-1.0) | 0.0 |
+| `tags` | array | Filter results by tag | `[]` |
+| `global_tags` | array | Always-applied tag filter | `[]` |
+| `file_types` | array | File extensions to index | `["md","txt","pdf","docx","html"]` |
+| `exclude_patterns` | array | Glob patterns to skip | defaults |
+| `no_results_message` | string | Message when nothing matches | default template |
+| `response_prefix` | string | Prepended to result text | — |
+| `response_postfix` | string | Appended to result text | — |
+| `max_content_length` | integer | Max result chars | 32768 |
+| `description` | string | Tool description override | — |
+
```python
from signalwire import AgentBase
@@ -418,7 +490,7 @@ class LocalSearchAgent(AgentBase):
self.add_language("English", "en-US", "rime.spore")
self.add_skill("native_vector_search", {
- "index_path": "/path/to/knowledge.swsearch",
+ "index_file": "/path/to/knowledge.swsearch",
"tool_name": "search_docs"
})
```
@@ -495,9 +567,12 @@ Validate addresses and compute driving routes using Google Maps. Supports geocod
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
-| `api_key` | string | Google Maps API key | Required |
-| `lookup_tool_name` | string | Custom name for address lookup function | "lookup_address" |
-| `route_tool_name` | string | Custom name for route computation function | "compute_route" |
+| `api_key` | string | Google Maps API key (falls back to `GOOGLE_MAPS_API_KEY`) | Required |
+| `lookup_tool_name` | string | Address lookup function name | "lookup_address" |
+| `route_tool_name` | string | Route computation function name | "compute_route" |
+| `geocode_tool_name` | string | Reverse-geocoding function name | "geocode_address" |
+| `route_by_coords_tool_name` | string | Coord-based route function name | "compute_route_by_coords" |
+| `default_mode` | string | `"driving"`, `"walking"`, `"bicycling"`, or `"transit"` | "driving" |
```python
from signalwire import AgentBase
@@ -532,8 +607,9 @@ Gather answers to a configurable list of questions. This is the skill version of
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
-| `questions` | list | List of question dictionaries (key_name, question_text, confirm) | Required |
+| `questions` | list | List of question dictionaries (`key_name`, `question_text`, `confirm`, `prompt_add`) | Required |
| `prefix` | string | Prefix for tool names and namespace (enables multi-instance) | None |
+| `completion_message` | string | Message read after the last question | default template |
**Multi-instance support:** Yes - use the `prefix` parameter to run multiple question sets on a single agent. With `prefix="intake"`, tools become `intake_start_questions` and `intake_submit_answer`, and state is stored under `skill:intake` in global_data.
@@ -577,7 +653,18 @@ Load Claude Code-style SKILL.md files as agent tools. Each SKILL.md file in the
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `skills_path` | string | Path to directory containing SKILL.md files | Required |
+| `include` | array | Glob patterns of SKILL.md files to load | `["*"]` |
+| `exclude` | array | Glob patterns to skip | `[]` |
| `tool_prefix` | string | Prefix for generated function names | "claude_" |
+| `prompt_title` | string | Section title added to agent prompt | "Claude Skills" |
+| `prompt_intro` | string | Prose introducing the loaded skills | default template |
+| `skill_descriptions` | object | Override descriptions, keyed by skill name | `{}` |
+| `response_prefix` | string | Prepended to each skill response | — |
+| `response_postfix` | string | Appended to each skill response | — |
+| `allow_shell_injection` | boolean | Permit shell metacharacters in arguments | false |
+| `allow_script_execution` | boolean | Permit running scripts referenced by a skill | false |
+| `ignore_invocation_control` | boolean | Bypass per-skill invocation gating | false |
+| `shell_timeout` | integer | Shell command timeout (seconds) | 30 |
```python
from signalwire import AgentBase
@@ -611,5 +698,10 @@ class ClaudeSkillsAgent(AgentBase):
| `google_maps` | 2 | Yes | No |
| `info_gatherer` | 2 | No | Yes |
| `claude_skills` | Dynamic | No | Yes |
+| `api_ninjas_trivia` | 1 | Yes | Yes |
+| `ask_claude` | 1 | Yes | No |
+| `custom_skills` | Dynamic | No | No |
+| `datasphere_serverless` | 1 | Yes | Yes |
+| `spider` | 1 | No | Yes |
\* Requires MCP Gateway service, not external API
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/call-flow.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/call-flow.mdx
index 3c27446c1..00fa68171 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/call-flow.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/call-flow.mdx
@@ -86,10 +86,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'ringback', port: 3000 });
agent.addPreAnswerVerb('play', { urls: ['ring:us'], auto_answer: false });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -97,7 +96,6 @@ agent.promptAddSection('Role', { body: 'You are a helpful assistant.' });
agent.run();
```
-*/}
{/*
@@ -269,10 +267,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'welcome', port: 3000 });
agent.addPostAnswerVerb('play', {
url: 'say:Thank you for calling Acme Corporation. Your call may be recorded for quality assurance.',
@@ -285,7 +282,6 @@ agent.promptAddSection('Role', {
agent.run();
```
-*/}
{/*
@@ -499,10 +495,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'call-flow', port: 3000 });
agent.addPreAnswerVerb('play', { urls: ['ring:us'], auto_answer: false });
agent.addPostAnswerVerb('play', { url: 'say:Welcome to Acme Corporation.' });
@@ -517,7 +512,6 @@ agent.addPostAiVerb('hangup', {});
agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/call-recording.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/call-recording.mdx
index b262fe251..ca08cdc32 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/call-recording.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/call-recording.mdx
@@ -41,7 +41,7 @@ Recording methods across all languages:
| Language | Start Recording | Stop Recording |
|----------|----------------|----------------|
| Python | `result.record_call(control_id="main", stereo=True, format="wav")` | `result.stop_record_call(control_id="main")` |
-| TypeScript | `result.recordCall({ controlId: 'main', stereo: true, format: 'wav' })` | `result.stopRecordCall({ controlId: 'main' })` |
+| TypeScript | `result.recordCall({ controlId: 'main', stereo: true, format: 'wav' })` | `result.stopRecordCall('main')` |
{/*
| Go | `result.RecordCall("main", true, "wav")` | `result.StopRecordCall("main")` |
@@ -98,7 +98,7 @@ if __name__ == "__main__":
|-----------|------|---------|-------------|
| `control_id` | str | None | Identifier to stop specific recording |
| `stereo` | bool | False | True for separate L/R channels |
-| `format` | str | `"wav"` | Output format: "wav", "mp3", or "mp4" |
+| `format` | str | `"wav"` | Output format: "wav", "mp3", or "mp4" (TypeScript: "wav" or "mp3" only) |
| `direction` | str | `"both"` | "speak", "listen", or "both" |
| `terminators` | str | None | DTMF digits that stop recording |
| `beep` | bool | False | Play beep before recording |
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/call-transfer.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/call-transfer.mdx
index 41f79de0d..d0494c303 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/call-transfer.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/call-transfer.mdx
@@ -24,7 +24,7 @@ Transfer methods across all languages:
| Language | connect() | swml_transfer() |
|----------|-----------|-----------------|
| Python | `result.connect("+15551234567", final=True)` | `result.swml_transfer(dest="https://...", final=True)` |
-| TypeScript | `result.connect('+15551234567', { final: true })` | `result.swmlTransfer({ dest: 'https://...', final: true })` |
+| TypeScript | `result.connect('+15551234567', true)` | `result.swmlTransfer('https://...', 'Transferring now', true)` |
{/*
| Go | `result.Connect("+15551234567", true)` | `result.SwmlTransfer("https://...", true)` |
@@ -318,10 +318,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
const DEPARTMENTS: Record = {
sales: '+15551111111',
@@ -331,8 +330,8 @@ const DEPARTMENTS: Record = {
};
const agent = new AgentBase({ name: 'receptionist-agent' });
-agent.addLanguage('English', 'en-US', 'rime.spore');
-agent.promptAddSection('Role', 'You are the company receptionist.');
+agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
+agent.promptAddSection('Role', { body: 'You are the company receptionist.' });
agent.defineTool({
name: 'transfer_to_department',
@@ -345,19 +344,18 @@ agent.defineTool({
required: ['department'],
},
handler: (args) => {
- const dept = (args.department as string).toLowerCase();
+ const dept = (args['department'] as string).toLowerCase();
if (!(dept in DEPARTMENTS)) {
return new FunctionResult(`I don't recognize '${dept}'.`);
}
return new FunctionResult(`Transferring you to ${dept} now.`)
- .connect(DEPARTMENTS[dept], { final: true });
+ .connect(DEPARTMENTS[dept], true);
},
});
agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/concierge.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/concierge.mdx
index 9ec6008b9..67f1b318d 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/concierge.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/concierge.mdx
@@ -29,10 +29,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { ConciergeAgent } from 'signalwire-agents';
+import { ConciergeAgent } from '@signalwire/sdk';
const agent = new ConciergeAgent({
venueName: 'Grand Hotel',
@@ -47,7 +46,6 @@ const agent = new ConciergeAgent({
agent.run();
```
-*/}
{/*
@@ -199,7 +197,7 @@ amenities = {
| Language | Import |
|----------|--------|
| Python | `from signalwire.prefabs import ConciergeAgent` |
-| TypeScript | `import { ConciergeAgent } from 'signalwire-agents'` |
+| TypeScript | `import { ConciergeAgent } from '@signalwire/sdk'` |
{/*
| Go | `"github.com/signalwire/signalwire-agents-go/pkg/prefabs"` |
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/contexts-workflows.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/contexts-workflows.mdx
index 38ee0be75..2bb269f3d 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/contexts-workflows.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/contexts-workflows.mdx
@@ -109,10 +109,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'order-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -136,7 +135,6 @@ order.addStep('confirm', { task: 'Confirm the order details and thank them.' })
agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/custom-skills.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/custom-skills.mdx
index aaebc18ff..7c473df18 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/custom-skills.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/custom-skills.mdx
@@ -98,10 +98,9 @@ class GreetingSkill(SkillBase):
return FunctionResult(greeting)
```
-{/*
```typescript
-import { SkillBase, FunctionResult, AgentBase } from 'signalwire-agents';
+import { SkillBase, FunctionResult } from '@signalwire/sdk';
class GreetingSkill extends SkillBase {
static SKILL_NAME = 'greeting';
@@ -110,24 +109,25 @@ class GreetingSkill extends SkillBase {
private greetingStyle: string = 'friendly';
- setup(agent: AgentBase): boolean {
- this.greetingStyle = this.params.style || 'friendly';
- return true;
- }
-
- registerTools(): void {
+ async setup(): Promise {
+ this.greetingStyle = (this.getConfig('style') as string) || 'friendly';
this.defineTool({
name: 'greet_user',
description: 'Generate a personalized greeting',
parameters: {
- name: { type: 'string', description: 'Name of the person to greet' },
+ type: 'object',
+ properties: {
+ name: { type: 'string', description: 'Name of the person to greet' },
+ },
+ required: ['name'],
},
handler: this.greetHandler.bind(this),
});
+ return true;
}
- greetHandler(args: Record, rawData: any): FunctionResult {
- const name = args.name || 'friend';
+ greetHandler(args: Record): FunctionResult {
+ const name = (args['name'] as string) || 'friend';
const greeting = this.greetingStyle === 'formal'
? `Good day, ${name}. How may I assist you?`
: `Hey ${name}! Great to hear from you!`;
@@ -136,7 +136,6 @@ class GreetingSkill extends SkillBase {
}
```
-*/}
{/*
@@ -382,7 +381,7 @@ class GreetingSkill : SkillBase {
|-----------|------|-------------|
| `REQUIRED_PACKAGES` | `List[str]` | Python packages needed |
| `REQUIRED_ENV_VARS` | `List[str]` | Environment variables needed |
-| `SUPPORTS_MULTIPLE` | `bool` | Allow multiple instances |
+| `SUPPORTS_MULTIPLE_INSTANCES` | `bool` | Allow multiple instances |
### Required Methods
@@ -545,7 +544,7 @@ Register the skill directory and use the custom skill in your agent:
| Language | Register & use custom skill |
|----------|----------------------------|
| Python | `skill_registry.add_skill_directory("/path/to/skills")` then `agent.add_skill("product_search", {...})` |
-| TypeScript | `skillRegistry.addSkillDirectory('/path/to/skills')` then `agent.addSkill('product_search', {...})` |
+| TypeScript | `await SkillRegistry.getInstance().discoverFromDirectory('/path/to/skills')` then `await agent.addSkillByName('product_search', {...})` |
{/*
| Go | `skills.AddSkillDirectory("/path/to/skills")` then `a.AddSkill("product_search", map[string]any{...})` |
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/datamap.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/datamap.mdx
index d9b74c258..224672361 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/datamap.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/datamap.mdx
@@ -91,14 +91,12 @@ class WeatherAgent(AgentBase):
self.register_swaig_function(weather_dm.to_swaig_function())
```
-{/*
```typescript
-import { AgentBase, FunctionResult } from 'signalwire-agents';
-import { DataMap } from 'signalwire-agents/data-map';
+import { AgentBase, FunctionResult, DataMap } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'weather-agent' });
-agent.addLanguage('English', 'en-US', 'rime.spore');
+agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
const weatherDm = new DataMap('get_weather')
.purpose('Get current weather for a city')
@@ -112,7 +110,6 @@ const weatherDm = new DataMap('get_weather')
agent.registerSwaigFunction(weatherDm.toSwaigFunction());
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/defining-functions.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/defining-functions.mdx
index ca5e490f6..a4ffa519f 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/defining-functions.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/defining-functions.mdx
@@ -81,14 +81,13 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'order-agent' });
-agent.addLanguage('English', 'en-US', 'rime.spore');
-agent.promptAddSection('Role', 'You are an order status assistant. Help customers check their orders.');
+agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
+agent.promptAddSection('Role', { body: 'You are an order status assistant. Help customers check their orders.' });
agent.defineTool({
name: 'check_order',
@@ -105,15 +104,15 @@ agent.defineTool({
'12345': 'Shipped Monday, arriving Thursday',
'67890': 'Processing, ships tomorrow'
};
- const status = orders[args.order_number] || 'Order not found';
- return new FunctionResult(`Order ${args.order_number}: ${status}`);
+ const orderNumber = args['order_number'] as string;
+ const status = orders[orderNumber] || 'Order not found';
+ return new FunctionResult(`Order ${orderNumber}: ${status}`);
}
});
agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/faq-bot.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/faq-bot.mdx
index b8929e285..23c9eb922 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/faq-bot.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/faq-bot.mdx
@@ -35,10 +35,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { FAQBotAgent } from 'signalwire-agents';
+import { FAQBotAgent } from '@signalwire/sdk';
const agent = new FAQBotAgent({
faqs: [
@@ -51,7 +50,6 @@ const agent = new FAQBotAgent({
agent.run();
```
-*/}
{/*
@@ -185,7 +183,7 @@ agent.Run();
| Language | Import |
|----------|--------|
| Python | `from signalwire.prefabs import FAQBotAgent` |
-| TypeScript | `import { FAQBotAgent } from 'signalwire-agents'` |
+| TypeScript | `import { FAQBotAgent } from '@signalwire/sdk'` |
{/*
| Go | `"github.com/signalwire/signalwire-agents-go/pkg/prefabs"` |
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/hints.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/hints.mdx
index 0282f28ba..821466c25 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/hints.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/hints.mdx
@@ -367,23 +367,21 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({ name: "hinted-agent" });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
agent.addHints(['Acme', 'Acme Pro', 'Acme Enterprise', 'AcmePay', 'AcmeCloud']);
agent.addHints(['SKU', 'A100', 'A200', 'A300', 'PRO100', 'ENT500']);
agent.addHints(['account', 'billing', 'invoice', 'refund', 'cancel', 'upgrade', 'downgrade', 'representative', 'supervisor']);
agent.addHints(['API', 'webhook', 'integration', 'OAuth', 'SSO', 'MFA']);
-agent.promptAddSection('Role', 'You are a customer service agent for Acme Corporation.');
+agent.promptAddSection('Role', { body: 'You are a customer service agent for Acme Corporation.' });
const products: Record = { 'A100': 'Acme Basic - $99/month', 'A200': 'Acme Standard - $199/month', 'A300': 'Acme Premium - $299/month', 'PRO100': 'Acme Pro - $499/month', 'ENT500': 'Acme Enterprise - Custom pricing' };
-agent.defineTool({ name: 'lookup_product', description: 'Look up product by SKU', parameters: { type: 'object', properties: { sku: { type: 'string', description: 'Product SKU like A100 or PRO100' } }, required: ['sku'] }, handler: async (args) => { const sku = (args.sku as string).toUpperCase(); return new FunctionResult(products[sku] ? `${sku}: ${products[sku]}` : `SKU ${sku} not found.`); } });
+agent.defineTool({ name: 'lookup_product', description: 'Look up product by SKU', parameters: { type: 'object', properties: { sku: { type: 'string', description: 'Product SKU like A100 or PRO100' } }, required: ['sku'] }, handler: async (args) => { const sku = (args['sku'] as string).toUpperCase(); return new FunctionResult(products[sku] ? `${sku}: ${products[sku]}` : `SKU ${sku} not found.`); } });
agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/info-gatherer.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/info-gatherer.mdx
index 0be1db252..783988e67 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/info-gatherer.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/info-gatherer.mdx
@@ -26,23 +26,21 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { InfoGathererAgent } from 'signalwire-agents';
+import { InfoGathererAgent } from '@signalwire/sdk';
const agent = new InfoGathererAgent({
questions: [
- { keyName: 'full_name', questionText: 'What is your full name?' },
- { keyName: 'email', questionText: 'What is your email address?', confirm: true },
- { keyName: 'reason', questionText: 'How can I help you today?' },
+ { key_name: 'full_name', question_text: 'What is your full name?' },
+ { key_name: 'email', question_text: 'What is your email address?', confirm: true },
+ { key_name: 'reason', question_text: 'How can I help you today?' },
],
});
agent.run();
```
-*/}
{/*
@@ -187,7 +185,7 @@ InfoGathererAgent(
| Language | Import |
|----------|--------|
| Python | `from signalwire.prefabs import InfoGathererAgent` |
-| TypeScript | `import { InfoGathererAgent } from 'signalwire-agents'` |
+| TypeScript | `import { InfoGathererAgent } from '@signalwire/sdk'` |
{/*
| Go | `"github.com/signalwire/signalwire-agents-go/pkg/prefabs"` |
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/lifecycle.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/lifecycle.mdx
index 9201de3e5..eea2af428 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/lifecycle.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/lifecycle.mdx
@@ -153,20 +153,28 @@ class MyAgent(AgentBase):
self.log_call_summary(call_id, summary)
```
-{/*
```typescript
-agent.setPostPrompt(
- 'Summarize this call including: 1) The caller\'s main question '
- + '2) How it was resolved 3) Any follow-up actions needed'
-);
-
-agent.onSummary((summary, rawData) => {
- console.log('Call summary:', summary);
-});
+import { AgentBase } from '@signalwire/sdk';
+
+class SupportAgent extends AgentBase {
+ constructor() {
+ super({ name: 'support-agent' });
+ this.setPostPrompt(
+ "Summarize this call including: 1) The caller's main question "
+ + '2) How it was resolved 3) Any follow-up actions needed'
+ );
+ }
+
+ async onSummary(summary: Record, rawData?: Record): Promise {
+ console.log('Call summary:', summary);
+ }
+}
+
+const agent = new SupportAgent();
+agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/mcp-gateway.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/mcp-gateway.mdx
index 27629e90a..a44469583 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/mcp-gateway.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/mcp-gateway.mdx
@@ -128,7 +128,7 @@ The `mcp_gateway` skill connects agents to the gateway across all languages:
| Language | Syntax |
|----------|--------|
| Python | `self.add_skill("mcp_gateway", {"gateway_url": "http://localhost:8080", "services": [...]})` |
-| TypeScript | `agent.addSkill('mcp_gateway', { gatewayUrl: 'http://localhost:8080', services: [...] })` |
+| TypeScript | `await agent.addSkillByName('mcp_gateway', { gateway_url: 'http://localhost:8080', services: [...] })` |
{/*
| Go | `a.AddSkill("mcp_gateway", agents.SkillOpt("gateway_url", "http://localhost:8080"))` |
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/multi-agent.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/multi-agent.mdx
index 18733452b..41c18c206 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/multi-agent.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/multi-agent.mdx
@@ -70,10 +70,9 @@ if __name__ == "__main__":
server.run()
```
-{/*
```typescript
-import { AgentBase, AgentServer } from 'signalwire-agents';
+import { AgentBase, AgentServer } from '@signalwire/sdk';
const sales = new AgentBase({ name: 'sales-agent' });
sales.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -89,7 +88,6 @@ server.register(support, '/support');
server.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/prompts-pom.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/prompts-pom.mdx
index a341400ab..c461114fc 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/prompts-pom.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/prompts-pom.mdx
@@ -56,15 +56,13 @@ class MyAgent(AgentBase):
)
```
-{/*
```typescript
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'my-agent' });
agent.promptAddSection('Role', { body: 'You are a helpful customer service representative for Acme Corp.' });
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/receptionist.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/receptionist.mdx
index defdc9c8d..98ab68a43 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/receptionist.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/receptionist.mdx
@@ -38,10 +38,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { ReceptionistAgent } from 'signalwire-agents';
+import { ReceptionistAgent } from '@signalwire/sdk';
const agent = new ReceptionistAgent({
departments: [
@@ -54,7 +53,6 @@ const agent = new ReceptionistAgent({
agent.run();
```
-*/}
{/*
@@ -188,7 +186,7 @@ agent.Run();
| Language | Import |
|----------|--------|
| Python | `from signalwire.prefabs import ReceptionistAgent` |
-| TypeScript | `import { ReceptionistAgent } from 'signalwire-agents'` |
+| TypeScript | `import { ReceptionistAgent } from '@signalwire/sdk'` |
{/*
| Go | `"github.com/signalwire/signalwire-agents-go/pkg/prefabs"` |
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/results-actions.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/results-actions.mdx
index 0ea266e62..99aa96584 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/results-actions.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/results-actions.mdx
@@ -21,17 +21,15 @@ def check_order(self, args, raw_data):
return FunctionResult(f"Order {order_number} shipped yesterday")
```
-{/*
```typescript
-import { FunctionResult } from 'signalwire-agents';
+import { FunctionResult } from '@signalwire/sdk';
-function checkOrder(args: Record): FunctionResult {
- return new FunctionResult(`Order ${args.order_number} shipped yesterday`);
+function checkOrder(args: Record): FunctionResult {
+ return new FunctionResult(`Order ${args['order_number']} shipped yesterday`);
}
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/search-knowledge.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/search-knowledge.mdx
index 9a35a372d..c69d52525 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/search-knowledge.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/search-knowledge.mdx
@@ -135,7 +135,7 @@ Add the `native_vector_search` skill to enable search:
| Language | Syntax |
|----------|--------|
| Python | `self.add_skill("native_vector_search", index_file="./knowledge.swsearch", count=5, tool_name="search_documents")` |
-| TypeScript | `agent.addSkill('native_vector_search', { indexFile: './knowledge.swsearch', count: 5, toolName: 'search_documents' })` |
+| TypeScript | `await agent.addSkillByName('native_vector_search', { index_file: './knowledge.swsearch', count: 5, tool_name: 'search_documents' })` |
{/*
| Go | `a.AddSkill("native_vector_search", agents.SkillOpt("index_file", "./knowledge.swsearch"), agents.SkillOpt("count", 5))` |
@@ -188,7 +188,7 @@ self.add_skill(
# Search parameters
count=5, # Results to return (1-20)
- distance_threshold=0.0, # Min score (0.0-1.0)
+ similarity_threshold=0.0, # Min score (0.0-1.0)
tags=["docs", "api"], # Filter by tags
# Tool configuration
@@ -201,6 +201,8 @@ self.add_skill(
For production deployments, use PostgreSQL with pgvector:
+
+
```python
self.add_skill(
"native_vector_search",
@@ -211,6 +213,19 @@ self.add_skill(
tool_name="search_docs"
)
```
+
+
+```typescript
+await agent.addSkillByName('native_vector_search', {
+ backend: 'pgvector',
+ connection_string: 'postgresql://user:pass@localhost/db',
+ collection_name: 'knowledge_base',
+ count: 5,
+ tool_name: 'search_docs',
+});
+```
+
+
### CLI Commands
@@ -411,7 +426,7 @@ self.prompt_add_section(
- `count=5`: Good balance (default)
- `count=10`: More comprehensive, but may include less relevant results
-**distance_threshold**: Minimum relevance score (0.0 to 1.0)
+**similarity_threshold**: Minimum relevance score (0.0 to 1.0) — higher is better.
- `0.0`: Return all results regardless of relevance
- `0.3`: Filter out clearly irrelevant results
- `0.5+`: Only high-confidence matches (may miss relevant content)
@@ -432,7 +447,7 @@ self.add_skill(
- Check that the index file exists and is readable
- Verify the query is meaningful (not too short or generic)
-- Lower distance_threshold if set too high
+- Lower similarity_threshold if set too high
- Ensure documents were actually indexed (check with `sw-search validate`)
#### Poor result relevance
@@ -462,7 +477,7 @@ self.add_skill(
#### Agent Configuration
- Set count=3-5 for most use cases
-- Use distance_threshold to filter noise
+- Use similarity_threshold to filter noise
- Give descriptive tool_name and tool_description
- Tell AI when/how to use search in the prompt
- Handle "no results" gracefully in your prompt
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/security.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/security.mdx
index 15fe0730e..0921ff065 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/security.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/security.mdx
@@ -85,6 +85,8 @@ INFO: Password: a7b3x9k2m5n1p8q4 # Use this in SignalWire webhook config
#### Credentials in Your Agent
+
+
```python
from signalwire import AgentBase
import os
@@ -98,6 +100,22 @@ class MyAgent(AgentBase):
basic_auth_password=os.getenv("SWML_BASIC_AUTH_PASSWORD")
)
```
+
+
+```typescript
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({
+ name: 'my-agent',
+ // Credentials from environment or defaults
+ basicAuth: [
+ process.env['SWML_BASIC_AUTH_USER']!,
+ process.env['SWML_BASIC_AUTH_PASSWORD']!,
+ ],
+});
+```
+
+
### Function Token Security
@@ -145,6 +163,8 @@ Enable per-function token validation with the `secure` flag:
*/}
+
+
```python
from signalwire import AgentBase, FunctionResult
@@ -176,6 +196,36 @@ class SecureAgent(AgentBase):
# This only executes if token is valid
return FunctionResult("Transfer complete")
```
+
+
+```typescript
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
+
+class SecureAgent extends AgentBase {
+ constructor() {
+ super({ name: 'secure-agent' });
+
+ // Regular function - Basic Auth only
+ this.defineTool({
+ name: 'get_balance',
+ description: 'Get account balance',
+ parameters: { type: 'object', properties: {} },
+ handler: () => new FunctionResult('Balance is $150.00'),
+ });
+
+ // Secure function - Basic Auth + Token validation
+ this.defineTool({
+ name: 'transfer_funds',
+ description: 'Transfer funds between accounts',
+ parameters: { type: 'object', properties: {} },
+ handler: () => new FunctionResult('Transfer complete'),
+ secure: true, // Enable token security
+ });
+ }
+}
+```
+
+
#### Token Generation
@@ -224,6 +274,13 @@ class SecureAgent(AgentBase):
)
```
+
+The TypeScript `AgentBase` does not expose SSL directly — `agent.serve()`
+accepts only `{ host, port }`. For production TypeScript deployments, use
+the reverse-proxy pattern below (recommended) or see the `WebService`
+reference for programmatic SSL.
+
+
#### Using a Reverse Proxy (Recommended)
Most production deployments use a reverse proxy for SSL:
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/skill-config.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/skill-config.mdx
index 244d8b6ed..d1d6260de 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/skill-config.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/skill-config.mdx
@@ -21,7 +21,7 @@ Pass configuration when adding a skill:
| Language | Passing config parameters |
|----------|--------------------------|
| Python | `self.add_skill("web_search", {"api_key": "...", "num_results": 5})` |
-| TypeScript | `agent.addSkill('web_search', { apiKey: '...', numResults: 5 })` |
+| TypeScript | `await agent.addSkillByName('web_search', { api_key: '...', num_results: 5 })` |
{/*
| Go | `a.AddSkill("web_search", map[string]any{"api_key": "...", "num_results": 5})` |
@@ -108,7 +108,7 @@ Override SWAIG function metadata for skill tools:
| Language | SWAIG fields override |
|----------|----------------------|
| Python | `self.add_skill("datetime", {"swaig_fields": {"fillers": {...}}})` |
-| TypeScript | `agent.addSkill('datetime', { swaigFields: { fillers: {...} } })` |
+| TypeScript | `await agent.addSkillByName('datetime', { swaig_fields: { fillers: {...} } })` |
{/*
| Go | `a.AddSkill("datetime", map[string]any{"swaig_fields": map[string]any{"fillers": ...}})` |
@@ -197,7 +197,7 @@ Skills supporting multiple instances need unique tool names:
| Language | Multi-instance with unique tool_name |
|----------|--------------------------------------|
| Python | `self.add_skill("web_search", {"tool_name": "search_news", "api_key": "KEY"})` |
-| TypeScript | `agent.addSkill('web_search', { toolName: 'search_news', apiKey: 'KEY' })` |
+| TypeScript | `await agent.addSkillByName('web_search', { tool_name: 'search_news', api_key: 'KEY' })` |
{/*
| Go | `a.AddSkill("web_search", map[string]any{"tool_name": "search_news", "api_key": "KEY"})` |
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/state-management.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/state-management.mdx
index f67c71fe8..31f15cdc3 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/state-management.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/state-management.mdx
@@ -411,13 +411,12 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'order-agent' });
-agent.addLanguage('English', 'en-US', 'rime.spore');
+agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
agent.setGlobalData({
store_name: 'Pizza Palace',
@@ -425,10 +424,12 @@ agent.setGlobalData({
order_total: 0.0,
});
-agent.promptAddSection('Role',
- 'You are an order assistant for ${global_data.store_name}. Help customers place their order.');
-agent.promptAddSection('Current Order',
- 'Items: ${global_data.order_items}\nTotal: $${global_data.order_total}');
+agent.promptAddSection('Role', {
+ body: 'You are an order assistant for ${global_data.store_name}. Help customers place their order.',
+});
+agent.promptAddSection('Current Order', {
+ body: 'Items: ${global_data.order_items}\nTotal: $${global_data.order_total}',
+});
agent.setPostPrompt('Extract the final order as JSON: { "items": [], "total": 0.00 }');
@@ -444,15 +445,16 @@ agent.defineTool({
required: ['item', 'price'],
},
handler: (args) => {
- return new FunctionResult(`Added ${args.item} ($${args.price}) to your order`)
- .updateGlobalData({ last_item_added: args.item, last_item_price: args.price });
+ const item = args['item'] as string;
+ const price = args['price'] as number;
+ return new FunctionResult(`Added ${item} ($${price}) to your order`)
+ .updateGlobalData({ last_item_added: item, last_item_price: price });
},
});
agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/static-vs-dynamic.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/static-vs-dynamic.mdx
index b10a79674..1cc3bcc98 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/static-vs-dynamic.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/static-vs-dynamic.mdx
@@ -77,19 +77,19 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({ name: "static-support" });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
-agent.promptAddSection('Role', 'You are a customer service agent for Acme Corp. ' + 'Help callers with general inquiries about our products.');
+agent.promptAddSection('Role', {
+ body: 'You are a customer service agent for Acme Corp. Help callers with general inquiries about our products.',
+});
agent.promptAddSection('Guidelines', { bullets: ['Be helpful and professional', 'Answer questions about products', 'Transfer complex issues to support'] });
-agent.defineTool({ name: 'get_store_hours', description: 'Get store hours', parameters: {}, handler: async () => new FunctionResult("We're open Monday through Friday, 9 AM to 5 PM.") });
+agent.defineTool({ name: 'get_store_hours', description: 'Get store hours', parameters: { type: 'object', properties: {} }, handler: async () => new FunctionResult("We're open Monday through Friday, 9 AM to 5 PM.") });
agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/survey.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/survey.mdx
index 3852962e6..edaa3cd6c 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/survey.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/survey.mdx
@@ -41,10 +41,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { SurveyAgent } from 'signalwire-agents';
+import { SurveyAgent } from '@signalwire/sdk';
const agent = new SurveyAgent({
surveyName: 'Customer Satisfaction Survey',
@@ -58,7 +57,6 @@ const agent = new SurveyAgent({
agent.run();
```
-*/}
{/*
@@ -207,7 +205,7 @@ agent.Run();
| Language | Import |
|----------|--------|
| Python | `from signalwire.prefabs import SurveyAgent` |
-| TypeScript | `import { SurveyAgent } from 'signalwire-agents'` |
+| TypeScript | `import { SurveyAgent } from '@signalwire/sdk'` |
{/*
| Go | `"github.com/signalwire/signalwire-agents-go/pkg/prefabs"` |
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/swaig.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/swaig.mdx
index eedcaf62f..f6fd42f5c 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/swaig.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/swaig.mdx
@@ -96,22 +96,24 @@ class MyAgent(AgentBase):
return FunctionResult(f"Account {account_id} has a balance of $150.00")
```
-{/*
```typescript
agent.defineTool({
name: 'get_balance',
description: 'Get account balance for a customer',
parameters: {
- account_id: { type: 'string', description: 'The account ID to look up' },
+ type: 'object',
+ properties: {
+ account_id: { type: 'string', description: 'The account ID to look up' },
+ },
+ required: ['account_id'],
},
handler: (args) => {
- return new FunctionResult(`Account ${args.account_id} has a balance of $150.00`);
+ return new FunctionResult(`Account ${args['account_id']} has a balance of $150.00`);
},
});
```
-*/}
{/*
@@ -386,7 +388,6 @@ def response_with_data(self, args, raw_data):
return result
```
-{/*
```typescript
// Simple response
@@ -394,14 +395,13 @@ return new FunctionResult('Your order has been placed successfully.');
// With transfer
return new FunctionResult('Transferring you now.')
- .connect('+15551234567', { final: true });
+ .connect('+15551234567', true);
// With data
return new FunctionResult("I've saved your preferences.")
.updateGlobalData({ user_preference: 'email', confirmed: true });
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/swml.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/swml.mdx
index 508176368..62349aaf9 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/swml.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/swml.mdx
@@ -253,18 +253,23 @@ class MyAgent(AgentBase):
self.define_tool(name="get_help", description="Get help", parameters={}, handler=self.get_help) # -> SWAIG
```
-{/*
```typescript
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
+
const agent = new AgentBase({ name: 'my-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' }); // -> languages
agent.promptAddSection('Role', { body: 'You are helpful.' }); // -> prompt
agent.addHints(['help', 'support']); // -> hints
agent.setParams({ end_of_speech_timeout: 500 }); // -> params
-agent.defineTool({ name: 'get_help', description: 'Get help', parameters: {}, handler: fn }); // -> SWAIG
+agent.defineTool({ // -> SWAIG
+ name: 'get_help',
+ description: 'Get help',
+ parameters: { type: 'object', properties: {} },
+ handler: async () => new FunctionResult('Here is some help.'),
+});
```
-*/}
{/*
@@ -350,7 +355,7 @@ agent.DefineTool(name: "get_help", description: "Get help", parameters: new Dict
The above examples all produce identical SWML output. See the [Architecture][architecture] section for the full API comparison table.
-When SignalWire requests SWML, the agent's `_render_swml()` method:
+When SignalWire requests SWML, the agent's render method (`_render_swml()` in Python, `renderSwml()` in TypeScript):
1. Collects all configuration (prompts, languages, hints, params)
2. Builds the SWAIG functions array with webhook URLs
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/understanding-skills.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/understanding-skills.mdx
index b407ad290..ea30c7900 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/understanding-skills.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/understanding-skills.mdx
@@ -44,7 +44,7 @@ The `add_skill()` method is available across all SDK languages:
| Language | Syntax |
|----------|--------|
| Python | `agent.add_skill("weather")` |
-| TypeScript | `agent.addSkill('weather')` |
+| TypeScript | `await agent.addSkillByName('weather_api')` |
{/*
| Go | `a.AddSkill("weather", nil)` |
@@ -83,10 +83,9 @@ class MyAgent(AgentBase):
)
```
-{/*
```typescript
-import { AgentBase, DateTimeSkill, MathSkill } from 'signalwire-agents';
+import { AgentBase, DateTimeSkill, MathSkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'my-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -101,10 +100,9 @@ agent.promptAddSection('Role', {
body: 'You are a helpful assistant that can tell time and do math.',
});
-agent.run();
+await agent.run();
```
-*/}
{/*
@@ -277,6 +275,15 @@ agent.Run();
| `swml_transfer` | Transfer calls to SWML endpoints |
| `datasphere` | Search DataSphere documents |
| `native_vector_search` | Local vector search |
+| `mcp_gateway` | Connect to MCP server tools |
+| `google_maps` | Address validation and routing |
+| `info_gatherer` | Structured question collection |
+| `claude_skills` | Load SKILL.md files as tools |
+| `api_ninjas_trivia` | Trivia questions from API Ninjas |
+| `ask_claude` | Anthropic Claude reasoning / sub-queries |
+| `custom_skills` | Register one-off SWAIG tools from config |
+| `datasphere_serverless` | DataSphere search via serverless DataMap |
+| `spider` | Web scraping and crawling |
## Chapter Contents
@@ -303,7 +310,7 @@ The `add_skill()` vs `define_tool()` distinction applies across all languages:
| Language | add_skill | define_tool |
|----------|-----------|-------------|
| Python | `agent.add_skill("name")` | `agent.define_tool(...)` |
-| TypeScript | `agent.addSkill('name')` | `agent.defineTool(...)` |
+| TypeScript | `await agent.addSkillByName('name')` | `agent.defineTool(...)` |
{/*
| Go | `a.AddSkill("name", nil)` | `a.DefineTool(...)` |
@@ -373,10 +380,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase, DateTimeSkill, MathSkill } from 'signalwire-agents';
+import { AgentBase, DateTimeSkill, MathSkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'assistant' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -394,10 +400,9 @@ agent.promptAddSection('Capabilities', {
],
});
-agent.run();
+await agent.run();
```
-*/}
{/*
@@ -643,7 +648,7 @@ All skills inherit from [`SkillBase`][ref-skillbase]. The pattern is similar acr
| Language | Pattern |
|----------|---------|
| Python | `class MySkill(SkillBase): def setup(self, agent): ...` |
-| TypeScript | `class MySkill extends SkillBase { setup(agent) { ... } }` |
+| TypeScript | `class MySkill extends SkillBase { async setup() { ... return true; } }` |
{/*
| Go | `type MySkill struct { skills.SkillBase } func (s *MySkill) Setup(a *agent.AgentBase) { ... }` |
@@ -806,7 +811,7 @@ Usage across languages:
| Language | Adding multiple instances |
|----------|--------------------------|
| Python | `agent.add_skill("web_search", {"tool_name": "search_news", "api_key": "KEY"})` |
-| TypeScript | `agent.addSkill('web_search', { toolName: 'search_news', apiKey: 'KEY' })` |
+| TypeScript | `await agent.addSkillByName('web_search', { tool_name: 'search_news', api_key: 'KEY' })` |
{/*
| Go | `a.AddSkill("web_search", map[string]any{"tool_name": "search_news", "api_key": "KEY"})` |
diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/voice-language.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/voice-language.mdx
index 55dbae7e0..a4f7e935f 100644
--- a/fern/products/server-sdks/pages/guides/build-ai-agents/voice-language.mdx
+++ b/fern/products/server-sdks/pages/guides/build-ai-agents/voice-language.mdx
@@ -410,20 +410,25 @@ class FullyConfiguredVoiceAgent(AgentBase):
self.prompt_add_section("Role", "You are a friendly customer service agent.")
```
-{/*
```typescript
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'voice-configured' });
agent.addLanguage({
name: 'English', code: 'en-US', voice: 'rime.spore',
- fillers: ['Um', 'Well', 'Let me see', 'So'],
- functionFillers: ['Let me look that up for you', 'One moment while I check', "I'm searching for that now", 'Just a second'],
+ fillers: { default: ['Um', 'Well', 'Let me see', 'So'] },
+ functionFillers: {
+ lookup_product: {
+ 'en-US': ['Let me look that up for you', 'One moment while I check', "I'm searching for that now", 'Just a second'],
+ },
+ },
});
agent.addLanguage({
name: 'Spanish', code: 'es-MX', voice: 'rime.luna',
- fillers: ['Pues', 'Bueno'],
- functionFillers: ['Un momento', 'Dejame ver'],
+ fillers: { default: ['Pues', 'Bueno'] },
+ functionFillers: {
+ lookup_product: { 'es-MX': ['Un momento', 'Dejame ver'] },
+ },
});
agent.setPronunciations([
{ replace: 'ACME', with: 'Ack-me' },
@@ -434,7 +439,6 @@ agent.setPronunciations([
agent.promptAddSection('Role', { body: 'You are a friendly customer service agent.' });
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/deploy/cgi-mode.mdx b/fern/products/server-sdks/pages/guides/deploy/cgi-mode.mdx
index 25dd2ec15..e951123bf 100644
--- a/fern/products/server-sdks/pages/guides/deploy/cgi-mode.mdx
+++ b/fern/products/server-sdks/pages/guides/deploy/cgi-mode.mdx
@@ -16,10 +16,8 @@ CGI mode is primarily supported by the **Python** and **Perl** SDKs. Compiled la
| Language | CGI Support | Notes |
|----------|-------------|-------|
| Python | Full | Automatic detection via `GATEWAY_INTERFACE` |
-
-| TypeScript | Possible | Via `node` as CGI; prefer server mode instead |
{/*
-
+| TypeScript | Possible | Via `node` as CGI; prefer server mode instead |
| Perl | Full | Natural CGI fit; works with `CGI.pm` and the SDK |
| Ruby | Possible | Via `ruby` interpreter as CGI; prefer Rack instead |
| Go | Not recommended | Compiled binary; use server mode |
diff --git a/fern/products/server-sdks/pages/guides/deploy/docker-kubernetes.mdx b/fern/products/server-sdks/pages/guides/deploy/docker-kubernetes.mdx
index 500394be1..aef1d88a5 100644
--- a/fern/products/server-sdks/pages/guides/deploy/docker-kubernetes.mdx
+++ b/fern/products/server-sdks/pages/guides/deploy/docker-kubernetes.mdx
@@ -34,20 +34,22 @@ EXPOSE 3000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "3000", "--workers", "4"]
```
-{/*
```dockerfile
FROM node:20-slim
WORKDIR /app
-## Install dependencies
+## Install dependencies (package.json must include "type": "module" — @signalwire/sdk is ESM-only)
COPY package*.json ./
RUN npm ci --only=production
## Copy application
COPY . .
+## Build TypeScript to dist/
+RUN npm run build
+
## Create non-root user
RUN groupadd -r appuser && useradd -r -g appuser appuser && chown -R appuser:appuser /app
USER appuser
@@ -57,7 +59,6 @@ EXPOSE 3000
CMD ["node", "dist/app.js"]
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/deploy/overview.mdx b/fern/products/server-sdks/pages/guides/deploy/overview.mdx
index e35aeb2ca..fe9ee7b4f 100644
--- a/fern/products/server-sdks/pages/guides/deploy/overview.mdx
+++ b/fern/products/server-sdks/pages/guides/deploy/overview.mdx
@@ -76,10 +76,9 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'my-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -88,7 +87,6 @@ agent.promptAddSection('Role', { body: 'You are a helpful assistant.' });
agent.run();
```
-*/}
{/*
@@ -190,9 +188,21 @@ agent.Run();
The `run()` method automatically:
-- Detects serverless environments (Lambda, Cloud Functions, Azure)
+- Detects serverless environments (Lambda, Cloud Functions, Azure) **(Python only)**
- Starts a development server on localhost for local development
-- Handles CGI mode when deployed to traditional web servers
+- Handles CGI mode when deployed to traditional web servers **(Python only)**
+
+
+In TypeScript, `run()` is an alias for `serve()` and only starts an HTTP server.
+For serverless deployments (Lambda, Cloud Functions, Azure, CGI) call
+`agent.runServerless(event, context, platform?)` from your platform handler,
+or use the `ServerlessAdapter.createLambdaHandler` / `createGcfHandler` /
+`createAzureHandler` helpers. See the [Serverless](/docs/server-sdks/guides/serverless) guide.
+
+
+The SignalWire TypeScript SDK (`@signalwire/sdk`) is ESM-only. Your
+`package.json` must set `"type": "module"`, or your entry file must be named
+`.mjs`. Otherwise Node will try to load it as CommonJS and imports will fail.
## Starting the development server
@@ -201,7 +211,7 @@ The simplest way to run your agent locally:
| Language | Run Command |
|----------|-------------|
| Python | `python my_agent.py` |
-| TypeScript | `npx ts-node my_agent.ts` or `node my_agent.js` |
+| TypeScript | `npx tsx my_agent.ts` or `node my_agent.mjs` |
{/*
| Go | `go run my_agent.go` |
diff --git a/fern/products/server-sdks/pages/guides/deploy/production.mdx b/fern/products/server-sdks/pages/guides/deploy/production.mdx
index e3694feee..ee763c992 100644
--- a/fern/products/server-sdks/pages/guides/deploy/production.mdx
+++ b/fern/products/server-sdks/pages/guides/deploy/production.mdx
@@ -84,13 +84,12 @@ if __name__ == "__main__":
agent.run(host="0.0.0.0", port=3000)
```
-{/*
Use Node.js with clustering or a process manager like PM2:
```typescript
// app.ts
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'my-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -99,13 +98,15 @@ agent.promptAddSection('Role', { body: 'You are a helpful assistant.' });
agent.run({ host: '0.0.0.0', port: 3000 });
```
+Build to `app.mjs` (or set `"type": "module"` in `package.json`) — `@signalwire/sdk`
+is ESM-only. For PM2 cluster mode, use PM2 5.2+ and point at the `.mjs` entry.
+
```bash
## Run with PM2 for process management
npm install -g pm2
-pm2 start app.js -i 4 --name signalwire-agent
+pm2 start app.mjs -i 4 --name signalwire-agent
```
-*/}
{/*
@@ -277,7 +278,7 @@ Create `/etc/systemd/system/signalwire-agent.service`. Adjust `ExecStart` for yo
| Language | ExecStart Example |
|----------|-------------------|
| Python | `/opt/agent/venv/bin/uvicorn app:app --host 127.0.0.1 --port 3000 --workers 4` |
-| TypeScript | `/usr/bin/node /opt/agent/app.js` |
+| TypeScript | `/usr/bin/node /opt/agent/app.mjs` |
{/*
| Go | `/opt/agent/signalwire-agent` |
diff --git a/fern/products/server-sdks/pages/guides/deploy/serverless.mdx b/fern/products/server-sdks/pages/guides/deploy/serverless.mdx
index 76dbcf6a8..64236fa06 100644
--- a/fern/products/server-sdks/pages/guides/deploy/serverless.mdx
+++ b/fern/products/server-sdks/pages/guides/deploy/serverless.mdx
@@ -20,7 +20,6 @@ max-toc-depth: 3
| Language | AWS Lambda | Google Cloud Functions | Azure Functions |
|----------|------------|------------------------|-----------------|
| Python | Yes | Yes | Yes |
-
| TypeScript | Yes (Node.js runtime) | Yes (Node.js runtime) | Yes (Node.js runtime) |
{/*
@@ -90,16 +89,15 @@ def lambda_handler(event, context):
return agent.handle_serverless_request(event, context)
```
-{/*
-`handler.ts`:
+`handler.ts` (deploy as `handler.mjs` or ensure `package.json` has `"type": "module"` — `@signalwire/sdk` is ESM-only):
```typescript
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({ name: "my-agent" });
-agent.addLanguage("English", "en-US", "rime.spore");
-agent.promptAddSection("Role", "You are a helpful assistant.");
+agent.addLanguage({ name: "English", code: "en-US", voice: "rime.spore" });
+agent.promptAddSection("Role", { body: "You are a helpful assistant." });
agent.defineTool({
name: "say_hello",
@@ -111,18 +109,17 @@ agent.defineTool({
},
required: ["name"]
},
- handler: (args: any) => {
- const name = args.name || "World";
+ handler: (args: Record) => {
+ const name = (args['name'] as string) || "World";
return new FunctionResult(`Hello ${name}!`);
}
});
-export const handler = async (event: any, context: any) => {
- return agent.handleRequest(event, context);
+export const handler = async (event: unknown, context: unknown) => {
+ return agent.runServerless(event, context);
};
```
-*/}
{/*
@@ -302,13 +299,12 @@ def main(request):
return agent.handle_serverless_request(request)
```
-{/*
-`index.ts`:
+`index.ts` (deploy as `.mjs` or ensure `package.json` has `"type": "module"` — `@signalwire/sdk` is ESM-only):
```typescript
-import { AgentBase, FunctionResult } from 'signalwire-agents';
-import { HttpFunction } from '@google-cloud/functions-framework';
+import { AgentBase, FunctionResult, ServerlessAdapter } from '@signalwire/sdk';
+import type { HttpFunction } from '@google-cloud/functions-framework';
const agent = new AgentBase({ name: 'my-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -324,17 +320,14 @@ agent.defineTool({
},
required: ['name'],
},
- handler: (args: any) => {
- return new FunctionResult(`Hello ${args.name || 'World'}!`);
+ handler: (args: Record) => {
+ return new FunctionResult(`Hello ${(args['name'] as string) || 'World'}!`);
},
});
-export const main: HttpFunction = (req, res) => {
- return agent.handleRequest(req, res);
-};
+export const main: HttpFunction = ServerlessAdapter.createGcfHandler(agent.getApp());
```
-*/}
{/*
@@ -468,13 +461,11 @@ def main(req: func.HttpRequest) -> func.HttpResponse:
return agent.handle_serverless_request(req)
```
-{/*
-`src/functions/agent.ts`:
+`src/functions/agent.ts` (deploy as `.mjs` or set `"type": "module"` in `package.json` — `@signalwire/sdk` is ESM-only). This example uses the Azure Functions v3 programming model with `function.json` (shown below). The SDK's Azure helper follows that shape.
```typescript
-import { app, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions';
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult, ServerlessAdapter } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'my-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -490,19 +481,15 @@ agent.defineTool({
},
required: ['name'],
},
- handler: (args: any) => {
- return new FunctionResult(`Hello ${args.name || 'World'}!`);
+ handler: (args: Record) => {
+ return new FunctionResult(`Hello ${(args['name'] as string) || 'World'}!`);
},
});
-export async function main(req: HttpRequest, context: InvocationContext): Promise {
- return agent.handleRequest(req);
-}
-
-app.http('agent', { methods: ['GET', 'POST'], authLevel: 'anonymous', handler: main });
+// Azure Functions v3 entry point — `context.res` is populated by the adapter.
+export default ServerlessAdapter.createAzureHandler(agent.getApp());
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/getting-started/dev-environment.mdx b/fern/products/server-sdks/pages/guides/getting-started/dev-environment.mdx
index 62ebb7524..d8b9cb15b 100644
--- a/fern/products/server-sdks/pages/guides/getting-started/dev-environment.mdx
+++ b/fern/products/server-sdks/pages/guides/getting-started/dev-environment.mdx
@@ -32,7 +32,6 @@ my-agent-project/
└── main.py # Entry point
```
-{/*
```text
my-agent-project/
@@ -48,7 +47,6 @@ my-agent-project/
└── tsconfig.json
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/getting-started/installation.mdx b/fern/products/server-sdks/pages/guides/getting-started/installation.mdx
index 206a8423e..14eda8393 100644
--- a/fern/products/server-sdks/pages/guides/getting-started/installation.mdx
+++ b/fern/products/server-sdks/pages/guides/getting-started/installation.mdx
@@ -30,13 +30,15 @@ max-toc-depth: 3
pip install signalwire-sdk
```
-{/*
```bash
-npm install signalwire-agents
+npm install @signalwire/sdk
```
+
+
+`@signalwire/sdk` is published as an ES module only (no CommonJS build). Your project must use ESM — add `"type": "module"` to your `package.json`, use `.mjs` file extensions, or use a bundler/transpiler that supports ESM. `import` syntax works; `require('@signalwire/sdk')` does not work in Node older than 22 without the `--experimental-require-module` flag.
+
-*/}
{/*
@@ -108,13 +110,11 @@ dotnet add package SignalWire.Sdk
python -c "from signalwire import AgentBase; print('SDK installed successfully!')"
```
-{/*
```bash
-node -e "const { AgentBase } = require('signalwire-agents'); console.log('SDK installed successfully!')"
+node --input-type=module -e "import { AgentBase } from '@signalwire/sdk'; console.log('SDK installed successfully!');"
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/getting-started/overview.mdx b/fern/products/server-sdks/pages/guides/getting-started/overview.mdx
index 487770f8f..203a2f0c8 100644
--- a/fern/products/server-sdks/pages/guides/getting-started/overview.mdx
+++ b/fern/products/server-sdks/pages/guides/getting-started/overview.mdx
@@ -25,7 +25,7 @@ The SignalWire Server SDK is available in multiple languages. Select the variant
-{/*
```typescript
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'my-agent' });
// Configure your agent here
```
-*/}
{/*
@@ -282,17 +280,20 @@ def lookup_customer(args, raw_data=None):
)
```
-{/*
```typescript
agent.defineTool({
name: 'lookup_customer',
description: 'Look up a customer by phone number',
parameters: {
- phone_number: { type: 'string', description: 'Phone number' }
+ type: 'object',
+ properties: {
+ phone_number: { type: 'string', description: 'Phone number' },
+ },
+ required: ['phone_number'],
},
handler: (args) => {
- const customer = database.find(args.phone_number);
+ const customer = database.find(args.phone_number as string);
return new FunctionResult(
`Customer: ${customer.name}, Account: ${customer.id}`
);
@@ -300,7 +301,6 @@ agent.defineTool({
});
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/getting-started/quickstart.mdx b/fern/products/server-sdks/pages/guides/getting-started/quickstart.mdx
index b59369fc1..f906008d5 100644
--- a/fern/products/server-sdks/pages/guides/getting-started/quickstart.mdx
+++ b/fern/products/server-sdks/pages/guides/getting-started/quickstart.mdx
@@ -63,13 +63,12 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
#!/usr/bin/env npx tsx
// my_first_agent.ts - A simple voice AI agent
-import { AgentBase } from 'signalwire-agents';
+import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'my-first-agent' });
@@ -96,7 +95,6 @@ console.log('Server running at: http://localhost:3000');
agent.run();
```
-*/}
{/*
@@ -498,13 +496,12 @@ if __name__ == "__main__":
```
-{/*
```typescript
#!/usr/bin/env npx tsx
// my_first_agent_with_function.ts - Agent with custom function
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'my-first-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
@@ -517,7 +514,7 @@ agent.promptAddSection('Role', {
agent.defineTool({
name: 'tell_joke',
description: 'Tell a joke to the caller',
- parameters: {},
+ parameters: { type: 'object', properties: {} },
handler: () => {
const jokes = [
'Why do programmers prefer dark mode? Because light attracts bugs!',
@@ -533,7 +530,6 @@ agent.run();
```
-*/}
{/*
@@ -928,12 +924,11 @@ if __name__ == "__main__":
agent.run()
```
-{/*
```typescript
#!/usr/bin/env npx tsx
// complete_first_agent.ts - Complete agent example with multiple features
-import { AgentBase, FunctionResult } from 'signalwire-agents';
+import { AgentBase, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'complete-agent', autoAnswer: true, recordCall: false });
@@ -955,14 +950,14 @@ agent.promptAddSection('Style', {
agent.defineTool({
name: 'get_current_time',
description: 'Get the current time',
- parameters: {},
+ parameters: { type: 'object', properties: {} },
handler: () => new FunctionResult(`The current time is ${new Date().toLocaleTimeString()}`),
});
agent.defineTool({
name: 'tell_joke',
description: 'Tell a random joke',
- parameters: {},
+ parameters: { type: 'object', properties: {} },
handler: () => {
const jokes = [
'Why do programmers prefer dark mode? Because light attracts bugs!',
@@ -977,7 +972,6 @@ console.log('Complete First Agent running at http://localhost:3000');
agent.run();
```
-*/}
{/*
diff --git a/fern/products/server-sdks/pages/guides/make-and-receive-calls/overview.mdx b/fern/products/server-sdks/pages/guides/make-and-receive-calls/overview.mdx
index f77daee1b..6ac697fdc 100644
--- a/fern/products/server-sdks/pages/guides/make-and-receive-calls/overview.mdx
+++ b/fern/products/server-sdks/pages/guides/make-and-receive-calls/overview.mdx
@@ -66,14 +66,13 @@ async def handle_call(call):
client.run()
```
-{/*
```typescript
-import { RelayClient } from 'signalwire-agents';
+import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
- projectId: 'your-project-id',
- apiToken: 'your-api-token',
+ project: 'your-project-id',
+ token: 'your-api-token',
host: 'your-space.signalwire.com',
contexts: ['default'],
});
@@ -88,7 +87,6 @@ client.onCall(async (call) => {
client.run();
```
-*/}
{/*
@@ -260,7 +258,7 @@ The RELAY client supports two authentication methods:
| Language | Syntax |
|----------|--------|
| Python | `RelayClient(project="...", token="...", host="...")` |
-| TypeScript | `new RelayClient({ projectId: '...', apiToken: '...', host: '...' })` |
+| TypeScript | `new RelayClient({ project: '...', token: '...', host: '...' })` |
{/*
| Go | `relay.NewClient(relay.WithProjectID("..."), relay.WithAPIToken("..."), relay.WithHost("..."))` |
diff --git a/fern/products/server-sdks/pages/guides/manage-resources/overview.mdx b/fern/products/server-sdks/pages/guides/manage-resources/overview.mdx
index cd821de52..2c4f99647 100644
--- a/fern/products/server-sdks/pages/guides/manage-resources/overview.mdx
+++ b/fern/products/server-sdks/pages/guides/manage-resources/overview.mdx
@@ -47,15 +47,14 @@ available = client.phone_numbers.search(area_code="512")
print(available)
```
-{/*
```typescript
-import { RestClient } from 'signalwire-agents';
+import { RestClient } from '@signalwire/sdk';
const client = new RestClient({
- projectId: 'your-project-id',
- apiToken: 'your-api-token',
- spaceName: 'your-space.signalwire.com',
+ project: 'your-project-id',
+ token: 'your-api-token',
+ host: 'your-space.signalwire.com',
});
// List AI agents
@@ -67,7 +66,6 @@ const available = await client.phoneNumbers.search({ areaCode: '512' });
console.log(available);
```
-*/}
{/*
@@ -213,7 +211,7 @@ Console.WriteLine(available);
| Language | Syntax |
|----------|--------|
| Python | `SignalWireClient(project="...", token="...", host="...")` |
-| TypeScript | `new RestClient({ projectId: '...', apiToken: '...', spaceName: '...' })` |
+| TypeScript | `new RestClient({ project: '...', token: '...', host: '...' })` |
{/*
| Go | `rest.NewClient(rest.WithProjectID("..."), rest.WithAPIToken("..."), rest.WithSpaceName("..."))` |
diff --git a/fern/products/server-sdks/pages/guides/manage-resources/testing.mdx b/fern/products/server-sdks/pages/guides/manage-resources/testing.mdx
index d8bc5be8d..284ef0dc0 100644
--- a/fern/products/server-sdks/pages/guides/manage-resources/testing.mdx
+++ b/fern/products/server-sdks/pages/guides/manage-resources/testing.mdx
@@ -50,7 +50,7 @@ Run your agent locally using the appropriate command for your language:
| Language | Start Command |
|----------|---------------|
| Python | `python my_agent.py` |
-| TypeScript | `npx ts-node my_agent.ts` |
+| TypeScript | `npx tsx my_agent.ts` |
{/*
| Go | `go run my_agent.go` |
@@ -156,7 +156,7 @@ Test call transfers carefully. The transfer API is the same across languages via
| Language | Transfer Call |
|----------|-------------|
| Python | `FunctionResult("Transferring").connect(number, final=True)` |
-| TypeScript | `new FunctionResult("Transferring").connect(number, { final: true })` |
+| TypeScript | `new FunctionResult("Transferring").connect(number, true)` |
{/*
| Go | `agent.NewFunctionResult("Transferring").Connect(number, true)` |
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-internal-filler.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-internal-filler.mdx
index 89b3a3d15..ed57076c3 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-internal-filler.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-internal-filler.mdx
@@ -1,19 +1,27 @@
---
title: "addInternalFiller"
slug: /reference/typescript/agents/agent-base/add-internal-filler
-description: Add filler phrases for a specific SWAIG function and language.
+description: Add filler phrases for a specific native SWAIG function and language.
max-toc-depth: 3
---
[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
-Add filler phrases spoken while a specific SWAIG function is executing. The AI
+Add filler phrases spoken while a specific native SWAIG function is executing. The AI
randomly selects from the list each time the function is invoked.
+
+Only a fixed set of native function names accept fillers: `hangup`, `check_time`,
+`wait_for_user`, `wait_seconds`, `adjust_response_latency`, `next_step`,
+`change_context`, `get_visual_input`, `get_ideal_strategy`. Passing any other name
+logs a warning and is silently ignored by the runtime.
+
+
## **Parameters**
- Name of the SWAIG function these fillers apply to (e.g., `"next_step"`, `"check_time"`).
+ One of the supported native function names (e.g., `"next_step"`, `"check_time"`).
+ Unknown names log a warning and are ignored.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-pattern-hint.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-pattern-hint.mdx
index 5837f4a45..ce0bc0e14 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-pattern-hint.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-pattern-hint.mdx
@@ -18,6 +18,10 @@ consistent misrecognitions or normalizing variations.
+
+ Descriptive label for the hint (surfaced to the ASR alongside the pattern).
+
+
Regular expression pattern to match.
@@ -44,6 +48,7 @@ const agent = new AgentBase({ name: 'support', route: '/support' });
agent.setPromptText('You are a helpful assistant.');
// Correct common ASR misrecognition
agent.addPatternHint({
+ hint: 'SignalWire brand name',
pattern: 'signal\\s*wire|signal\\s*wired',
replace: 'SignalWire',
ignoreCase: true,
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-skill-by-name.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-skill-by-name.mdx
new file mode 100644
index 000000000..bb5174e74
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-skill-by-name.mdx
@@ -0,0 +1,36 @@
+---
+title: "addSkillByName"
+slug: /reference/typescript/agents/agent-base/add-skill-by-name
+description: Look up a skill class in the global registry and add it by name.
+max-toc-depth: 3
+---
+
+[ref-registry]: /docs/server-sdks/reference/typescript/agents/skill-registry
+[ref-addskill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
+
+Look up a skill class by name in the global
+[`SkillRegistry`][ref-registry], instantiate it, and add it to the agent via
+[`addSkill`][ref-addskill]. Fails closed like `addSkill`.
+
+## **Parameters**
+
+
+ Registered skill name (read from the target class's `SKILL_NAME`).
+
+
+
+ Optional configuration forwarded to the skill constructor.
+
+
+## **Returns**
+
+`Promise` — the agent for method chaining.
+
+## **Example**
+
+```typescript {3}
+const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
+agent.setPromptText('You are a helpful assistant.');
+await agent.addSkillByName('datetime');
+await agent.addSkillByName('web_search', { num_results: 3 });
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-skill.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-skill.mdx
index 658f6b3e3..a8cfa5911 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-skill.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/add-skill.mdx
@@ -15,8 +15,15 @@ takes a `SkillBase` instance (not a string name).
This is an `async` method that returns `Promise`. Use `await` when calling.
-Throws `Error` if a duplicate non-multi-instance skill is added. Check available
-skills with [`listSkills()`][list-skills] or consult the [skills catalog][skills-catalog].
+
+`addSkill()` **fails closed**: it throws if a duplicate non-multi-instance
+skill is added, if required environment variables or packages are missing,
+if the skill's parameter schema is empty, or if the skill's `setup()`
+returns `false`. The method also registers any DataMap-style tools the
+skill exposes via `getDataMapTools()`.
+
+Check available skills with [`listSkills()`][list-skills] or consult the
+[skills catalog][skills-catalog].
## **Parameters**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/auto-map-sip-usernames.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/auto-map-sip-usernames.mdx
new file mode 100644
index 000000000..99b13c537
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/auto-map-sip-usernames.mdx
@@ -0,0 +1,54 @@
+---
+title: "autoMapSipUsernames"
+slug: /reference/typescript/agents/agent-base/auto-map-sip-usernames
+description: Automatically register common SIP usernames derived from the agent's name and route.
+max-toc-depth: 3
+---
+
+[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
+[enable-sip-routing]: /docs/server-sdks/reference/typescript/agents/agent-base/enable-sip-routing
+[register-sip-username]: /docs/server-sdks/reference/typescript/agents/agent-base/register-sip-username
+
+Automatically register SIP usernames based on the agent's `name` and `route`
+properties. Convenience method that derives common username variations so callers
+can reach the agent via SIP without manual registration.
+
+The method registers:
+- A lowercase, alphanumeric-only version of the agent name (e.g., `"supportagent"`)
+- A lowercase, alphanumeric-only version of the route when different from the name
+- A vowel-stripped abbreviation of the name when the cleaned name is longer than
+ 3 characters and the stripped result is longer than 2 characters
+
+
+[`enableSipRouting()`][enable-sip-routing] calls this method automatically when
+invoked without arguments. You only need to call `autoMapSipUsernames()` directly
+to trigger it after disabling auto-mapping.
+
+
+## **Parameters**
+
+None.
+
+## **Returns**
+
+[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining.
+
+## **Example**
+
+```typescript {5}
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'Support Agent', route: '/support' });
+agent.setPromptText('You are a support assistant.');
+agent.autoMapSipUsernames();
+// Registers: "supportagent", "support", "spprtgnt"
+await agent.serve();
+```
+
+To register specific usernames instead, use
+[`registerSipUsername()`][register-sip-username]:
+
+```typescript {2-3}
+agent.registerSipUsername('helpdesk');
+agent.registerSipUsername('support');
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/clear-swaig-query-params.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/clear-swaig-query-params.mdx
new file mode 100644
index 000000000..2ebde3100
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/clear-swaig-query-params.mdx
@@ -0,0 +1,41 @@
+---
+title: "clearSwaigQueryParams"
+slug: /reference/typescript/agents/agent-base/clear-swaig-query-params
+description: Remove all SWAIG query parameters from the agent.
+max-toc-depth: 3
+---
+
+[add-swaig-query-params]: /docs/server-sdks/reference/typescript/agents/agent-base/add-swaig-query-params
+[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
+
+Clear all query parameters previously added with
+[`addSwaigQueryParams()`][add-swaig-query-params]. After calling this method,
+SWAIG webhook URLs will no longer include any extra query parameters.
+
+## **Parameters**
+
+None.
+
+## **Returns**
+
+[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining.
+
+## **Examples**
+
+### Reset params in dynamic config
+
+```typescript {9}
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
+agent.setPromptText('You are a helpful assistant.');
+
+agent.setDynamicConfigCallback((queryParams, bodyParams, headers, agentCopy) => {
+ // Start fresh each request to avoid stale params
+ agentCopy.clearSwaigQueryParams();
+ const tier = queryParams.tier ?? 'free';
+ agentCopy.addSwaigQueryParams({ tier });
+});
+
+await agent.serve();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/define-tool.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/define-tool.mdx
index 04f2ab425..bec3e3dc4 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/define-tool.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/define-tool.mdx
@@ -53,8 +53,8 @@ instead.
return a [`FunctionResult`][functionresult].
-
- Whether to require token validation on tool calls.
+
+ Whether to require token validation on tool calls. Recommended for production.
"} toc={true}>
@@ -73,6 +73,17 @@ instead.
List of required parameter names from the JSON Schema.
+
+
+ External webhook URL. When set, the tool is treated as externally-hosted and
+ the tool call is forwarded to this URL instead of being dispatched to a local
+ handler.
+
+
+"} toc={true}>
+ Additional fields merged into the SWAIG function definition. Equivalent to
+ Python's `**swaig_fields` kwargs (e.g., `meta_data`).
+
## **Returns**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/define-typed-tool.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/define-typed-tool.mdx
index ced64b153..b19976d55 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/define-typed-tool.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/define-typed-tool.mdx
@@ -47,8 +47,8 @@ the args object.
object. Parameter names must match the JSON Schema property names.
-
- Whether to require token validation on tool calls.
+
+ Whether to require token validation on tool calls. Recommended for production.
"} toc={true}>
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/enable-debug-routes.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/enable-debug-routes.mdx
new file mode 100644
index 000000000..2c8d56c04
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/enable-debug-routes.mdx
@@ -0,0 +1,32 @@
+---
+title: "enableDebugRoutes"
+slug: /reference/typescript/agents/agent-base/enable-debug-routes
+description: Enable debug and testing routes on the agent's HTTP server.
+max-toc-depth: 3
+---
+
+[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
+
+Enable debug routes on the agent's Hono server for development and testing. In
+the TypeScript SDK, debug routes (health, ready, debug_events) are automatically
+registered in `getApp()`; this method exists as a no-op stub for API parity with
+the Python SDK.
+
+## **Parameters**
+
+None.
+
+## **Returns**
+
+[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining.
+
+## **Example**
+
+```typescript {5}
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'dev-agent', route: '/dev' });
+agent.setPromptText('You are a helpful assistant.');
+agent.enableDebugRoutes();
+await agent.serve();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/get-basic-auth-credentials.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/get-basic-auth-credentials.mdx
index ae5ae2c0d..a3c02db67 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/get-basic-auth-credentials.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/get-basic-auth-credentials.mdx
@@ -13,8 +13,8 @@ includes a source label indicating where the credentials came from.
When `true`, the returned tuple includes a third element indicating the credential
source: `"provided"` (set explicitly), `"environment"` (from `SWML_BASIC_AUTH_USER`
- / `SWML_BASIC_AUTH_PASSWORD` environment variables), or `"generated"` (auto-generated
- at startup).
+ / `SWML_BASIC_AUTH_PASSWORD` environment variables), or `"auto-generated"`
+ (auto-generated at startup).
## **Returns**
@@ -46,7 +46,7 @@ import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
agent.setPromptText('You are a helpful assistant.');
const [user, password, source] = agent.getBasicAuthCredentials(true);
-if (source === 'generated') {
+if (source === 'auto-generated') {
console.log(`Auto-generated credentials: ${user}:${password}`);
console.log('Set SWML_BASIC_AUTH_USER and SWML_BASIC_AUTH_PASSWORD to use your own.');
}
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/get-prompt-pom.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/get-prompt-pom.mdx
new file mode 100644
index 000000000..9fb248efd
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/get-prompt-pom.mdx
@@ -0,0 +1,35 @@
+---
+title: "getPromptPom"
+slug: /reference/typescript/agents/agent-base/get-prompt-pom
+description: Return the current prompt as a POM (Prompt Object Model) array.
+max-toc-depth: 3
+---
+
+[set-prompt-pom]: /docs/server-sdks/reference/typescript/agents/agent-base/set-prompt-pom
+[prompt-add-section]: /docs/server-sdks/reference/typescript/agents/agent-base/prompt-add-section
+
+Return the current prompt as a POM (Prompt Object Model) array — the structured,
+section-based representation built via [`setPromptPom()`][set-prompt-pom] or
+[`promptAddSection()`][prompt-add-section]. Returns `null` when the agent is
+configured with a raw text prompt (`usePom: false`) or when no sections have been
+added.
+
+## **Parameters**
+
+None.
+
+## **Returns**
+
+`Record[] | null` -- Array of POM section data objects, or
+`null` if not in POM mode or POM is empty.
+
+## **Example**
+
+```typescript {5}
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'support', route: '/support' });
+agent.promptAddSection('Role', { body: 'You are a support agent.' });
+const sections = agent.getPromptPom();
+console.log(sections);
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/index.mdx
index 8a69a8cc5..41c3038bf 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/index.mdx
@@ -69,7 +69,7 @@ const agent = new AgentBase({
plain text prompts only.
-
+
Expiration time in seconds for SWAIG function authentication tokens.
@@ -109,6 +109,32 @@ const agent = new AgentBase({
Suppress SDK log output. Useful in testing or when integrating with external logging.
+
+ When `true`, register the `/post_prompt_override` route allowing external callers to
+ replace the post-prompt text at runtime.
+
+
+
+ When `true`, register the `/check_for_input` route allowing external callers to inject
+ input checks at runtime.
+
+
+
+ Path to a JSON configuration file. When provided, its `service` section supplies
+ defaults for `name`, `route`, `host`, and `port`. Constructor arguments still take
+ precedence over file values.
+
+
+
+ Path to a custom SWML JSON Schema file used for validation. Falls back to the built-in
+ schema when omitted.
+
+
+
+ Enable SWML schema validation on rendered documents. Can also be disabled via
+ `SWML_SKIP_SCHEMA_VALIDATION` env var.
+
+
## **Properties**
@@ -245,6 +271,42 @@ await agent.run();
Load and activate a skill on the agent.
+
+ Look up a skill class in the global registry and add it by name.
+
+
+ Remove every skill instance matching a given name.
+
+
+ Clear every context from the agent's ContextBuilder.
+
+
+ Return the current POM-structured prompt.
+
+
+ Replace the prompt with the supplied POM array.
+
+
+ Replace every pronunciation rule in a single call.
+
+
+ Set every internal-filler entry in one call.
+
+
+ Replace the SWAIG function-includes list.
+
+
+ Auto-register the agent's route as the SIP username target.
+
+
+ Validate a per-tool HMAC token.
+
+
+ Remove every SWAIG query-param override.
+
+
+ Expose the agent's debug HTTP endpoints.
+
Append query parameters to all SWAIG webhook URLs.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/on-function-call.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/on-function-call.mdx
index 57d6865e8..51c376673 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/on-function-call.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/on-function-call.mdx
@@ -11,11 +11,12 @@ Pre-execution hook called before each SWAIG function is executed. The default
implementation is a no-op. Override this method in a subclass to intercept tool
calls for logging, metrics, or custom dispatch logic.
-
-This is a **pre-execution hook only** — it does not replace the function dispatch.
-The tool handler still executes regardless of what this method does. If you need
-to block execution, throw an error from this hook.
-
+
+Return a result object from this hook to **short-circuit** default execution —
+the returned value is sent as the function response and the registered tool
+handler is skipped. Return `void` / `undefined` to let the normal dispatch
+proceed.
+
## **Parameters**
@@ -34,7 +35,9 @@ to block execution, throw an error from this hook.
## **Returns**
-`void | Promise`
+`Record | void | Promise | void>` --
+Return a result object to short-circuit default execution; return `void` /
+`undefined` to proceed normally.
## **Example**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/on-swml-request.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/on-swml-request.mdx
index 4069cb7ee..138ae222e 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/on-swml-request.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/on-swml-request.mdx
@@ -21,9 +21,23 @@ prompts based on request metadata, or logging request details.
`caller_id_number`, `caller_id_name`, and any custom SIP headers.
+
+ Optional callback path from the request body (`callback_path` field), when
+ the request was triggered via a callback URL.
+
+
+
+ The raw Hono request context (`c`), providing access to headers, query
+ parameters, and the underlying HTTP request.
+
+
## **Returns**
-`void | Promise`
+`Record | void | Promise | void>` --
+Return a modifications object to merge into the AI verb config before
+rendering. `global_data` is deep-merged; all other keys override AI config
+fields directly. Return `void` / `undefined` to render without
+modifications.
For most per-request customization scenarios, prefer
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/register-swaig-function.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/register-swaig-function.mdx
index 3b73f4bd3..6b6664519 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/register-swaig-function.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/register-swaig-function.mdx
@@ -26,8 +26,8 @@ accepts pre-built objects rather than taking a handler callback.
## **Example**
-```typescript {17}
-import { AgentBase, DataMap } from '@signalwire/sdk';
+```typescript {15}
+import { AgentBase, DataMap, FunctionResult } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'plant-agent', route: '/plants' });
agent.setPromptText('You are a helpful plant care assistant.');
@@ -37,10 +37,9 @@ const plantTool = new DataMap('get_plant_info')
.description('Get care information for a plant')
.parameter('plantId', 'string', 'Plant ID', { required: true })
.webhook('GET', 'https://api.plants.example.com/plants/${args.plantId}')
- .output({
- response: 'The plant ${args.plantId} needs ${response.water_schedule} watering.',
- action: [{ say: 'Here is the plant care information.' }],
- });
+ .output(new FunctionResult(
+ 'The plant ${args.plantId} needs ${response.water_schedule} watering.',
+ ));
// Register the DataMap as a SWAIG function
agent.registerSwaigFunction(plantTool.toSwaigFunction());
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/remove-skill-by-name.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/remove-skill-by-name.mdx
new file mode 100644
index 000000000..24a8335d5
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/remove-skill-by-name.mdx
@@ -0,0 +1,37 @@
+---
+title: "removeSkillByName"
+slug: /reference/typescript/agents/agent-base/remove-skill-by-name
+description: Remove a skill from the agent by skill name.
+max-toc-depth: 3
+---
+
+[remove-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/remove-skill
+[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
+
+Remove the first loaded skill whose name matches `skillName`. Provides name-based
+removal for parity with Python's `remove_skill(skill_name)`. Use
+[`removeSkill()`][remove-skill] when you need to remove a specific instance by
+its `instanceId`.
+
+## **Parameters**
+
+
+ Skill name to match. Only the first matching instance is removed.
+
+
+## **Returns**
+
+`Promise` -- `true` if a matching skill was found and removed, `false`
+otherwise.
+
+## **Example**
+
+```typescript {6}
+import { AgentBase, DateTimeSkill, MathSkill } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
+await agent.addSkill(new DateTimeSkill());
+await agent.addSkill(new MathSkill());
+await agent.removeSkillByName('math');
+console.log(agent.listSkills().map((s) => s.name)); // ["datetime"]
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/render-swml.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/render-swml.mdx
index 5dcc894d0..c90195aab 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/render-swml.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/render-swml.mdx
@@ -16,6 +16,13 @@ debugging.
Optional call ID to use for session tokens. Auto-generated if omitted.
+"} toc={true}>
+ Optional object (typically returned from
+ [`onSwmlRequest()`](/docs/server-sdks/reference/typescript/agents/agent-base/on-swml-request))
+ merged into the AI verb config before rendering. `global_data` is deep-merged;
+ all other keys override AI config fields directly.
+
+
## **Returns**
`string` -- The rendered SWML document as a JSON string.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/reset-contexts.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/reset-contexts.mdx
new file mode 100644
index 000000000..a750f6e01
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/reset-contexts.mdx
@@ -0,0 +1,40 @@
+---
+title: "resetContexts"
+slug: /reference/typescript/agents/agent-base/reset-contexts
+description: Clear every context defined on this agent's ContextBuilder.
+max-toc-depth: 3
+---
+
+[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
+[ref-ctxbuilder]: /docs/server-sdks/reference/typescript/agents/context-builder
+[define-contexts]: /docs/server-sdks/reference/typescript/agents/agent-base/define-contexts
+
+Remove every context defined on this agent's internal
+[`ContextBuilder`][ref-ctxbuilder], returning the builder to its initial state.
+Convenience wrapper around [`defineContexts()`][define-contexts]`.reset()`. Use
+this inside a dynamic-config callback when you need to rebuild contexts from
+scratch for a specific request.
+
+## **Parameters**
+
+None.
+
+## **Returns**
+
+[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining.
+
+## **Example**
+
+```typescript {6}
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'intake', route: '/intake' });
+
+agent.setDynamicConfigCallback((queryParams, bodyParams, headers, agentCopy) => {
+ agentCopy.resetContexts();
+ const ctx = agentCopy.defineContexts().addContext('default');
+ ctx.addStep('greeting').setText('Greet the caller.');
+});
+
+await agent.serve();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/run.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/run.mdx
index d53253a9d..80983d07f 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/run.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/run.mdx
@@ -12,7 +12,19 @@ for requests.
## **Parameters**
-None.
+
+ Optional host and port overrides.
+
+
+
+
+ Host to bind the server to. Falls back to the constructor's `host` option.
+
+
+
+ Port to listen on. Falls back to the constructor's `port` option.
+
+
## **Returns**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/serve.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/serve.mdx
index 2ea00ec3d..07bef5cef 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/serve.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/serve.mdx
@@ -26,7 +26,25 @@ TypeScript SDK.
## **Parameters**
-None.
+
+ Optional host and port overrides.
+
+
+
+
+ Host to bind the server to. Falls back to the constructor's `host` option.
+
+
+
+ Port to listen on. Falls back to the constructor's `port` option.
+
+
+
+
+When the `SWAIG_CLI_MODE` environment variable is set to `"true"`, `serve()`
+returns immediately without starting the server. This lets the `swaig-test`
+CLI load the agent's configuration without binding a port.
+
## **Returns**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-function-includes.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-function-includes.mdx
new file mode 100644
index 000000000..67cbb320a
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-function-includes.mdx
@@ -0,0 +1,49 @@
+---
+title: "setFunctionIncludes"
+slug: /reference/typescript/agents/agent-base/set-function-includes
+description: Replace the agent's SWAIG function-includes list.
+max-toc-depth: 3
+---
+
+[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
+[ref-add-include]: /docs/server-sdks/reference/typescript/agents/agent-base/add-function-include
+
+Replace the agent's SWAIG function-includes list in a single call. Each
+include pulls a remote SWAIG function definition into the agent's toolset. Use
+[`addFunctionInclude()`][ref-add-include] to append a single include instead
+of replacing the list.
+
+
+Entries without a `url` or without an array `functions` field are silently
+filtered out.
+
+
+## **Parameters**
+
+
+ Ordered list of function-include entries. Each entry must provide `url` and
+ an array of `functions` names; an optional `meta_data` object is passed to
+ the remote server.
+
+
+## **Returns**
+
+[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining.
+
+## **Example**
+
+```typescript {5}
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
+agent.setPromptText('You are a helpful assistant.');
+agent.setFunctionIncludes([
+ { url: 'https://tools.example.com/swaig', functions: ['lookup_order'] },
+ {
+ url: 'https://analytics.example.com/swaig',
+ functions: ['log_event'],
+ meta_data: { api_key: 'secret' },
+ },
+]);
+await agent.serve();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-global-data.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-global-data.mdx
index f34128232..4b59e607a 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-global-data.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-global-data.mdx
@@ -1,13 +1,23 @@
---
title: "setGlobalData"
slug: /reference/typescript/agents/agent-base/set-global-data
-description: Replace the global data object available to the AI throughout a conversation.
+description: Merge key-value pairs into the global data object available to the AI throughout a conversation.
max-toc-depth: 3
---
[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
-Replace the entire global data object available to the AI throughout the conversation.
+Merge key-value pairs into the `global_data` object available to the AI
+throughout the conversation. Matches Python's `set_global_data`, which calls
+`.update()` on the internal dict — existing keys are preserved; incoming keys
+overwrite on collision. Skills and other callers can each contribute keys
+without clobbering one another.
+
+
+Despite the `set` prefix, this method **merges** rather than replaces. There is
+no built-in "clear" method; construct a new agent if you need an empty
+`global_data` object.
+
## **Parameters**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-internal-fillers.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-internal-fillers.mdx
new file mode 100644
index 000000000..ffb177ae1
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-internal-fillers.mdx
@@ -0,0 +1,53 @@
+---
+title: "setInternalFillers"
+slug: /reference/typescript/agents/agent-base/set-internal-fillers
+description: Set every internal-filler entry in one call.
+max-toc-depth: 3
+---
+
+[add-internal-filler]: /docs/server-sdks/reference/typescript/agents/agent-base/add-internal-filler
+[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
+
+Set every internal-filler entry on the agent in a single call. Internal fillers
+are short phrases the agent speaks (via TTS) while a native SWAIG function is
+running, so the caller doesn't hear dead air during transitions or background
+work. Use [`addInternalFiller()`][add-internal-filler] to add a single entry
+instead.
+
+
+Filler names outside the SWML schema's supported set are logged as a warning
+and silently ignored by the runtime. Supported names: `hangup`, `check_time`,
+`wait_for_user`, `wait_seconds`, `adjust_response_latency`, `next_step`,
+`change_context`, `get_visual_input`, `get_ideal_strategy`.
+
+
+## **Parameters**
+
+>"} required={true} toc={true}>
+ Outer key: native SWAIG function name (e.g. `"next_step"`). Inner key:
+ language code (e.g. `"en-US"`). Value: array of filler phrases played
+ randomly while that function executes.
+
+
+## **Returns**
+
+[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining.
+
+## **Example**
+
+```typescript {5-14}
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
+agent.setPromptText('You are a helpful assistant.');
+agent.setInternalFillers({
+ next_step: {
+ 'en-US': ['Moving to the next step...', 'Great, let us continue...'],
+ es: ['Pasando al siguiente paso...'],
+ },
+ check_time: {
+ 'en-US': ['Let me check the time...'],
+ },
+});
+await agent.serve();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-prompt-pom.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-prompt-pom.mdx
new file mode 100644
index 000000000..8bbc64251
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-prompt-pom.mdx
@@ -0,0 +1,50 @@
+---
+title: "setPromptPom"
+slug: /reference/typescript/agents/agent-base/set-prompt-pom
+description: Replace the agent's prompt with the supplied POM sections.
+max-toc-depth: 3
+---
+
+[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
+[prompt-add-section]: /docs/server-sdks/reference/typescript/agents/agent-base/prompt-add-section
+[get-prompt-pom]: /docs/server-sdks/reference/typescript/agents/agent-base/get-prompt-pom
+
+Replace the agent's prompt with the supplied POM (Prompt Object Model) array.
+Existing sections are cleared before the new ones are applied, so this is the
+batch equivalent of calling [`promptAddSection()`][prompt-add-section] for
+every entry. The shape must match what [`getPromptPom()`][get-prompt-pom]
+returns.
+
+
+Requires the agent to be constructed with `usePom: true`. Throws `Error("usePom must be true to use setPromptPom")` otherwise.
+
+
+## **Parameters**
+
+[]"} required={true} toc={true}>
+ Ordered array of POM section objects. Each section supports `title` (string),
+ `body` (string), `bullets` (string[]), `numbered` (boolean),
+ `numberedBullets` (boolean), and `subsections` (array of
+ `{ title, body?, bullets? }`).
+
+
+## **Returns**
+
+[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining.
+
+## **Example**
+
+```typescript {5}
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'support', route: '/support', usePom: true });
+
+agent.setPromptPom([
+ { title: 'Role', body: 'You are a support agent for Acme Corp.' },
+ {
+ title: 'Guidelines',
+ bullets: ['Greet by name', 'Never share internal pricing'],
+ },
+]);
+await agent.serve();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-pronunciations.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-pronunciations.mdx
new file mode 100644
index 000000000..d360443db
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/set-pronunciations.mdx
@@ -0,0 +1,40 @@
+---
+title: "setPronunciations"
+slug: /reference/typescript/agents/agent-base/set-pronunciations
+description: Replace the agent's pronunciation rules in a single call.
+max-toc-depth: 3
+---
+
+[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
+[ref-add-pronunciation]: /docs/server-sdks/reference/typescript/agents/agent-base/add-pronunciation
+
+Replace every pronunciation rule on the agent with the provided array. Use
+[`addPronunciation()`][ref-add-pronunciation] to append a single rule without
+replacing the list.
+
+## **Parameters**
+
+
+ Ordered list of pronunciation rules. Each rule has `replace` (the spelled-out
+ token), `with` (the phonetic replacement), and an optional
+ `ignoreCase` boolean.
+
+
+## **Returns**
+
+[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining.
+
+## **Example**
+
+```typescript {5-9}
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'support', route: '/support' });
+agent.setPromptText('You are a helpful assistant.');
+agent.setPronunciations([
+ { replace: 'SignalWire', with: 'signal wire' },
+ { replace: 'SWML', with: 'swim el' },
+ { replace: 'SWAIG', with: 'swayg' },
+]);
+await agent.serve();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/update-global-data.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/update-global-data.mdx
index 88f534223..392d61cd4 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/update-global-data.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/update-global-data.mdx
@@ -8,10 +8,12 @@ max-toc-depth: 3
[set-global-data]: /docs/server-sdks/reference/typescript/agents/agent-base/set-global-data
[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
-Merge additional entries into the existing global data object. Unlike
-[`setGlobalData()`][set-global-data] which replaces, this method merges so that
-multiple callers (skills, dynamic config callbacks, etc.) can each contribute keys
-without overwriting each other.
+Merge additional entries into the existing `global_data` object. Functionally
+equivalent to [`setGlobalData()`][set-global-data] — both methods call
+`.update()` on the internal dict so multiple callers (skills, dynamic config
+callbacks, etc.) can each contribute keys without overwriting each other.
+`updateGlobalData()` is the idiomatically named variant for call sites that
+want to make the merge semantics explicit.
## **Parameters**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/validate-tool-token.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/validate-tool-token.mdx
new file mode 100644
index 000000000..cd03deb9f
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-base/validate-tool-token.mdx
@@ -0,0 +1,40 @@
+---
+title: "validateToolToken"
+slug: /reference/typescript/agents/agent-base/validate-tool-token
+description: Validate a per-tool HMAC token attached to a SWAIG function call.
+max-toc-depth: 3
+---
+
+[define-tool]: /docs/server-sdks/reference/typescript/agents/agent-base/define-tool
+
+Validate a per-tool HMAC token attached to an incoming SWAIG function call.
+Returns `false` for unknown tools, short-circuits to `true` for tools
+registered without [`secure: true`][define-tool], and otherwise delegates to
+`SessionManager.validateToolToken`. Raw-dict descriptors (e.g. `DataMap`
+output) are always treated as secure.
+
+
+Called automatically by the SWAIG dispatch path before a tool handler runs.
+You rarely need to invoke it directly; it is exposed for custom dispatch logic
+and test harnesses.
+
+
+## **Parameters**
+
+
+ Name of the SWAIG function the token was issued for.
+
+
+
+ HMAC token to validate. Missing tokens on secure tools return `false`.
+
+
+
+ Call ID the token is bound to. Empty strings are forwarded unchanged and
+ rejected by the underlying validator.
+
+
+## **Returns**
+
+`boolean` -- `true` when the token is valid for the given function and call,
+or when the tool is registered as non-secure.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/index.mdx
index 7218568da..c11dcbdf9 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/index.mdx
@@ -11,14 +11,17 @@ max-toc-depth: 3
[getagent]: /docs/server-sdks/reference/typescript/agents/agent-server/get-agent
[getagents]: /docs/server-sdks/reference/typescript/agents/agent-server/get-agents
[register]: /docs/server-sdks/reference/typescript/agents/agent-server/register
+[registerglobalroutingcallback]: /docs/server-sdks/reference/typescript/agents/agent-server/routing-callback
[run]: /docs/server-sdks/reference/typescript/agents/agent-server/run
[servestaticfiles]: /docs/server-sdks/reference/typescript/agents/agent-server/static-files
+[setupsiprouting]: /docs/server-sdks/reference/typescript/agents/agent-server/sip-routing
[unregister]: /docs/server-sdks/reference/typescript/agents/agent-server/unregister
`AgentServer` hosts multiple [`AgentBase`][agentbase] instances
on a single Hono HTTP server. Each agent registers at its own URL route, and the server
-provides unified health monitoring and static file serving. Use `AgentServer` when you
-have several related agents (sales, support, billing) that share the same deployment.
+provides unified health monitoring, SIP-based routing, and static file serving.
+Use `AgentServer` when you have several related agents (sales, support, billing)
+that share the same deployment.
For a single agent, use [`AgentBase.serve()`][agentbase-serve]
or [`AgentBase.run()`][agentbase-run] instead.
@@ -45,6 +48,10 @@ const server = new AgentServer({ host: '0.0.0.0', port: 3000 });
Port the server listens on. Also reads from the `PORT` environment variable.
+
+
+ Logging level: `'debug'`, `'info'`, `'warn'`, or `'error'`. Lowercased and applied globally via `setGlobalLogLevel`.
+
## **Properties**
@@ -57,6 +64,10 @@ const server = new AgentServer({ host: '0.0.0.0', port: 3000 });
The port the server listens on.
+
+ The logging level for the server (read-only).
+
+
## **Methods**
@@ -66,21 +77,27 @@ const server = new AgentServer({ host: '0.0.0.0', port: 3000 });
Return all registered agents as a Map.
+
+ Get the fully configured Hono application.
+
Register an agent at a URL route on the server.
+
+ Register a routing callback across all agents for custom request routing.
+
Start the multi-agent HTTP server.
Serve static files from a directory alongside agent routes.
+
+ Configure SIP-based routing to direct calls to specific agents by username.
+
Remove an agent from the server's registry by route.
-
- Get the fully configured Hono application.
-
## **Example**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/routing-callback.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/routing-callback.mdx
new file mode 100644
index 000000000..f67addf05
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/routing-callback.mdx
@@ -0,0 +1,66 @@
+---
+title: "registerGlobalRoutingCallback"
+slug: /reference/typescript/agents/agent-server/routing-callback
+description: Register a routing callback across all agents for custom request routing.
+max-toc-depth: 3
+---
+
+[setup-sip-routing]: /docs/server-sdks/reference/typescript/agents/agent-server/sip-routing
+
+Register a custom routing callback on every registered agent at the specified path.
+When a request arrives at that path on any agent, the callback is invoked to determine
+whether to redirect the request to a different agent route.
+
+Use this alongside or instead of [`setupSipRouting()`][setup-sip-routing] when you
+need custom routing logic — for example, routing based on request body content,
+tenant IDs, or feature flags.
+
+
+The callback is also applied to agents registered **after** this method is called.
+The server stores each callback internally so new agents automatically receive it.
+
+
+## **Parameters**
+
+
+ A function that receives the parsed request body and returns a route string
+ (e.g., `"/sales"`) to redirect the request, or `null` / `undefined` to let the
+ current agent handle it. May return a `Promise` for asynchronous routing decisions.
+ Signature: `(body: Record) => string | null | undefined | Promise`.
+
+
+
+ The URL path where the callback is triggered (e.g., `"/route"`). Leading slashes are
+ added and trailing slashes are stripped automatically.
+
+
+## **Returns**
+
+`void`
+
+## **Example**
+
+```typescript {21}
+import { AgentBase, AgentServer } from '@signalwire/sdk';
+
+function routeByLanguage(body: Record): string | undefined {
+ const lang = (body['lang'] as string | undefined) ?? 'en';
+ if (lang.startsWith('es')) return '/spanish-agent';
+ if (lang.startsWith('fr')) return '/french-agent';
+ return undefined;
+}
+
+const english = new AgentBase({ name: 'english', route: '/english-agent' });
+english.setPromptText('You are a helpful assistant. Respond in English.');
+const spanish = new AgentBase({ name: 'spanish', route: '/spanish-agent' });
+spanish.setPromptText('You are a helpful assistant. Respond in Spanish.');
+const french = new AgentBase({ name: 'french', route: '/french-agent' });
+french.setPromptText('You are a helpful assistant. Respond in French.');
+
+const server = new AgentServer({ port: 3000 });
+server.register(english);
+server.register(spanish);
+server.register(french);
+server.registerGlobalRoutingCallback(routeByLanguage, '/route');
+await server.run();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/run.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/run.mdx
index 803b69ca7..684fbb7ec 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/run.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/run.mdx
@@ -6,7 +6,9 @@ max-toc-depth: 3
---
Start the HTTP server and begin listening for requests. Uses `@hono/node-server`
-to serve the Hono application with all registered agents.
+to serve the Hono application with all registered agents. Handles server mode only —
+for serverless deployments (AWS Lambda, Google Cloud Functions, Azure Functions),
+use `ServerlessAdapter` instead.
## **Parameters**
@@ -28,6 +30,12 @@ use `getApp()` to retrieve the underlying Hono app and pass its `fetch` handler
your own `@hono/node-server` `serve()` call instead of using `run()`.
+
+When the environment variable `SWAIG_CLI_MODE=true` is set (used by the `swaig-test`
+CLI tool), `run()` returns immediately without starting the server so only the agent
+configuration is loaded.
+
+
## **Example**
```typescript {8}
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/sip-routing.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/sip-routing.mdx
new file mode 100644
index 000000000..a8dbe99ab
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/sip-routing.mdx
@@ -0,0 +1,116 @@
+---
+title: "setupSipRouting"
+slug: /reference/typescript/agents/agent-server/sip-routing
+description: Configure SIP-based routing to direct calls to specific agents by username.
+max-toc-depth: 3
+---
+
+Enable SIP-based routing across all registered agents. When a SIP call arrives, the server
+extracts the username from the SIP address and routes the request to the matching agent.
+
+With `autoMap` enabled, the server automatically creates username-to-route mappings from
+each agent's name and route path. You can add explicit mappings with
+[`registerSipUsername()`](#manual-username-registration).
+
+
+Call this method **after** registering agents. Agents registered after `setupSipRouting()`
+also receive SIP routing automatically.
+
+
+## **Parameters**
+
+
+ The URL path where SIP routing requests are handled. Each registered agent receives a
+ routing callback at this path.
+
+
+
+ Automatically generate SIP username mappings from agent names and route paths. For example,
+ an agent named `"sales-agent"` at route `"/sales"` gets two mappings:
+ - `"salesagent"` (agent name, lowercase alphanumeric and underscores only)
+ - `"sales"` (route path without leading slash)
+
+
+## **Returns**
+
+`void`
+
+
+Calling `setupSipRouting()` more than once logs a warning and returns early.
+SIP routing can only be configured once per server.
+
+
+---
+
+## **registerSipUsername**
+
+Create an explicit mapping from a SIP username to an agent route. The username is
+stored lowercase for case-insensitive matching. Routes are normalized: leading `/`
+is added if missing and trailing slashes are stripped.
+
+
+SIP routing must be enabled via `setupSipRouting()` before calling this method.
+If routing is not enabled, a warning is logged and the call is a no-op.
+
+
+## **Parameters**
+
+
+ The SIP username to map (e.g., `"sales-team"`). Matched case-insensitively.
+
+
+
+ The target agent route (e.g., `"/sales"`). A warning is logged if the route
+ does not correspond to a registered agent.
+
+
+## **Returns**
+
+`void`
+
+## **Examples**
+
+### SIP routing with auto-mapping
+
+```typescript {13}
+import { AgentBase, AgentServer } from '@signalwire/sdk';
+
+const sales = new AgentBase({ name: 'sales', route: '/sales' });
+sales.setPromptText('You are a sales assistant.');
+const support = new AgentBase({ name: 'support', route: '/support' });
+support.setPromptText('You are a support assistant.');
+
+const server = new AgentServer({ port: 3000 });
+server.register(sales);
+server.register(support);
+
+server.setupSipRouting('/sip', true);
+server.registerSipUsername('help-desk', '/support');
+
+await server.run();
+```
+
+With this configuration, SIP calls are routed as follows:
+
+| SIP Address | Resolves To |
+|-------------|-------------|
+| `sip:sales@example.com` | `/sales` (auto-mapped from route) |
+| `sip:salesagent@example.com` | `/sales` (auto-mapped from agent name) |
+| `sip:help-desk@example.com` | `/support` (manual mapping) |
+
+### Manual username registration
+
+```typescript {10-12}
+import { AgentBase, AgentServer } from '@signalwire/sdk';
+
+const sales = new AgentBase({ name: 'sales', route: '/sales' });
+sales.setPromptText('You are a sales assistant.');
+
+const server = new AgentServer({ port: 3000 });
+server.register(sales);
+server.setupSipRouting('/sip');
+server.registerSipUsername('sales-team', '/sales');
+server.registerSipUsername('tech-support', '/support');
+server.registerSipUsername('accounts', '/billing');
+await server.run();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/static-files.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/static-files.mdx
index 4ec6bcab1..69075931a 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/static-files.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/static-files.mdx
@@ -19,8 +19,8 @@ an admin dashboard or a configuration UI.
(resolved via `path.resolve()` at registration time).
-
- URL path prefix for static files.
+
+ URL path prefix for static files. Trailing slashes are stripped; `'/'` serves from the root.
## **Returns**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/unregister.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/unregister.mdx
index 729f4b5e9..79d177e25 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/unregister.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/agent-server/unregister.mdx
@@ -22,7 +22,8 @@ internal registry used by `getAgents()` and the root listing endpoint.
## **Returns**
-`void`
+`boolean` -- `true` if an agent was registered at that route and was removed,
+`false` if no agent was found at the route.
## **Example**
@@ -33,5 +34,6 @@ const server = new AgentServer({ port: 3000 });
const agent = new AgentBase({ name: 'sales', route: '/sales' });
server.register(agent);
-server.unregister('/sales');
+const removed = server.unregister('/sales');
+console.log(removed); // true
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/express-middleware.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/express-middleware.mdx
new file mode 100644
index 000000000..1910eafe3
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/express-middleware.mdx
@@ -0,0 +1,60 @@
+---
+title: "expressMiddleware"
+slug: /reference/typescript/agents/configuration/auth-handler/express-middleware
+description: "Create an Express/Connect-compatible middleware adapter."
+max-toc-depth: 3
+---
+
+[ref-middleware]: /docs/server-sdks/reference/typescript/agents/configuration/auth-handler/middleware
+[ref-validate]: /docs/server-sdks/reference/typescript/agents/configuration/auth-handler/validate
+
+Create an Express/Connect-compatible middleware function that validates
+incoming requests against the configured authentication methods and returns a
+`401 Unauthorized` response when auth fails. Framework-agnostic equivalent of
+the Python SDK's `get_fastapi_dependency`.
+
+
+For Hono apps, use [`middleware()`][ref-middleware] instead. For standalone
+validation without a framework, use [`validate()`][ref-validate] directly.
+
+
+## **Parameters**
+
+
+ When `true`, unauthenticated requests are allowed through instead of being
+ rejected. Useful for progressive-auth flows where the handler downstream
+ decides whether to require credentials.
+
+
+## **Returns**
+
+An async Express-compatible middleware:
+`(req, res, next) => Promise`.
+
+On failed auth with `optional=false`, responds with HTTP 401 and body
+`{ error: 'Unauthorized' }`. On success or when `optional=true`, calls `next()`.
+
+## **Example**
+
+```typescript {11}
+import express from 'express';
+import { AuthHandler } from '@signalwire/sdk';
+
+const auth = new AuthHandler({
+ bearerToken: 'sk_live_abc123',
+});
+
+const app = express();
+
+// Protect all /api/* routes
+app.use('/api', auth.expressMiddleware());
+
+app.get('/api/status', (req, res) => {
+ res.json({ ok: true });
+});
+
+// Public route with optional auth
+app.get('/public', auth.expressMiddleware(true), (req, res) => {
+ res.json({ authenticated: false });
+});
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/get-auth-info.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/get-auth-info.mdx
new file mode 100644
index 000000000..4ce670eb4
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/get-auth-info.mdx
@@ -0,0 +1,52 @@
+---
+title: "getAuthInfo"
+slug: /reference/typescript/agents/configuration/auth-handler/get-auth-info
+description: "Get structured metadata describing the enabled authentication methods."
+max-toc-depth: 3
+---
+
+Return structured metadata describing each enabled authentication method on
+this handler. Useful for generating diagnostic pages, startup banners, or
+developer-facing hints about which auth schemes are active. Missing entries
+indicate the corresponding method is not configured.
+
+## **Returns**
+
+An object with three optional keys:
+
+
+ Present when Basic Auth is configured. Contains the configured username (the
+ password is never returned).
+
+
+
+ Present when Bearer token auth is configured. `hint` is a human-readable
+ string like `"Use Authorization: Bearer "`.
+
+
+
+ Present when API key auth is configured. `header` is the configured header
+ name (defaults to `"X-Api-Key"`). `hint` is a human-readable usage string.
+
+
+## **Example**
+
+```typescript {9}
+import { AuthHandler } from '@signalwire/sdk';
+
+const auth = new AuthHandler({
+ basicAuth: ['admin', 'secret'],
+ bearerToken: 'sk_live_abc123',
+});
+
+const info = auth.getAuthInfo();
+console.log(info);
+// {
+// basic: { enabled: true, username: 'admin' },
+// bearer: { enabled: true, hint: 'Use Authorization: Bearer ' }
+// }
+
+if (info.apiKey) {
+ console.log(`API key expected in header ${info.apiKey.header}`);
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/index.mdx
index 3c53253bb..a9ffb59c0 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/index.mdx
@@ -37,7 +37,13 @@ const auth = new AuthHandler({
- API key matched against the `X-Api-Key` header.
+ API key matched against the `X-Api-Key` header (or the custom header named
+ by `config.apiKeyHeader`).
+
+
+
+ Custom header name to use for API key lookup instead of the default
+ `X-Api-Key`. Lookup is case-insensitive.
@@ -63,6 +69,21 @@ const auth = new AuthHandler({
Create a Hono-compatible middleware that rejects unauthorized requests.
+
+ Create an Express/Connect-compatible middleware adapter.
+
+
+ Verify a username/password pair with constant-time comparison.
+
+
+ Verify a Bearer token with constant-time comparison.
+
+
+ Verify an API key with constant-time comparison.
+
+
+ Get metadata describing the enabled auth methods.
+
Check whether Bearer token authentication is configured.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/middleware.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/middleware.mdx
index be3b340ac..9068ff511 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/middleware.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/middleware.mdx
@@ -7,11 +7,16 @@ max-toc-depth: 3
Create a Hono-compatible middleware function that validates incoming requests
against the configured auth methods. Unauthorized requests receive a
-`401 Unauthorized` JSON response.
+`401 Unauthorized` JSON response by default; pass `optional: true` to let them
+pass through without blocking.
## **Parameters**
-None.
+
+ When `true`, unauthenticated requests are allowed through instead of being
+ rejected with a 401. Useful for routes that expose richer data to
+ authenticated callers but still serve unauthenticated traffic.
+
## **Returns**
@@ -29,8 +34,11 @@ const auth = new AuthHandler({
});
const app = new Hono();
-// Protect all routes
+// Protect all routes — unauthorized returns 401
app.use('*', auth.middleware());
app.get('/', (c) => c.json({ status: 'ok' }));
+
+// Or allow unauthenticated access through
+app.use('/public/*', auth.middleware(true));
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/verify-api-key.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/verify-api-key.mdx
new file mode 100644
index 000000000..60526bb49
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/verify-api-key.mdx
@@ -0,0 +1,45 @@
+---
+title: "verifyApiKey"
+slug: /reference/typescript/agents/configuration/auth-handler/verify-api-key
+description: "Verify an API key against the configured key."
+max-toc-depth: 3
+---
+
+[ref-validate]: /docs/server-sdks/reference/typescript/agents/configuration/auth-handler/validate
+
+Verify an API key against the configured key. Uses a constant-time comparison
+to prevent timing attacks. Returns `false` immediately when API key auth is
+not configured.
+
+
+Pass only the key value -- this method does not parse headers. For full
+header-based validation (which reads the configured `apiKeyHeader`, case-
+insensitive), use [`validate()`][ref-validate].
+
+
+## **Parameters**
+
+
+ The API key string to verify.
+
+
+## **Returns**
+
+`boolean` -- `true` if the key matches; `false` if it doesn't, or if API key
+auth was not configured.
+
+## **Example**
+
+```typescript {8}
+import { AuthHandler } from '@signalwire/sdk';
+
+const auth = new AuthHandler({
+ apiKey: 'sk_live_abc123',
+ apiKeyHeader: 'X-Api-Key',
+});
+
+function authorize(headerValue: string | undefined) {
+ if (!headerValue) return false;
+ return auth.verifyApiKey(headerValue);
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/verify-basic-auth.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/verify-basic-auth.mdx
new file mode 100644
index 000000000..49727569f
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/verify-basic-auth.mdx
@@ -0,0 +1,53 @@
+---
+title: "verifyBasicAuth"
+slug: /reference/typescript/agents/configuration/auth-handler/verify-basic-auth
+description: "Verify a username/password pair against the configured Basic Auth credentials."
+max-toc-depth: 3
+---
+
+[ref-validate]: /docs/server-sdks/reference/typescript/agents/configuration/auth-handler/validate
+[ref-middleware]: /docs/server-sdks/reference/typescript/agents/configuration/auth-handler/middleware
+
+Verify a Basic Auth username/password pair against the configured credentials.
+Uses a constant-time comparison to prevent timing attacks. Useful for custom
+auth flows where you need to check credentials outside a middleware context.
+
+
+Returns `false` immediately when Basic Auth is not configured (i.e.,
+`basicAuth` was not passed to the constructor). For full request validation
+including Bearer and API key fallbacks, use
+[`validate()`][ref-validate] or attach
+[`middleware()`][ref-middleware] to your Hono app.
+
+
+## **Parameters**
+
+
+ The username to verify.
+
+
+
+ The password to verify.
+
+
+## **Returns**
+
+`boolean` -- `true` if the credentials match; `false` if they don't, or if
+Basic Auth was not configured.
+
+## **Example**
+
+```typescript {12}
+import { AuthHandler } from '@signalwire/sdk';
+
+const auth = new AuthHandler({
+ basicAuth: ['admin', 'secret-password'],
+});
+
+function login(username: string, password: string) {
+ if (auth.verifyBasicAuth(username, password)) {
+ return { ok: true, user: username };
+ }
+ return { ok: false };
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/verify-bearer-token.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/verify-bearer-token.mdx
new file mode 100644
index 000000000..48d073dff
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/auth-handler/verify-bearer-token.mdx
@@ -0,0 +1,44 @@
+---
+title: "verifyBearerToken"
+slug: /reference/typescript/agents/configuration/auth-handler/verify-bearer-token
+description: "Verify a Bearer token against the configured token."
+max-toc-depth: 3
+---
+
+[ref-validate]: /docs/server-sdks/reference/typescript/agents/configuration/auth-handler/validate
+
+Verify a Bearer token against the configured token. Uses a constant-time
+comparison to prevent timing attacks. Returns `false` immediately when Bearer
+token auth is not configured.
+
+
+Pass the raw token -- do **not** include the `"Bearer "` prefix. For full
+header-based validation (including prefix parsing), use
+[`validate()`][ref-validate].
+
+
+## **Parameters**
+
+
+ The Bearer token string to verify, without the `"Bearer "` prefix.
+
+
+## **Returns**
+
+`boolean` -- `true` if the token matches; `false` if it doesn't, or if Bearer
+auth was not configured.
+
+## **Example**
+
+```typescript {8}
+import { AuthHandler } from '@signalwire/sdk';
+
+const auth = new AuthHandler({
+ bearerToken: 'sk_live_abc123',
+});
+
+function authorize(header: string | undefined) {
+ const token = header?.replace(/^Bearer\s+/i, '') ?? '';
+ return auth.verifyBearerToken(token);
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/find-config-file.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/find-config-file.mdx
new file mode 100644
index 000000000..03139a0ab
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/find-config-file.mdx
@@ -0,0 +1,54 @@
+---
+title: "findConfigFile"
+slug: /reference/typescript/agents/configuration/config-loader/find-config-file
+description: "Find a config file path without loading it (static helper)."
+max-toc-depth: 3
+---
+
+[ref-search]: /docs/server-sdks/reference/typescript/agents/configuration/config-loader/search
+
+Static helper that searches for a config file and returns the first match's
+absolute path without loading it. Useful for detecting whether a configuration
+exists before deciding whether to instantiate a `ConfigLoader`. For searching
+from an instance that also loads on match, use
+[`search()`][ref-search] instead.
+
+The search order is:
+
+1. `{serviceName}_config.json` (cwd) and `.swml/{serviceName}_config.json` (if `serviceName`)
+2. Each path in `additionalPaths` (if provided)
+3. `config.json`
+4. `agent_config.json`
+5. `.swml/config.json`
+6. `~/.swml/config.json`
+7. `/etc/swml/config.json`
+
+## **Parameters**
+
+
+ Service name. When provided, service-specific config filenames are checked
+ before defaults.
+
+
+
+ Extra file paths to check between service-specific and default locations.
+
+
+## **Returns**
+
+`string | null` -- absolute path of the first existing config file, or `null`
+if none match.
+
+## **Example**
+
+```typescript {4}
+import { ConfigLoader } from '@signalwire/sdk';
+
+const path = ConfigLoader.findConfigFile('my-service');
+if (path) {
+ const loader = new ConfigLoader(path);
+ console.log(`Loaded from ${loader.getFilePath()}`);
+} else {
+ console.log('No config file found');
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/get-config-file.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/get-config-file.mdx
new file mode 100644
index 000000000..38fbb92ec
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/get-config-file.mdx
@@ -0,0 +1,30 @@
+---
+title: "getConfigFile"
+slug: /reference/typescript/agents/configuration/config-loader/get-config-file
+description: "Return the path of the loaded config file (Python-compat alias for getFilePath)."
+max-toc-depth: 3
+---
+
+[ref-getfilepath]: /docs/server-sdks/reference/typescript/agents/configuration/config-loader/get-file-path
+
+Return the absolute path of the loaded config file, or `null` when the loader
+was populated via `loadFromObject()`. Python-compat alias for
+[`getFilePath()`][ref-getfilepath]; the two are functionally identical.
+
+## **Returns**
+
+`string | null` -- the file path, or `null` if config was loaded from an
+object.
+
+## **Example**
+
+```typescript {4}
+import { ConfigLoader } from '@signalwire/sdk';
+
+const loader = new ConfigLoader('config.json');
+console.log(loader.getConfigFile()); // absolute path
+
+const inMemory = new ConfigLoader();
+inMemory.loadFromObject({ server: { port: 3000 } });
+console.log(inMemory.getConfigFile()); // null
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/get-config.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/get-config.mdx
new file mode 100644
index 000000000..a608ba163
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/get-config.mdx
@@ -0,0 +1,26 @@
+---
+title: "getConfig"
+slug: /reference/typescript/agents/configuration/config-loader/get-config
+description: "Return a shallow copy of the entire configuration (Python-compat alias for getAll)."
+max-toc-depth: 3
+---
+
+[ref-getall]: /docs/server-sdks/reference/typescript/agents/configuration/config-loader/get-all
+
+Return a shallow copy of the entire loaded configuration. Python-compat alias
+for [`getAll()`][ref-getall]; the two are functionally identical. Use
+`getConfig()` when porting from the Python SDK.
+
+## **Returns**
+
+`Record` -- a shallow copy of the top-level config object.
+
+## **Example**
+
+```typescript {4}
+import { ConfigLoader } from '@signalwire/sdk';
+
+const loader = new ConfigLoader('config.json');
+const config = loader.getConfig();
+console.log(Object.keys(config));
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/get-section.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/get-section.mdx
new file mode 100644
index 000000000..c940899bb
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/get-section.mdx
@@ -0,0 +1,42 @@
+---
+title: "getSection"
+slug: /reference/typescript/agents/configuration/config-loader/get-section
+description: "Get a configuration section with environment variables substituted."
+max-toc-depth: 3
+---
+
+[ref-substitutevars]: /docs/server-sdks/reference/typescript/agents/configuration/config-loader/substitute-vars
+[ref-get]: /docs/server-sdks/reference/typescript/agents/configuration/config-loader/get
+
+Get an entire top-level configuration section with all
+`${VAR|default}` environment-variable references substituted. Internally
+calls [`substituteVars()`][ref-substitutevars] on the resolved value.
+
+Returns an empty object (`{}`) if the section does not exist or is not an
+object. For single-value lookups, use [`get()`][ref-get] instead.
+
+## **Parameters**
+
+
+ The top-level section name (e.g., `"security"`, `"server"`).
+
+
+## **Returns**
+
+`Record` -- the configuration section, with env-var
+substitution applied; empty object if the section is missing or not an object.
+
+## **Example**
+
+```typescript {8}
+import { ConfigLoader } from '@signalwire/sdk';
+
+// Given config.json:
+// { "server": { "host": "${HOST|0.0.0.0}", "port": "${PORT|3000}" } }
+
+const loader = new ConfigLoader('config.json');
+
+const serverCfg = loader.getSection('server');
+console.log(serverCfg.host); // "0.0.0.0" (or HOST env var)
+console.log(serverCfg.port); // 3000 (coerced to number)
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/has-config.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/has-config.mdx
new file mode 100644
index 000000000..abfcf2b66
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/has-config.mdx
@@ -0,0 +1,39 @@
+---
+title: "hasConfig"
+slug: /reference/typescript/agents/configuration/config-loader/has-config
+description: "Check whether any configuration data is loaded (file or object)."
+max-toc-depth: 3
+---
+
+[ref-getfilepath]: /docs/server-sdks/reference/typescript/agents/configuration/config-loader/get-file-path
+
+Check whether any configuration data has been loaded. Returns `true` if a file
+was loaded or data was set via `loadFromObject()`.
+
+
+**Deliberate deviation from the Python SDK.** Python's `has_config()` returns
+`True` only when a *file* was loaded. The TypeScript version also returns
+`true` for object-loaded data, because `loadFromObject()` is a TS-only entry
+point with no Python equivalent -- treating object-loaded data as "configured"
+matches the TS API surface.
+
+If you specifically need file-load detection, check
+`loader.getFilePath() !== null` via
+[`getFilePath()`][ref-getfilepath].
+
+
+## **Returns**
+
+`boolean` -- `true` if any configuration data exists (from file or object),
+`false` if the loader is empty.
+
+## **Example**
+
+```typescript {4}
+import { ConfigLoader } from '@signalwire/sdk';
+
+const loader = new ConfigLoader('config.json');
+if (loader.hasConfig()) {
+ console.log('Config loaded, proceed with startup');
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/index.mdx
index 3992e2df0..384167fab 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/index.mdx
@@ -27,9 +27,19 @@ const port = config.get('server.port', 3000);
## **Constructor**
-
- Path to a JSON config file to load on construction. If omitted, use
- [`load()`][load] or [`loadFromObject()`][loadfromobject] later.
+
+ Path(s) to a JSON config file to load on construction. A single string is
+ loaded directly; an array is searched in order and the first existing file
+ is loaded (mirroring the Python SDK's ordered-search behaviour). If no file
+ in the array exists, the paths are recorded but no error is thrown. If
+ omitted, use [`load()`][load] or [`loadFromObject()`][loadfromobject] later.
+
+
+## **Properties**
+
+
+ The ordered list of config file paths passed to the constructor or searched
+ during loading. Returns a defensive copy.
## **Methods**
@@ -59,6 +69,30 @@ const port = config.get('server.port', 3000);
Load configuration from a plain object instead of a file.
+
+ Find a config file without loading it (static).
+
+
+ Return the full config (Python-compat alias for getAll).
+
+
+ Return the loaded file path (Python-compat alias for getFilePath).
+
+
+ Check whether any configuration data is loaded.
+
+
+ Get a top-level section with env-var substitution.
+
+
+ Recursively substitute ${VAR} references with coercion.
+
+
+ Merge config with prefixed environment variables.
+
+
+ Interpolate ${VAR} in a raw string without coercion.
+
## **Example**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/interpolate-env-vars.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/interpolate-env-vars.mdx
new file mode 100644
index 000000000..32a0bceba
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/interpolate-env-vars.mdx
@@ -0,0 +1,42 @@
+---
+title: "interpolateEnvVars"
+slug: /reference/typescript/agents/configuration/config-loader/interpolate-env-vars
+description: "Interpolate ${VAR|default} patterns in a raw string."
+max-toc-depth: 3
+---
+
+[ref-substitutevars]: /docs/server-sdks/reference/typescript/agents/configuration/config-loader/substitute-vars
+
+Interpolate `${VAR|default}` environment-variable references in a raw string.
+Unlike [`substituteVars()`][ref-substitutevars], this method does not apply
+type coercion -- the result is always a string. Missing env vars with no
+default resolve to an empty string.
+
+
+This is a TS-specific helper (no Python SDK equivalent). Use it when building
+URLs, log messages, or any string output where numeric/boolean coercion would
+corrupt the value.
+
+
+## **Parameters**
+
+
+ The string containing `${VAR}` or `${VAR|default}` references.
+
+
+## **Returns**
+
+`string` -- the input with all env var references resolved.
+
+## **Example**
+
+```typescript {4}
+import { ConfigLoader } from '@signalwire/sdk';
+
+const loader = new ConfigLoader();
+const url = loader.interpolateEnvVars(
+ 'https://${HOST|api.example.com}/v1/${VERSION|latest}',
+);
+console.log(url);
+// "https://api.example.com/v1/latest" (defaults used when env vars unset)
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/merge-with-env.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/merge-with-env.mdx
new file mode 100644
index 000000000..b0fb2aea5
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/merge-with-env.mdx
@@ -0,0 +1,53 @@
+---
+title: "mergeWithEnv"
+slug: /reference/typescript/agents/configuration/config-loader/merge-with-env
+description: "Merge configuration with prefix-matched environment variables."
+max-toc-depth: 3
+---
+
+[ref-substitutevars]: /docs/server-sdks/reference/typescript/agents/configuration/config-loader/substitute-vars
+
+Merge the loaded configuration with environment variables whose names start
+with a given prefix. Config file values take precedence over environment
+variables -- env vars only fill in keys that are missing from the config.
+
+Matching env var names are:
+
+1. Stripped of the prefix
+2. Lowercased
+3. Split on `_` to produce a nested object path
+
+For example, with prefix `SWML_`, `SWML_SERVER_PORT=3000` produces
+`{ server: { port: "3000" } }`.
+
+
+All values inherited from env vars are written as strings (Node returns
+`process.env` values as strings). Apply
+[`substituteVars()`][ref-substitutevars] to the result if you need type
+coercion.
+
+
+## **Parameters**
+
+
+ Prefix for environment variables to consider.
+
+
+## **Returns**
+
+`Record` -- the merged configuration (file + prefixed env
+vars) with `${VAR}` substitution applied to file values.
+
+## **Example**
+
+```typescript {7}
+import { ConfigLoader } from '@signalwire/sdk';
+
+// Given config.json: { "server": { "host": "0.0.0.0" } }
+// And env: SWML_SERVER_PORT=3000
+
+const loader = new ConfigLoader('config.json');
+const merged = loader.mergeWithEnv();
+console.log(merged);
+// { server: { host: "0.0.0.0", port: "3000" } }
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/search.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/search.mdx
index 2640bd63b..26a6dbbc2 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/search.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/search.mdx
@@ -5,10 +5,28 @@ description: "Search for a config file in standard locations and load it if foun
max-toc-depth: 3
---
-Static method that searches for a config file in standard locations: the
-current working directory, `./config/`, and `~/.signalwire/`. Returns a
-loaded `ConfigLoader` if found, or `null` if the file does not exist in
-any search path.
+Static method that searches for a config file across service-specific paths,
+caller-supplied directories, and default standard locations. Returns a loaded
+`ConfigLoader` as soon as the first existing file is found, or `null` if none
+of the candidates exist.
+
+Default search paths (joined with `filename`, in order):
+
+- `${cwd}/${filename}`
+- `${cwd}/config/${filename}`
+- `$HOME/.signalwire/${filename}`
+- `${cwd}/.swml/${filename}`
+- `$HOME/.swml/${filename}`
+- `/etc/swml/${filename}`
+
+When `serviceName` is provided, two service-specific variants are checked
+*before* any other path:
+
+- `${cwd}/${serviceName}_${filename}`
+- `${cwd}/.swml/${serviceName}_${filename}`
+
+When `additionalPaths` is provided, those directories are checked (joined
+with `filename`) after the service-specific variants but before the defaults.
## **Parameters**
@@ -16,16 +34,28 @@ any search path.
The config file name to search for (e.g., `"config.json"`).
+
+ Extra directories to search before the default locations. Each directory
+ is joined with `filename` to form a candidate path.
+
+
+
+ Optional service name. When provided, adds `${serviceName}_${filename}`
+ variants to the front of the search order so a service can override the
+ generic config file.
+
+
## **Returns**
-`ConfigLoader | null` -- A loaded ConfigLoader instance, or `null` if not found.
+`ConfigLoader | null` -- A loaded ConfigLoader instance, or `null` if no
+candidate path exists.
## **Example**
```typescript {3}
import { ConfigLoader } from '@signalwire/sdk';
-const config = ConfigLoader.search('agent-config.json');
+const config = ConfigLoader.search('agent-config.json', ['/etc/myapp'], 'myservice');
if (config) {
console.log('Config found at:', config.getFilePath());
console.log('Port:', config.get('server.port', 3000));
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/substitute-vars.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/substitute-vars.mdx
new file mode 100644
index 000000000..07f600a3d
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/config-loader/substitute-vars.mdx
@@ -0,0 +1,55 @@
+---
+title: "substituteVars"
+slug: /reference/typescript/agents/configuration/config-loader/substitute-vars
+description: "Recursively substitute environment variables in any value."
+max-toc-depth: 3
+---
+
+[ref-interpolateenvvars]: /docs/server-sdks/reference/typescript/agents/configuration/config-loader/interpolate-env-vars
+
+Recursively substitute `${VAR|default}` environment-variable references in any
+value. Walks strings, objects, and arrays. After substitution, resulting
+strings are coerced to:
+
+- `true` / `false` when they equal `"true"` / `"false"` (case-insensitive)
+- an integer when they match `/^\d+$/`
+- a float when they match `/^\d+\.\d+$/`
+- otherwise left as a string
+
+
+For raw string interpolation without type coercion, use
+[`interpolateEnvVars()`][ref-interpolateenvvars] instead.
+
+
+## **Parameters**
+
+
+ The value to process. Can be a string, object, array, or primitive.
+
+
+
+ Maximum recursion depth. Throws `Error("Maximum variable substitution depth
+ exceeded")` when the limit is reached.
+
+
+## **Returns**
+
+The input value with all environment variables substituted. Type depends on
+the input and the coercion rules above.
+
+## **Example**
+
+```typescript {5}
+import { ConfigLoader } from '@signalwire/sdk';
+
+const loader = new ConfigLoader();
+const config = {
+ port: '${PORT|8080}',
+ debug: '${DEBUG|false}',
+ name: '${SERVICE_NAME|my-service}',
+};
+
+const resolved = loader.substituteVars(config);
+console.log(resolved);
+// { port: 8080, debug: false, name: "my-service" } (types coerced)
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/environment-variables.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/environment-variables.mdx
index b402843cb..d259561cf 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/environment-variables.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/environment-variables.mdx
@@ -33,8 +33,9 @@ const agent = new AgentBase({ name: 'my-agent' });
## Authentication
-
+
Username for HTTP Basic Authentication on all agent webhook endpoints.
+ When unset, the username falls back to the agent's `name`.
@@ -77,17 +78,20 @@ until you update the credentials in your SignalWire dashboard.
The agent uses this URL to generate correct webhook URLs in SWML documents.
-
- Fallback for `SWML_PROXY_URL_BASE` when that variable is not set.
+
+ Enable proxy request debug logging. Only the string `"true"` is accepted.
-
- Enable proxy request debug logging.
+
+ Trust `X-Forwarded-For`, `X-Forwarded-Proto`, and `X-Forwarded-Host` headers
+ for client IP detection (used by rate limiting) and auto-detection of the
+ public URL. Only the string `"true"` is accepted. Enable only when running
+ behind a reverse proxy you control.
-Setting `SWML_PROXY_URL_BASE` (or `APP_URL`) overrides SSL configuration and port
-settings for webhook URL generation.
+Setting `SWML_PROXY_URL_BASE` overrides SSL configuration and port settings
+for webhook URL generation.
---
@@ -101,8 +105,10 @@ settings for webhook URL generation.
## Security
-
- Comma-separated list of allowed hosts. Set to specific domain(s) in production
+
+ Comma-separated list of allowed `Host` header values. When unset, no host
+ check is applied. When set, requests with a `Host` header not in the list
+ are rejected with HTTP 403. Set to specific domain(s) in production
(e.g., `"agent.example.com,api.example.com"`).
@@ -111,16 +117,21 @@ settings for webhook URL generation.
production.
-
- Maximum request body size in bytes. Default is 10 MB.
+
+ When set to `"true"`, `POST` requests whose `Origin` header is not in
+ `SWML_CORS_ORIGINS` are rejected with HTTP 403. Only the string `"true"` is
+ accepted.
-
- Rate limit in requests per minute.
+
+ Maximum request body size in bytes. Default is 1 MB. Requests exceeding this
+ size are rejected with HTTP 413.
-
- Request timeout in seconds.
+
+ Rate limit in requests per minute per client IP. When unset, no rate limit
+ is applied. When set to a positive integer, clients exceeding the limit
+ receive HTTP 429.
## Logging
@@ -131,7 +142,6 @@ settings for webhook URL generation.
- `"auto"` -- automatic detection based on environment
- `"off"` -- disable all logging
- `"stderr"` -- log to stderr
- - `"default"` -- standard logging output
@@ -264,7 +274,7 @@ SWML_CORS_ORIGINS=https://app.example.com
SWML_RATE_LIMIT=100
# Logging
-SIGNALWIRE_LOG_MODE=default
+SIGNALWIRE_LOG_MODE=auto
SIGNALWIRE_LOG_LEVEL=info
# RELAY / REST
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/schema-utils/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/schema-utils/index.mdx
index 49f9b8cee..9c623a873 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/schema-utils/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/schema-utils/index.mdx
@@ -33,6 +33,12 @@ console.log(result.valid, result.errors);
Maximum number of cached validation results before LRU eviction.
+
+
+ Path to a custom JSON Schema file. When omitted, the bundled `schema.json`
+ is used. Mirrors the Python SDK's `schema_path` parameter. A load failure
+ falls back to the bundled schema silently.
+
## **Methods**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/debug-token.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/debug-token.mdx
index 30cef9e47..9f2a9e74b 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/debug-token.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/debug-token.mdx
@@ -1,12 +1,21 @@
---
title: "debugToken"
slug: /reference/typescript/agents/configuration/session-manager/debug-token
-description: "Decode token components for debugging without validating the signature."
+description: "Decode token components for inspection without validating the signature."
max-toc-depth: 3
---
-Decode token components for debugging without validating the signature. Useful
-for inspecting token contents and checking expiration.
+Decode token components for inspection without validating the signature. Useful
+for debugging token contents and checking expiration.
+
+
+ `debugToken` returns diagnostic data only when
+ [`debugMode`](/docs/server-sdks/reference/typescript/agents/configuration/session-manager#properties)
+ is `true`. With `debugMode: false` (the default), it returns
+ `{ valid_format: false, error: "debug mode not enabled" }` — matching the
+ Python SDK's behavior. Enable `debugMode` at runtime only when you need to
+ inspect tokens.
+
## **Parameters**
@@ -16,19 +25,93 @@ for inspecting token contents and checking expiration.
## **Returns**
-`{ callId: string; functionName: string; expiry: number; nonce: string; signature: string; expired: boolean } | null`
--- The decoded token fields and expiration status, or `null` if malformed.
+`DebugTokenResult` — a nested object with the following optional fields:
+
+
+ `true` when the token decoded into five dot-separated parts; `false` otherwise.
+
+
+
+ Present only when `valid_format` is `true`.
+
+
+
+
+ Call ID extracted from the token. Truncated to 8 characters followed by `...`
+ when longer than 8 characters.
+
+
+
+ Function name encoded in the token.
+
+
+
+ Token expiry as a Unix timestamp string.
+
+
+
+ ISO 8601 string representation of the expiry, or `null` when the expiry
+ component did not parse as a number.
+
+
+
+ The random nonce component of the token.
+
+
+
+ Token signature. Truncated to 8 characters followed by `...` when longer than
+ 8 characters.
+
+
+
+
+ Present only when `valid_format` is `true`.
+
+
+
+
+ Current Unix timestamp in seconds.
+
+
+
+ `true` if expired, `false` if still valid, `null` if the expiry component
+ did not parse.
+
+
+
+ Seconds remaining until expiry, or `0` when expired, or `null` when expiry
+ did not parse.
+
+
+
+
+ Only populated when `valid_format` is `false` because the decoded token had
+ an unexpected number of dot-separated parts.
+
+
+
+ Length of the raw token string. Populated when `valid_format` is `false`.
+
+
+
+ Set to `"debug mode not enabled"` when `debugMode` is `false`, or to the
+ caught error message when decoding failed.
+
## **Example**
-```typescript {5}
+```typescript {4,6}
import { SessionManager } from '@signalwire/sdk';
const sm = new SessionManager();
+sm.debugMode = true; // enable before calling debugToken
const token = sm.generateToken('get_weather', 'call-abc123');
const info = sm.debugToken(token);
-if (info) {
- console.log('Function:', info.functionName);
- console.log('Expired:', info.expired);
+
+if (info.valid_format) {
+ console.log('Function:', info.components!.function);
+ console.log('Expired:', info.status!.is_expired);
+} else {
+ console.log('Error:', info.error);
}
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/get-session-metadata.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/get-session-metadata.mdx
index e01fdcc81..e374f96a2 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/get-session-metadata.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/get-session-metadata.mdx
@@ -5,7 +5,8 @@ description: "Retrieve metadata associated with a session."
max-toc-depth: 3
---
-Retrieve metadata associated with a session.
+Retrieve metadata associated with a session. Always returns an object —
+callers can check truthiness or iterate keys without a null guard.
## **Parameters**
@@ -15,8 +16,9 @@ Retrieve metadata associated with a session.
## **Returns**
-`Record | undefined` -- The metadata record, or `undefined`
-if no metadata exists for this session.
+`Record` -- The metadata record for the session, or an empty
+object (`{}`) when no metadata has been stored. This matches the Python SDK's
+`get_session_metadata` behavior.
## **Example**
@@ -28,4 +30,7 @@ sm.setSessionMetadata('session-1', { caller: 'John', topic: 'billing' });
const meta = sm.getSessionMetadata('session-1');
console.log(meta); // { caller: "John", topic: "billing" }
+
+const missing = sm.getSessionMetadata('unknown-session');
+console.log(missing); // {}
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/index.mdx
index c162a0c7d..80e8f6676 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/index.mdx
@@ -28,6 +28,15 @@ const valid = sm.validateToken('call-123', 'get_weather', token);
HMAC signing secret. A random 32-byte key is generated if omitted.
+## **Properties**
+
+
+ When `true`, [`debugToken`](/docs/server-sdks/reference/typescript/agents/configuration/session-manager/debug-token)
+ decodes token internals for inspection. When `false`, `debugToken` returns
+ `{ error: "debug mode not enabled" }`. Set this to `true` at runtime only when
+ you need to inspect token contents.
+
+
## **Methods**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/set-session-metadata.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/set-session-metadata.mdx
index dc03fcae6..078b41565 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/set-session-metadata.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/session-manager/set-session-metadata.mdx
@@ -6,7 +6,19 @@ max-toc-depth: 3
---
Merge metadata into a session, creating the entry if it does not exist.
-Automatically triggers cleanup when the metadata map exceeds 1000 entries.
+Automatically triggers [`cleanup`](/docs/server-sdks/reference/typescript/agents/configuration/session-manager/cleanup)
+when the metadata map exceeds 1000 entries.
+
+
+ Two call signatures are supported for Python SDK compatibility:
+
+ - **Bulk merge (TS-native):** `setSessionMetadata(sessionId, metadata)` — merges
+ every key in the `metadata` object into the session, returning `void`.
+ - **Single key/value (Python-compatible):** `setSessionMetadata(sessionId, key, value)`
+ — sets a single key, returning `true` for parity with Python.
+
+ Both forms merge into any existing metadata; they do not replace.
+
## **Parameters**
@@ -14,21 +26,31 @@ Automatically triggers cleanup when the metadata map exceeds 1000 entries.
The session identifier.
-
- Key-value pairs to merge into the session metadata.
+
+ A metadata record to merge into the session (bulk-merge form), or a single
+ `string` key (three-argument form).
+
+
+
+ The value to set when `metadataOrKey` is a `string` key. Only used by the
+ three-argument form.
## **Returns**
-`void`
+`void` for the bulk-merge form; `boolean` (`true`) for the three-argument,
+Python-compatible form.
## **Example**
-```typescript {4-5}
+```typescript {4-5,8}
import { SessionManager } from '@signalwire/sdk';
const sm = new SessionManager();
sm.setSessionMetadata('session-1', { caller: 'John' });
sm.setSessionMetadata('session-1', { topic: 'billing' });
// Metadata is now { caller: "John", topic: "billing" }
+
+sm.setSessionMetadata('session-1', 'priority', 'high');
+// Metadata is now { caller: "John", topic: "billing", priority: "high" }
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/ssl-config/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/ssl-config/index.mdx
index 0ea7e6eac..3e02afb5c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/configuration/ssl-config/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/configuration/ssl-config/index.mdx
@@ -24,6 +24,15 @@ import { SslConfig } from '@signalwire/sdk';
const ssl = new SslConfig({ certPath: './cert.pem', keyPath: './key.pem' });
```
+## **Constructor**
+
+
+ Optional SSL configuration overrides. Any field omitted falls back to the
+ corresponding `SWML_SSL_*` environment variable. Accepts the same keys as
+ the [`Properties`](#properties) section below (`enabled`, `certPath`,
+ `keyPath`, `domain`, `hsts`, `hstsMaxAge`).
+
+
## **Properties**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/add-step.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/add-step.mdx
index ef8eab658..3f2dbeef0 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/add-step.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/add-step.mdx
@@ -11,6 +11,9 @@ Add a new step to this context. When called with only `name`, the returned Step
can be configured via method chaining. When an options object is provided, the
step is fully configured in one call.
+Throws an `Error` if the step name already exists in this context or if the
+maximum steps per context limit (100) is exceeded.
+
## **Parameters**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/index.mdx
index a88ed2549..dc523e6a7 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/index.mdx
@@ -90,6 +90,9 @@ You obtain a Context by calling `addContext()` on a ContextBuilder or by calling
Set whether to fully reset conversation history when entering this context.
+
+ Set which step the context starts on when entered.
+
Set whether to truncate conversation history when entering this context.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/set-initial-step.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/set-initial-step.mdx
new file mode 100644
index 000000000..a10140a2c
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/set-initial-step.mdx
@@ -0,0 +1,38 @@
+---
+title: "setInitialStep"
+slug: /reference/typescript/agents/context-builder/context/set-initial-step
+description: Set which step the context starts on when entered.
+max-toc-depth: 3
+---
+
+[ref-context]: /docs/server-sdks/reference/typescript/agents/context-builder/context
+
+Set which step the context starts on when entered. By default, a context
+starts on its first step (index 0). Use this to skip a preamble step on
+re-entry via `change_context`.
+
+The step name is validated by `ContextBuilder.validate()` — the target step
+must exist in this context or validation throws.
+
+## **Parameters**
+
+
+ The step to start on when the context is entered. Must be an existing step
+ in this context.
+
+
+## **Returns**
+
+[`Context`][ref-context] — self for method chaining.
+
+## **Example**
+
+```typescript {7}
+import { ContextBuilder } from '@signalwire/sdk';
+
+const builder = new ContextBuilder();
+const billing = builder.addContext('billing');
+billing.addStep('greeting').setText('Welcome to billing.');
+billing.addStep('verify').setText('Please verify your account.');
+billing.setInitialStep('verify'); // skip the greeting on re-entry
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/set-isolated.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/set-isolated.mdx
index 578c20a12..05da1891c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/set-isolated.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/context/set-isolated.mdx
@@ -8,7 +8,16 @@ max-toc-depth: 3
[ref-context]: /docs/server-sdks/reference/typescript/agents/context-builder/context
Set whether this context is isolated from other contexts' conversation history.
-When `true`, conversation history from other contexts is not carried over.
+When `true`, entering this context via `change_context` wipes the conversation
+array — the model starts fresh with only this context's system prompt and step
+instructions, with no memory of prior turns.
+
+
+If the context also has a reset configured (`setConsolidate(true)` or
+`setFullReset(true)`), the wipe is skipped in favor of the reset behavior.
+Use reset with `setConsolidate(true)` to summarize prior history into a
+single message instead of dropping it entirely.
+
## **Parameters**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/create-simple-context.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/create-simple-context.mdx
new file mode 100644
index 000000000..7a3600b77
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/create-simple-context.mdx
@@ -0,0 +1,39 @@
+---
+title: "createSimpleContext"
+slug: /reference/typescript/agents/context-builder/create-simple-context
+description: Helper function to create a standalone Context without a ContextBuilder.
+max-toc-depth: 3
+---
+
+[context]: /docs/server-sdks/reference/typescript/agents/context-builder/context
+[contextbuilder]: /docs/server-sdks/reference/typescript/agents/context-builder
+
+Helper function that creates a standalone [`Context`][context] object without
+requiring a [`ContextBuilder`][contextbuilder]. Useful for quick prototyping or
+when you need a single context outside of the builder pattern.
+
+
+This is a module-level function, not a method on `ContextBuilder`. Import it
+directly: `import { createSimpleContext } from '@signalwire/sdk';`.
+
+
+## **Parameters**
+
+
+ Context name. Defaults to `"default"`, which is the required name for
+ single-context agents.
+
+
+## **Returns**
+
+[`Context`][context] -- A new Context object ready for adding steps.
+
+## **Example**
+
+```typescript {3}
+import { createSimpleContext } from '@signalwire/sdk';
+
+const ctx = createSimpleContext();
+ctx.addStep('greet').setText('Welcome the caller and ask how you can help.');
+ctx.addStep('farewell').setText('Thank the caller and end the conversation.');
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/index.mdx
index 5760cb7a3..9505087a3 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/index.mdx
@@ -9,6 +9,7 @@ max-toc-depth: 3
[step]: /docs/server-sdks/reference/typescript/agents/context-builder/step
[agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
[addcontext]: /docs/server-sdks/reference/typescript/agents/context-builder/add-context
+[createsimplecontext]: /docs/server-sdks/reference/typescript/agents/context-builder/create-simple-context
[getcontext]: /docs/server-sdks/reference/typescript/agents/context-builder/get-context
[todict]: /docs/server-sdks/reference/typescript/agents/context-builder/to-dict
[validate]: /docs/server-sdks/reference/typescript/agents/context-builder/validate
@@ -38,12 +39,18 @@ automatically.
Retrieve an existing context by name.
+
+ Remove all contexts, returning the builder to its initial state.
+
Convert all contexts to a dictionary for SWML generation.
Validate the entire context configuration tree.
+
+ Helper function to create a standalone Context without a ContextBuilder.
+
---
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/reset.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/reset.mdx
new file mode 100644
index 000000000..f212ed3c5
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/reset.mdx
@@ -0,0 +1,30 @@
+---
+title: "reset"
+slug: /reference/typescript/agents/context-builder/reset
+description: Remove all contexts, returning the builder to its initial state.
+max-toc-depth: 3
+---
+
+[ref-context-builder]: /docs/server-sdks/reference/typescript/agents/context-builder
+
+Remove all contexts, returning the builder to its initial state. Use this
+inside a dynamic-config callback when you need to rebuild contexts from
+scratch for a specific request, rather than mutating the shared builder.
+
+## **Returns**
+
+[`ContextBuilder`][ref-context-builder] — self for method chaining.
+
+## **Example**
+
+```typescript {3}
+agent.setDynamicConfigCallback((queryParams, bodyParams, headers, ephemeralAgent) => {
+ if (queryParams['tenant'] === 'billing') {
+ const builder = (ephemeralAgent as any).defineContexts();
+ builder.reset();
+ builder.addContext('default')
+ .addStep('greeting')
+ .setText('Welcome to billing.');
+ }
+});
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/add-gather-question.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/add-gather-question.mdx
index 5ed2155e1..6b9d2ae1f 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/add-gather-question.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/add-gather-question.mdx
@@ -12,6 +12,21 @@ Add a question to this step's gather_info configuration.
[`setGatherInfo()`][set-gather-info]
must be called before this method.
+
+**Gather mode locks function access.** While the model is asking gather
+questions, the runtime forcibly deactivates all of the step's other
+functions. The only callable tools during a gather question are:
+
+- `gather_submit` (the native answer-submission tool)
+- Whatever names you list in this question's `functions` option
+
+`next_step` and `change_context` are also filtered out — the model
+cannot navigate away until the gather completes. If a question needs
+to call out to a tool (e.g. validate an email, geocode a ZIP), list
+that tool name in this question's `functions`. Functions listed here
+are active only for this question.
+
+
## **Parameters**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/set-end.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/set-end.mdx
index 466cf2e22..1eb4b8189 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/set-end.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/set-end.mdx
@@ -1,18 +1,28 @@
---
title: "setEnd"
slug: /reference/typescript/agents/context-builder/step/set-end
-description: Set whether the conversation should end after this step completes.
+description: Mark this step as terminal for the step flow.
max-toc-depth: 3
---
[ref-step]: /docs/server-sdks/reference/typescript/agents/context-builder/step
-Set whether the conversation should end after this step completes.
+Mark this step as terminal for the step flow. After the step executes, step
+mode exits entirely — the steps list, current step index, valid steps, and
+valid contexts are all cleared. The agent keeps running under the base system
+prompt and context-level prompt, with no more step instructions injected and
+no `next_step` tool offered.
+
+
+`setEnd(true)` does **not** end the conversation or hang up the call. To
+actually end the call, call a hangup tool from a SWAIG handler or define a
+hangup hook.
+
## **Parameters**
- Whether to end the conversation after this step.
+ `true` to exit step mode after this step executes.
## **Returns**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/set-functions.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/set-functions.mdx
index 4848e5fff..c408641ce 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/set-functions.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/step/set-functions.mdx
@@ -7,13 +7,38 @@ max-toc-depth: 3
[ref-step]: /docs/server-sdks/reference/typescript/agents/context-builder/step
-Set which SWAIG functions are available during this step. Restricting functions
-per step prevents the AI from calling irrelevant tools.
+Set which non-internal functions are callable while this step is active.
+Restricting functions per step prevents the AI from calling irrelevant tools
+and keeps the per-step active set small — LLM tool selection accuracy
+degrades noticeably past ~7–8 simultaneously-active tools per call.
+
+
+**Step toolsets inherit from the previous step.** If you do not call
+`setFunctions()` on a step, it inherits whichever function set was active on
+the previous step (or the previous context's last step). The server-side
+runtime only resets the active set when a step explicitly declares its
+`functions` field. This is the most common source of bugs in multi-step
+agents — forgetting `setFunctions()` on a later step lets the previous
+step's tools leak through. Best practice: call `setFunctions()` explicitly
+on every step that should have a different toolset than the previous one.
+
+
+
+Internal functions (`startup_hook`, `hangup_hook`, `gather_submit`, etc.)
+are always protected and cannot be deactivated by this whitelist. The
+native navigation tools `next_step` and `change_context` are injected
+automatically when `setValidSteps()` / `setValidContexts()` is set; they
+are not affected by this list and do not need to appear in it.
+
## **Parameters**
- Either `"none"` to disable all functions, or a list of function names to allow.
+ One of:
+ - `string[]` — whitelist of function names allowed in this step. Functions
+ not in the list become inactive.
+ - `[]` — explicit disable-all (no user functions callable).
+ - `"none"` — synonym for `[]`, same effect.
## **Returns**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/validate.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/validate.mdx
index d63876572..5a4d975fe 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/validate.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/context-builder/validate.mdx
@@ -13,8 +13,13 @@ Checks performed:
- At least one context exists.
- A single context is named `"default"`.
- Every context has at least one step.
+- Each context's `initial_step` (if set) references a real step in that context.
- All context-level `valid_contexts` references point to contexts that exist in the builder.
-- All `gather_info` `completion_action` targets point to valid steps.
+- All step-level `valid_steps` references point to real step names (or the literal `"next"`) in the same context.
+- All step-level `valid_contexts` references point to contexts that exist in the builder.
+- All `gather_info` question keys are unique within a single step.
+- All `gather_info` `completion_action` targets point to `"next_step"` or a real step in the same context.
+- No user-defined SWAIG tool collides with the reserved native tool names (`next_step`, `change_context`, `gather_submit`).
## **Returns**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/function-result/execute-swml.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/function-result/execute-swml.mdx
index bc037f610..bec43194d 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/function-result/execute-swml.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/function-result/execute-swml.mdx
@@ -25,10 +25,11 @@ convenience methods.
## **Parameters**
-
- SWML content in one of two formats:
+ | { toDict(): Record }"} required={true} toc={true}>
+ SWML content in one of three formats:
- `string` -- raw SWML JSON text (parsed via `JSON.parse`; invalid JSON is wrapped as `{ raw_swml: content }`)
- - `Record` -- SWML data structure (spread into the action)
+ - `Record` -- SWML data structure (shallow-copied into the action)
+ - An object exposing a `toDict()` method (e.g., a `SwmlBuilder` instance) -- the returned dictionary is used as the SWML payload
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/function-result/join-conference.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/function-result/join-conference.mdx
index 5fa58c039..c704a9d59 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/function-result/join-conference.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/function-result/join-conference.mdx
@@ -29,7 +29,7 @@ used internally. Passing any non-default parameter triggers the full object form
Join the conference muted.
-
+
Beep configuration for join/leave notifications.
- `"true"` -- beep on both enter and exit
@@ -52,7 +52,7 @@ used internally. Passing any non-default parameter triggers the full object form
When omitted, default hold music is used.
-
+
Maximum number of participants.
@@ -97,7 +97,7 @@ used internally. Passing any non-default parameter triggers the full object form
URL to receive conference status event webhooks.
-
+
HTTP method for status callbacks.
- `"GET"` -- send status callbacks as GET requests
@@ -108,14 +108,14 @@ used internally. Passing any non-default parameter triggers the full object form
URL to receive recording status event webhooks.
-
+
HTTP method for recording status callbacks.
- `"GET"` -- send recording status callbacks as GET requests
- `"POST"` -- send recording status callbacks as POST requests
-
+
Space-separated list of recording events to report.
- `"in-progress"` -- recording is currently in progress
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/function-result/tap.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/function-result/tap.mdx
index 22cb36d46..fd511f45b 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/function-result/tap.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/function-result/tap.mdx
@@ -29,7 +29,7 @@ WebSocket (`wss://`, `ws://`) and RTP (`rtp://`) destinations.
specific tap. If omitted, a default ID is generated.
-
+
Audio direction to tap.
- `"speak"` -- what the party says
@@ -37,14 +37,14 @@ WebSocket (`wss://`, `ws://`) and RTP (`rtp://`) destinations.
- `"both"` -- both directions
-
+
Audio codec for the stream.
- `"PCMU"` -- G.711 mu-law
- `"PCMA"` -- G.711 A-law
-
+
Packetization time in milliseconds for RTP streams.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/helpers.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/helpers.mdx
index b914e2ef1..de4db6f17 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/helpers.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/helpers.mdx
@@ -370,6 +370,40 @@ console.log(redactUrl('https://admin:secret@example.com/api'));
---
+## **validateUrl**
+
+Validate that a URL is safe to fetch — rejects URLs whose hostname resolves to
+a private or reserved IP range (loopback, RFC1918, link-local, IPv6 private).
+Never throws; returns `false` on failure.
+
+## **Parameters**
+
+
+ The URL to validate.
+
+
+
+ When `true`, skip the private-IP check.
+
+
+## **Returns**
+
+`Promise` -- `true` if the URL is safe to fetch, `false` otherwise.
+
+## **Example**
+
+```typescript {3}
+import { validateUrl } from '@signalwire/sdk';
+
+const ok = await validateUrl('https://api.example.com/endpoint');
+console.log(ok); // true
+
+const bad = await validateUrl('http://127.0.0.1:8080/admin');
+console.log(bad); // false
+```
+
+---
+
## **MAX_SKILL_INPUT_LENGTH**
Maximum allowed input length for skill handler arguments (characters). Value: `1000`.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/index.mdx
index 2f9dea278..1e5ba37be 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/index.mdx
@@ -39,44 +39,83 @@ new AgentSession(options?: {
llm?: any;
vad?: any;
turnDetection?: any;
+ tools?: FunctionTool[];
+ mcpServers?: unknown;
userData?: UserData;
- voiceOptions?: Partial;
+ allowInterruptions?: boolean;
+ minInterruptionDuration?: number;
+ minEndpointingDelay?: number;
+ maxEndpointingDelay?: number;
+ maxToolSteps?: number;
+ preemptiveGeneration?: boolean;
})
```
-
+
STT provider instance. Accepted for API compatibility; SignalWire handles speech
recognition automatically. Logs an informational message on first use.
-
+
TTS provider instance. Accepted for API compatibility; SignalWire handles
text-to-speech automatically. Logs an informational message on first use.
-
+
LLM provider or model string. If provided, the model name is extracted (stripping
any provider prefix like `"openai/"`) and set on the underlying SignalWire agent.
-
+
VAD provider instance. Accepted for API compatibility; SignalWire handles voice
activity detection automatically.
-
+
Turn detection configuration. Accepted for API compatibility; SignalWire handles
turn detection automatically.
+
+ Optional additional tools merged with the agent's tools when `start()` is called.
+
+
+
+ Accepted for LiveKit parity. MCP servers are not yet supported in LiveWire —
+ logs a one-time advisory and has no effect.
+
+
Arbitrary data attached to the session. Accessible from tool handlers via
[`RunContext.userData`][runcontext].
-
- Voice configuration (`voice`, `engine`, `language`) passed through to the
- SignalWire AI config.
+
+ Forwarded to the SignalWire AI params when the session starts.
+
+
+
+ Accepted for LiveKit parity. Forwarded to the SignalWire AI params when the
+ session starts.
+
+
+
+ Minimum endpointing delay in seconds. Forwarded to the SignalWire AI params
+ when the session starts.
+
+
+
+ Maximum endpointing delay in seconds. Forwarded to the SignalWire AI params
+ when the session starts.
+
+
+
+ Accepted for LiveKit parity. SignalWire handles tool-execution depth
+ automatically — logs a one-time advisory if set to a non-default value.
+
+
+
+ Accepted for LiveKit parity. Stored on the session but not currently used.
## **Properties**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/say.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/say.mdx
index 5266d1053..1e51fb940 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/say.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/say.mdx
@@ -8,6 +8,13 @@ max-toc-depth: 3
Queue text to be spoken by the agent. Internally, this appends a prompt section
to the underlying SignalWire `AgentBase` so the AI speaks the provided text.
+
+Calls to `say()` made **before** `start({ agent })` are buffered on an internal
+queue and replayed in order when the session starts (matches the Python SDK's
+always-queue semantics). You do not need to await start before queuing
+greetings.
+
+
## **Signature**
```typescript {1}
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/start.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/start.mdx
index 746095448..a841d2651 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/start.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent-session/start.mdx
@@ -16,7 +16,7 @@ AI model parameter.
## **Signature**
```typescript {1}
-async start(params: { agent: Agent; room?: any }): Promise
+async start(params: { agent: Agent; room?: any; record?: boolean }): Promise
```
## **Parameters**
@@ -25,10 +25,14 @@ async start(params: { agent: Agent; room?: any }): Promise
The [`Agent`][agent] instance to bind to this session.
-
+
A room instance. Accepted for API compatibility with LiveKit.
+
+ Whether to record the session. Accepted for API compatibility with LiveKit.
+
+
## **Returns**
`Promise`
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent/index.mdx
index b79aaec87..20acb749e 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/livewire/agent/index.mdx
@@ -9,8 +9,8 @@ max-toc-depth: 3
[agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
[functiontool]: /docs/server-sdks/reference/typescript/agents/livewire/function-tool
-The `Agent` class mirrors a LiveKit voice agent. It holds the system prompt
-(instructions), a map of tools, and optional user data. When bound to an
+The `Agent` class mirrors a LiveKit voice agent. It holds the system
+prompt (instructions), a set of tools, and optional user data. When bound to an
[`AgentSession`][agentsession], the session translates this into a SignalWire
[`AgentBase`][agentbase] under the hood.
@@ -27,28 +27,46 @@ const getWeather = tool({
const agent = new Agent({
instructions: 'You are a helpful weather assistant.',
- tools: { getWeather },
+ tools: [getWeather],
});
```
## **Constructor**
-```typescript {1}
-new Agent(options: {
- instructions: string;
- tools?: Record;
+```typescript {1-13}
+new Agent(options?: {
+ instructions?: string;
+ tools?: FunctionTool[];
userData?: UserData;
+ chatCtx?: unknown;
+ stt?: unknown;
+ tts?: unknown;
+ llm?: unknown;
+ vad?: unknown;
+ turnDetection?: unknown;
+ mcpServers?: unknown;
+ allowInterruptions?: boolean;
+ minEndpointingDelay?: number;
+ maxEndpointingDelay?: number;
})
```
-
- The system prompt text for the agent. Mapped to the SignalWire prompt when the
- session starts.
+
+The constructor options are source-compatible with LiveKit's `Agent`
+constructor, including pipeline fields like `stt`, `tts`, `vad`,
+`turnDetection`, and `mcpServers`. SignalWire handles speech, TTS, and VAD on
+the control plane, so those fields are accepted but logged as a no-op the
+first time they are supplied.
+
+
+
+ System prompt text. Mapped to the SignalWire prompt when the session starts.
-
- A map of tool names to [`FunctionTool`][functiontool] definitions. Each tool is
- registered as a SWAIG function on the underlying SignalWire agent.
+
+ Array of [`FunctionTool`][functiontool] objects. Stored internally as a
+ name-keyed record; each tool is registered as a SWAIG function on the
+ underlying agent.
@@ -56,6 +74,32 @@ new Agent(options: {
`RunContext.userData`.
+
+ Accepted for LiveKit parity. Pipeline mapping hint — SignalWire selects the
+ model from the SWML `ai.params`.
+
+
+
+ Accepted for LiveKit parity. Forwarded to the SignalWire AI params when the
+ session starts.
+
+
+
+ Accepted for LiveKit parity. Forwarded to the SignalWire AI params when the
+ session starts.
+
+
+
+ Accepted for LiveKit parity. Forwarded to the SignalWire AI params when the
+ session starts.
+
+
+
+ Accepted for LiveKit source compatibility. SignalWire handles these
+ capabilities on the control plane; passing a value logs a one-time
+ "no-op" advisory and does not affect behavior.
+
+
## **Properties**
@@ -63,13 +107,18 @@ new Agent(options: {
- The map of registered tools.
+ Internal name-keyed map of registered tools.
The user data attached to this agent.
+
+ The [`AgentSession`][agentsession] bound to this agent, if any. Set when
+ `session.start({ agent })` is called.
+
+
## **Example**
```typescript {13-17}
@@ -87,7 +136,7 @@ const agentDef = defineAgent({
entry: async (ctx: JobContext) => {
const agent = new Agent({
instructions: 'You are a customer support agent. Help users with their accounts.',
- tools: { lookupAccount },
+ tools: [lookupAccount],
userData: { department: 'support' },
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/livewire/signals.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/livewire/signals.mdx
index 849fd3a71..b787579a4 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/livewire/signals.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/livewire/signals.mdx
@@ -125,17 +125,38 @@ Factory function that creates an `AgentHandoff` instance.
## **ChatContext**
-A minimal empty class mirroring the LiveKit `ChatContext`. Exists for API
-compatibility. On SignalWire, conversation history is managed by the platform.
+A minimal class mirroring the LiveKit `ChatContext`. Stores an in-memory list
+of chat messages. On SignalWire, the platform manages conversation history
+for the active call — this class exists so that existing livekit-agents code
+that references `ChatContext` compiles without errors, and so callers can
+stage messages in prewarm code.
-```typescript {3}
+```typescript {4}
import { llm } from '@signalwire/sdk/livewire';
const chat = new llm.ChatContext();
+chat.append({ role: 'system', text: 'You are a helpful agent.' });
```
-
-`ChatContext` has no methods or properties in the LiveWire implementation. It is an
-empty stub provided solely so that existing livekit-agents code that references
-`ChatContext` compiles without errors.
-
+### Properties
+
+
+ Appended chat messages. Each entry is stored as `{ role, content }`.
+
+
+### append
+
+```typescript {1}
+append(options: { role?: string; text?: string }): this
+```
+
+Append a message to `messages`. The stored entry uses `content` (not `text`)
+as the body key — `text` is renamed to match the on-wire message shape.
+
+
+ The message role (`"user"`, `"assistant"`, `"system"`, etc.).
+
+
+
+ The message content.
+
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/overview.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/overview.mdx
index 73dbf95c4..8eeb991bb 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/overview.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/overview.mdx
@@ -1,7 +1,7 @@
---
title: "Agents"
sidebar-title: Overview
-subtitle: "TypeScript API reference for AgentBase, SWMLService, SWAIG functions, skills, contexts, LiveWire, search, and more"
+subtitle: "TypeScript API reference for AgentBase, SWMLService, SWAIG functions, skills, contexts, LiveWire, and more"
slug: /reference/typescript/agents
description: "Core framework for building AI-powered voice agents."
max-toc-depth: 3
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/add-pom-as-subsection.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/add-pom-as-subsection.mdx
new file mode 100644
index 000000000..38c3f1960
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/add-pom-as-subsection.mdx
@@ -0,0 +1,52 @@
+---
+title: "addPomAsSubsection"
+slug: /reference/typescript/agents/pom-builder/add-pom-as-subsection
+description: "Append another PomBuilder's sections as subsections of a target section."
+max-toc-depth: 3
+---
+
+[ref-findsection]: /docs/server-sdks/reference/typescript/agents/pom-builder/find-section
+
+Append every top-level section of another `PomBuilder` as a subsection of a
+target section in this builder. Useful for composing prompts assembled
+separately into a single document.
+
+
+Throws `Error("No section with title '' found.")` when `target` is a
+string and no section with that title exists. For deeper lookups, resolve the
+section yourself via [`findSection()`][ref-findsection] and pass the
+`PomSection` directly.
+
+
+## **Parameters**
+
+
+ The target section to append into. Pass a title string for top-level
+ sections, or a `PomSection` instance (from `findSection()`) for nested
+ sections.
+
+
+
+ The builder whose sections should be appended.
+
+
+## **Returns**
+
+`this` -- returns the builder for fluent chaining.
+
+## **Example**
+
+```typescript {11}
+import { PomBuilder } from '@signalwire/sdk';
+
+const subPom = new PomBuilder();
+subPom.addSection('Policy A', { body: 'Always greet by name.' });
+subPom.addSection('Policy B', { body: 'Escalate billing issues.' });
+
+const main = new PomBuilder();
+main.addSection('Introduction', { body: 'You are a helpful agent.' });
+main.addSection('Policies');
+
+main.addPomAsSubsection('Policies', subPom);
+console.log(main.renderMarkdown());
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/from-sections.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/from-sections.mdx
new file mode 100644
index 000000000..65b74a542
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/from-sections.mdx
@@ -0,0 +1,40 @@
+---
+title: "fromSections"
+slug: /reference/typescript/agents/pom-builder/from-sections
+description: "Create a new PomBuilder from an array of section data objects (static)."
+max-toc-depth: 3
+---
+
+[ref-tojson]: /docs/server-sdks/reference/typescript/agents/pom-builder/to-json
+[ref-todict]: /docs/server-sdks/reference/typescript/agents/pom-builder/to-dict
+
+Static factory method that reconstructs a `PomBuilder` from an array of
+`PomSectionData` objects. Use this to restore a prompt serialized via
+[`toJson()`][ref-tojson] or
+[`toDict()`][ref-todict].
+
+## **Parameters**
+
+
+ Array of section data objects. Each must include at minimum a `title`, and
+ may include `body`, `bullets`, `numbered`, `numberedBullets`, and nested
+ `subsections`.
+
+
+## **Returns**
+
+`PomBuilder` -- a new builder populated with the given sections.
+
+## **Example**
+
+```typescript {8}
+import { PomBuilder } from '@signalwire/sdk';
+
+const data = [
+ { title: 'Intro', body: 'Welcome.' },
+ { title: 'Rules', bullets: ['Be nice.', 'Stay on topic.'] },
+];
+
+const pom = PomBuilder.fromSections(data);
+console.log(pom.renderMarkdown());
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/index.mdx
index e4f3a3967..7d2495ef0 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/index.mdx
@@ -49,9 +49,24 @@ can render to Markdown format.
Render the POM as a Markdown string.
+
+ Render the POM as an XML document.
+
Convert the POM to a list of section objects.
+
+ Serialize all sections to a JSON string.
+
+
+ Create a new PomBuilder from section data (static).
+
+
+ Append another PomBuilder's sections as subsections.
+
+
+ Clear all sections and start over.
+
## **Examples**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/render-xml.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/render-xml.mdx
new file mode 100644
index 000000000..357afeba9
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/render-xml.mdx
@@ -0,0 +1,43 @@
+---
+title: "renderXml"
+slug: /reference/typescript/agents/pom-builder/render-xml
+description: "Render all sections as a combined XML document."
+max-toc-depth: 3
+---
+
+[ref-rendermarkdown]: /docs/server-sdks/reference/typescript/agents/pom-builder/render-markdown
+
+Render all top-level sections as a single XML document wrapped in a
+`` root element. Each section becomes a nested XML element with its
+title as the tag text or attribute, and bullets/numbered lists rendered as
+child elements.
+
+
+The markdown variant -- [`renderMarkdown()`][ref-rendermarkdown] -- is the
+default render format. Use `renderXml()` only for prompts where the
+downstream LLM or template expects XML-structured input.
+
+
+## **Returns**
+
+`string` -- XML document starting with ``
+and wrapping all sections in a `` root.
+
+## **Example**
+
+```typescript {7}
+import { PomBuilder } from '@signalwire/sdk';
+
+const pom = new PomBuilder();
+pom.addSection('Intro', { body: 'Welcome.' });
+pom.addSection('Rules', { bullets: ['Be nice.', 'Stay on topic.'] });
+
+console.log(pom.renderXml());
+//
+//
+//
+// ...
+//
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/reset.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/reset.mdx
new file mode 100644
index 000000000..e57a90c98
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/reset.mdx
@@ -0,0 +1,29 @@
+---
+title: "reset"
+slug: /reference/typescript/agents/pom-builder/reset
+description: "Clear all sections and return the builder to its initial empty state."
+max-toc-depth: 3
+---
+
+Clear all top-level sections from the builder, returning it to an empty
+initial state. Also clears the internal section lookup map used by
+[`hasSection()`](/docs/server-sdks/reference/typescript/agents/pom-builder/has-section)
+and
+[`getSection()`](/docs/server-sdks/reference/typescript/agents/pom-builder/get-section).
+
+## **Returns**
+
+`this` -- returns the builder for fluent chaining.
+
+## **Example**
+
+```typescript {7}
+import { PomBuilder } from '@signalwire/sdk';
+
+const pom = new PomBuilder();
+pom.addSection('Intro', { body: 'Welcome.' });
+pom.addSection('Rules', { bullets: ['Be nice.', 'Stay on topic.'] });
+
+pom.reset();
+console.log(pom.renderMarkdown()); // "" (empty)
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/to-json.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/to-json.mdx
new file mode 100644
index 000000000..a1206ac7c
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/pom-builder/to-json.mdx
@@ -0,0 +1,32 @@
+---
+title: "toJson"
+slug: /reference/typescript/agents/pom-builder/to-json
+description: "Serialize all sections to a JSON string."
+max-toc-depth: 3
+---
+
+[ref-todict]: /docs/server-sdks/reference/typescript/agents/pom-builder/to-dict
+[ref-fromsections]: /docs/server-sdks/reference/typescript/agents/pom-builder/from-sections
+
+Serialize all top-level sections to a JSON string. Internally calls
+[`toDict()`][ref-todict] and wraps the result in `JSON.stringify()`. Use this
+to persist a prompt for later restoration via
+[`PomBuilder.fromSections()`][ref-fromsections].
+
+## **Returns**
+
+`string` -- JSON-serialized array of section data.
+
+## **Example**
+
+```typescript {7}
+import { PomBuilder } from '@signalwire/sdk';
+
+const pom = new PomBuilder();
+pom.addSection('Intro', { body: 'Welcome.' });
+pom.addSection('Rules', { bullets: ['Be nice.', 'Stay on topic.'] });
+
+const json = pom.toJson();
+// Persist, send over the wire, etc.
+const restored = PomBuilder.fromSections(JSON.parse(json));
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/concierge-agent.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/concierge-agent.mdx
index b48358472..0b90a05ae 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/concierge-agent.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/concierge-agent.mdx
@@ -1,14 +1,15 @@
---
title: "ConciergeAgent"
slug: /reference/typescript/agents/prefabs/concierge-agent
-description: A concierge agent that provides multi-department routing with a knowledge base of department info, hours of operation, and call transfer capabilities.
+description: A virtual concierge for a venue — provides information about services, amenities, hours of operation, and directions.
---
[agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
[functionresult]: /docs/server-sdks/reference/typescript/agents/function-result
-A concierge that provides multi-department routing with a knowledge base of department
-info, hours of operation, and call transfer capabilities.
+A virtual concierge for a venue or business. Answers questions about
+services, amenities, and hours of operation, and offers directions and
+recommendations.
```typescript {3}
import { ConciergeAgent } from '@signalwire/sdk';
@@ -18,80 +19,64 @@ const agent = new ConciergeAgent({ /* ConciergeConfig */ });
## ConciergeConfig
-
- List of departments available for routing. Each `Department` object has:
+
+ Name of the venue or business (used in greetings and prompts).
+
+
+
+ List of services offered by the venue.
+
- - `name` (string, required) -- Department name (e.g., `"Sales"`).
- - `description` (string, required) -- What this department handles.
- - `transferNumber` (string) -- Phone number or SIP address for transfers.
- - `keywords` (string[]) -- Keywords that help route callers to this department.
- - `hoursOfOperation` (string) -- Human-readable hours (e.g., `"Mon-Fri 9am-5pm EST"`).
+>"} required={true} toc={true}>
+ Map of amenity names to detail key/value pairs. For example,
+ `{ "Pool": { "hours": "9am-9pm", "location": "3rd floor" } }`.
-
- Company name used in greetings and prompts.
+"} default={'{ default: "9 AM - 5 PM" }'} toc={true}>
+ Hours of operation by category. Use `"default"` for a single block, or
+ keyed entries like `{ weekdays: "9-5", weekends: "10-4" }`.
-
- General company information the agent can share with callers.
+
+ Extra instruction bullets appended to the agent's prompt.
-
- Message spoken when a department is closed or has no transfer number.
+
+ Optional custom welcome message played as a non-bargeable static greeting.
-
+
Agent display name.
+
+ HTTP route for the agent.
+
+
Additional [`AgentBase`][agentbase] options forwarded to the constructor.
-## Built-in Tools
-
-| Tool | Description | Parameters |
-|------|-------------|------------|
-| `list_departments` | List all departments with descriptions and hours | (none) |
-| `get_department_info` | Get detailed info about a specific department | `department_name` (string) |
-| `transfer_to_department` | Transfer the caller to a department via its transfer number | `department_name` (string) |
-
-
-The `transfer_to_department` tool uses `FunctionResult.connect()` to transfer the call.
-If the department has no `transferNumber`, the agent returns the `afterHoursMessage` instead.
-
-
## Example
```typescript {3}
import { ConciergeAgent } from '@signalwire/sdk';
const agent = new ConciergeAgent({
- companyName: 'Riverside Resort',
- generalInfo: 'A luxury resort on the riverfront with 200 rooms.',
- departments: [
- {
- name: 'Front Desk',
- description: 'Check-in, check-out, and room inquiries',
- transferNumber: '+15551001001',
- hoursOfOperation: '24 hours',
- keywords: ['room', 'reservation', 'check-in'],
- },
- {
- name: 'Spa',
- description: 'Spa treatments and wellness appointments',
- transferNumber: '+15551001002',
- hoursOfOperation: '9 AM - 9 PM',
- keywords: ['massage', 'facial', 'wellness'],
- },
- {
- name: 'Restaurant',
- description: 'Dining reservations and room service',
- transferNumber: '+15551001003',
- hoursOfOperation: '7 AM - 10 PM',
- },
+ venueName: 'Riverside Resort',
+ services: ['Dining', 'Spa', 'Concierge'],
+ amenities: {
+ Pool: { hours: '9 AM - 9 PM', location: 'Level 3' },
+ Gym: { hours: '24 hours', access: 'Room key' },
+ },
+ hoursOfOperation: {
+ default: '9 AM - 5 PM',
+ weekends: '10 AM - 4 PM',
+ },
+ specialInstructions: [
+ 'Always mention our weekend jazz brunch when discussing dining.',
],
- afterHoursMessage: 'This department is currently closed. Please call back during business hours.',
+ welcomeMessage: 'Welcome to Riverside Resort. How can I help you?',
});
agent.serve();
@@ -103,9 +88,8 @@ agent.serve();
import { createConciergeAgent } from '@signalwire/sdk';
const agent = createConciergeAgent({
- companyName: 'Riverside Resort',
- departments: [
- { name: 'Front Desk', description: 'Room inquiries', transferNumber: '+15551001001' },
- ],
+ venueName: 'Riverside Resort',
+ services: ['Dining'],
+ amenities: { Pool: { hours: '9-9' } },
});
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/faq-bot-agent.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/faq-bot-agent.mdx
index c52524d08..145243481 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/faq-bot-agent.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/faq-bot-agent.mdx
@@ -25,6 +25,24 @@ const agent = new FAQBotAgent({ /* FAQBotConfig */ });
- `question` (string, required) -- The representative question text.
- `answer` (string, required) -- The answer to provide when matched.
- `keywords` (string[]) -- Additional keywords to boost matching accuracy.
+ - `categories` (string[]) -- Taxonomy categories used for filtering and hints.
+
+
+
+ Agent display name.
+
+
+
+ HTTP route for the agent.
+
+
+
+ Whether to suggest related questions alongside a match.
+
+
+
+ Custom personality description injected into the agent's "Personality"
+ prompt section. Defaults to a helpful-FAQ-bot persona.
@@ -39,10 +57,6 @@ const agent = new FAQBotAgent({ /* FAQBotConfig */ });
Phone number to transfer to on escalation. If not set, the `escalate` tool is not registered.
-
- Agent display name.
-
-
Additional [`AgentBase`][agentbase] options forwarded to the constructor.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/index.mdx
index a999d4c83..238209883 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/index.mdx
@@ -25,11 +25,11 @@ import {
| Prefab | Purpose | Built-in Tools |
|--------|---------|----------------|
-| [ConciergeAgent](/docs/server-sdks/reference/typescript/agents/prefabs/concierge-agent) | Multi-department routing with knowledge base | `list_departments`, `get_department_info`, `transfer_to_department` |
+| [ConciergeAgent](/docs/server-sdks/reference/typescript/agents/prefabs/concierge-agent) | Venue concierge with services, amenities, and hours | `check_availability`, `get_directions` |
| [FAQBotAgent](/docs/server-sdks/reference/typescript/agents/prefabs/faq-bot-agent) | Answer questions using keyword matching | `search_faq`, `escalate` (optional) |
-| [InfoGathererAgent](/docs/server-sdks/reference/typescript/agents/prefabs/info-gatherer-agent) | Collect named fields from a caller | `save_field`, `get_status` |
-| [ReceptionistAgent](/docs/server-sdks/reference/typescript/agents/prefabs/receptionist-agent) | Front-desk check-in, directory, and transfers | `get_department_list`, `transfer_to_department`, `check_in_visitor` (optional) |
-| [SurveyAgent](/docs/server-sdks/reference/typescript/agents/prefabs/survey-agent) | Conduct surveys with branching and scoring | `answer_question`, `get_current_question`, `get_survey_progress` |
+| [InfoGathererAgent](/docs/server-sdks/reference/typescript/agents/prefabs/info-gatherer-agent) | Collect answers to a list of questions | `start_questions`, `submit_answer` |
+| [ReceptionistAgent](/docs/server-sdks/reference/typescript/agents/prefabs/receptionist-agent) | Front-desk check-in, directory, and transfers | `collect_caller_info`, `transfer_call`, `check_in_visitor` (optional) |
+| [SurveyAgent](/docs/server-sdks/reference/typescript/agents/prefabs/survey-agent) | Conduct surveys with branching and scoring | `validate_response`, `log_response`, `answer_question`, `get_current_question`, `get_survey_progress` |
Each prefab also has a corresponding factory function (e.g., `createConciergeAgent()`)
that creates and returns a configured instance.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/info-gatherer-agent.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/info-gatherer-agent.mdx
index 54866d866..d5e3c2e5b 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/info-gatherer-agent.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/info-gatherer-agent.mdx
@@ -1,15 +1,15 @@
---
title: "InfoGathererAgent"
slug: /reference/typescript/agents/prefabs/info-gatherer-agent
-description: An info gatherer agent that sequentially collects named fields from a caller through conversational interaction with validation and completion callbacks.
+description: A prefab agent that collects answers to a series of questions — supporting both static and dynamic (per-request callback) modes.
---
[agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
[functionresult]: /docs/server-sdks/reference/typescript/agents/function-result
-Sequentially collects named fields from a caller through conversational interaction.
-Tracks fields per call, validates values with optional regex patterns, and fires an
-`onComplete` callback once all required fields are gathered.
+Sequentially asks a caller a list of questions and stores each answer in
+`global_data`. Supports **static mode** (questions provided at construction)
+and **dynamic mode** (questions resolved per request via a callback).
```typescript {3}
import { InfoGathererAgent } from '@signalwire/sdk';
@@ -19,83 +19,92 @@ const agent = new InfoGathererAgent({ /* InfoGathererConfig */ });
## InfoGathererConfig
-
- Fields to collect from the caller. Each `InfoGathererField` object has:
+
+ Questions to ask (static mode). Each `InfoGathererQuestion` has:
- - `name` (string, required) -- Unique field name used as the key in collected data.
- - `description` (string, required) -- Human-readable description shown to the AI agent.
- - `required` (boolean, default `true`) -- Whether this field must be collected before completion.
- - `validation` (RegExp | string) -- Optional validation pattern. Strings are compiled to `RegExp`.
-
+ - `key_name` (string, required) — key used to store the caller's answer.
+ - `question_text` (string, required) — the question to ask.
+ - `confirm` (boolean) — when `true`, the agent insists the caller confirms
+ the answer before moving on.
-
- Opening message the agent speaks when the call starts.
+ Omit this field to run the agent in dynamic mode (see `questionCallback` /
+ `setQuestionCallback()`).
-
- Message spoken after all required fields are gathered.
-
+
+ Convenience alternative to calling `setQuestionCallback()` after
+ construction. Consulted only when `questions` is not provided. Signature:
+
+ ```typescript
+ (queryParams, bodyParams, headers) => InfoGathererQuestion[] | Promise
+ ```
-
- Callback fired when all required fields have been collected. Receives a record of
- field names to their collected values.
+ If the callback throws or is not registered in dynamic mode, the agent
+ falls back to a built-in two-question list (name + "how can I help").
-
+
Agent display name.
+
+ HTTP route for the agent.
+
+
Additional [`AgentBase`][agentbase] options forwarded to the constructor.
+## **Methods**
+
+### setQuestionCallback
+
+```typescript
+setQuestionCallback(callback: InfoGathererQuestionCallback): this
+```
+
+Register (or replace) the callback that resolves questions per request. Only
+used in dynamic mode (when `questions` was not supplied at construction).
+
## Built-in Tools
-| Tool | Description | Parameters |
-|------|-------------|------------|
-| `save_field` | Save a collected field value, validating against the field's pattern if configured | `field_name` (string), `value` (string) |
-| `get_status` | Get the current collection status showing collected and remaining fields | (none) |
+| Tool | Description |
+|------|-------------|
+| `start_questions` | Begin the question sequence with the first question. |
+| `submit_answer` | Submit the caller's answer to the current question and advance. |
-## Example
+## Example — static mode
```typescript {3}
import { InfoGathererAgent } from '@signalwire/sdk';
const agent = new InfoGathererAgent({
- fields: [
- { name: 'full_name', description: 'Full legal name' },
- {
- name: 'email',
- description: 'Email address',
- validation: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
- },
- {
- name: 'phone',
- description: 'Phone number',
- validation: '^\\+?\\d{10,15}$',
- },
- {
- name: 'preferred_date',
- description: 'Preferred appointment date',
- },
- {
- name: 'notes',
- description: 'Any additional notes',
- required: false,
- },
+ questions: [
+ { key_name: 'full_name', question_text: 'What is your full name?' },
+ { key_name: 'email', question_text: 'What is your email address?', confirm: true },
+ { key_name: 'issue', question_text: 'How can we help you today?' },
],
- introMessage: 'Hi! I need a few details to schedule your appointment.',
- confirmationMessage: 'All set! Your appointment details have been recorded.',
- onComplete: (data) => {
- console.log('Collected data:', data);
- // { full_name: "Jane Doe", email: "jane@example.com", ... }
- },
- name: 'appointment-scheduler',
+ name: 'intake-agent',
});
-agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
-agent.promptAddSection('Brand', {
- body: 'You are scheduling appointments for Dr. Smith\'s office.',
+agent.serve();
+```
+
+## Example — dynamic mode
+
+```typescript {3-14}
+import { InfoGathererAgent, type InfoGathererQuestion } from '@signalwire/sdk';
+
+const agent = new InfoGathererAgent({
+ questionCallback: async (queryParams) => {
+ const tenant = queryParams['tenant'] ?? 'default';
+ const rows = await db.loadQuestions(tenant);
+ return rows.map((r) => ({
+ key_name: r.key,
+ question_text: r.prompt,
+ confirm: r.requiresConfirmation,
+ }));
+ },
});
agent.serve();
@@ -107,9 +116,9 @@ agent.serve();
import { createInfoGathererAgent } from '@signalwire/sdk';
const agent = createInfoGathererAgent({
- fields: [
- { name: 'name', description: 'Full name' },
- { name: 'issue', description: 'Describe your issue' },
+ questions: [
+ { key_name: 'name', question_text: 'What is your name?' },
+ { key_name: 'issue', question_text: 'Describe your issue' },
],
});
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/receptionist-agent.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/receptionist-agent.mdx
index 908a59f85..436fbfc1c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/receptionist-agent.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/receptionist-agent.mdx
@@ -1,15 +1,14 @@
---
title: "ReceptionistAgent"
slug: /reference/typescript/agents/prefabs/receptionist-agent
-description: A front-desk agent that handles visitor check-in, department directory lookup, and call transfers by extension.
+description: A front-desk agent that greets callers, looks up departments, and transfers calls. Optional visitor check-in.
---
[agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
[functionresult]: /docs/server-sdks/reference/typescript/agents/function-result
-A front-desk agent that handles visitor check-in, department directory lookup, and
-call transfers by extension. The `check_in_visitor` tool is enabled by default and
-fires an optional callback when a visitor checks in.
+A front-desk agent that greets callers and transfers them to the correct
+department by phone number or SIP address. Visitor check-in is opt-in.
```typescript {3}
import { ReceptionistAgent } from '@signalwire/sdk';
@@ -19,50 +18,60 @@ const agent = new ReceptionistAgent({ /* ReceptionistConfig */ });
## ReceptionistConfig
-
- Company name displayed in greetings and prompts.
+
+ Departments the agent can transfer callers to. Each `ReceptionistDepartment`
+ has:
+
+ - `name` (string, required) — department identifier (e.g. `"sales"`).
+ - `description` (string, required) — description shown to the AI.
+ - `number` (string, required) — phone number or SIP address dialed by
+ `transfer_call`.
-
- Departments with extensions for the directory. Each `ReceptionistDepartment` object has:
+
+ Initial greeting spoken when the call starts.
+
- - `name` (string, required) -- Department name (e.g., `"Engineering"`).
- - `extension` (string, required) -- Internal extension number or SIP address.
- - `description` (string) -- Optional description of the department.
+
+ Voice identifier passed to `addLanguage`.
-
- Custom welcome message. Defaults to `"Welcome to {companyName}! How may I help you today?"`.
+
+ Optional company name appended to the greeting.
-
- Whether visitor check-in functionality is enabled. When `true`, the `check_in_visitor` tool is registered.
+
+ When `true`, registers the `check_in_visitor` tool.
- Callback fired when a visitor checks in. Receives a record with `visitor_name`, `purpose`,
- `visiting`, and `checked_in_at` fields.
+ Callback fired when a visitor checks in. Receives a record with the fields
+ collected during check-in.
-
+
Agent display name.
+
+ HTTP route for the agent.
+
+
Additional [`AgentBase`][agentbase] options forwarded to the constructor.
## Built-in Tools
-| Tool | Description | Parameters |
-|------|-------------|------------|
-| `get_department_list` | List all departments with extensions and descriptions | (none) |
-| `transfer_to_department` | Transfer the caller to a department by dialing its extension | `department_name` (string) |
-| `check_in_visitor` | Check in a visitor (only when `checkInEnabled` is `true`) | `visitor_name` (string), `purpose` (string), `visiting` (string) |
+| Tool | Description |
+|------|-------------|
+| `collect_caller_info` | Collect the caller's name and reason for calling; stored in `global_data.caller_info`. |
+| `transfer_call` | Dial a department's number and transfer the caller. The `department` param is an enum of the configured department names. |
+| `check_in_visitor` | Record a visitor check-in (only when `checkInEnabled` is `true`). |
-The `transfer_to_department` tool uses [`FunctionResult.connect()`][functionresult] to
-dial the department's extension and transfer the call.
+`transfer_call` uses [`FunctionResult.connect()`][functionresult] to dial the
+department's configured `number`.
## Example
@@ -72,22 +81,18 @@ import { ReceptionistAgent } from '@signalwire/sdk';
const agent = new ReceptionistAgent({
companyName: 'Acme Corporation',
+ greeting: 'Thank you for calling Acme Corporation. How may I direct your call?',
departments: [
- { name: 'Sales', extension: '1001', description: 'New orders and pricing' },
- { name: 'Support', extension: '1002', description: 'Technical issues' },
- { name: 'Billing', extension: '1003', description: 'Invoices and payments' },
- { name: 'HR', extension: '1004', description: 'Employment and benefits' },
+ { name: 'sales', description: 'New orders and pricing', number: '+15551001001' },
+ { name: 'support', description: 'Technical issues', number: '+15551001002' },
+ { name: 'billing', description: 'Invoices and payments', number: '+15551001003' },
],
- welcomeMessage: 'Thank you for calling Acme Corporation. How may I direct your call?',
+ checkInEnabled: true,
onVisitorCheckIn: (visitor) => {
- console.log(`Visitor checked in: ${visitor.visitor_name} visiting ${visitor.visiting}`);
+ console.log(`Visitor checked in: ${JSON.stringify(visitor)}`);
},
});
-agent.promptAddSection('Company', {
- body: 'You are the receptionist for Acme Corporation.',
-});
-
agent.serve();
```
@@ -97,10 +102,8 @@ agent.serve();
import { createReceptionistAgent } from '@signalwire/sdk';
const agent = createReceptionistAgent({
- companyName: 'Acme Corporation',
departments: [
- { name: 'Sales', extension: '1001', description: 'New orders' },
- { name: 'Support', extension: '1002' },
+ { name: 'sales', description: 'Orders', number: '+15551001001' },
],
});
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/survey-agent.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/survey-agent.mdx
index 9a9bbfcae..835c9ce00 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/survey-agent.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/prefabs/survey-agent.mdx
@@ -19,6 +19,10 @@ const agent = new SurveyAgent({ /* SurveyConfig */ });
## SurveyConfig
+
+ Human-readable survey name used in prompts and global data.
+
+
Ordered list of survey questions. Each `SurveyQuestion` object has:
@@ -26,26 +30,40 @@ const agent = new SurveyAgent({ /* SurveyConfig */ });
- `text` (string, required) -- The question text to ask the caller.
- `type` (string, required) -- One of `"multiple_choice"`, `"open_ended"`, `"rating"`, or `"yes_no"`.
- `options` (string[]) -- Required for `multiple_choice` questions.
+ - `scale` (number, default `5`) -- For `rating` questions, the upper bound of the scale (1..scale).
+ - `required` (boolean, default `true`) -- Whether the question must be answered.
- `nextQuestion` (string | Record<string, string>) -- Next question ID, or a map from answer value to next question ID for branching. If omitted, proceeds in array order.
- `points` (number | Record<string, number>) -- Fixed points for any answer, or per-answer scoring map.
-
- Opening message before the first question.
+
+ Opening message before the first question. Defaults to a generic intro.
+
+
+
+ Closing message spoken after the survey completes.
-
- Message after the survey is complete.
+
+ Brand or company name the agent represents. Used in prompt sections.
+
+
+
+ Maximum number of times to retry invalid answers before moving on.
Callback fired when the survey is finished. Receives all responses and the total score.
-
+
Agent display name.
+
+ HTTP route for the agent.
+
+
Additional [`AgentBase`][agentbase] options forwarded to the constructor.
@@ -54,6 +72,8 @@ const agent = new SurveyAgent({ /* SurveyConfig */ });
| Tool | Description | Parameters |
|------|-------------|------------|
+| `validate_response` | Validate a response against the question's type and rules without advancing | `question_id` (string), `response` (string) |
+| `log_response` | Log a validated response to the session without scoring or advancing | `question_id` (string), `response` (string) |
| `answer_question` | Record the caller's answer, validate it, apply scoring, and advance to the next question | `question_id` (string), `answer` (string) |
| `get_current_question` | Get the current question that should be asked | (none) |
| `get_survey_progress` | Get progress stats: questions answered, total score, and answer history | (none) |
@@ -73,8 +93,10 @@ for any answer. A `Record` awards different points per answer va
import { SurveyAgent } from '@signalwire/sdk';
const agent = new SurveyAgent({
- introMessage: 'Thank you for purchasing our product. We\'d love your feedback!',
- completionMessage: 'Thanks for your time. Your feedback helps us improve!',
+ surveyName: 'Product Feedback',
+ brandName: 'Acme Corporation',
+ introduction: 'Thank you for purchasing our product. We\'d love your feedback!',
+ conclusion: 'Thanks for your time. Your feedback helps us improve!',
questions: [
{
id: 'overall_rating',
@@ -125,6 +147,7 @@ agent.serve();
import { createSurveyAgent } from '@signalwire/sdk';
const agent = createSurveyAgent({
+ surveyName: 'Quick Feedback',
questions: [
{ id: 'q1', text: 'How was your experience?', type: 'rating' },
{ id: 'q2', text: 'Any comments?', type: 'open_ended' },
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/define-tool.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/define-tool.mdx
new file mode 100644
index 000000000..706ccea10
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/define-tool.mdx
@@ -0,0 +1,79 @@
+---
+title: "defineTool"
+slug: /reference/typescript/agents/skill-base/define-tool
+description: "Imperatively register a tool with this skill."
+max-toc-depth: 3
+---
+
+[ref-gettools]: /docs/server-sdks/reference/typescript/agents/skill-base/get-tools
+
+Imperatively register a SWAIG tool with this skill. The tool definition is
+merged with the skill's `swaigFields` (explicit fields on `toolDef` take
+precedence) and then appended to the internal dynamic tool list. The default
+[`getTools()`][ref-gettools] implementation returns these dynamic tools at
+SWML render time.
+
+
+Use `defineTool()` from `setup()` when the tool shape depends on config
+evaluated at setup time (e.g., an API key that changes the available
+actions). Skills with a static tool list should override `getTools()`
+directly instead.
+
+
+## **Parameters**
+
+
+ The tool definition. Must include at minimum `name`, `description`,
+ `parameters`, and `handler`.
+
+
+
+
+ Tool name exposed to the AI.
+
+
+
+ One-sentence summary the AI sees when choosing whether to call the tool.
+
+
+
+ JSON-Schema-style parameter description.
+
+
+
+ Async function invoked when the AI calls the tool.
+
+
+
+ When `true`, the tool requires signed tokens for invocation.
+
+
+
+## **Returns**
+
+`void`
+
+## **Example**
+
+```typescript {9-17}
+import { SkillBase, FunctionResult } from '@signalwire/sdk';
+
+export class TimeSkill extends SkillBase {
+ static SKILL_NAME = 'time';
+ static SKILL_DESCRIPTION = 'Tells the current time.';
+
+ async setup(): Promise {
+ const timezone = this.getConfig('timezone', 'UTC');
+ this.defineTool({
+ name: 'get_time',
+ description: `Get the current time in ${timezone}.`,
+ parameters: { type: 'object', properties: {} },
+ handler: async () => {
+ const now = new Date().toLocaleString('en-US', { timeZone: timezone });
+ return new FunctionResult().setResponse(`It's ${now}`);
+ },
+ });
+ return true;
+ }
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-agent.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-agent.mdx
new file mode 100644
index 000000000..097d2658e
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-agent.mdx
@@ -0,0 +1,40 @@
+---
+title: "getAgent"
+slug: /reference/typescript/agents/skill-base/get-agent
+description: "Get the agent this skill is attached to."
+max-toc-depth: 3
+---
+
+[ref-setagent]: /docs/server-sdks/reference/typescript/agents/skill-base/set-agent
+
+Get the [`AgentBase`](/docs/server-sdks/reference/typescript/agents/agent-base)
+that owns this skill instance. Called internally from `setup()` and tool
+handlers to interact with the agent's configuration, tools, or global data.
+
+
+Throws `Error` when called before the skill has been attached. The
+`SkillManager` calls [`setAgent()`][ref-setagent] as part of
+`addSkill()`; only call `getAgent()` from `setup()` or tool handlers where
+attachment is guaranteed.
+
+
+## **Returns**
+
+`AgentBase` -- the owning agent.
+
+## **Example**
+
+```typescript {9}
+import { SkillBase } from '@signalwire/sdk';
+
+export class MySkill extends SkillBase {
+ static SKILL_NAME = 'my-skill';
+ static SKILL_DESCRIPTION = 'An example skill';
+
+ async setup(): Promise {
+ const agent = this.getAgent();
+ agent.addHint('Prefer concise answers.');
+ return true;
+ }
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-config.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-config.mdx
new file mode 100644
index 000000000..d9de5474c
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-config.mdx
@@ -0,0 +1,44 @@
+---
+title: "getConfig"
+slug: /reference/typescript/agents/skill-base/get-config
+description: "Look up a configuration value passed to the skill's constructor."
+max-toc-depth: 3
+---
+
+Look up a configuration value by key, with an optional default. The `config`
+object is whatever was passed to the skill's constructor (typed as
+`SkillConfig`, a string-keyed record). Values are returned as-is; the caller
+provides the type argument for casting.
+
+## **Parameters**
+
+
+ The configuration key to look up.
+
+
+
+ Value to return when the key is not present. The result is cast to `T`.
+
+
+## **Returns**
+
+`T` -- the configured value cast to the generic type, or the default value.
+
+## **Example**
+
+```typescript {9,10}
+import { SkillBase } from '@signalwire/sdk';
+
+export class WeatherSkill extends SkillBase {
+ static SKILL_NAME = 'weather';
+ static SKILL_DESCRIPTION = 'Fetches current weather for a city.';
+
+ async setup(): Promise {
+ const apiKey = this.getConfig('api_key');
+ const units = this.getConfig<'metric' | 'imperial'>('units', 'metric');
+ if (!apiKey) return false;
+ this.logger.info(`Weather skill configured in ${units} units`);
+ return true;
+ }
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-data-map-tools.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-data-map-tools.mdx
new file mode 100644
index 000000000..0dffa9743
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-data-map-tools.mdx
@@ -0,0 +1,43 @@
+---
+title: "getDataMapTools"
+slug: /reference/typescript/agents/skill-base/get-data-map-tools
+description: Return fully-built SWAIG function dicts (DataMap-style tools).
+max-toc-depth: 3
+---
+
+[ref-skillbase]: /docs/server-sdks/reference/typescript/agents/skill-base
+[ref-datamap]: /docs/server-sdks/reference/typescript/agents/data-map
+
+Return fully-built SWAIG function dicts for tools that this skill builds via
+[`DataMap`][ref-datamap] or any other path that produces a complete SWAIG
+function object (rather than a `SkillToolDefinition` handled by the default
+tool pipeline).
+
+When a skill is added to an agent, `AgentBase.addSkill()` iterates the result
+and registers each entry via `registerSwaigFunction`.
+
+Default returns `[]`. Skills that only use the declarative `getTools()` path
+do not need to override this method.
+
+## **Returns**
+
+`Record[]` — array of pre-built SWAIG function dicts.
+
+## **Example**
+
+```typescript {6-10}
+import { SkillBase, DataMap } from '@signalwire/sdk';
+
+class LookupSkill extends SkillBase {
+ static override SKILL_NAME = 'lookup';
+ static override SKILL_DESCRIPTION = 'Server-side lookup via DataMap';
+
+ override getDataMapTools(): Record[] {
+ const dm = new DataMap('do_lookup')
+ .description('Look up a value by id')
+ .parameter('id', 'string', 'Record id', { required: true })
+ .webhook('GET', 'https://api.example.com/lookup/${args.id}');
+ return [dm.toSwaigFunction()];
+ }
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-hints.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-hints.mdx
index 140a36d89..46bf44901 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-hints.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-hints.mdx
@@ -18,23 +18,16 @@ Takes no parameters.
## **Example**
-```typescript {17}
-import { SkillBase, SkillManifest, SkillToolDefinition } from '@signalwire/sdk';
+```typescript {9}
+import { SkillBase, type SkillToolDefinition } from '@signalwire/sdk';
class WeatherSkill extends SkillBase {
- constructor(config?: Record) {
- super('weather', config);
- }
-
- getManifest(): SkillManifest {
- return { name: 'weather', description: 'Provides weather information', version: '1.0.0' };
- }
+ static override SKILL_NAME = 'weather';
+ static override SKILL_DESCRIPTION = 'Provides weather information';
- getTools(): SkillToolDefinition[] {
- return [];
- }
+ override getTools(): SkillToolDefinition[] { return []; }
- getHints(): string[] {
+ override getHints(): string[] {
return ['weather', 'temperature', 'forecast', 'humidity', 'wind speed'];
}
}
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-parameter-schema.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-parameter-schema.mdx
index 8ee4cd8f2..ba8a1fb58 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-parameter-schema.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-parameter-schema.mdx
@@ -32,15 +32,14 @@ and values describe the parameter.
## **Example**
-```typescript {8}
-import { SkillBase, SkillManifest, SkillToolDefinition, ParameterSchemaEntry } from '@signalwire/sdk';
+```typescript {7}
+import { SkillBase, type SkillToolDefinition, type ParameterSchemaEntry } from '@signalwire/sdk';
class WeatherSkill extends SkillBase {
- constructor(config?: Record) {
- super('weather', config);
- }
+ static override SKILL_NAME = 'weather';
+ static override SKILL_DESCRIPTION = 'Provides weather information';
- static getParameterSchema(): Record {
+ static override getParameterSchema(): Record {
return {
...super.getParameterSchema(),
units: {
@@ -59,11 +58,7 @@ class WeatherSkill extends SkillBase {
};
}
- getManifest(): SkillManifest {
- return { name: 'weather', description: 'Provides weather information', version: '1.0.0' };
- }
-
- getTools(): SkillToolDefinition[] {
+ override getTools(): SkillToolDefinition[] {
return [];
}
}
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-prompt-sections.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-prompt-sections.mdx
index 82f0cde40..5a83b9feb 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-prompt-sections.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-prompt-sections.mdx
@@ -22,23 +22,18 @@ and either a `body` string or a `bullets` array. An optional `numbered` boolean
## **Example**
-```typescript {17}
-import { SkillBase, SkillManifest, SkillToolDefinition, SkillPromptSection } from '@signalwire/sdk';
+```typescript {11}
+import { SkillBase, type SkillToolDefinition, type SkillPromptSection } from '@signalwire/sdk';
class WeatherSkill extends SkillBase {
- constructor(config?: Record) {
- super('weather', config);
- }
-
- getManifest(): SkillManifest {
- return { name: 'weather', description: 'Provides weather information', version: '1.0.0' };
- }
+ static override SKILL_NAME = 'weather';
+ static override SKILL_DESCRIPTION = 'Provides weather information';
- getTools(): SkillToolDefinition[] {
+ override getTools(): SkillToolDefinition[] {
return [];
}
- protected _getPromptSections(): SkillPromptSection[] {
+ protected override _getPromptSections(): SkillPromptSection[] {
return [
{
title: 'Weather Information',
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-tools.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-tools.mdx
new file mode 100644
index 000000000..d5bada4af
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/get-tools.mdx
@@ -0,0 +1,68 @@
+---
+title: "getTools"
+slug: /reference/typescript/agents/skill-base/get-tools
+description: Return the SWAIG tool definitions this skill exposes.
+max-toc-depth: 3
+---
+
+[ref-skillbase]: /docs/server-sdks/reference/typescript/agents/skill-base
+
+Return the SWAIG tool definitions this skill exposes. Called by the
+`SkillManager` at SWML render time to collect every tool that should appear in
+the agent's SWAIG block.
+
+The default implementation returns tools registered imperatively via
+`defineTool()`. Skills that build their tool list declaratively should
+override this method to return a static array.
+
+
+This replaces the Python `register_tools()` abstract method. TS uses a pull
+model: you return the list, rather than calling back into the agent once per
+tool.
+
+
+## **Returns**
+
+`SkillToolDefinition[]` — array of tool definitions.
+
+## **Example — declarative override**
+
+```typescript {8-17}
+import { SkillBase, type SkillToolDefinition } from '@signalwire/sdk';
+
+class WeatherSkill extends SkillBase {
+ static override SKILL_NAME = 'weather';
+ static override SKILL_DESCRIPTION = 'Provides weather information';
+
+ override getTools(): SkillToolDefinition[] {
+ return [{
+ name: 'get_weather',
+ description: 'Get current weather for a location',
+ parameters: {
+ location: { type: 'string', description: 'City name' },
+ },
+ required: ['location'],
+ handler: async (args) => ({ response: `Weather in ${args.location}: sunny, 72F` }),
+ }];
+ }
+}
+```
+
+## **Example — imperative via defineTool()**
+
+```typescript {5-13}
+class ConfigurableSkill extends SkillBase {
+ static override SKILL_NAME = 'configurable';
+ static override SKILL_DESCRIPTION = 'Tools depend on config';
+
+ override async setup(): Promise {
+ this.defineTool({
+ name: this.getConfig('tool_name', 'run'),
+ description: this.getConfig('description', 'Run the action'),
+ parameters: {},
+ handler: async () => ({ response: 'done' }),
+ });
+ return true;
+ }
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/has-all-env-vars.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/has-all-env-vars.mdx
new file mode 100644
index 000000000..a5307e5d4
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/has-all-env-vars.mdx
@@ -0,0 +1,37 @@
+---
+title: "hasAllEnvVars"
+slug: /reference/typescript/agents/skill-base/has-all-env-vars
+description: "Check whether all required environment variables are set."
+max-toc-depth: 3
+---
+
+[ref-validateenvvars]: /docs/server-sdks/reference/typescript/agents/skill-base/validate-env-vars
+
+Convenience wrapper around
+[`validateEnvVars()`][ref-validateenvvars] that returns a boolean. Mirrors the
+Python SDK's `validate_env_vars() -> bool` return shape. Checks each entry in
+the skill class's `REQUIRED_ENV_VARS` static array against `process.env`.
+
+## **Returns**
+
+`boolean` -- `true` if every required env var is present, `false` otherwise.
+
+## **Example**
+
+```typescript {10}
+import { SkillBase } from '@signalwire/sdk';
+
+export class WeatherSkill extends SkillBase {
+ static SKILL_NAME = 'weather';
+ static SKILL_DESCRIPTION = 'Fetches current weather.';
+ static REQUIRED_ENV_VARS = ['WEATHER_API_KEY'];
+
+ async setup(): Promise {
+ if (!this.hasAllEnvVars()) {
+ this.logger.error('Missing required environment variables');
+ return false;
+ }
+ return true;
+ }
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/has-all-packages.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/has-all-packages.mdx
new file mode 100644
index 000000000..dc06017f1
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/has-all-packages.mdx
@@ -0,0 +1,38 @@
+---
+title: "hasAllPackages"
+slug: /reference/typescript/agents/skill-base/has-all-packages
+description: "Check whether all required packages are importable."
+max-toc-depth: 3
+---
+
+[ref-validatepackages]: /docs/server-sdks/reference/typescript/agents/skill-base/validate-packages
+
+Convenience wrapper around
+[`validatePackages()`][ref-validatepackages] that returns a boolean. Mirrors
+the Python SDK's `validate_packages() -> bool` return shape. Because it
+performs dynamic `import()` calls, the method is async.
+
+## **Returns**
+
+`Promise` -- `true` if every package in `REQUIRED_PACKAGES` imports
+successfully, `false` otherwise.
+
+## **Example**
+
+```typescript {9}
+import { SkillBase } from '@signalwire/sdk';
+
+export class ScraperSkill extends SkillBase {
+ static SKILL_NAME = 'scraper';
+ static SKILL_DESCRIPTION = 'Scrapes web pages.';
+ static REQUIRED_PACKAGES = ['cheerio'];
+
+ async setup(): Promise {
+ if (!(await this.hasAllPackages())) {
+ this.logger.error('Missing required packages');
+ return false;
+ }
+ return true;
+ }
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/index.mdx
index d467a6288..7b1bb318b 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/index.mdx
@@ -7,6 +7,7 @@ max-toc-depth: 3
[agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base
[skills]: /docs/server-sdks/reference/typescript/agents/skills
+[skillregistry]: /docs/server-sdks/reference/typescript/agents/skill-registry
[cleanup]: /docs/server-sdks/reference/typescript/agents/skill-base/cleanup
[getglobaldata]: /docs/server-sdks/reference/typescript/agents/skill-base/get-global-data
[gethints]: /docs/server-sdks/reference/typescript/agents/skill-base/get-hints
@@ -23,22 +24,51 @@ max-toc-depth: 3
SkillBase is the abstract base class for all agent skills. Skills are modular,
reusable capabilities -- such as weather lookup, web search, or calendar access --
-that can be added to any [`AgentBase`][agentbase]
-agent with a single call to `agent.addSkill()`.
+that can be added to any [`AgentBase`][agentbase] agent with a single call to
+`agent.addSkill()`.
-Extend SkillBase to create custom skills. You must implement the abstract methods
-`getManifest()` and `getTools()`, and optionally override lifecycle and prompt methods.
+Extend SkillBase to create custom skills. Metadata (name, description, version,
+required packages, required environment variables, multi-instance support) is
+declared as **static class constants** on the subclass — the [`SkillRegistry`][skillregistry]
+and `SkillManager` read these constants directly. You override `getTools()` to
+expose SWAIG tools and optionally override lifecycle and prompt methods.
For the catalog of built-in skills and their configuration parameters, see
the [Skills][skills] page.
-## **Static Members**
+## **Static Class Constants**
+
+Subclasses declare their identity and requirements by overriding these static
+members. The [`SkillRegistry`][skillregistry] reads them directly — no manifest
+object is exchanged.
+
+
+ Unique skill name used for registration. Subclasses **must** override with a
+ non-empty string; the constructor throws otherwise.
+
+
+
+ Human-readable description. Subclasses **must** override with a non-empty
+ string; the constructor throws otherwise.
+
+
+
+ Semantic version string.
+
+
+
+ NPM packages the skill depends on. Checked at load time by `validatePackages()`.
+
+
+
+ Environment variables the skill requires. Checked at load time by `validateEnvVars()`.
+
When `true`, the same skill can be added to an agent multiple times with
- different configurations.
+ different configurations (distinguished by `tool_name`).
@@ -49,21 +79,22 @@ the [Skills][skills] page.
## **Constructor**
```typescript {1}
-constructor(skillName: string, config?: SkillConfig)
+constructor(config?: SkillConfig)
```
-
- Unique identifier for the skill (e.g., `"weather"`, `"web_search"`).
-
+The skill name, description, and version come from the subclass's static
+constants — not from constructor arguments.
- Optional configuration key-value pairs for the skill instance.
+ Optional configuration key-value pairs for the skill instance. Any
+ `swaig_fields` entry is extracted and automatically merged into tool
+ definitions.
## **Instance Properties**
- The registered name for this skill instance (readonly).
+ The registered name for this skill instance, copied from `SKILL_NAME` (readonly).
@@ -83,11 +114,17 @@ constructor(skillName: string, config?: SkillConfig)
- Initialize the skill and prepare resources.
+ Initialize the skill. Return `false` to fail-closed on missing config.
Release resources when the skill is removed or the agent shuts down.
+
+ Return SWAIG tool definitions this skill exposes.
+
+
+ Return fully-built SWAIG function dicts (DataMap style).
+
Return metadata about all parameters the skill accepts.
@@ -121,25 +158,40 @@ constructor(skillName: string, config?: SkillConfig)
Validate that required environment variables are set.
+
+ Check whether all required env vars are present.
+
+
+ Validate that required packages can be imported.
+
+
+ Check whether all required packages are importable.
+
+
+ Look up a configuration value by key.
+
+
+ Get the agent this skill is attached to.
+
+
+ Attach the skill to an agent.
+
+
+ Imperatively register a tool with this skill.
+
-### getManifest (abstract)
-
-```typescript {1}
-abstract getManifest(): SkillManifest
-```
-
-Returns the skill's metadata including name, description, version, required environment
-variables, and required packages. You **must** implement this in every subclass.
-
-### getTools (abstract)
+### defineTool (protected)
```typescript {1}
-abstract getTools(): SkillToolDefinition[]
+protected defineTool(toolDef: SkillToolDefinition): void
```
-Returns the SWAIG tool definitions this skill provides. You **must** implement this
-in every subclass. Each tool is registered with the agent when the skill is loaded.
+Imperatively register a tool. Use from `setup()` when the tool shape depends on
+config evaluated at runtime. The method merges `this.swaigFields` into the
+definition and pushes it onto the internal dynamic-tools list; the default
+`getTools()` returns that list. Skills with a static tool list should override
+`getTools()` directly instead.
### getConfig
@@ -147,8 +199,7 @@ in every subclass. Each tool is registered with the agent when the skill is load
getConfig(key: string, defaultValue?: T): T
```
-Read a configuration value by key, with an optional fallback default. Returns the
-value cast to type `T`, or `defaultValue` if the key is not present.
+Read a configuration value by key, with an optional fallback default.
The configuration key to look up.
@@ -158,23 +209,28 @@ value cast to type `T`, or `defaultValue` if the key is not present.
Value to return if the key is not present in the config.
+### hasAllEnvVars / hasAllPackages
+
+```typescript {1-2}
+hasAllEnvVars(): boolean
+async hasAllPackages(): Promise
+```
+
+Boolean wrappers around `validateEnvVars()` and `validatePackages()`.
+
## **Examples**
### Custom skill
-```typescript {3}
-import { SkillBase, SkillManifest, SkillToolDefinition } from '@signalwire/sdk';
+```typescript {4-6}
+import { SkillBase, type SkillToolDefinition } from '@signalwire/sdk';
class MyWeatherSkill extends SkillBase {
- constructor(config?: Record) {
- super('my_weather', config);
- }
-
- getManifest(): SkillManifest {
- return { name: 'my_weather', description: 'Look up weather', version: '1.0.0' };
- }
+ static override SKILL_NAME = 'my_weather';
+ static override SKILL_DESCRIPTION = 'Look up weather';
+ static override SKILL_VERSION = '1.0.0';
- getTools(): SkillToolDefinition[] {
+ override getTools(): SkillToolDefinition[] {
return [{
name: 'get_weather',
description: 'Get current weather for a city',
@@ -191,12 +247,11 @@ class MyWeatherSkill extends SkillBase {
import { AgentBase } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'weather-agent' });
-agent.setPromptText("You are a helpful assistant.")
-agent.addSkill("weather")
+agent.setPromptText("You are a helpful assistant.");
+agent.addSkill("weather");
// Or with custom configuration
-agent.addSkill("weather", { units: "celsius" })
+agent.addSkill("weather", { units: "celsius" });
-// Entry point
-agent.run()
+agent.run();
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/set-agent.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/set-agent.mdx
new file mode 100644
index 000000000..19cb6332f
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/set-agent.mdx
@@ -0,0 +1,42 @@
+---
+title: "setAgent"
+slug: /reference/typescript/agents/skill-base/set-agent
+description: "Attach the skill to an agent (called by the SkillManager)."
+max-toc-depth: 3
+---
+
+[ref-getagent]: /docs/server-sdks/reference/typescript/agents/skill-base/get-agent
+[ref-skillmanager]: /docs/server-sdks/reference/typescript/agents/skill-manager
+
+Attach this skill to an [`AgentBase`](/docs/server-sdks/reference/typescript/agents/agent-base).
+Called by the [`SkillManager`][ref-skillmanager] during
+`agent.addSkill()` before `setup()` runs, so [`getAgent()`][ref-getagent] is
+safe from within `setup()` and tool handlers.
+
+
+Normally not called directly. If you are implementing a custom skill loader
+that bypasses `addSkill()`, call this yourself before invoking `setup()`.
+
+
+## **Parameters**
+
+
+ The agent instance that owns this skill.
+
+
+## **Returns**
+
+`void`
+
+## **Example**
+
+```typescript {7}
+import { AgentBase, SkillBase } from '@signalwire/sdk';
+
+class InlineSkill extends SkillBase { /* ... */ }
+
+const agent = new AgentBase({ name: 'demo' });
+const skill = new InlineSkill();
+skill.setAgent(agent);
+await skill.setup();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/setup.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/setup.mdx
index 31c920ae3..7f55c066e 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/setup.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/setup.mdx
@@ -1,31 +1,45 @@
---
title: "setup"
slug: /reference/typescript/agents/skill-base/setup
-description: Initialize the skill and prepare resources.
+description: Initialize the skill and prepare resources. Return false to fail closed.
max-toc-depth: 3
---
[ref-skillbase]: /docs/server-sdks/reference/typescript/agents/skill-base
+[ref-addskill]: /docs/server-sdks/reference/typescript/agents/skill-manager/add-skill
Initialize the skill: validate environment variables, initialize API clients, and
-prepare resources. Called once when the skill is loaded.
+prepare resources. Called once when the skill is loaded, before any tool
+registration.
-This is a concrete method with a default no-op implementation. Override it in your
-[SkillBase][ref-skillbase] subclass if you need initialization logic.
+This is a concrete method with a default that returns `true`. Override it in
+your [SkillBase][ref-skillbase] subclass when you need initialization logic or
+need to short-circuit loading on invalid config.
+
+
+Returning `false` from `setup()` causes [`SkillManager.addSkill()`][ref-addskill]
+(and `AgentBase.addSkill()`) to **fail closed**: the skill is not registered
+and the call throws. This matches the Python SDK's behavior — never silently
+continue with a half-initialized skill.
+
Takes no parameters.
## **Returns**
-`Promise`
+`Promise` — `true` on success, `false` to signal that the skill
+cannot be loaded (invalid config, missing credentials, failed handshake, etc.).
## **Example**
-```typescript {2}
+```typescript {2-9}
class MySkill extends SkillBase {
- async setup(): Promise {
- // Initialize API connections, validate config
- console.log('Skill setup complete');
+ override async setup(): Promise {
+ if (!this.hasAllEnvVars()) return false;
+ const missing = await this.validatePackages();
+ if (missing.length) return false;
+ // Initialize API connections here
+ return true;
}
}
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/validate-packages.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/validate-packages.mdx
new file mode 100644
index 000000000..317776c15
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-base/validate-packages.mdx
@@ -0,0 +1,46 @@
+---
+title: "validatePackages"
+slug: /reference/typescript/agents/skill-base/validate-packages
+description: "Validate that all required packages can be imported."
+max-toc-depth: 3
+---
+
+[ref-hasallpackages]: /docs/server-sdks/reference/typescript/agents/skill-base/has-all-packages
+
+Attempt to `import()` every package listed in the skill class's
+`REQUIRED_PACKAGES` static array. Returns the list of packages that failed to
+import (empty array means everything is available). Python parity:
+`validate_packages()` at `core/skill_base.py:112-124`.
+
+Logs an error listing every missing package when the result is non-empty.
+
+
+For a boolean check, use [`hasAllPackages()`][ref-hasallpackages]. Because
+the TS version uses dynamic `import()`, this method is async.
+
+
+## **Returns**
+
+`Promise` -- array of package names that failed to import. Empty when
+all packages are available.
+
+## **Example**
+
+```typescript {9}
+import { SkillBase } from '@signalwire/sdk';
+
+export class ScraperSkill extends SkillBase {
+ static SKILL_NAME = 'scraper';
+ static SKILL_DESCRIPTION = 'Scrapes web pages.';
+ static REQUIRED_PACKAGES = ['cheerio'];
+
+ async setup(): Promise {
+ const missing = await this.validatePackages();
+ if (missing.length > 0) {
+ this.logger.error(`Install: npm install ${missing.join(' ')}`);
+ return false;
+ }
+ return true;
+ }
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/add-skill.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/add-skill.mdx
index b047144c4..0bd8332df 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/add-skill.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/add-skill.mdx
@@ -1,14 +1,28 @@
---
title: "addSkill"
slug: /reference/typescript/agents/skill-manager/add-skill
-description: "Add and initialize a skill instance."
+description: "Add and initialize a skill instance. Fails closed on invalid config."
---
[ref-skillbase]: /docs/server-sdks/reference/typescript/agents/skill-base
+[ref-setup]: /docs/server-sdks/reference/typescript/agents/skill-base/setup
-Add a skill to the manager. Validates env vars, calls `setup()`, and marks
-the skill as initialized. Throws `Error` if a duplicate non-multi-instance
-skill is added.
+Add a skill to the manager. The call sequence is:
+
+1. Deduplicate by instance key (multi-instance skills with the same key are
+ skipped with a warning; single-instance duplicates throw).
+2. Validate required environment variables — throws if any are missing.
+3. Validate that the skill's `getParameterSchema()` returns a non-empty object.
+4. Validate required NPM packages — throws if any cannot be imported.
+5. Call [`setup()`][ref-setup] — **throws if it returns `false`**.
+6. Mark the skill initialized and register it.
+
+
+`addSkill` **fails closed**: any validation miss or a `setup()` returning
+`false` throws and the skill is not registered. The wrapper methods
+`loadSkill` / `loadSkillByName` catch and convert the throw into a
+`[false, message]` tuple that matches the Python SDK's `load_skill` contract.
+
## **Parameters**
@@ -19,3 +33,11 @@ skill is added.
## **Returns**
`Promise`
+
+## **Throws**
+
+- `Error` — duplicate single-instance skill already loaded.
+- `Error` — missing required environment variables.
+- `Error` — `getParameterSchema()` returns an empty object.
+- `Error` — missing required NPM packages.
+- `Error` — `setup()` returned `false`.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/has-skill-by-key.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/has-skill-by-key.mdx
new file mode 100644
index 000000000..524b8a9df
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/has-skill-by-key.mdx
@@ -0,0 +1,19 @@
+---
+title: "hasSkillByKey"
+slug: /reference/typescript/agents/skill-manager/has-skill-by-key
+description: "Check if a skill with the given instance key is loaded."
+---
+
+Direct map lookup by instance key (matches Python's `has_skill(skill_identifier)`
+semantics). Use `hasSkill(name)` to search by skill name instead.
+
+## **Parameters**
+
+
+ The instance key to look up (e.g., `"weather"` for single-instance skills, or
+ `"weather_forecast"` for a multi-instance skill keyed by `tool_name`).
+
+
+## **Returns**
+
+`boolean`
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/index.mdx
index 7e9b1f79f..26766dee2 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/index.mdx
@@ -32,7 +32,13 @@ Most users should use `AgentBase.addSkill()`, `AgentBase.removeSkill()`, and
- Add and initialize a skill instance.
+ Add and initialize a skill instance (fails closed).
+
+
+ Instantiate a skill class and add it; returns [ok, error].
+
+
+ Look up a skill by name in the global registry and add it.
Remove a skill by key or ID.
@@ -41,7 +47,13 @@ Most users should use `AgentBase.addSkill()`, `AgentBase.removeSkill()`, and
Remove all instances of a named skill.
- Check if a skill is loaded.
+ Check if any skill with the given name is loaded.
+
+
+ Check if a skill with the given instance key is loaded.
+
+
+ List instance keys of all loaded skills.
Get a skill instance by key or ID.
@@ -67,6 +79,9 @@ Most users should use `AgentBase.addSkill()`, `AgentBase.removeSkill()`, and
Remove all skills.
+
+ Read-only map of loaded skill instances (getter).
+
## **Example**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/list-skill-keys.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/list-skill-keys.mdx
new file mode 100644
index 000000000..d84e2fe2c
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/list-skill-keys.mdx
@@ -0,0 +1,12 @@
+---
+title: "listSkillKeys"
+slug: /reference/typescript/agents/skill-manager/list-skill-keys
+description: "List instance keys of all currently loaded skills."
+---
+
+Matches Python's `list_loaded_skills() -> List[str]`. Use `listSkills()` for
+richer objects (name, instanceId, initialized flag).
+
+## **Returns**
+
+`string[]` — array of instance key strings.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/load-skill-by-name.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/load-skill-by-name.mdx
new file mode 100644
index 000000000..9cbfb95de
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/load-skill-by-name.mdx
@@ -0,0 +1,35 @@
+---
+title: "loadSkillByName"
+slug: /reference/typescript/agents/skill-manager/load-skill-by-name
+description: "Look up a skill class in the global registry by name and load it."
+---
+
+[ref-addskill]: /docs/server-sdks/reference/typescript/agents/skill-manager/add-skill
+[ref-registry]: /docs/server-sdks/reference/typescript/agents/skill-registry
+
+Look up a registered skill class by name in the global
+[`SkillRegistry`][ref-registry], construct an instance, and add it via
+[`addSkill`][ref-addskill]. Returns `[false, message]` if the name is not
+registered, the instantiation fails, or `addSkill` throws.
+
+## **Parameters**
+
+
+ Registered skill name (read from the target class's `SKILL_NAME`).
+
+
+
+ Optional configuration forwarded to the skill constructor.
+
+
+## **Returns**
+
+`Promise<[boolean, string]>` — `[true, '']` on success, `[false, errorMessage]`
+otherwise.
+
+## **Example**
+
+```typescript {1}
+const [ok, err] = await agent.skillManager.loadSkillByName('datetime');
+if (!ok) throw new Error(err);
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/load-skill.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/load-skill.mdx
new file mode 100644
index 000000000..afec519da
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/load-skill.mdx
@@ -0,0 +1,37 @@
+---
+title: "loadSkill"
+slug: /reference/typescript/agents/skill-manager/load-skill
+description: "Instantiate a skill class and add it; returns a [success, error] tuple."
+---
+
+[ref-addskill]: /docs/server-sdks/reference/typescript/agents/skill-manager/add-skill
+[ref-skillbase]: /docs/server-sdks/reference/typescript/agents/skill-base
+
+Construct a skill instance from the provided class and add it via
+[`addSkill`][ref-addskill]. Catches any throw from `addSkill` and returns a
+`[success, errorMessage]` tuple — matching the Python SDK's `load_skill`
+return contract.
+
+## **Parameters**
+
+
+ A concrete subclass of [`SkillBase`][ref-skillbase].
+
+
+
+ Optional configuration forwarded to the skill constructor.
+
+
+## **Returns**
+
+`Promise<[boolean, string]>` — `[true, '']` on success, `[false, errorMessage]`
+on any validation or setup failure.
+
+## **Example**
+
+```typescript {3}
+import { MyCustomSkill } from './my-skill.js';
+
+const [ok, err] = await agent.skillManager.loadSkill(MyCustomSkill, { api_key: 'secret' });
+if (!ok) console.error(err);
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/loaded-skills.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/loaded-skills.mdx
new file mode 100644
index 000000000..4d3d40432
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-manager/loaded-skills.mdx
@@ -0,0 +1,43 @@
+---
+title: "loadedSkills"
+slug: /reference/typescript/agents/skill-manager/loaded-skills
+description: "Read-only view of all loaded skill instances keyed by instance key."
+max-toc-depth: 3
+---
+
+[ref-listskillkeys]: /docs/server-sdks/reference/typescript/agents/skill-manager/list-skill-keys
+[ref-getskill]: /docs/server-sdks/reference/typescript/agents/skill-manager/get-skill
+
+Read-only getter exposing every loaded skill instance keyed by its instance
+key (e.g., `"weather"` or `"weather#main_tool"` for multi-instance skills).
+Use this to iterate or inspect loaded skills without mutating the internal
+map.
+
+Python equivalent: `self.loaded_skills` (public `Dict[str, SkillBase]`).
+
+
+The returned `ReadonlyMap` is a live view of the internal map, not a copy.
+Iterating concurrently with `addSkill()` / `removeSkill()` can see updates
+as they happen. For a snapshot of skill keys, use
+[`listSkillKeys()`][ref-listskillkeys]; for a single lookup, use
+[`getSkill()`][ref-getskill].
+
+
+## **Type**
+
+`ReadonlyMap`
+
+## **Example**
+
+```typescript {5}
+import { AgentBase } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'demo' });
+await agent.addSkillByName('weather');
+await agent.addSkillByName('datetime');
+
+const manager = agent.getSkillManager();
+for (const [key, skill] of manager.loadedSkills) {
+ console.log(`${key} -> ${(skill.constructor as typeof skill).SKILL_NAME}`);
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/get-manifest.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/get-manifest.mdx
deleted file mode 100644
index a2f52b74c..000000000
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/get-manifest.mdx
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: "getManifest"
-slug: /reference/typescript/agents/skill-registry/get-manifest
-description: "Get the manifest for a registered skill."
----
-
-Get the manifest for a registered skill, if available.
-
-## **Parameters**
-
-
- The skill name to look up.
-
-
-## **Returns**
-
-`SkillManifest | undefined`
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/get-skill-class.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/get-skill-class.mdx
new file mode 100644
index 000000000..a5fef61a8
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/get-skill-class.mdx
@@ -0,0 +1,42 @@
+---
+title: "getSkillClass"
+slug: /reference/typescript/agents/skill-registry/get-skill-class
+description: "Look up a registered skill class by name."
+max-toc-depth: 3
+---
+
+[ref-create]: /docs/server-sdks/reference/typescript/agents/skill-registry/create
+[ref-has]: /docs/server-sdks/reference/typescript/agents/skill-registry/has
+
+Look up a registered skill class by its `SKILL_NAME`. Returns the class
+reference itself (not an instance); use
+[`create()`][ref-create] to get an instance. Returns `undefined` if no skill
+is registered under that name -- for a boolean check use
+[`has()`][ref-has].
+
+Matches Python's `get_skill_class(skill_name)` (`registry.py:196-203`).
+
+## **Parameters**
+
+
+ The registered skill name (the skill class's static `SKILL_NAME`).
+
+
+## **Returns**
+
+`typeof SkillBase | undefined` -- the skill class, or `undefined` if not
+registered.
+
+## **Example**
+
+```typescript {5}
+import { SkillRegistry } from '@signalwire/sdk';
+
+const registry = SkillRegistry.getInstance();
+
+const WeatherSkill = registry.getSkillClass('weather');
+if (WeatherSkill) {
+ console.log(WeatherSkill.SKILL_DESCRIPTION);
+ console.log(WeatherSkill.REQUIRED_ENV_VARS);
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/index.mdx
index a53073915..8887d2936 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/index.mdx
@@ -9,9 +9,10 @@ max-toc-depth: 3
[ref-skills]: /docs/server-sdks/reference/typescript/agents/skills
`SkillRegistry` is a global singleton for registering, discovering, and
-instantiating skills by name. Skills can be registered programmatically or
-auto-discovered from directories via the `SIGNALWIRE_SKILL_PATHS` environment
-variable.
+instantiating skills by class reference. Skills can be registered
+programmatically by passing the class itself (the registry reads metadata from
+static class properties like `SKILL_NAME`), or auto-discovered from
+directories via the `SIGNALWIRE_SKILL_PATHS` environment variable.
```typescript {1}
import { SkillRegistry } from '@signalwire/sdk';
@@ -24,7 +25,7 @@ import { SkillRegistry } from '@signalwire/sdk';
Get the global singleton instance.
- Register a skill factory by name.
+ Register a skill class.
Create a skill instance from the registry.
@@ -41,12 +42,6 @@ import { SkillRegistry } from '@signalwire/sdk';
List all registered skill names.
-
- List skills with manifests.
-
-
- Get a skill's manifest.
-
Add a directory for skill discovery.
@@ -71,6 +66,15 @@ import { SkillRegistry } from '@signalwire/sdk';
Remove all registrations.
+
+ Look up a registered skill class by name.
+
+
+ List all registered skills with full metadata.
+
+
+ Reset the global singleton (test helper).
+
## **Properties**
@@ -85,7 +89,7 @@ import { SkillRegistry } from '@signalwire/sdk';
import { SkillRegistry, SkillBase } from '@signalwire/sdk';
const registry = SkillRegistry.getInstance();
-registry.register('my-skill', (config) => new MySkill(config));
+registry.register(MySkill); // class reference — name read from MySkill.SKILL_NAME
console.log(registry.listRegistered()); // ['my-skill', ...]
// Create an instance from the registry
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/list-registered-with-manifests.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/list-registered-with-manifests.mdx
deleted file mode 100644
index 1053f4bab..000000000
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/list-registered-with-manifests.mdx
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "listRegisteredWithManifests"
-slug: /reference/typescript/agents/skill-registry/list-registered-with-manifests
-description: "List all registered skills with their manifests."
----
-
-List all registered skills with their optional manifests.
-
-## **Parameters**
-
-None.
-
-## **Returns**
-
-`{ name: string; manifest?: SkillManifest }[]`
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/list-skills.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/list-skills.mdx
new file mode 100644
index 000000000..44fef9af5
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/list-skills.mdx
@@ -0,0 +1,69 @@
+---
+title: "listSkills"
+slug: /reference/typescript/agents/skill-registry/list-skills
+description: "List all registered skills with their full metadata."
+max-toc-depth: 3
+---
+
+[ref-listregistered]: /docs/server-sdks/reference/typescript/agents/skill-registry/list-registered
+
+List every registered skill with its full metadata. Each entry includes the
+name, description, version, multi-instance flag, required env vars, required
+packages, and parameter schema. Use [`listRegistered()`][ref-listregistered]
+for just the names.
+
+Matches Python's `list_skills()` shape (`registry.py:205-227`) with
+TS-idiomatic camelCase keys.
+
+## **Returns**
+
+`SkillSchemaInfo[]` -- array of metadata objects.
+
+
+ Each entry has the following shape:
+
+
+
+
+ The skill's `SKILL_NAME`.
+
+
+
+ The skill's `SKILL_DESCRIPTION`.
+
+
+
+ The skill's `SKILL_VERSION`.
+
+
+
+ Whether the skill supports multiple instances.
+
+
+
+ Required environment variable names.
+
+
+
+ Required npm package names.
+
+
+
+ Parameter schema describing the config the skill accepts.
+
+
+
+## **Example**
+
+```typescript {4}
+import { SkillRegistry } from '@signalwire/sdk';
+
+const registry = SkillRegistry.getInstance();
+const skills = registry.listSkills();
+for (const s of skills) {
+ console.log(`${s.name} v${s.version} - ${s.description}`);
+ if (s.requiredEnvVars.length > 0) {
+ console.log(` Needs: ${s.requiredEnvVars.join(', ')}`);
+ }
+}
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/register.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/register.mdx
index 84bc967f3..1053914fc 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/register.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/register.mdx
@@ -1,25 +1,41 @@
---
title: "register"
slug: /reference/typescript/agents/skill-registry/register
-description: "Register a skill factory by name."
+description: "Register a skill class by its static SKILL_NAME."
---
-Register a skill factory by name. Optionally provide a manifest for metadata.
+Register a skill class. The skill name is read from the class's static
+`SKILL_NAME`. The registry validates that `SKILL_NAME` is non-empty and that
+`getParameterSchema()` returns a non-empty object before registering.
## **Parameters**
-
- Unique skill name.
-
-
-
- Factory function `(config?: SkillConfig) => SkillBase` that creates skill instances.
-
-
-
- Optional manifest metadata for the skill.
+
+ A concrete subclass of `SkillBase` with a non-empty static `SKILL_NAME` and
+ a non-empty `getParameterSchema()` return value.
## **Returns**
`void`
+
+## **Throws**
+
+- `Error` if the class has no `SKILL_NAME`.
+- `Error` if `getParameterSchema()` throws or returns an empty object.
+
+Locked skill names (see [`lock`](/docs/server-sdks/reference/typescript/agents/skill-registry/lock))
+are skipped with a warning rather than throwing.
+
+## **Example**
+
+```typescript {5}
+import { SkillRegistry, SkillBase } from '@signalwire/sdk';
+
+class MySkill extends SkillBase {
+ static override SKILL_NAME = 'my-skill';
+ // ...
+}
+
+SkillRegistry.getInstance().register(MySkill);
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/reset-instance.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/reset-instance.mdx
new file mode 100644
index 000000000..aaa181934
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skill-registry/reset-instance.mdx
@@ -0,0 +1,45 @@
+---
+title: "resetInstance"
+slug: /reference/typescript/agents/skill-registry/reset-instance
+description: "Reset the global SkillRegistry singleton (test helper)."
+max-toc-depth: 3
+---
+
+[ref-getinstance]: /docs/server-sdks/reference/typescript/agents/skill-registry/get-instance
+
+Static helper that clears the process-wide `SkillRegistry` singleton. The next
+call to [`getInstance()`][ref-getinstance] constructs a fresh registry with
+no registered skills, cleared search paths, and no locked names.
+
+
+Intended for use in test suites that need a clean registry per test case.
+Calling this in production is almost always a bug -- every previously
+registered skill is forgotten, and any code still holding the old instance
+reference will diverge from the new one.
+
+
+## **Returns**
+
+`void`
+
+## **Example**
+
+```typescript {10}
+import { SkillRegistry } from '@signalwire/sdk';
+
+describe('MySkill', () => {
+ beforeEach(() => {
+ SkillRegistry.resetInstance();
+ const registry = SkillRegistry.getInstance();
+ registry.register(MySkill);
+ });
+
+ afterAll(() => {
+ SkillRegistry.resetInstance();
+ });
+
+ it('registers correctly', () => {
+ expect(SkillRegistry.getInstance().has('my-skill')).toBe(true);
+ });
+});
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/api-ninjas-trivia.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/api-ninjas-trivia.mdx
index a5baba854..4f9657d66 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/api-ninjas-trivia.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/api-ninjas-trivia.mdx
@@ -10,21 +10,34 @@ Fetch trivia questions from the API Ninjas service with optional category filter
**Class:** `ApiNinjasTriviaSkill`
-**Tools:** `get_trivia`
+**Tools:** Configurable via `tool_name` (default `get_trivia`)
**Env vars:** `API_NINJAS_KEY`
+**Multi-instance:** Yes — each instance must use a distinct `tool_name`.
+
+
+ Custom name for the SWAIG trivia tool. Set a distinct value per instance when
+ registering multiple `ApiNinjasTriviaSkill` instances on the same agent.
+
+
API Ninjas API key. Falls back to the `API_NINJAS_KEY` environment variable.
-
- Default trivia category if none is specified by the user. Available categories:
+
+ Subset of trivia categories to enable. Defaults to all 14 supported categories.
+ Values outside the allowed set are filtered out. Available categories:
`artliterature`, `language`, `sciencenature`, `general`, `fooddrink`,
`peopleplaces`, `geography`, `historyholidays`, `entertainment`, `toysgames`,
`music`, `mathematics`, `religionmythology`, `sportsleisure`.
+
+ Default trivia category if none is specified by the user. Must be one of the
+ enabled `categories`.
+
+
Whether to include the answer in the response. When `false`, the AI receives
the answer privately so it can quiz the user.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/ask-claude.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/ask-claude.mdx
index 87e15f084..d3e0d112c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/ask-claude.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/ask-claude.mdx
@@ -16,7 +16,8 @@ sub-tasks that benefit from a dedicated AI query.
**Env vars:** `ANTHROPIC_API_KEY`
- Anthropic API key. Falls back to the `ANTHROPIC_API_KEY` environment variable.
+ Anthropic API key. The handler reads the `ANTHROPIC_API_KEY` environment
+ variable at request time; a config value is not used as a fallback.
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/datasphere-serverless.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/datasphere-serverless.mdx
index 5a1f667a8..0f1ec392b 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/datasphere-serverless.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/datasphere-serverless.mdx
@@ -1,61 +1,97 @@
---
title: "DataSphereServerlessSkill"
slug: /reference/typescript/agents/skills/datasphere-serverless
-description: Search SignalWire DataSphere documents using a DataMap for serverless execution.
+description: Search a SignalWire DataSphere document via a serverless DataMap tool — no agent webhook round-trip.
---
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
[ref-datamap]: /docs/server-sdks/reference/typescript/agents/data-map
-Search SignalWire DataSphere documents using a [DataMap][ref-datamap] for
-serverless execution. Unlike the standard `datasphere` skill, this version
-executes entirely server-side without a webhook round-trip.
+Same DataSphere search as
+[`DataSphereSkill`](/docs/server-sdks/reference/typescript/agents/skills/datasphere),
+but the tool is registered as a [DataMap][ref-datamap] — the SignalWire
+platform executes the search directly, without calling back to your agent
+process.
+
+Credentials and URL are **baked into the DataMap** from config at registration
+time, so the same parameters are required here as on DataSphereSkill.
**Class:** `DataSphereServerlessSkill`
-**Tools:** `search_datasphere`
+**Tools:** Custom per instance via `tool_name` (default `search_knowledge`),
+registered as a DataMap-style SWAIG function.
+
+**Env vars:** None. `space_name`, `project_id`, and `token` must be supplied as
+config values — the serverless build path reads config only, not environment
+variables.
+
+**Multi-instance:** yes
+
+
+ Custom tool name for this instance. Required when registering multiple
+ instances on the same agent.
+
+
+
+ SignalWire space name (e.g., `"mycompany"` from `mycompany.signalwire.com`).
+
+
+
+ SignalWire project ID.
+
-**Env vars:** `SIGNALWIRE_PROJECT_ID`, `SIGNALWIRE_TOKEN`, `SIGNALWIRE_SPACE`
+
+ SignalWire API token.
+
-**Multi-instance:** Yes
+
+ DataSphere document ID to search within.
+
-
- Custom tool name for this instance. Required when using multiple instances.
+
+ Number of results to return (range `1-10`).
-
- SignalWire space name. Falls back to the `SIGNALWIRE_SPACE` environment variable.
+
+ Maximum distance threshold (range `0-10`; lower is more relevant).
-
- SignalWire project ID. Falls back to the `SIGNALWIRE_PROJECT_ID` environment variable.
+
+ Tags to filter results.
-
- SignalWire auth token. Falls back to the `SIGNALWIRE_TOKEN` environment variable.
+
+ Language code for query expansion (e.g., `"en"`, `"es"`).
-
- Restrict search to a specific document ID.
+
+ Parts of speech to expand with synonyms. Entries must be one of `"NOUN"`,
+ `"VERB"`, `"ADJ"`, `"ADV"`.
-
- Maximum number of results to return.
+
+ Maximum number of synonyms used for query expansion (range `1-10`).
-
- Maximum distance threshold for results (0-1, lower is more similar).
+
+ Message returned when no results match the query. Supports a `{query}`
+ placeholder that is substituted with the user's query text at registration
+ time.
-```typescript {6-9}
+## Example
+
+```typescript {6-11}
import { AgentBase, DataSphereServerlessSkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
agent.setPromptText('You are a helpful assistant.');
await agent.addSkill(new DataSphereServerlessSkill({
- document_id: 'YOUR_DOCUMENT_ID',
- max_results: 3,
+ space_name: 'mycompany',
+ document_id: 'doc_1234',
+ count: 3,
+ tool_name: 'search_product_docs',
}));
agent.run();
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/datasphere.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/datasphere.mdx
index 2ec04aea7..ecfd89854 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/datasphere.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/datasphere.mdx
@@ -1,59 +1,90 @@
---
title: "DataSphereSkill"
slug: /reference/typescript/agents/skills/datasphere
-description: Search documents uploaded to SignalWire DataSphere using semantic search.
+description: Search a SignalWire DataSphere knowledge document via the RAG stack.
---
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
-Search documents uploaded to SignalWire DataSphere using semantic search.
-Executes the search via a webhook call from the agent process.
+Search a document uploaded to SignalWire DataSphere using the RAG stack.
+The skill issues the search via a webhook call from the agent process.
+
+Credentials (`space_name`, `project_id`, `token`, `document_id`) are all
+required — `setup()` fails closed if any are missing.
**Class:** `DataSphereSkill`
-**Tools:** `search_datasphere`
+**Tools:** Custom per instance via `tool_name` (default `search_knowledge`)
**Env vars:** `SIGNALWIRE_PROJECT_ID`, `SIGNALWIRE_TOKEN`, `SIGNALWIRE_SPACE`
-**Multi-instance:** Yes
+**Multi-instance:** yes
+
+
+ Custom tool name for this DataSphere instance. Required when registering
+ multiple instances on the same agent.
+
+
+
+ SignalWire space name (e.g., `"mycompany"` from
+ `mycompany.signalwire.com`). Falls back to `SIGNALWIRE_SPACE`.
+
+
+
+ SignalWire project ID. Falls back to `SIGNALWIRE_PROJECT_ID`.
+
+
+
+ SignalWire API token. Falls back to `SIGNALWIRE_TOKEN`.
+
-
- Custom tool name for this instance. Required when using multiple instances.
+
+ DataSphere document ID to search within.
-
- SignalWire space name. Falls back to the `SIGNALWIRE_SPACE` environment variable.
+
+ Number of results to return (range `1-10`).
-
- SignalWire project ID. Falls back to the `SIGNALWIRE_PROJECT_ID` environment variable.
+
+ Maximum distance threshold (range `0-10`; lower is more relevant).
-
- SignalWire auth token. Falls back to the `SIGNALWIRE_TOKEN` environment variable.
+
+ Tags to filter search results.
-
- Restrict search to a specific document ID.
+
+ Language code for query expansion (e.g., `"en"`, `"es"`).
-
- Maximum number of results to return.
+
+ Parts of speech to expand with synonyms. Each entry must be one of
+ `"NOUN"`, `"VERB"`, `"ADJ"`, `"ADV"`.
-
- Maximum distance threshold for results (0-1, lower is more similar).
+
+ Maximum number of synonyms used for query expansion (range `1-10`).
-```typescript {6-9}
+
+ Message returned when no results match the query. Supports a `{query}`
+ placeholder that is substituted with the user's query text.
+
+
+## Example
+
+```typescript {6-11}
import { AgentBase, DataSphereSkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
agent.setPromptText('You are a helpful assistant.');
await agent.addSkill(new DataSphereSkill({
- max_results: 3,
- distance_threshold: 0.5,
+ document_id: 'doc_1234',
+ count: 3,
+ distance: 2.5,
+ tool_name: 'search_product_docs',
}));
agent.run();
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/datetime.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/datetime.mdx
index f78f35e36..21e7b6edd 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/datetime.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/datetime.mdx
@@ -11,7 +11,7 @@ Get the current date and time with optional timezone support.
**Class:** `DateTimeSkill`
-**Tools:** `get_datetime`
+**Tools:** `get_current_time`, `get_current_date`
**Env vars:** None
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/google-maps.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/google-maps.mdx
index 0da4bd17c..45e058a4f 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/google-maps.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/google-maps.mdx
@@ -6,21 +6,42 @@ description: Get driving/walking/transit directions and search for places using
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
-Get driving/walking/transit directions and search for places using Google Maps APIs.
+Get driving/walking/transit directions, find places, geocode addresses, and
+compute routes by coordinates using Google Maps APIs.
**Class:** `GoogleMapsSkill`
-**Tools:** `get_directions`, `find_place`
+**Tools:** `compute_route`, `lookup_address`, `geocode_address`,
+`compute_route_by_coords` (each tool name is configurable).
-**Env vars:** `GOOGLE_MAPS_API_KEY`
+**Env vars:** `GOOGLE_MAPS_API_KEY` (required — the tool handlers read this
+directly and do not fall back to an `api_key` config value).
- Google Maps API key with Directions and Places APIs enabled.
- Falls back to the `GOOGLE_MAPS_API_KEY` environment variable.
+ Schema-level declaration for the Google Maps API key. The tool handlers read
+ the `GOOGLE_MAPS_API_KEY` environment variable at request time; a config
+ value is not used as a fallback.
- Default travel mode: `"driving"`, `"walking"`, `"bicycling"`, or `"transit"`.
+ Default travel mode for `compute_route`: `"driving"`, `"walking"`,
+ `"bicycling"`, or `"transit"`.
+
+
+
+ Custom name for the route computation tool.
+
+
+
+ Custom name for the address / place lookup tool.
+
+
+
+ Custom name for the address-to-coordinates geocode tool.
+
+
+
+ Custom name for the coordinate-based route computation tool.
```typescript {6-8}
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/index.mdx
index a0d9396bf..5bc3957d5 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/index.mdx
@@ -29,7 +29,7 @@ await agent.addSkill(new DateTimeSkill());
// Skill with parameters
await agent.addSkill(new WebSearchSkill({
- max_results: 5,
+ num_results: 5,
safe_search: 'high',
}));
@@ -40,21 +40,21 @@ agent.run();
| Skill | Class | Tools | Env Vars Required | Multi-Instance |
|-------|-------|-------|-------------------|----------------|
-| [`datetime`](/docs/server-sdks/reference/typescript/agents/skills/datetime) | `DateTimeSkill` | 1 | No | No |
+| [`datetime`](/docs/server-sdks/reference/typescript/agents/skills/datetime) | `DateTimeSkill` | 2 | No | No |
| [`math`](/docs/server-sdks/reference/typescript/agents/skills/math) | `MathSkill` | 1 | No | No |
| [`joke`](/docs/server-sdks/reference/typescript/agents/skills/joke) | `JokeSkill` | 1 | No | No |
| [`weather_api`](/docs/server-sdks/reference/typescript/agents/skills/weather-api) | `WeatherApiSkill` | 1 | Yes | No |
-| [`web_search`](/docs/server-sdks/reference/typescript/agents/skills/web-search) | `WebSearchSkill` | 1 | Yes | No |
+| [`web_search`](/docs/server-sdks/reference/typescript/agents/skills/web-search) | `WebSearchSkill` | 1 | Yes | Yes |
| [`wikipedia_search`](/docs/server-sdks/reference/typescript/agents/skills/wikipedia-search) | `WikipediaSearchSkill` | 1 | No | No |
-| [`google_maps`](/docs/server-sdks/reference/typescript/agents/skills/google-maps) | `GoogleMapsSkill` | 2 | Yes | No |
-| [`play_background_file`](/docs/server-sdks/reference/typescript/agents/skills/play-background-file) | `PlayBackgroundFileSkill` | 2 | No | No |
-| [`swml_transfer`](/docs/server-sdks/reference/typescript/agents/skills/swml-transfer) | `SwmlTransferSkill` | 1-2 | No | No |
+| [`google_maps`](/docs/server-sdks/reference/typescript/agents/skills/google-maps) | `GoogleMapsSkill` | 4 | Yes | No |
+| [`play_background_file`](/docs/server-sdks/reference/typescript/agents/skills/play-background-file) | `PlayBackgroundFileSkill` | 1-3 | No | Yes |
+| [`swml_transfer`](/docs/server-sdks/reference/typescript/agents/skills/swml-transfer) | `SwmlTransferSkill` | 1-2 | No | Yes |
| [`datasphere`](/docs/server-sdks/reference/typescript/agents/skills/datasphere) | `DataSphereSkill` | 1 | Yes | Yes |
| [`datasphere_serverless`](/docs/server-sdks/reference/typescript/agents/skills/datasphere-serverless) | `DataSphereServerlessSkill` | 1 | Yes | Yes |
| [`native_vector_search`](/docs/server-sdks/reference/typescript/agents/skills/native-vector-search) | `NativeVectorSearchSkill` | 1 | No | Yes |
-| [`info_gatherer`](/docs/server-sdks/reference/typescript/agents/skills/info-gatherer) | `InfoGathererSkill` | 2 | No | No |
-| [`api_ninjas_trivia`](/docs/server-sdks/reference/typescript/agents/skills/api-ninjas-trivia) | `ApiNinjasTriviaSkill` | 1 | Yes | No |
-| [`spider`](/docs/server-sdks/reference/typescript/agents/skills/spider) | `SpiderSkill` | 1 | Yes | No |
+| [`info_gatherer`](/docs/server-sdks/reference/typescript/agents/skills/info-gatherer) | `InfoGathererSkill` | 2 | No | Yes |
+| [`api_ninjas_trivia`](/docs/server-sdks/reference/typescript/agents/skills/api-ninjas-trivia) | `ApiNinjasTriviaSkill` | 1 | Yes | Yes |
+| [`spider`](/docs/server-sdks/reference/typescript/agents/skills/spider) | `SpiderSkill` | 3 | No | Yes |
| [`ask_claude`](/docs/server-sdks/reference/typescript/agents/skills/ask-claude) | `AskClaudeSkill` | 1 | Yes | No |
| [`claude_skills`](/docs/server-sdks/reference/typescript/agents/skills/claude-skills) | `ClaudeSkillsSkill` | Dynamic | No | Yes |
| [`custom_skills`](/docs/server-sdks/reference/typescript/agents/skills/custom-skills) | `CustomSkillsSkill` | Dynamic | No | No |
@@ -70,13 +70,13 @@ parameter is not provided directly.
import { WebSearchSkill } from '@signalwire/sdk';
// Direct configuration
-const skill = new WebSearchSkill({ max_results: 5, safe_search: 'high' });
+const skill = new WebSearchSkill({ num_results: 5, safe_search: 'high' });
// Environment variable fallback (api_key falls back to GOOGLE_SEARCH_API_KEY,
// search_engine_id falls back to GOOGLE_SEARCH_CX)
process.env.GOOGLE_SEARCH_API_KEY = 'YOUR_KEY';
process.env.GOOGLE_SEARCH_CX = 'YOUR_ENGINE_ID';
-const skillWithEnv = new WebSearchSkill({ max_results: 5 });
+const skillWithEnv = new WebSearchSkill({ num_results: 5 });
```
### SWAIG Field Overrides
@@ -112,11 +112,13 @@ agent.setPromptText('You are a helpful assistant.');
await agent.addSkill(new DataSphereSkill({
tool_name: 'search_products',
- max_results: 3,
+ document_id: 'doc_products',
+ count: 3,
}));
await agent.addSkill(new DataSphereSkill({
tool_name: 'search_policies',
- max_results: 5,
+ document_id: 'doc_policies',
+ count: 5,
}));
agent.run();
@@ -144,20 +146,20 @@ them with the `SkillRegistry`.
### Defining a Custom Skill
-```typescript {10}
+```typescript {10-14}
import { SkillBase, FunctionResult } from '@signalwire/sdk';
import type {
- SkillManifest,
SkillToolDefinition,
SkillPromptSection,
- SkillConfig,
ParameterSchemaEntry,
} from '@signalwire/sdk';
export class StockPriceSkill extends SkillBase {
- constructor(config?: SkillConfig) {
- super('stock_price', config);
- }
+ // Identity is declared with static class constants.
+ static override SKILL_NAME = 'stock_price';
+ static override SKILL_DESCRIPTION = 'Look up current stock prices.';
+ static override SKILL_VERSION = '1.0.0';
+ static override REQUIRED_ENV_VARS = ['STOCK_API_KEY'] as const;
static override getParameterSchema(): Record {
return {
@@ -172,16 +174,7 @@ export class StockPriceSkill extends SkillBase {
};
}
- getManifest(): SkillManifest {
- return {
- name: 'stock_price',
- description: 'Look up current stock prices.',
- version: '1.0.0',
- requiredEnvVars: ['STOCK_API_KEY'],
- };
- }
-
- getTools(): SkillToolDefinition[] {
+ override getTools(): SkillToolDefinition[] {
return [
{
name: 'get_stock_price',
@@ -226,7 +219,7 @@ import { SkillRegistry } from '@signalwire/sdk';
import { StockPriceSkill } from './stock-price-skill.js';
const registry = SkillRegistry.getInstance();
-registry.register('stock_price', (config) => new StockPriceSkill(config));
+registry.register(StockPriceSkill); // pass the class; name comes from SKILL_NAME
```
### Using a Custom Skill
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/info-gatherer.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/info-gatherer.mdx
index e59bd42b9..7175a1244 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/info-gatherer.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/info-gatherer.mdx
@@ -1,61 +1,64 @@
---
title: "InfoGathererSkill"
slug: /reference/typescript/agents/skills/info-gatherer
-description: Collect structured information from the user based on configurable fields.
+description: Gather answers to a configurable list of questions, one at a time.
---
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
-Collect structured information from the user based on configurable fields. Fields
-support optional validation patterns and required/optional flags. Collected data
-can be stored in global data.
+Collect answers to a configured list of questions. The skill registers a
+`start_questions` tool and a `submit_answer` tool; the agent advances through
+the question list and reports completion when every question is answered.
+
+Fails closed during `setup()` when `questions` is missing or invalid.
**Class:** `InfoGathererSkill`
-**Tools:** `save_info`, `get_gathered_info`
+**Tools:** `start_questions`, `submit_answer` (names are prefixed when
+`prefix` is set)
**Env vars:** None
-[]"} toc={true}>
- Array of field definitions to collect. Each object has:
- - `name` (string, required) -- Field name used as the parameter key.
- - `description` (string, required) -- Description of what this field collects.
- - `required` (boolean, optional) -- Whether this field must be provided.
- - `validation` (string, optional) -- Regex pattern for validating the field value.
- - `type` (string, optional) -- Parameter type for the tool schema (defaults to `"string"`).
-
+**Multi-instance:** yes
-
- A description of why this information is being collected (shown in prompt).
+
+ Ordered list of questions to ask. Each question has:
+
+ - `key_name` (string, required) — key used to store the caller's answer.
+ - `question_text` (string, required) — the question to ask.
+ - `confirm` (boolean) — when `true`, the agent asks the caller to confirm
+ the answer before moving on.
+ - `prompt_add` (string) — optional extra prompt text appended while this
+ question is active.
-
- Custom message returned after successful info collection.
+
+ Optional prefix for tool names and the global-data namespace. When set,
+ tools are named `_start_questions` / `_submit_answer` and
+ state is stored under `skill:`. Required when loading multiple
+ `InfoGathererSkill` instances on the same agent.
-
- Whether to store gathered info in global data.
+
+ Message returned after every question has been answered. Defaults to a
+ generic completion message.
-```typescript {6-15}
+## Example
+
+```typescript {6-14}
import { AgentBase, InfoGathererSkill } from '@signalwire/sdk';
-const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
-agent.setPromptText('You are a helpful assistant.');
+const agent = new AgentBase({ name: 'intake', route: '/intake' });
+agent.setPromptText('Collect contact information for follow-up.');
await agent.addSkill(new InfoGathererSkill({
- purpose: 'Collect contact information for follow-up.',
- fields: [
- { name: 'name', description: 'Full name', required: true },
- {
- name: 'email',
- description: 'Email address',
- required: true,
- validation: '^[\\w.+-]+@[\\w-]+\\.[\\w.]+$',
- },
- { name: 'phone', description: 'Phone number', required: false },
+ questions: [
+ { key_name: 'full_name', question_text: 'What is your full name?' },
+ { key_name: 'email', question_text: 'What is your email address?', confirm: true },
+ { key_name: 'phone', question_text: 'What is your phone number?' },
],
- store_globally: true,
+ completion_message: 'Thanks — we will be in touch shortly.',
}));
agent.run();
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/joke.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/joke.mdx
index 060fdf28a..f12d37c47 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/joke.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/joke.mdx
@@ -12,11 +12,15 @@ categories. No external API required.
**Class:** `JokeSkill`
-**Tools:** `tell_joke`
+**Tools:** `tell_joke` (configurable via `tool_name`)
**Env vars:** None
-No custom parameters. This skill inherits only the [base parameters][base-parameters].
+
+ Custom name for the joke tool. Overrides the default SWAIG function name.
+
+
+Plus the [base parameters][base-parameters] (`swaig_fields`, `skip_prompt`).
```typescript {5}
import { AgentBase, JokeSkill } from '@signalwire/sdk';
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/mcp-gateway.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/mcp-gateway.mdx
index 8d44b367f..0207ac481 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/mcp-gateway.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/mcp-gateway.mdx
@@ -1,45 +1,92 @@
---
title: "McpGatewaySkill"
slug: /reference/typescript/agents/skills/mcp-gateway
-description: Placeholder skill for future Model Context Protocol (MCP) server integration.
+description: Bridge an MCP Gateway server into SWAIG functions for the agent.
---
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
-Placeholder skill for future Model Context Protocol (MCP) server integration.
-Currently provides a stub `mcp_invoke` tool.
+Bridge a Model Context Protocol (MCP) Gateway service with SWAIG functions.
+The skill connects to the gateway at load time, enumerates the configured
+services and tools, and registers each as a SWAIG function on the agent.
+
+The gateway URL is validated by an SSRF guard — private, loopback, and
+cloud-metadata endpoints are rejected. Requests use retry semantics with
+`retry_attempts` and a per-request timeout of `request_timeout` seconds.
**Class:** `McpGatewaySkill`
-**Tools:** `mcp_invoke` (placeholder, not yet functional)
+**Tools:** Dynamically registered from the gateway (prefixed by `tool_prefix`)
-**Env vars:** None
+**Required packages:** `undici`
-
- URL of the MCP gateway server.
-
+**Env vars:** `MCP_GATEWAY_AUTH_TOKEN`, `MCP_GATEWAY_AUTH_USER`,
+`MCP_GATEWAY_AUTH_PASSWORD`
-
- Prefix for tool names from this gateway.
+
+ URL of the MCP Gateway service. Must pass the SSRF guard.
- Authentication token for the MCP gateway.
+ Bearer token for authentication. Falls back to the
+ `MCP_GATEWAY_AUTH_TOKEN` environment variable. Takes precedence over
+ basic auth when provided.
+
+
+
+ Basic-auth username (used when `auth_token` is not supplied). Falls back
+ to `MCP_GATEWAY_AUTH_USER`.
+
+
+
+ Basic-auth password. Falls back to `MCP_GATEWAY_AUTH_PASSWORD`.
+
+
+
+ Services to expose. Each entry has:
+
+ - `name` (string) — service name registered on the gateway.
+ - `tools` (`"*"` or `string[]`) — which tools to expose from that service.
+
+ Empty array exposes every available service/tool.
+
+
+
+ Gateway session timeout in seconds.
+
+
+
+ Prefix prepended to each SWAIG function name registered from the gateway
+ (e.g., `mcp_todo_add_todo`).
+
+
+
+ Number of retry attempts for failed requests.
+
+
+
+ Per-request timeout in seconds.
+
+
+
+ Whether to verify SSL certificates on outbound requests.
-
-This skill is a placeholder. The `mcp_invoke` tool returns a "not yet implemented"
-message. Full MCP integration is planned for a future release.
-
+## Example
-```typescript {6-8}
+```typescript {6-13}
import { AgentBase, McpGatewaySkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
agent.setPromptText('You are a helpful assistant.');
await agent.addSkill(new McpGatewaySkill({
- gateway_url: 'http://localhost:8080',
+ gateway_url: 'https://mcp.internal.example.com',
+ services: [
+ { name: 'search', tools: '*' },
+ { name: 'calendar', tools: ['list_events', 'create_event'] },
+ ],
+ tool_prefix: 'mcp_',
}));
agent.run();
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/native-vector-search.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/native-vector-search.mdx
index 92bd9defe..aee1db3c4 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/native-vector-search.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/native-vector-search.mdx
@@ -1,56 +1,211 @@
---
title: "NativeVectorSearchSkill"
slug: /reference/typescript/agents/skills/native-vector-search
-description: In-memory document search using TF-IDF-like word overlap scoring.
+description: Vector + keyword document search against a local .swsearch index, an in-memory document array, or a remote search server.
---
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
-In-memory document search using TF-IDF-like word overlap scoring. No external
-dependencies or API keys required. Documents are provided via config and indexed
-at construction time.
+Search documents using vector similarity and keyword matching. Supports three
+modes:
+
+- **In-memory (TF-IDF)** — supply a `documents` array in config; the skill
+ tokenizes and indexes at startup (TypeScript-specific fast path).
+- **Local (SQLite)** — point `index_file` at a `.swsearch` index, or set
+ `build_index: true` and `source_dir` to index at startup.
+- **Remote (network)** — point `remote_url` at a search server and optionally
+ name the index via `index_name`. Validated by the SSRF guard before each
+ request; health check uses a 5-second timeout.
**Class:** `NativeVectorSearchSkill`
-**Tools:** `search_documents`
+**Tools:** `search_knowledge` (default — `tool_name` override supported)
**Env vars:** None
-**Multi-instance:** Yes
+**Multi-instance:** yes (distinguished by `tool_name` + `index_file`)
+
+## Core Parameters
+
+
+ Custom tool name for this skill instance. Required when registering multiple
+ instances on the same agent.
+
+
+
+ Path to a local `.swsearch` SQLite index file.
+
+
+
+ Whether to build the index from source files at startup.
+
+
+
+ Directory containing documents to index. Required when `build_index` is
+ `true`.
+
+
+
+ URL of a remote search server (network mode). Validated by the SSRF guard —
+ private, loopback, and cloud-metadata endpoints are rejected.
+
+
+
+ Name of the index on a remote server. Only used with `remote_url`.
+
+
+
+ In-memory array of documents to index (TypeScript-specific). Each entry has
+ `id` (string), `text` (string), optional `metadata` (object), and optional
+ `tags` (string[]).
+
+
+## Search Parameters
+
+
+ Number of search results to return (range `1-20`).
+
+
+
+ Minimum similarity score for results (`0.0` — no limit, `1.0` — exact match).
+
+
+
+ Manual keyword weight in the hybrid TF-IDF + keyword score
+ (range `0.0-1.0`). Overrides the automatic default of `0.3`.
+
+
+
+ Embedding model for remote/SQLite modes. Shortcuts: `"mini"` (fastest,
+ 384 dims), `"base"` or `"large"` (768 dims). Full model names also accepted.
+
+
+## Content Parameters
+
+
+ Tag filter applied to search queries. Only documents carrying at least one
+ matching tag are returned.
+
+
+
+ Tags applied to every document at index-build time.
+
+
+
+ File extensions to include when building an index from `source_dir`.
+
+
+
+ Glob patterns excluded from index builds. Defaults include
+ `**/node_modules/**`, `**/.git/**`, `**/dist/**`, `**/build/**`.
+
-
- Custom tool name for this instance. Required when using multiple instances.
+
+ Maximum total response size in characters (distributed across all results).
-[]"} toc={true}>
- Array of documents to index. Each object has:
- - `id` (string, required) -- Unique document identifier.
- - `text` (string, required) -- Full text content of the document.
- - `metadata` (object, optional) -- Metadata associated with the document.
+## Response Parameters
+
+
+ Message returned when no results match. Supports a `{query}` placeholder
+ that is substituted with the user's query text.
-
- Default number of top results to return.
+
+ Text prepended to the search response.
-
- Minimum relevance score threshold.
+
+ Text appended to the search response.
-```typescript {6-13}
+
+ Optional callback to transform the final response. Receives
+ `{ response, agent, query, results, args, count, skill }` and must return a
+ string.
+
+
+
+ Description of the search tool presented to the AI.
+
+
+
+ Additional speech recognition hints for the tool.
+
+
+## NLP Parameters
+
+
+ NLP backend for query processing: `"basic"`, `"spacy"`, or `"nltk"`.
+ **Deprecated** — use `query_nlp_backend` and `index_nlp_backend` instead.
+
+
+
+ NLP backend for query expansion: `"basic"`, `"spacy"`, or `"nltk"`.
+
+
+
+ NLP backend for indexing: `"basic"`, `"spacy"`, or `"nltk"`.
+
+
+## Backend Parameters
+
+
+ Storage backend for local database mode: `"sqlite"` or `"pgvector"`. Ignored
+ when `remote_url` is set. SQLite and pgvector backends require native
+ Python-only dependencies; configurations written for the Python SDK remain
+ valid but the TypeScript SDK only exercises the in-memory (`documents`) and
+ remote (`remote_url`) paths.
+
+
+
+ PostgreSQL connection string. Required when `backend="pgvector"`.
+
+
+
+ PostgreSQL collection name. Required when `backend="pgvector"`.
+
+
+## Other Parameters
+
+
+ Enable verbose logging during indexing and search.
+
+
+
+ Overwrite existing pgvector collection when building the index.
+
+
+## Example — in-memory documents
+
+```typescript {6-16}
import { AgentBase, NativeVectorSearchSkill } from '@signalwire/sdk';
-const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
-agent.setPromptText('You are a helpful assistant.');
+const agent = new AgentBase({ name: 'kb-bot', route: '/kb' });
+agent.setPromptText('Answer questions from the knowledge base.');
await agent.addSkill(new NativeVectorSearchSkill({
- tool_name: 'search_faqs',
+ tool_name: 'search_kb',
documents: [
- { id: 'faq-1', text: 'To reset your password, visit the settings page...' },
- { id: 'faq-2', text: 'Refund requests must be submitted within 30 days...' },
+ { id: 'faq-1', text: 'Hours are 9am to 5pm Monday to Friday.', tags: ['hours'] },
+ { id: 'faq-2', text: 'Returns are accepted within 30 days.', tags: ['returns'] },
],
- num_results: 3,
+ count: 3,
+ similarity_threshold: 0.1,
+ keyword_weight: 0.5,
}));
agent.run();
```
+
+## Example — remote server
+
+```typescript {6-10}
+await agent.addSkill(new NativeVectorSearchSkill({
+ remote_url: 'https://search.internal.example.com',
+ index_name: 'support-kb',
+ count: 3,
+ similarity_threshold: 0.4,
+ tags: ['public'],
+}));
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/play-background-file.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/play-background-file.mdx
index aec5930cf..6860da72c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/play-background-file.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/play-background-file.mdx
@@ -1,40 +1,94 @@
---
title: "PlayBackgroundFileSkill"
slug: /reference/typescript/agents/skills/play-background-file
-description: Control background audio playback during calls.
+description: Control background audio/video playback during calls. Supports pre-configured file list or free-form URL playback.
---
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
-Control background audio playback during calls. Play hold music, ambient sounds,
-or any audio file using SWML playback actions.
+Control background audio/video playback during calls using SWML playback
+actions. Two configuration modes are supported:
+
+- **Pre-configured mode (matches Python)** — supply `files` and the skill
+ emits a single tool whose `action` enum includes `start_` for each
+ configured file plus `stop`.
+- **Free-form mode (TypeScript-specific)** — omit `files` and supply
+ `default_file_url` and/or `allowed_domains`. The skill emits two tools,
+ `play_background` and `stop_background`, which accept arbitrary URLs (with
+ optional domain allowlist).
**Class:** `PlayBackgroundFileSkill`
-**Tools:** `play_background`, `stop_background`
+**Tools (pre-configured mode):** `play_background_file` (configurable via
+`tool_name`)
+
+**Tools (free-form mode):** `play_background`, `stop_background`
**Env vars:** None
+**Multi-instance:** yes — set a distinct `tool_name` per instance.
+
+
+ Custom name for the generated SWAIG tool in pre-configured mode. Required
+ when registering multiple instances on the same agent.
+
+
+
+ Array of pre-configured file entries that become selectable via the tool's
+ `action` enum. When supplied (and non-empty), the skill runs in
+ pre-configured mode; when omitted or empty, the skill falls back to
+ free-form mode.
+
+ Each entry has:
+
+ - `key` (string, required) — unique identifier (alphanumeric, underscores,
+ hyphens); mapped to `start_` in the `action` enum.
+ - `description` (string, required) — human-readable description shown to
+ the AI.
+ - `url` (string, required) — URL of the audio/video file.
+ - `wait` (boolean, optional, default `false`) — whether to wait for the
+ file to finish playing.
+
+
- Default audio file URL to use when no URL is specified by the caller.
- When set, the `file_url` parameter becomes optional on the `play_background` tool.
+ Default audio file URL for free-form mode. When set, the `file_url`
+ parameter on the `play_background` tool becomes optional.
- List of allowed domains for audio file URLs. If set, only URLs from these
- domains are accepted.
+ Allowlist of domains for audio file URLs in free-form mode. When set, only
+ URLs whose hostname matches or is a subdomain of one of these entries are
+ accepted.
-```typescript {6-9}
+## Example — pre-configured files
+
+```typescript {6-14}
import { AgentBase, PlayBackgroundFileSkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
agent.setPromptText('You are a helpful assistant.');
await agent.addSkill(new PlayBackgroundFileSkill({
- default_file_url: 'https://example.com/hold-music.mp3',
- allowed_domains: ['example.com', 'cdn.example.com'],
+ tool_name: 'play_testimonial',
+ files: [
+ {
+ key: 'massey',
+ description: 'Customer success story from Massey Energy',
+ url: 'https://example.com/massey.mp4',
+ wait: true,
+ },
+ ],
}));
agent.run();
```
+
+## Example — free-form URL
+
+```typescript {6-9}
+await agent.addSkill(new PlayBackgroundFileSkill({
+ default_file_url: 'https://example.com/hold-music.mp3',
+ allowed_domains: ['example.com', 'cdn.example.com'],
+}));
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/spider.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/spider.mdx
index ec85f4d45..9e860304b 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/spider.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/spider.mdx
@@ -1,36 +1,107 @@
---
title: "SpiderSkill"
slug: /reference/typescript/agents/skills/spider
-description: Scrape webpage content using the Spider API.
+description: Fast web scraping and crawling using cheerio-based extraction with SSRF protection.
---
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
-Scrape webpage content using the Spider API. Extracts text or markdown from any
-public URL, with optional CSS selector filtering.
+Fast web scraping and crawling. Extracts text, markdown, or structured data
+from any public URL, optionally following links up to a bounded depth. Uses
+`cheerio` for parsing and enforces an SSRF guard on crawl hops.
**Class:** `SpiderSkill`
-**Tools:** `scrape_url`
+**Tools:** `scrape_url`, `crawl_site`, `extract_structured_data` (each is
+prefixed with `_` when `tool_name` is set).
-**Env vars:** `SPIDER_API_KEY`
+**Required packages:** `cheerio`
-
- Spider API key. Falls back to the `SPIDER_API_KEY` environment variable.
+**Env vars:** `SWML_ALLOW_PRIVATE_URLS=true` relaxes the SSRF guard for local
+testing.
+
+**Multi-instance:** yes — set a distinct `tool_name` per instance.
+
+
+ Prefix prepended to each emitted tool name (e.g., `tool_name="news"` gives
+ `news_scrape_url`, `news_crawl_site`, `news_extract_structured_data`).
+ Required when registering multiple instances on the same agent.
+
+
+
+ Delay between requests in seconds (minimum `0`).
+
+
+
+ Number of concurrent requests allowed (range `1-20`).
+
+
+
+ Per-request timeout in seconds (range `1-60`).
-
- Maximum length of returned content in characters.
+
+ Maximum number of pages to scrape (range `1-100`).
-```typescript {6-8}
+
+ Maximum crawl depth. `0` restricts to a single page; range `0-5`.
+
+
+
+ Content extraction method. One of `"fast_text"`, `"clean_text"`,
+ `"full_text"`, `"html"`, `"markdown"`, `"structured"`, `"custom"`. Only
+ `fast_text`, `markdown`, and `structured` are wired through the handlers
+ in the TypeScript port; the others fall back to `fast_text`.
+
+
+
+ Maximum extracted text length in characters (range `100-100000`).
+
+
+
+ Whether to clean extracted text (trim whitespace, collapse runs, etc.).
+
+
+"} default="{}" toc={true}>
+ Map of name → CSS selector used for structured extraction.
+
+
+
+ URL patterns to follow when crawling.
+
+
+
+ User-Agent header for outbound requests. Defaults to a Chrome-compatible
+ UA string.
+
+
+"} default="{}" toc={true}>
+ Additional HTTP headers sent with each request.
+
+
+
+ Whether to respect `robots.txt`. Defaults to `false` to match Python's
+ runtime behavior.
+
+
+
+ Whether to cache scraped pages in memory.
+
+
+## Example
+
+```typescript {6-11}
import { AgentBase, SpiderSkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
-agent.setPromptText('You are a helpful assistant.');
+agent.setPromptText('You are a research assistant.');
await agent.addSkill(new SpiderSkill({
- max_content_length: 10000,
+ extract_type: 'markdown',
+ max_pages: 5,
+ max_depth: 1,
+ follow_patterns: ['/docs/'],
}));
agent.run();
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/swml-transfer.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/swml-transfer.mdx
index e8b573bd7..13737117a 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/swml-transfer.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/swml-transfer.mdx
@@ -1,37 +1,89 @@
---
title: "SwmlTransferSkill"
slug: /reference/typescript/agents/skills/swml-transfer
-description: Transfer calls using SWML transfer actions.
+description: Transfer calls between agents/endpoints based on pattern matching.
---
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
-Transfer calls using SWML transfer actions. Supports named pattern-based transfers
-with friendly destination names, or arbitrary direct-destination transfers.
+Transfer calls between agents or endpoints using SWML transfer actions. The
+skill accepts either a **Python-style `transfers`** config (regex pattern →
+per-entry config) or a **TypeScript-style `patterns`** array of named
+destinations. At least one of the two shapes is required — `setup()` fails
+closed otherwise.
**Class:** `SwmlTransferSkill`
-**Tools:** `transfer_call` (always), `list_transfer_destinations` (when `patterns` are configured)
+**Tools:** `transfer_call` always; `list_transfer_destinations` additionally
+registered when at least one entry is supplied in `patterns`.
**Env vars:** None
-[]"} toc={true}>
- Array of named transfer patterns. Each object has:
- - `name` (string, required) -- Friendly name for the destination.
- - `destination` (string, required) -- SIP URI, phone number, or agent URL.
- - `description` (string, optional) -- Human-readable description.
+**Multi-instance:** yes — set a distinct `tool_name` per instance.
+
+"} toc={true}>
+ Python-style map of transfer configs keyed by regex pattern (or name). Each
+ entry includes either `url` or `address` (not both), plus optional
+ `message`, `return_message`, `post_process`, `final`, and `from_addr`.
+
+ Either `transfers` or `patterns` must be provided; both may be combined.
+ `setup()` fails closed when neither is configured.
+
+
+
+ TypeScript-style array of named transfer patterns. Each object has:
+
+ - `name` (string, required) — friendly name for the destination.
+ - `destination` (string, required) — SIP URI, phone number, or agent URL.
+ - `description` (string) — optional human-readable description.
+ - `message` / `returnMessage` / `postProcess` / `final` / `fromAddr` —
+ optional per-pattern overrides.
- Whether to allow transfers to arbitrary destinations not in the patterns list.
- Defaults to `true` when no patterns are configured, `false` when patterns exist.
+ Whether to allow transfers to arbitrary destinations not listed in
+ `patterns` / `transfers`. When unset, defaults depend on whether any
+ patterns are configured.
+
+
+
+ Name of the transfer tool exposed to the AI.
+
+
+
+ Description for the transfer tool shown to the AI.
+
+
+
+ Name of the parameter that accepts the transfer type.
+
+
+
+ Description for the transfer-type parameter.
+
+
+
+ Message spoken when no pattern matches.
-
- Default message to say before transferring.
+
+ Whether to post-process the default message with the AI.
-```typescript {6-16}
+"} default="{}" toc={true}>
+ Map of additional fields (name → description) the agent must collect before
+ a transfer.
+
+
+
+Regex patterns in `transfers` are matched **case-sensitively**. Use character
+classes or flags in the source pattern when case-insensitive matching is
+needed.
+
+
+## Example — TypeScript patterns
+
+```typescript {6-20}
import { AgentBase, SwmlTransferSkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
@@ -50,7 +102,25 @@ await agent.addSkill(new SwmlTransferSkill({
description: 'Technical support line',
},
],
- default_message: 'Let me connect you now.',
+ default_message: 'Please specify sales or support.',
+}));
+
+agent.run();
+```
+
+## Example — Python-style transfers
+
+```typescript {6-14}
+import { AgentBase, SwmlTransferSkill } from '@signalwire/sdk';
+
+const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
+agent.setPromptText('You are a helpful assistant.');
+
+await agent.addSkill(new SwmlTransferSkill({
+ transfers: {
+ '^sales$': { address: 'sip:sales@signalwire.com' },
+ '^support$': { url: 'https://your-server.com/support-agent' },
+ },
}));
agent.run();
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/weather-api.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/weather-api.mdx
index 6b6ac063a..8de889e13 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/weather-api.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/weather-api.mdx
@@ -8,19 +8,32 @@ description: Get current weather conditions for any location using the OpenWeath
Get current weather conditions for any location using the OpenWeatherMap API.
+
+**Provider note:** This skill uses OpenWeatherMap
+(`api.openweathermap.org/data/2.5/weather`), not WeatherAPI.com. An
+OpenWeatherMap API key is required — a WeatherAPI.com key will not work.
+Obtain a key at https://openweathermap.org/api.
+
+
**Class:** `WeatherApiSkill`
-**Tools:** `get_weather`
+**Tools:** `get_weather` (configurable via `tool_name`)
**Env vars:** `WEATHER_API_KEY`
- OpenWeatherMap API key. Falls back to the `WEATHER_API_KEY` environment variable.
+ OpenWeatherMap API key. Falls back to the `WEATHER_API_KEY` environment
+ variable when the config value is not supplied.
+
+
+
+ Custom name for the generated weather tool.
-
- Temperature units: `"metric"` (Celsius), `"imperial"` (Fahrenheit), or
- `"standard"` (Kelvin).
+
+ Temperature units. Preferred values: `"metric"` (Celsius), `"imperial"`
+ (Fahrenheit), or `"standard"` (Kelvin). Python SDK aliases are also
+ accepted: `"celsius"` → `"metric"`, `"fahrenheit"` → `"imperial"`.
```typescript {6-8}
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/web-search.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/web-search.mdx
index 51187f78c..632662a3c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/web-search.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/web-search.mdx
@@ -1,45 +1,83 @@
---
title: "WebSearchSkill"
slug: /reference/typescript/agents/skills/web-search
-description: Search the web using the Google Custom Search JSON API.
+description: Search the web via Google Custom Search, scrape results, and quality-filter the output.
---
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
-Search the web using the Google Custom Search JSON API. Returns titles, links,
-and snippets.
+Search the web using the Google Custom Search JSON API. The skill fetches
+more results than requested, scrapes each page, scores the extracted
+content, and returns only the highest-quality matches to the AI.
**Class:** `WebSearchSkill`
-**Tools:** `web_search`
+**Tools:** `web_search` (configurable via `tool_name`)
-**Env vars:** `GOOGLE_SEARCH_API_KEY`, `GOOGLE_SEARCH_CX`
+**Env vars:** `GOOGLE_SEARCH_API_KEY`, `GOOGLE_SEARCH_ENGINE_ID` (legacy
+`GOOGLE_SEARCH_CX` is still accepted)
+
+**Multi-instance:** yes — instance key combines `search_engine_id` and
+`tool_name`.
- Google Custom Search API key. Falls back to the `GOOGLE_SEARCH_API_KEY` environment variable.
+ Google Custom Search API key. Falls back to the `GOOGLE_SEARCH_API_KEY`
+ environment variable.
- Google Custom Search Engine ID (CX). Falls back to the `GOOGLE_SEARCH_CX` environment variable.
+ Google Custom Search Engine ID. Falls back to the
+ `GOOGLE_SEARCH_ENGINE_ID` environment variable (or the legacy
+ `GOOGLE_SEARCH_CX`).
+
+
+
+ Custom tool name for this Web Search instance (useful when registering
+ multiple instances at once).
+
+
+
+ Number of high-quality results to return (range `1-10`).
+
+
+
+ Delay between scraping pages in seconds (minimum `0`).
-
- Maximum number of results to return (1-10).
+
+ Maximum total response size in characters (minimum `1000`).
+
+
+
+ How many extra results to fetch for quality filtering — e.g. `2.5` fetches
+ 2.5× the requested `num_results` before scoring. Range `1.0-3.5`.
+
+
+
+ Minimum quality score (0–1) required to include a result.
+
+
+
+ Message returned when no quality results are found. Use `{query}` as a
+ placeholder for the original search term.
- Safe search level: `"off"`, `"medium"`, or `"high"`.
+ Safe-search level. One of `"off"`, `"medium"`, `"high"`.
-```typescript {6-9}
+## Example
+
+```typescript {6-10}
import { AgentBase, WebSearchSkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
agent.setPromptText('You are a helpful assistant.');
await agent.addSkill(new WebSearchSkill({
- max_results: 3,
+ num_results: 3,
safe_search: 'high',
+ min_quality_score: 0.4,
}));
agent.run();
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/skills/wikipedia-search.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/skills/wikipedia-search.mdx
index 6922b1826..1555060ac 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/skills/wikipedia-search.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/skills/wikipedia-search.mdx
@@ -1,40 +1,41 @@
---
title: "WikipediaSearchSkill"
slug: /reference/typescript/agents/skills/wikipedia-search
-description: Search Wikipedia for article summaries and extracts.
+description: Search Wikipedia for article summaries. No API key required.
---
[add-skill]: /docs/server-sdks/reference/typescript/agents/agent-base/add-skill
-Search Wikipedia for article summaries and extracts. No API key required.
+Search Wikipedia for information about a topic and return article summaries.
+Uses Node's native `fetch` with a 10-second timeout. No API key required.
**Class:** `WikipediaSearchSkill`
-**Tools:** `search_wikipedia`
+**Tools:** `search_wiki`
**Env vars:** None
-
- Wikipedia language edition to search (e.g., `"en"`, `"fr"`, `"de"`).
+
+ Maximum number of Wikipedia articles to return (range `1-5`).
-
- Maximum number of search results to consider.
+
+ Custom message returned when no articles match the query. Supports a
+ `{query}` placeholder that is substituted with the user's query text.
+ Defaults to a generic "couldn't find any Wikipedia articles for '{query}'"
+ fallback.
-
- Maximum length of returned content in characters.
-
+## Example
-```typescript {6-9}
+```typescript {6-8}
import { AgentBase, WikipediaSearchSkill } from '@signalwire/sdk';
const agent = new AgentBase({ name: 'assistant', route: '/assistant' });
agent.setPromptText('You are a helpful assistant.');
await agent.addSkill(new WikipediaSearchSkill({
- language: 'en',
- max_results: 1,
+ num_results: 2,
}));
agent.run();
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/execute.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/execute.mdx
index 8784d79f8..2f4213585 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/execute.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/execute.mdx
@@ -34,7 +34,7 @@ or a plain string. All formats are normalized to a result dictionary.
## **Example**
-```typescript {20}
+```typescript {19}
import { SwaigFunction, FunctionResult } from '@signalwire/sdk';
const func = new SwaigFunction({
@@ -55,5 +55,5 @@ const func = new SwaigFunction({
const result = await func.execute({ account_id: "12345" });
console.log(result);
-// { response: "Account 12345 is active.", action: [] }
+// { response: "Account 12345 is active." }
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/index.mdx
index b68d3afba..6b94b12e8 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/index.mdx
@@ -14,6 +14,7 @@ max-toc-depth: 3
[swml-swaig-functions-reference]: /docs/swml/reference/ai/swaig/functions
[execute]: /docs/server-sdks/reference/typescript/agents/swaig-function/execute
[toswaig]: /docs/server-sdks/reference/typescript/agents/swaig-function/to-swaig
+[validateargs]: /docs/server-sdks/reference/typescript/agents/swaig-function/validate-args
SwaigFunction wraps a function as a SWAIG (SignalWire AI Gateway) tool
that the AI can invoke during a conversation. It manages the function's name,
@@ -166,13 +167,16 @@ type SwaigHandler = (
## **Methods**
-
+
Execute the tool with the given arguments.
Convert the tool to a SWAIG-compatible dictionary for SWML.
+
+ Validate arguments against the parameter JSON Schema.
+
---
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/validate-args.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/validate-args.mdx
new file mode 100644
index 000000000..4be47d05e
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swaig-function/validate-args.mdx
@@ -0,0 +1,54 @@
+---
+title: "validateArgs"
+slug: /reference/typescript/agents/swaig-function/validate-args
+description: Validate arguments against the parameter JSON Schema.
+max-toc-depth: 3
+---
+
+Validate arguments against the parameter JSON Schema. Uses
+[Ajv](https://ajv.js.org/) to compile and run the schema. When the function
+has no parameters declared (empty schema), validation is skipped and the
+arguments are treated as valid — matching the Python SDK's early-return
+behavior.
+
+## **Parameters**
+
+
+ Arguments to validate.
+
+
+## **Returns**
+
+`[boolean, string[]]` -- A tuple of `[isValid, errors]`. When no validation is
+needed (empty schema), returns `[true, []]`. Error strings include the
+offending property path where available (e.g., `"'account_id' is a required
+property"`).
+
+## **Example**
+
+```typescript {18,22}
+import { SwaigFunction, FunctionResult } from '@signalwire/sdk';
+
+const fn = new SwaigFunction({
+ name: 'lookup_account',
+ handler: async () => new FunctionResult('ok'),
+ description: 'Look up account status',
+ parameters: {
+ type: 'object',
+ properties: {
+ account_id: { type: 'string', description: 'Account ID' },
+ },
+ required: ['account_id'],
+ },
+});
+
+// Valid arguments
+const [ok1, errs1] = fn.validateArgs({ account_id: '12345' });
+console.log(`Valid: ${ok1}, Errors: ${JSON.stringify(errs1)}`);
+// Valid: true, Errors: []
+
+// Missing required argument
+const [ok2, errs2] = fn.validateArgs({});
+console.log(`Valid: ${ok2}, Errors: ${JSON.stringify(errs2)}`);
+// Valid: false, Errors: ["must have required property 'account_id'"]
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/add-section.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/add-section.mdx
new file mode 100644
index 000000000..2537f04c0
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/add-section.mdx
@@ -0,0 +1,42 @@
+---
+title: "addSection"
+slug: /reference/typescript/agents/swml-builder/add-section
+description: "Add a new empty named section to the SWML document."
+max-toc-depth: 3
+---
+
+[ref-addverbtosection]: /docs/server-sdks/reference/typescript/agents/swml-builder/add-verb-to-section
+
+Add a new empty named section to the SWML document. Sections are named
+containers for ordered lists of verbs. Every document starts with a `main`
+section -- use this method to create additional sections (e.g., a `transfer`
+flow).
+
+Silently no-ops if a section with the given name already exists. Follow up
+with [`addVerbToSection()`][ref-addverbtosection] to populate the section.
+
+## **Parameters**
+
+
+ Name of the section to create.
+
+
+## **Returns**
+
+`this` -- returns the builder for fluent chaining.
+
+## **Example**
+
+```typescript {5}
+import { SwmlBuilder } from '@signalwire/sdk';
+
+const builder = new SwmlBuilder();
+builder.answer();
+builder.addSection('fallback');
+builder.addVerbToSection('fallback', 'play', {
+ url: 'https://example.com/sorry.mp3',
+});
+builder.addVerbToSection('fallback', 'hangup', {});
+
+console.log(builder.renderDocument());
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/build.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/build.mdx
new file mode 100644
index 000000000..358cf3f5d
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/build.mdx
@@ -0,0 +1,32 @@
+---
+title: "build"
+slug: /reference/typescript/agents/swml-builder/build
+description: "Build and return the SWML document as an object (Python-compat alias for getDocument)."
+max-toc-depth: 3
+---
+
+[ref-getdocument]: /docs/server-sdks/reference/typescript/agents/swml-builder/get-document
+[ref-render]: /docs/server-sdks/reference/typescript/agents/swml-builder/render
+
+Return the SWML document as a plain object. Python-compat alias for
+[`getDocument()`][ref-getdocument]; the two are functionally identical. Use
+`build()` when porting from the Python SDK. For a JSON string, use
+[`render()`][ref-render] or `renderDocument()`.
+
+## **Returns**
+
+`Record` -- the SWML document with `version` and `sections`
+keys.
+
+## **Example**
+
+```typescript {6}
+import { SwmlBuilder } from '@signalwire/sdk';
+
+const builder = new SwmlBuilder();
+builder.answer();
+builder.ai({ prompt: { text: 'You are a helpful assistant.' } });
+
+const doc = builder.build();
+console.log(JSON.stringify(doc, null, 2));
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/document.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/document.mdx
new file mode 100644
index 000000000..3155a9f1e
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/document.mdx
@@ -0,0 +1,34 @@
+---
+title: "document"
+slug: /reference/typescript/agents/swml-builder/document
+description: "Read-only accessor for the underlying SWML document."
+max-toc-depth: 3
+---
+
+[ref-getdocument]: /docs/server-sdks/reference/typescript/agents/swml-builder/get-document
+
+Read-only getter for the underlying SWML document object. Provides direct
+access to the mutable document (the returned reference is the internal object,
+not a copy). Equivalent to the Python SDK's `service` property on `SWMLBuilder`.
+
+
+Prefer [`getDocument()`][ref-getdocument] when you want an explicit method
+call for symmetry with other accessors. The `document` getter exists for
+callers that want property-style access.
+
+
+## **Type**
+
+`{ version: string; sections: Record }`
+
+## **Example**
+
+```typescript {6}
+import { SwmlBuilder } from '@signalwire/sdk';
+
+const builder = new SwmlBuilder();
+builder.answer();
+
+console.log(builder.document.version); // "1.0.0"
+console.log(builder.document.sections.main.length); // 1
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/index.mdx
index 844f9cedc..1fad956ef 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/index.mdx
@@ -37,11 +37,28 @@ SwmlBuilder constructs [SWML][swml] documents programmatically. See the
## **Constructor**
```typescript {1}
-const builder = new SwmlBuilder();
+const builder = new SwmlBuilder(opts?);
```
-The constructor takes no parameters. It initializes an empty SWML document and
-installs dynamic verb methods from the bundled schema.
+Initializes an empty SWML document and installs dynamic verb methods from the
+bundled schema. All constructor options are optional.
+
+### SwmlBuilderOptions
+
+ }"} toc={true}>
+ Seed the builder with an existing document instead of creating an empty one.
+ Enables document injection — mirrors the Python SDK's `SWMLService` injection pattern.
+
+
+
+ Explicit override for verb schema validation. Defaults to `true` unless
+ `SWML_SKIP_SCHEMA_VALIDATION=true` is set in the environment.
+
+
+
+ Path to a custom SWML schema JSON file. When set, the builder uses a
+ per-instance `SchemaUtils` loaded from this path instead of the bundled schema.
+
## **Dynamic Verb Methods**
@@ -110,6 +127,21 @@ console.log(builder.renderDocument());
Reset the SWML document to an empty state.
+
+ Add a new named section to the document.
+
+
+ Build and return the document (Python-compat alias for getDocument).
+
+
+ Render the document as JSON (Python-compat alias for renderDocument).
+
+
+ Property-style read-only accessor for the underlying document.
+
+
+ Enable or disable verb schema validation.
+
---
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/render.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/render.mdx
new file mode 100644
index 000000000..b68fa11db
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/render.mdx
@@ -0,0 +1,32 @@
+---
+title: "render"
+slug: /reference/typescript/agents/swml-builder/render
+description: "Render the SWML document as a JSON string (Python-compat alias for renderDocument)."
+max-toc-depth: 3
+---
+
+[ref-renderdocument]: /docs/server-sdks/reference/typescript/agents/swml-builder/render-document
+[ref-build]: /docs/server-sdks/reference/typescript/agents/swml-builder/build
+
+Render the SWML document as a JSON string. Python-compat alias for
+[`renderDocument()`][ref-renderdocument]; the two are functionally identical.
+Use `render()` when porting from the Python SDK. For the document as a plain
+object, use [`build()`][ref-build] or `getDocument()`.
+
+## **Returns**
+
+`string` -- JSON-serialized SWML document.
+
+## **Example**
+
+```typescript {6}
+import { SwmlBuilder } from '@signalwire/sdk';
+
+const builder = new SwmlBuilder();
+builder.answer();
+builder.ai({ prompt: { text: 'You are a helpful assistant.' } });
+
+const json = builder.render();
+console.log(json);
+// '{"version":"1.0.0","sections":{"main":[{"answer":{}},{"ai":{...}}]}}'
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/reset.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/reset.mdx
index 4a8ff0aae..00edb2d83 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/reset.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/reset.mdx
@@ -13,7 +13,7 @@ This method takes no parameters.
## **Returns**
-`void`
+`this` -- The builder instance for method chaining.
## **Example**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/say.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/say.mdx
index f84f33aa2..5b0b8b251 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/say.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/say.mdx
@@ -1,30 +1,56 @@
---
title: "say"
slug: /reference/typescript/agents/swml-builder/say
-description: The say method does not exist on SwmlBuilder.
+description: "Add a play verb with a say: prefix for text-to-speech."
max-toc-depth: 3
---
[play]: /docs/server-sdks/reference/typescript/agents/swml-builder/play
-[addverb]: /docs/server-sdks/reference/typescript/agents/swml-builder/add-verb
-
-`say` is **not** a method on `SwmlBuilder`. The SWML schema does not define a `say`
-verb, so no dynamic method is generated for it.
-
+Convenience wrapper that appends a `play` verb with a `say:`-prefixed URL for
+text-to-speech. Equivalent to calling `builder.play({ url: 'say:${text}', ... })`
+but exposes the TTS options as typed arguments.
-To produce text-to-speech output, use the [`play()`][play] verb with a `say:` URL
-prefix, or pass the `say:` URL directly via [`addVerb()`][addverb]:
+## **Parameters**
-```typescript {7}
+
+ Text the agent should speak. The method prepends `say:` to produce the
+ final URL passed to the underlying [`play`][play] verb.
+
+
+
+ Optional TTS parameters.
+
+
+
+
+ Voice name for the TTS engine. Maps to `say_voice` in the emitted SWML.
+
+
+
+ Language code (e.g., `"en-US"`). Maps to `say_language` in the emitted SWML.
+
+
+
+ Gender for TTS voice selection. Maps to `say_gender` in the emitted SWML.
+
+
+
+ Volume adjustment in dB (−40 to 40). Maps to `volume` on the play verb.
+
+
+
+## **Returns**
+
+`this` -- The builder instance for method chaining.
+
+## **Example**
+
+```typescript {5}
import { SwmlBuilder } from '@signalwire/sdk';
const builder = new SwmlBuilder();
builder.answer();
-
-// Use the play verb with a say: URL prefix for text-to-speech
-builder.play({ url: 'say:Hello, welcome to our service.' });
-
-// Or use addVerb directly
-builder.addVerb('play', { url: 'say:Goodbye!' });
+builder.say('Welcome to our service.', { voice: 'rime.spore', language: 'en-US' });
+builder.hangup();
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/set-validation.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/set-validation.mdx
new file mode 100644
index 000000000..598ae1553
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-builder/set-validation.mdx
@@ -0,0 +1,47 @@
+---
+title: "setValidation"
+slug: /reference/typescript/agents/swml-builder/set-validation
+description: "Enable or disable verb schema validation at runtime."
+max-toc-depth: 3
+---
+
+[ref-addverb]: /docs/server-sdks/reference/typescript/agents/swml-builder/add-verb
+
+Toggle verb schema validation at runtime. When validation is enabled (the
+default), [`addVerb()`][ref-addverb] validates each verb's config against the
+schema and throws if it fails. Disable validation for performance-sensitive
+call paths or when constructing verbs with custom schemas not known to the
+built-in schema utilities.
+
+
+Matches the Python `schema_validation` constructor parameter on
+`AgentBase`. For SWML service validation at construct time, pass
+`schemaValidation: false` to the `SwmlBuilder` constructor via
+`SwmlBuilderOptions`.
+
+
+## **Parameters**
+
+
+ `true` to enable schema validation on subsequent `addVerb()` calls, `false`
+ to disable.
+
+
+## **Returns**
+
+`void`
+
+## **Example**
+
+```typescript {8}
+import { SwmlBuilder } from '@signalwire/sdk';
+
+const builder = new SwmlBuilder();
+
+// Validation on (default) — throws on invalid verb
+builder.answer();
+
+// Disable validation for a hot path
+builder.setValidation(false);
+builder.addVerb('custom_verb', { unusual: 'payload' });
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/add-section.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/add-section.mdx
new file mode 100644
index 000000000..2a50ebd8a
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/add-section.mdx
@@ -0,0 +1,42 @@
+---
+title: "addSection"
+slug: /reference/typescript/agents/swml-service/add-section
+description: "Add a new empty section to the SWML document."
+max-toc-depth: 3
+---
+
+[ref-addverbtosection]: /docs/server-sdks/reference/typescript/agents/swml-service/add-verb-to-section
+
+Add a new empty section to the SWML document. Sections are named containers for
+ordered lists of verbs. Every document starts with a `main` section.
+
+
+Silently no-ops if a section with the given name already exists (unlike the
+Python SDK which returns `False` on duplicate). Follow up with
+[`addVerbToSection()`][ref-addverbtosection] to populate the section.
+
+
+## **Parameters**
+
+
+ Name of the section to create.
+
+
+## **Returns**
+
+`this` -- returns the service for fluent chaining.
+
+## **Example**
+
+```typescript {4}
+import { SWMLService } from '@signalwire/sdk';
+
+const service = new SWMLService({ name: 'multi-section' });
+service.addSection('fallback');
+service.addVerbToSection('fallback', 'play', {
+ url: 'https://example.com/sorry.mp3',
+});
+service.addVerbToSection('fallback', 'hangup', {});
+
+console.log(service.renderDocument());
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/add-verb-to-section.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/add-verb-to-section.mdx
new file mode 100644
index 000000000..8b3b6ba52
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/add-verb-to-section.mdx
@@ -0,0 +1,59 @@
+---
+title: "addVerbToSection"
+slug: /reference/typescript/agents/swml-service/add-verb-to-section
+description: "Add a SWML verb to a specific named section of the document."
+max-toc-depth: 3
+---
+
+[ref-addsection]: /docs/server-sdks/reference/typescript/agents/swml-service/add-section
+[ref-addverb]: /docs/server-sdks/reference/typescript/agents/swml-service/add-verb
+
+Add a SWML verb to a specific named section of the document. If the section
+does not exist, it is created automatically before the verb is appended. Throws
+a validation error if schema validation is enabled and the verb config is
+invalid.
+
+
+Use [`addSection()`][ref-addsection] first to create an empty section if you
+prefer explicit creation, or use this method directly and let it auto-create.
+For the default `main` section, use [`addVerb()`][ref-addverb] instead.
+
+
+## **Parameters**
+
+
+ Name of the section to add the verb to (e.g., `"main"`, `"transfer_flow"`).
+
+
+
+ The SWML verb name.
+
+
+
+ Configuration for the verb. Typically a `Record` object;
+ certain verbs like `sleep` accept a bare number.
+
+
+## **Returns**
+
+`this` -- returns the service for fluent chaining.
+
+## **Example**
+
+```typescript {10}
+import { SWMLService } from '@signalwire/sdk';
+
+const service = new SWMLService({ name: 'transfer-flow' });
+
+// Build the main section
+service.addVerb('answer', {});
+service.addVerb('ai', { prompt: { text: 'You are a helpful assistant' } });
+
+// Build a separate transfer section
+service.addVerbToSection('transfer', 'connect', {
+ to: '+15551234567',
+ from: '+15559876543',
+});
+
+console.log(service.renderDocument());
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/as-router.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/as-router.mdx
new file mode 100644
index 000000000..9c1ace64f
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/as-router.mdx
@@ -0,0 +1,49 @@
+---
+title: "asRouter"
+slug: /reference/typescript/agents/swml-service/as-router
+description: "Get the underlying Hono app (Python-compat alias for getApp)."
+max-toc-depth: 3
+---
+
+[ref-serve]: /docs/server-sdks/reference/typescript/agents/swml-service/serve
+[ref-run]: /docs/server-sdks/reference/typescript/agents/swml-service/run
+[ref-getapp]: /docs/server-sdks/reference/typescript/agents/swml-service/get-app
+[ref-agentserver]: /docs/server-sdks/reference/typescript/agents/agent-server
+
+Return the underlying [`Hono`](https://hono.dev) app for this service. This is
+a Python-compat alias for [`getApp()`][ref-getapp] -- use either name
+interchangeably. Pick `asRouter()` when porting code from the Python SDK that
+called `as_router()` for a FastAPI `APIRouter`.
+
+Use this to mount the service into an existing Hono application rather than
+running a standalone server with [`run()`][ref-run] or
+[`serve()`][ref-serve].
+
+
+Use `asRouter()` for production deployments where you want to control the
+HTTP server lifecycle, or when hosting multiple services on the same Hono
+instance via [`AgentServer`][ref-agentserver].
+
+
+## **Returns**
+
+`Hono` -- the configured Hono app with all routes registered (SWML document
+endpoint plus any routing-callback paths).
+
+## **Example**
+
+```typescript {11}
+import { Hono } from 'hono';
+import { serve } from '@hono/node-server';
+import { SWMLService } from '@signalwire/sdk';
+
+const app = new Hono();
+
+const service = new SWMLService({ name: 'ivr', route: '/ivr' });
+service.addVerb('answer', {});
+service.addVerb('play', { url: 'https://example.com/welcome.mp3' });
+
+app.route('/ivr', service.asRouter());
+
+serve({ fetch: app.fetch, port: 3000 });
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/extract-sip-username.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/extract-sip-username.mdx
new file mode 100644
index 000000000..566c34e01
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/extract-sip-username.mdx
@@ -0,0 +1,54 @@
+---
+title: "extractSipUsername"
+slug: /reference/typescript/agents/swml-service/extract-sip-username
+description: "Static utility that extracts the username portion from a SIP URI in a request body."
+max-toc-depth: 3
+---
+
+[ref-registerroutingcallback]: /docs/server-sdks/reference/typescript/agents/swml-service/register-routing-callback
+
+Static utility method that extracts the username portion from the `call.to`
+field of a parsed request body. Handles three input formats:
+
+- `sip:username@domain` (or `sips:...`) -- strips the scheme and `@domain`
+ suffix, returning the username
+- `tel:+1234567890` -- strips the `tel:` scheme, returning the phone number
+- Plain string -- returned as-is
+
+Commonly paired with
+[`registerRoutingCallback()`][ref-registerroutingcallback] to route SIP traffic
+based on the dialed user.
+
+## **Parameters**
+
+
+ The parsed JSON body from an incoming request. Expected to contain a
+ `call.to` field with a SIP URI, TEL URI, or phone number string.
+
+
+## **Returns**
+
+`string | null` -- The extracted username or phone number, or `null` if the
+`call.to` field is missing or cannot be parsed.
+
+## **Examples**
+
+### Extract from SIP URI
+
+```typescript {4}
+import { SWMLService } from '@signalwire/sdk';
+
+const body = { call: { to: 'sip:sales@example.sip.signalwire.com' } };
+const username = SWMLService.extractSipUsername(body);
+// "sales"
+```
+
+### Extract from TEL URI
+
+```typescript {4}
+import { SWMLService } from '@signalwire/sdk';
+
+const body = { call: { to: 'tel:+15551234567' } };
+const number = SWMLService.extractSipUsername(body);
+// "+15551234567"
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/get-basic-auth-credentials.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/get-basic-auth-credentials.mdx
new file mode 100644
index 000000000..c04ecad01
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/get-basic-auth-credentials.mdx
@@ -0,0 +1,47 @@
+---
+title: "getBasicAuthCredentials"
+slug: /reference/typescript/agents/swml-service/get-basic-auth-credentials
+description: "Retrieve the HTTP Basic Auth credentials for the service."
+max-toc-depth: 3
+---
+
+[ref-swmlservice]: /docs/server-sdks/reference/typescript/agents/swml-service
+
+Retrieve the current HTTP Basic Auth credentials used by this service. Every
+[`SWMLService`][ref-swmlservice] instance has auth credentials -- either
+explicitly provided in the constructor, read from environment variables, or
+auto-generated at startup.
+
+## **Parameters**
+
+
+ When `true`, returns a 3-tuple that includes the credential source as the
+ third element. The source is one of:
+ - `"provided"` -- credentials were passed through constructor options
+ - `"environment"` -- credentials came from `SWML_BASIC_AUTH_USER` and `SWML_BASIC_AUTH_PASSWORD` environment variables
+ - `"auto-generated"` -- credentials were randomly generated at startup
+
+
+## **Returns**
+
+`[string, string]` -- A `[username, password]` tuple when `includeSource` is
+`false` or omitted.
+
+`[string, string, 'provided' | 'environment' | 'auto-generated']` -- A
+`[username, password, source]` tuple when `includeSource` is `true`.
+
+## **Example**
+
+```typescript {6,10}
+import { SWMLService } from '@signalwire/sdk';
+
+const service = new SWMLService({ name: 'my-service' });
+
+// Get credentials
+const [username, password] = service.getBasicAuthCredentials();
+console.log(`Auth: ${username}:${password}`);
+
+// Get credentials with source information
+const [user, pass, source] = service.getBasicAuthCredentials(true);
+console.log(`Auth source: ${source}`); // "provided", "environment", or "auto-generated"
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/get-builder.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/get-builder.mdx
index 04fce69ae..100e8d047 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/get-builder.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/get-builder.mdx
@@ -20,7 +20,7 @@ This method takes no parameters.
```typescript {4}
import { SWMLService } from '@signalwire/sdk';
-const sWMLService = new SWMLService();
-const result = sWMLService.getBuilder();
-console.log(result);
+const service = new SWMLService({ name: 'my-ivr' });
+const builder = service.getBuilder();
+builder.addVerb('answer', {});
```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/get-document.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/get-document.mdx
new file mode 100644
index 000000000..18e40cbbb
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/get-document.mdx
@@ -0,0 +1,48 @@
+---
+title: "getDocument"
+slug: /reference/typescript/agents/swml-service/get-document
+description: "Get the current SWML document as a plain object."
+max-toc-depth: 3
+---
+
+[ref-renderdocument]: /docs/server-sdks/reference/typescript/agents/swml-service/render-document
+[ref-renderswml]: /docs/server-sdks/reference/typescript/agents/swml-service/render-swml
+
+Get the current SWML document as a plain JavaScript object. The returned
+structure follows the standard SWML format with `version` and `sections` keys.
+
+
+Functionally identical to [`renderSwml()`][ref-renderswml]; `getDocument()` exists
+as a Python-compat alias. Use [`renderDocument()`][ref-renderdocument] when you
+need a JSON string rather than an object.
+
+
+## **Returns**
+
+`Record` — The current SWML document. Structure:
+
+```json
+{
+ "version": "1.0.0",
+ "sections": {
+ "main": [
+ {"answer": {}},
+ {"ai": {}}
+ ]
+ }
+}
+```
+
+## **Example**
+
+```typescript {7}
+import { SWMLService } from '@signalwire/sdk';
+
+const service = new SWMLService({ name: 'my-service' });
+service.addVerb('answer', {});
+service.addVerb('play', { url: 'https://example.com/audio.mp3' });
+
+const doc = service.getDocument();
+console.log((doc as any).version); // "1.0.0"
+console.log(((doc as any).sections.main as []).length); // 2
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/index.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/index.mdx
index afce27a36..ca8d506ac 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/index.mdx
@@ -29,24 +29,47 @@ See the [SWML reference][swml-reference] for the full document specification.
## **Constructor**
-
- Optional configuration object.
+
+ Configuration object.
-
- Service display name used in logging and startup messages.
+
+ Service display name used in logging and startup messages. Required to
+ match the Python SDK, where `name` is a positional required parameter.
HTTP route path where the service is accessible.
+
+ Host the HTTP server binds to.
+
+
+
+ Port the HTTP server binds to. Defaults to the `PORT` environment variable,
+ falling back to `3000`.
+
+
Basic auth credentials as `[username, password]`. Unlike `AgentBase`,
`SWMLService` does not fall back to environment variables — credentials
must be provided explicitly.
+
+
+ Path to a JSON Schema file for verb validation.
+
+
+
+ Path to a security configuration file for SSL, CORS, and host allowlist settings.
+
+
+
+ Enable schema validation. Can also be disabled via the
+ `SWML_SKIP_SCHEMA_VALIDATION=true` environment variable.
+
## **Properties**
@@ -59,27 +82,110 @@ See the [SWML reference][swml-reference] for the full document specification.
HTTP route path where this service is accessible.
+
+ Host address the HTTP server binds to.
+
+
+
+ Port the HTTP server binds to.
+
+
+
+ Structured logger bound to this service name. Exposed for subclass access.
+
+
+
+ Unified security configuration loaded from environment variables and optional
+ config file. Controls SSL, CORS, and host allowlist settings.
+
+
+
+ Whether SSL/HTTPS is enabled. Mirrors `security.sslEnabled`.
+
+
+
+ Path to the SSL certificate file.
+
+
+
+ Path to the SSL private key file.
+
+
+
+ Domain name for SSL certificates.
+
+
+
+ Schema validation utilities for SWML documents.
+
+
+
+ Registry of custom verb handlers for specialized SWML verb processing.
+
+
## **Methods**
Add a SWML verb to the document.
+
+ Add a new named section to the document.
+
+
+ Add a verb to a specific named section.
+
+
+ Reset the document to an empty state.
+
Render the SWML document as an object.
+
+ Get the SWML document as an object (Python-compat alias).
+
+
+ Render the SWML document as a JSON string.
+
Set a per-request callback for dynamic SWML generation.
+
+ Subclass override hook for per-request SWML.
+
+
+ Register a custom verb handler.
+
+
+ Register a routing callback at a given path.
+
+
+ Extract the username from a SIP URI (static).
+
+
+ Retrieve HTTP Basic Auth credentials.
+
+
+ Manually set the proxy URL for webhook generation.
+
Get the Hono app for mounting or testing.
+
+ Get the Hono app (Python-compat alias for getApp).
+
Get the underlying SwmlBuilder instance.
Start the HTTP server.
+
+ Start the HTTP server (Python-compat alias for run).
+
+
+ Stop the HTTP server.
+
## **Example**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/manual-set-proxy-url.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/manual-set-proxy-url.mdx
new file mode 100644
index 000000000..b5f62593e
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/manual-set-proxy-url.mdx
@@ -0,0 +1,46 @@
+---
+title: "manualSetProxyUrl"
+slug: /reference/typescript/agents/swml-service/manual-set-proxy-url
+description: "Manually set the proxy URL base for webhook callback generation."
+max-toc-depth: 3
+---
+
+Manually set the proxy URL base used for generating webhook callback URLs.
+Call this when automatic proxy detection does not work for your deployment
+(e.g., behind a custom load balancer or tunneling service).
+
+Overrides any value auto-detected from the `SWML_PROXY_URL_BASE` environment
+variable or inferred from request headers, and clears the "from env" flag so
+subsequent env changes won't overwrite your explicit setting.
+
+
+The proxy URL affects how webhook URLs are generated for SWAIG function
+callbacks, post-prompt URLs, and other webhook endpoints. Without a correct
+proxy URL, SignalWire cannot reach your service's webhook endpoints when
+deployed behind a reverse proxy or tunnel.
+
+
+## **Parameters**
+
+
+ The base URL to use for webhook generation (e.g., `"https://my-agent.ngrok.io"`).
+ Trailing slashes are stripped automatically. Empty strings are ignored.
+
+
+## **Returns**
+
+`this` -- returns the service for fluent chaining.
+
+## **Example**
+
+```typescript {6}
+import { SWMLService } from '@signalwire/sdk';
+
+const service = new SWMLService({ name: 'my-service' });
+
+// Set proxy URL for ngrok tunnel
+service.manualSetProxyUrl('https://abc123.ngrok.io');
+
+service.addVerb('answer', {});
+await service.serve();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/on-request.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/on-request.mdx
new file mode 100644
index 000000000..cd7dec7d8
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/on-request.mdx
@@ -0,0 +1,90 @@
+---
+title: "onRequest"
+slug: /reference/typescript/agents/swml-service/on-request
+description: "Subclass override hook for dynamic per-request SWML generation."
+max-toc-depth: 3
+---
+
+[ref-registerroutingcallback]: /docs/server-sdks/reference/typescript/agents/swml-service/register-routing-callback
+[ref-setonrequestcallback]: /docs/server-sdks/reference/typescript/agents/swml-service/set-on-request-callback
+[ref-swmlbuilder]: /docs/server-sdks/reference/typescript/agents/swml-builder
+
+Protected hook method called on every inbound SWML request, before the document
+is returned to SignalWire. Override this in a subclass to inspect the request
+and return a customized [`SwmlBuilder`][ref-swmlbuilder] for this request.
+
+Returning `null` delegates to the next handler in the chain (any callback
+registered via [`setOnRequestCallback()`][ref-setonrequestcallback], or the
+static builder). The default implementation returns `null`.
+
+
+The TypeScript signature differs from the Python SDK's `on_request(request_data,
+callback_path)` in two ways:
+
+1. TS receives query params, body params, and headers as separate arguments
+ instead of merged `request_data`.
+2. TS returns a full [`SwmlBuilder`][ref-swmlbuilder] instance (or `null`) rather
+ than a dictionary of modifications to merge. This means a TS override replaces
+ the document entirely rather than patching it.
+
+
+## **Parameters**
+
+
+ URL query parameters from the request.
+
+
+
+ Parsed POST body. Empty object for GET requests. Typically contains call
+ metadata from SignalWire (e.g., `call.to`, `call.from`, `call.headers`).
+
+
+
+ HTTP request headers.
+
+
+
+ The routing callback path that matched this request, if any. Set when the
+ request arrived through a path registered via
+ [`registerRoutingCallback()`][ref-registerroutingcallback]; `undefined` for
+ requests to the main route.
+
+
+## **Returns**
+
+`SwmlBuilder | null` -- a [`SwmlBuilder`][ref-swmlbuilder] whose document is
+served for this request, or `null` to delegate to the next handler.
+
+## **Example**
+
+```typescript {7}
+import { SWMLService, SwmlBuilder } from '@signalwire/sdk';
+
+class DynamicService extends SWMLService {
+ constructor() {
+ super({ name: 'dynamic-ivr', route: '/' });
+ }
+
+ protected onRequest(
+ _queryParams: Record,
+ bodyParams: Record,
+ _headers: Record,
+ ): SwmlBuilder | null {
+ const call = bodyParams?.call as Record | undefined;
+ const caller = (call?.from as string) ?? '';
+ if (caller.startsWith('+1555')) {
+ // Custom builder for VIP callers
+ const builder = new SwmlBuilder();
+ builder.answer();
+ builder.play({ url: 'https://example.com/vip-greeting.mp3' });
+ return builder;
+ }
+ return null; // Use default document
+ }
+}
+
+const service = new DynamicService();
+service.addVerb('answer', {});
+service.addVerb('play', { url: 'https://example.com/default.mp3' });
+await service.serve();
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/register-routing-callback.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/register-routing-callback.mdx
new file mode 100644
index 000000000..45ffe903f
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/register-routing-callback.mdx
@@ -0,0 +1,71 @@
+---
+title: "registerRoutingCallback"
+slug: /reference/typescript/agents/swml-service/register-routing-callback
+description: "Register routing callbacks for dynamic request handling and SIP routing."
+max-toc-depth: 3
+---
+
+[ref-serve]: /docs/server-sdks/reference/typescript/agents/swml-service/serve
+[ref-asrouter]: /docs/server-sdks/reference/typescript/agents/swml-service/as-router
+[ref-extractsipusername]: /docs/server-sdks/reference/typescript/agents/swml-service/extract-sip-username
+
+Register a callback for dynamic request routing. When a request arrives at the
+specified path, the callback inspects the POST body and decides whether to
+route the request to a different endpoint (via HTTP 307 redirect) or let
+normal SWML serving continue. Commonly used for SIP-based routing where the
+destination depends on the incoming SIP URI.
+
+A Hono endpoint is registered immediately for the specified path, serving both
+GET and POST.
+
+
+Unlike the Python SDK, the TypeScript `RoutingCallback` receives only the
+parsed request body -- not the underlying `Request` object. If you need access
+to headers or URL, use `asRouter()` and install custom middleware on the Hono
+app directly.
+
+
+## **Parameters**
+
+
+ A function that receives the parsed JSON request body. Return a route string
+ to redirect the request (HTTP 307 preserves the POST method and body), or
+ `null` / `undefined` to continue with normal SWML document serving. May be
+ async.
+
+ Type: `(body: Record) => string | null | undefined | Promise`
+
+
+
+ The URL path where this routing endpoint is created. The path is normalized:
+ a leading `/` is added if missing, trailing slashes are stripped.
+
+
+## **Returns**
+
+`void`
+
+## **Example**
+
+### Routing callback with SIP username
+
+```typescript {15}
+import { SWMLService } from '@signalwire/sdk';
+
+const service = new SWMLService({ name: 'sip-router', route: '/' });
+
+function routeSipCall(body: Record): string | null {
+ const username = SWMLService.extractSipUsername(body);
+ if (username === 'sales') return '/agents/sales';
+ if (username === 'support') return '/agents/support';
+ return null; // Default handling
+}
+
+service.addVerb('answer', {});
+service.registerRoutingCallback(routeSipCall, '/sip');
+
+await service.serve();
+```
+
+See also [`extractSipUsername()`][ref-extractsipusername] and
+[`serve()`][ref-serve] / [`asRouter()`][ref-asrouter].
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/register-verb-handler.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/register-verb-handler.mdx
new file mode 100644
index 000000000..8b4050a74
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/register-verb-handler.mdx
@@ -0,0 +1,63 @@
+---
+title: "registerVerbHandler"
+slug: /reference/typescript/agents/swml-service/register-verb-handler
+description: "Register custom verb handlers for specialized SWML verb processing."
+max-toc-depth: 3
+---
+
+[ref-addverb]: /docs/server-sdks/reference/typescript/agents/swml-service/add-verb
+
+Register a custom verb handler for specialized validation and configuration of
+a SWML verb. When a verb with a registered handler is added via
+[`addVerb()`][ref-addverb], the handler's
+`validateConfig()` method is used instead of generic schema validation.
+
+
+Custom verb handlers are useful when a verb has complex validation rules that
+go beyond JSON Schema checks -- for example, mutually exclusive parameters or
+conditional requirements.
+
+
+## **Parameters**
+
+
+ An object implementing the `SWMLVerbHandler` interface. Must implement three
+ methods:
+ - `getVerbName(): string` -- returns the verb name this handler manages
+ - `validateConfig(config): [boolean, string[]]` -- returns `[isValid, errors]`
+ - `buildConfig(opts): Record` -- returns a configuration object
+
+
+## **Returns**
+
+`void`
+
+## **Example**
+
+```typescript {21}
+import { SWMLService } from '@signalwire/sdk';
+import type { SWMLVerbHandler } from '@signalwire/sdk';
+
+const customHandler: SWMLVerbHandler = {
+ getVerbName() {
+ return 'my_verb';
+ },
+ validateConfig(config: Record) {
+ const errors: string[] = [];
+ if (!('target' in config)) {
+ errors.push("Missing required field 'target'");
+ }
+ return [errors.length === 0, errors];
+ },
+ buildConfig(opts: Record) {
+ return { target: opts.target };
+ },
+};
+
+const service = new SWMLService({ name: 'custom-service' });
+service.registerVerbHandler(customHandler);
+
+// Now addVerb will use the custom handler for validation
+service.addVerb('my_verb', { target: 'https://example.com' });
+console.log(service.renderDocument());
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/render-document.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/render-document.mdx
new file mode 100644
index 000000000..51e2156fb
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/render-document.mdx
@@ -0,0 +1,36 @@
+---
+title: "renderDocument"
+slug: /reference/typescript/agents/swml-service/render-document
+description: "Render the current SWML document as a JSON string."
+max-toc-depth: 3
+---
+
+[ref-getdocument]: /docs/server-sdks/reference/typescript/agents/swml-service/get-document
+[ref-renderswml]: /docs/server-sdks/reference/typescript/agents/swml-service/render-swml
+
+Render the current SWML document as a JSON string. This is the serialized form
+returned to SignalWire when a call requests SWML. Delegates to
+`SwmlBuilder.renderDocument()` under the hood.
+
+
+For the document as a plain object, use [`getDocument()`][ref-getdocument] or
+[`renderSwml()`][ref-renderswml] instead.
+
+
+## **Returns**
+
+`string` — The SWML document serialized as a JSON string.
+
+## **Example**
+
+```typescript {7}
+import { SWMLService } from '@signalwire/sdk';
+
+const service = new SWMLService({ name: 'my-service' });
+service.addVerb('answer', {});
+service.addVerb('hangup', {});
+
+const jsonStr = service.renderDocument();
+console.log(jsonStr);
+// '{"version":"1.0.0","sections":{"main":[{"answer":{}},{"hangup":{}}]}}'
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/reset-document.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/reset-document.mdx
new file mode 100644
index 000000000..52cd73a43
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/reset-document.mdx
@@ -0,0 +1,33 @@
+---
+title: "resetDocument"
+slug: /reference/typescript/agents/swml-service/reset-document
+description: "Reset the SWML document to an empty state."
+max-toc-depth: 3
+---
+
+[ref-swmlservice]: /docs/server-sdks/reference/typescript/agents/swml-service
+
+Reset the SWML document to an empty state. Clears all sections and verbs,
+leaving only an empty `main` section. Use this to rebuild the document from
+scratch without creating a new [`SWMLService`][ref-swmlservice] instance.
+
+## **Returns**
+
+`this` -- returns the service for fluent chaining.
+
+## **Example**
+
+```typescript {8}
+import { SWMLService } from '@signalwire/sdk';
+
+const service = new SWMLService({ name: 'my-service' });
+service.addVerb('answer', {});
+service.addVerb('play', { url: 'https://example.com/old.mp3' });
+
+// Start over with a fresh document
+service.resetDocument();
+service.addVerb('answer', {});
+service.addVerb('ai', { prompt: { text: 'You are a helpful assistant' } });
+
+console.log(service.renderDocument());
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/run.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/run.mdx
index 066ad7bf9..92d02deed 100644
--- a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/run.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/run.mdx
@@ -7,15 +7,45 @@ max-toc-depth: 3
Start the HTTP server to serve the SWML document.
+
+Returns immediately when `SWAIG_CLI_MODE=true` is set, so the CLI testing
+tool can load the service without opening a port.
+
+
## **Parameters**
-
- Hostname to bind to.
+
+ Hostname to bind to. Defaults to the `host` passed to the constructor, or `"0.0.0.0"`.
+
+
+
+ Port number to listen on. Defaults to the `port` passed to the constructor,
+ which itself falls back to the `PORT` environment variable or `3000`.
+
+
+
+ Optional SSL/TLS overrides. Each field falls back to the matching value on
+ the service instance.
+
+
+
+
+ Path to the SSL certificate file. When both `sslCert` and `sslKey` are
+ resolved and `sslEnabled` is `true`, the server runs over HTTPS.
+
+
+
+ Path to the SSL private key file.
+
+
+
+ Override whether SSL/HTTPS is enabled for this run.
-
- Port number to listen on. Falls back to the `PORT` environment variable.
+
+ Domain name associated with the SSL certificate.
+
## **Returns**
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/serve.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/serve.mdx
new file mode 100644
index 000000000..9e52d6617
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/serve.mdx
@@ -0,0 +1,80 @@
+---
+title: "serve"
+slug: /reference/typescript/agents/swml-service/serve
+description: "Start the HTTP server (Python-compat alias for run)."
+max-toc-depth: 3
+---
+
+[ref-run]: /docs/server-sdks/reference/typescript/agents/swml-service/run
+[ref-asrouter]: /docs/server-sdks/reference/typescript/agents/swml-service/as-router
+
+Start the HTTP server that serves the SWML document. This is a Python-compat
+alias for [`run()`][ref-run] and forwards all
+arguments unchanged. Use either name interchangeably -- pick `serve()` when
+porting code from the Python SDK.
+
+
+Returns immediately when `SWAIG_CLI_MODE=true` is set, so the CLI testing
+tool can load the service without opening a port.
+
+
+
+`serve()` (and `run()`) start a `@hono/node-server` instance that runs until
+explicitly stopped. For embedding into an existing application, use
+[`asRouter()`][ref-asrouter] to get a mountable Hono sub-app instead.
+
+
+## **Parameters**
+
+
+ Hostname to bind to. Defaults to the `host` passed to the constructor, or
+ `"0.0.0.0"`.
+
+
+
+ Port number to listen on. Defaults to the `port` passed to the constructor,
+ which itself falls back to the `PORT` environment variable or `3000`.
+
+
+
+ Optional SSL/TLS overrides. Each field falls back to the matching value on
+ the service instance.
+
+
+
+
+ Path to the SSL certificate file.
+
+
+
+ Path to the SSL private key file.
+
+
+
+ Override whether SSL/HTTPS is enabled for this run.
+
+
+
+ Domain name associated with the SSL certificate.
+
+
+
+## **Returns**
+
+`Promise` -- resolves once the listener is bound.
+
+## **Example**
+
+```typescript {8}
+import { SWMLService } from '@signalwire/sdk';
+
+const service = new SWMLService({ name: 'my-service', route: '/swml' });
+service.addVerb('answer', {});
+service.addVerb('play', { url: 'https://example.com/welcome.mp3' });
+
+// Start on default host/port (0.0.0.0:3000)
+await service.serve();
+
+// Or override host and port
+// await service.serve('127.0.0.1', 8080);
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/stop.mdx
new file mode 100644
index 000000000..052b5cbb2
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/agents/swml-service/stop.mdx
@@ -0,0 +1,38 @@
+---
+title: "stop"
+slug: /reference/typescript/agents/swml-service/stop
+description: "Stop the HTTP server started by run() or serve()."
+max-toc-depth: 3
+---
+
+[ref-run]: /docs/server-sdks/reference/typescript/agents/swml-service/run
+[ref-serve]: /docs/server-sdks/reference/typescript/agents/swml-service/serve
+
+Stop the HTTP server started by [`run()`][ref-run] or
+[`serve()`][ref-serve]. Closes the underlying `@hono/node-server`
+instance and releases the port.
+
+
+Unlike the Python counterpart (which only flips an internal flag), the TypeScript
+`stop()` actually closes the listener. It is safe to call when no server is
+running -- it no-ops if the service hasn't been started.
+
+
+## **Returns**
+
+`void`
+
+## **Example**
+
+```typescript {8}
+import { SWMLService } from '@signalwire/sdk';
+
+const service = new SWMLService({ name: 'my-service' });
+await service.run({ host: '0.0.0.0', port: 3000 });
+
+// In a signal handler or shutdown hook:
+process.on('SIGINT', () => {
+ service.stop();
+ process.exit(0);
+});
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/ai-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/ai-action/index.mdx
index e98e70c2b..f2cff576e 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/ai-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/ai-action/index.mdx
@@ -40,7 +40,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/ai-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/ai-action/stop.mdx
index 8923a6a8d..5253c3a8e 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/ai-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/ai-action/stop.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/index.mdx
index ce002ce70..1ecd31ba7 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/index.mdx
@@ -51,7 +51,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/start-input-timers.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/start-input-timers.mdx
index afa425996..57d467a12 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/start-input-timers.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/start-input-timers.mdx
@@ -19,7 +19,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/stop.mdx
index b96fcf521..6ea448271 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/stop.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/volume.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/volume.mdx
index e7d1dc205..b500a5600 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/volume.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/collect-action/volume.mdx
@@ -24,7 +24,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/detect-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/detect-action/index.mdx
index cf1390913..b82c1fa9a 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/detect-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/detect-action/index.mdx
@@ -42,7 +42,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -53,7 +53,7 @@ client.onCall(async (call) => {
params: { initialTimeout: 5.0 },
});
- const event = await action.wait(10000);
+ const event = await action.wait(10);
const detectResult = event.params.detect ?? {};
console.log(`Detected: ${JSON.stringify(detectResult)}`);
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/detect-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/detect-action/stop.mdx
index a3a53c736..33a044d94 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/detect-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/detect-action/stop.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/fax-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/fax-action/index.mdx
index 9e75bf73d..fea90037d 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/fax-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/fax-action/index.mdx
@@ -37,7 +37,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/fax-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/fax-action/stop.mdx
index 6604751e6..de28ca74c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/fax-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/fax-action/stop.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/index.mdx
index 5d39a740c..386a844bc 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/index.mdx
@@ -40,7 +40,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -89,8 +89,8 @@ All action classes share these properties and methods.
Await the action's completion and return the terminal event.
- Maximum milliseconds to wait. `undefined` waits indefinitely. Throws an `Error`
- if exceeded.
+ Maximum seconds to wait (matches Python SDK convention). `undefined` waits
+ indefinitely. Throws an `Error` if exceeded.
## **Subclasses**
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/pay-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/pay-action/index.mdx
index 2e51e62fb..4789cfef1 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/pay-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/pay-action/index.mdx
@@ -35,7 +35,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/pay-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/pay-action/stop.mdx
index 2f1d0d957..ddb255f97 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/pay-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/pay-action/stop.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/index.mdx
index 1d1f3e28b..32c705686 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/index.mdx
@@ -47,7 +47,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/pause.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/pause.mdx
index 546468abb..c2401a3e8 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/pause.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/pause.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/resume.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/resume.mdx
index 30c7da640..b8762d419 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/resume.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/resume.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/stop.mdx
index 0d66f6e71..72e157a0c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/stop.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/volume.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/volume.mdx
index acdd55445..66cddd4a6 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/volume.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/play-action/volume.mdx
@@ -24,7 +24,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/index.mdx
index 0c57a017c..289fcab5a 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/index.mdx
@@ -43,7 +43,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/pause.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/pause.mdx
index 48287e77d..0b011e6ba 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/pause.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/pause.mdx
@@ -25,7 +25,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/resume.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/resume.mdx
index d7d859952..54ded3ef7 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/resume.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/resume.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/stop.mdx
index ba5069fdf..e631e1efb 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/record-action/stop.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/index.mdx
index afbd9c4c3..1ae453042 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/index.mdx
@@ -40,14 +40,14 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
client.onCall(async (call) => {
await call.answer();
const action = await call.collect({
- speech: { endSilenceTimeout: 2.0 },
+ speech: { end_silence_timeout: 2.0 },
initialTimeout: 10.0,
startInputTimers: false,
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/start-input-timers.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/start-input-timers.mdx
index 075893f1a..1044536a6 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/start-input-timers.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/start-input-timers.mdx
@@ -19,14 +19,14 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
client.onCall(async (call) => {
await call.answer();
const action = await call.collect({
- speech: { endSilenceTimeout: 2.0 },
+ speech: { end_silence_timeout: 2.0 },
initialTimeout: 10.0,
startInputTimers: false,
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/stop.mdx
index 686236937..72e1457ed 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/standalone-collect-action/stop.mdx
@@ -18,14 +18,14 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
client.onCall(async (call) => {
await call.answer();
const action = await call.collect({
- speech: { endSilenceTimeout: 2.0 },
+ speech: { end_silence_timeout: 2.0 },
initialTimeout: 10.0,
startInputTimers: false,
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/stream-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/stream-action/index.mdx
index bac6492cf..e6749f04f 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/stream-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/stream-action/index.mdx
@@ -35,7 +35,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/stream-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/stream-action/stop.mdx
index 09a7be483..4bc681c7e 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/stream-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/stream-action/stop.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/tap-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/tap-action/index.mdx
index 88b419c59..f48a7603b 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/tap-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/tap-action/index.mdx
@@ -35,7 +35,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/tap-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/tap-action/stop.mdx
index 6e2daffea..b0c8f47df 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/tap-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/tap-action/stop.mdx
@@ -18,7 +18,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/transcribe-action/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/transcribe-action/index.mdx
index b759c13a7..97d20a5e6 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/transcribe-action/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/transcribe-action/index.mdx
@@ -36,7 +36,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/actions/transcribe-action/stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/actions/transcribe-action/stop.mdx
index 808ca28f5..ea5e7b7d5 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/actions/transcribe-action/stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/actions/transcribe-action/stop.mdx
@@ -19,7 +19,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-hold.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-hold.mdx
index 0a4eb1dbb..bdd47b9d2 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-hold.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-hold.mdx
@@ -37,7 +37,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-message.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-message.mdx
index a9aa669db..599ba6512 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-message.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-message.mdx
@@ -49,7 +49,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-unhold.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-unhold.mdx
index e1db38470..d146a25ca 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-unhold.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/ai-unhold.mdx
@@ -26,7 +26,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/ai.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/ai.mdx
index 5a143ea46..05ae64379 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/ai.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/ai.mdx
@@ -125,7 +125,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/amazon-bedrock.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/amazon-bedrock.mdx
index 8a039b52c..16827e0d4 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/amazon-bedrock.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/amazon-bedrock.mdx
@@ -48,7 +48,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/answer.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/answer.mdx
index 8cbdbdb86..5cf4b7d55 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/answer.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/answer.mdx
@@ -31,7 +31,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/bind-digit.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/bind-digit.mdx
index 0a3fa0368..cec98a77c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/bind-digit.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/bind-digit.mdx
@@ -51,7 +51,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/clear-digit-bindings.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/clear-digit-bindings.mdx
index 1ccedcd62..af76730ea 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/clear-digit-bindings.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/clear-digit-bindings.mdx
@@ -25,7 +25,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/collect.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/collect.mdx
index b19efe4b7..b62ee4794 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/collect.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/collect.mdx
@@ -102,7 +102,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/connect.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/connect.mdx
index 8af3ab1a6..6efe2f9a8 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/connect.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/connect.mdx
@@ -68,7 +68,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/denoise-stop.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/denoise-stop.mdx
index eb704eec0..6d8ad85f7 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/denoise-stop.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/denoise-stop.mdx
@@ -22,7 +22,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/denoise.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/denoise.mdx
index 033035569..7471a83ee 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/denoise.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/denoise.mdx
@@ -35,7 +35,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/detect.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/detect.mdx
index 4214eabb7..3c2eab6b9 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/detect.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/detect.mdx
@@ -66,7 +66,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/disconnect.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/disconnect.mdx
index b787105fa..716c27ec7 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/disconnect.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/disconnect.mdx
@@ -28,7 +28,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/echo.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/echo.mdx
index 5fd035b88..1a55fed92 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/echo.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/echo.mdx
@@ -38,7 +38,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/hangup.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/hangup.mdx
index d9b5e09c6..3be827d3d 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/hangup.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/hangup.mdx
@@ -30,7 +30,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/hold.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/hold.mdx
index 50af87005..73366fb40 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/hold.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/hold.mdx
@@ -35,7 +35,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/index.mdx
index 133d016f4..0a22a8fbf 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/index.mdx
@@ -248,7 +248,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/join-conference.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/join-conference.mdx
index 7320aa1ee..04512f580 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/join-conference.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/join-conference.mdx
@@ -120,7 +120,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/join-room.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/join-room.mdx
index 2a408a8d7..a402ef37c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/join-room.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/join-room.mdx
@@ -35,7 +35,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/leave-conference.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/leave-conference.mdx
index e76d23907..9e5d3471e 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/leave-conference.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/leave-conference.mdx
@@ -24,7 +24,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/leave-room.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/leave-room.mdx
index 717979e49..71a12e07f 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/leave-room.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/leave-room.mdx
@@ -20,7 +20,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/live-transcribe.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/live-transcribe.mdx
index 491316131..1e785989c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/live-transcribe.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/live-transcribe.mdx
@@ -50,7 +50,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/live-translate.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/live-translate.mdx
index 8f165f5f8..804a9f77b 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/live-translate.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/live-translate.mdx
@@ -46,7 +46,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/on.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/on.mdx
index e361639c6..71791eec8 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/on.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/on.mdx
@@ -37,7 +37,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/pass.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/pass.mdx
index b3aa859dc..1e84028d1 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/pass.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/pass.mdx
@@ -24,7 +24,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/pay.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/pay.mdx
index 173279c32..d2f7b61b8 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/pay.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/pay.mdx
@@ -114,7 +114,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/play-and-collect.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/play-and-collect.mdx
index 6652fd44f..6e19287d1 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/play-and-collect.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/play-and-collect.mdx
@@ -102,7 +102,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/play.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/play.mdx
index 72c61a3d6..96553cf40 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/play.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/play.mdx
@@ -72,7 +72,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -92,7 +92,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -117,7 +117,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/queue-enter.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/queue-enter.mdx
index 880120143..9ff196035 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/queue-enter.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/queue-enter.mdx
@@ -42,7 +42,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/queue-leave.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/queue-leave.mdx
index da89c7f4a..ea82ffe1f 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/queue-leave.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/queue-leave.mdx
@@ -44,7 +44,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/receive-fax.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/receive-fax.mdx
index 583133663..e89488575 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/receive-fax.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/receive-fax.mdx
@@ -40,7 +40,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/record.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/record.mdx
index 9688e8e29..9943bcad6 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/record.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/record.mdx
@@ -92,7 +92,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/refer.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/refer.mdx
index 60e77a373..4483db735 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/refer.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/refer.mdx
@@ -49,7 +49,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/send-digits.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/send-digits.mdx
index 44cf6dbfc..5652b9cf8 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/send-digits.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/send-digits.mdx
@@ -37,7 +37,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/send-fax.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/send-fax.mdx
index 413ab49d8..3c6f810ce 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/send-fax.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/send-fax.mdx
@@ -51,7 +51,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/stream.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/stream.mdx
index c9ff2aab0..c30ef8d10 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/stream.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/stream.mdx
@@ -82,7 +82,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/tap.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/tap.mdx
index 89f4850ca..ed15f70b4 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/tap.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/tap.mdx
@@ -75,7 +75,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/transcribe.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/transcribe.mdx
index a204aa2ea..9fbb5ece2 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/transcribe.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/transcribe.mdx
@@ -52,7 +52,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/transfer.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/transfer.mdx
index d01735232..f8b7b3ffd 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/transfer.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/transfer.mdx
@@ -26,7 +26,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/unhold.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/unhold.mdx
index e323dfa80..359ed2988 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/unhold.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/unhold.mdx
@@ -29,7 +29,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/user-event.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/user-event.mdx
index b4e8f6359..3bf3eee65 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/user-event.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/user-event.mdx
@@ -29,7 +29,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/wait-for-ended.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/wait-for-ended.mdx
index f8418542d..9b57c37a7 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/wait-for-ended.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/wait-for-ended.mdx
@@ -28,7 +28,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/call/wait-for.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/call/wait-for.mdx
index b3d1dc1a6..1942950e0 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/call/wait-for.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/call/wait-for.mdx
@@ -38,7 +38,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/connect.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/connect.mdx
index 733ff7f86..63ffa6328 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/connect.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/connect.mdx
@@ -34,7 +34,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/dial.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/dial.mdx
index 676c5681a..0b13d9d01 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/dial.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/dial.mdx
@@ -73,9 +73,9 @@ Throws `RelayError` if the dial fails or if no answer is received within the
limit is reached.
-
- How long in milliseconds to wait for the dial to complete (answer or failure) before
- throwing a timeout error.
+
+ How long in seconds to wait for the dial to complete (answer or failure) before
+ throwing a timeout error. Matches the Python SDK convention.
@@ -92,7 +92,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -122,7 +122,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -144,7 +144,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/disconnect.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/disconnect.mdx
index f37bde983..06014a1e9 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/disconnect.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/disconnect.mdx
@@ -34,7 +34,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -42,8 +42,8 @@ await client.connect();
// Do work ...
const message = await client.sendMessage({
- to: '+15559876543',
- from: '+15551234567',
+ toNumber: '+15559876543',
+ fromNumber: '+15551234567',
body: 'Hello!',
});
await message.wait();
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/execute.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/execute.mdx
index 57d15b54d..d71770f96 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/execute.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/execute.mdx
@@ -54,7 +54,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/index.mdx
index 6806d5b0c..e200fa6a0 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/index.mdx
@@ -32,23 +32,30 @@ token. Credentials can be passed directly or read from environment variables.
- API token for authentication. Set via constructor or `SIGNALWIRE_TOKEN` environment variable.
+ API token for authentication. Set via constructor or `SIGNALWIRE_API_TOKEN` environment variable.
- JWT token for alternative authentication. Read from the `SIGNALWIRE_JWT_TOKEN` environment variable.
+ JWT token for alternative authentication. Set via constructor or `SIGNALWIRE_JWT_TOKEN` environment variable.
When provided, `project` and `token` are not required.
-
+
SignalWire space hostname (e.g., `your-space.signalwire.com`). Set via constructor or `SIGNALWIRE_SPACE`
- environment variable. Defaults to `relay.signalwire.com`.
+ environment variable.
-
+
List of contexts to subscribe to for inbound call and message events.
+
+ Maximum number of concurrent inbound calls the client will track. Calls
+ arriving beyond this limit are dropped with a log warning. Set via constructor
+ or `RELAY_MAX_ACTIVE_CALLS` environment variable. Constructor-only -- not
+ accessible as a public attribute after initialization.
+
+
Server-assigned protocol string from the connect response. Read-only. Used internally
for session resumption on reconnect.
@@ -89,6 +96,34 @@ token. Credentials can be passed directly or read from environment variables.
+## **Async Disposable**
+
+`RelayClient` implements `Symbol.asyncDispose`, so it can be used with the
+`await using` statement for scoped connections. The client disconnects
+automatically when the scope exits.
+
+```typescript {4-5}
+import { RelayClient } from '@signalwire/sdk';
+
+async function main() {
+ await using client = new RelayClient({
+ project: process.env.SIGNALWIRE_PROJECT_ID!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
+ contexts: ['default'],
+ });
+ await client.connect();
+ const call = await client.dial([
+ [{ type: 'phone', params: { to_number: '+15559876543', from_number: '+15551234567' } }],
+ ]);
+ // Automatically disconnects on exit
+}
+
+await main();
+```
+
+For environments without `await using` support, use try/finally with
+`disconnect()`.
+
## **Example**
```typescript {3}
@@ -96,7 +131,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/on-call.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/on-call.mdx
index cd2759b6a..08a6c7ae5 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/on-call.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/on-call.mdx
@@ -24,7 +24,8 @@ the previous handler.
## **Returns**
-`void`
+`CallHandler` — the same handler, returned to support decorator-style usage
+(e.g., TypeScript 5 decorators or manual composition).
## **Example**
@@ -33,7 +34,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/on-message.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/on-message.mdx
index db73d25e8..df22c25cf 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/on-message.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/on-message.mdx
@@ -24,7 +24,8 @@ replaces the previous handler.
## **Returns**
-`void`
+`MessageHandler` — the same handler, returned to support decorator-style usage
+(e.g., TypeScript 5 decorators or manual composition).
## **Example**
@@ -33,7 +34,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/receive.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/receive.mdx
index dfd31d7bf..86df595bf 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/receive.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/receive.mdx
@@ -42,7 +42,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['sales']
});
@@ -62,7 +62,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['sales']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/run.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/run.mdx
index 27d77aa51..2dcceb745 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/run.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/run.mdx
@@ -39,7 +39,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/send-message.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/send-message.mdx
index 08166655c..df104b97e 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/send-message.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/send-message.mdx
@@ -19,11 +19,11 @@ with text and attached media.
## **Parameters**
-
+
Destination phone number in E.164 format (e.g., `"+15559876543"`).
-
+
Sender phone number in E.164 format. Must be a number owned by your SignalWire project.
@@ -68,21 +68,21 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
await client.connect();
const message = await client.sendMessage({
- to: '+15559876543',
- from: '+15551234567',
+ toNumber: '+15559876543',
+ fromNumber: '+15551234567',
body: 'Hello from SignalWire RELAY!',
});
console.log(`Message ID: ${message.messageId}`);
// Wait for delivery confirmation
-const result = await message.wait(30_000);
+const result = await message.wait(30);
console.log(`Final state: ${message.state}`);
await client.disconnect();
@@ -95,15 +95,15 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
await client.connect();
const message = await client.sendMessage({
- to: '+15559876543',
- from: '+15551234567',
+ toNumber: '+15559876543',
+ fromNumber: '+15551234567',
body: 'Check out this image!',
media: ['https://example.com/photo.jpg'],
});
@@ -118,15 +118,15 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
await client.connect();
const message = await client.sendMessage({
- to: '+15559876543',
- from: '+15551234567',
+ toNumber: '+15559876543',
+ fromNumber: '+15551234567',
body: 'Important notification',
onCompleted: (event) => {
console.log(`Message delivered: ${JSON.stringify(event.params)}`);
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/client/unreceive.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/client/unreceive.mdx
index ac756bc77..363a292ac 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/client/unreceive.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/client/unreceive.mdx
@@ -35,7 +35,7 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['sales', 'support', 'billing']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/constants.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/constants.mdx
index dc24dc32a..c029e06ae 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/constants.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/constants.mdx
@@ -1,22 +1,17 @@
---
title: "Constants"
slug: /reference/typescript/relay/constants
-description: "RELAY constants for call states, events, and message states."
+description: "RELAY constants for call states, connect states, event types, and message states."
max-toc-depth: 3
---
-[callstateevent-endreason]: /docs/server-sdks/reference/typescript/relay/events
[connectevent-connectstate]: /docs/server-sdks/reference/typescript/relay/events
[call-on]: /docs/server-sdks/reference/typescript/relay/call
[relayevent-eventtype]: /docs/server-sdks/reference/typescript/relay/events
-[message-wait]: /docs/server-sdks/reference/typescript/relay/message
-[playevent-state]: /docs/server-sdks/reference/typescript/relay/events
-[recordevent-state]: /docs/server-sdks/reference/typescript/relay/events
-[call-detect]: /docs/server-sdks/reference/typescript/relay/call/detect
-The `@signalwire/sdk` package exports string and numeric constants used
-throughout the RELAY namespace for call states, end reasons, connect states, event
-types, message states, media operation states, and protocol settings.
+The `@signalwire/sdk` package re-exports string constants for call states,
+connect states, event types, and message states. Import any of them from the
+package root:
```typescript {2-7}
import {
@@ -28,35 +23,6 @@ import {
} from '@signalwire/sdk';
```
-## Protocol
-
-
- RELAY protocol version. Value: `{ major: 2, minor: 0, revision: 0 }`.
-
-
-
- User agent string sent during connection. Value: `"@signalwire/sdk-typescript/2.0"`.
-
-
-
- Default WebSocket host for RELAY connections. Value: `"relay.signalwire.com"`.
-
-
-## JSON-RPC Methods
-
-Internal method identifiers used by the RELAY WebSocket protocol.
-
-| Constant | Value |
-|----------|-------|
-| `METHOD_SIGNALWIRE_CONNECT` | `"signalwire.connect"` |
-| `METHOD_SIGNALWIRE_EVENT` | `"signalwire.event"` |
-| `METHOD_SIGNALWIRE_PING` | `"signalwire.ping"` |
-| `METHOD_SIGNALWIRE_DISCONNECT` | `"signalwire.disconnect"` |
-| `METHOD_SIGNALWIRE_RECEIVE` | `"signalwire.receive"` |
-| `METHOD_SIGNALWIRE_UNRECEIVE` | `"signalwire.unreceive"` |
-
----
-
## Call States
Constants representing the lifecycle states of a RELAY call. A call progresses
@@ -70,29 +36,6 @@ through these states in order: `created` -> `ringing` -> `answered` -> `ending`
| `CALL_STATE_ENDING` | `"ending"` | Call is in the process of ending |
| `CALL_STATE_ENDED` | `"ended"` | Call has ended |
-
- Array of all call states in lifecycle order:
- `['created', 'ringing', 'answered', 'ending', 'ended']`.
-
-
-## End Reasons
-
-Constants for the reason a call ended. Available in
-[`CallStateEvent.endReason`][callstateevent-endreason] when the call
-reaches the `ended` state.
-
-| Constant | Value | Description |
-|----------|-------|-------------|
-| `END_REASON_HANGUP` | `"hangup"` | Normal hangup by either party |
-| `END_REASON_CANCEL` | `"cancel"` | Call was cancelled before answer |
-| `END_REASON_BUSY` | `"busy"` | Destination returned busy |
-| `END_REASON_NO_ANSWER` | `"noAnswer"` | No answer within timeout |
-| `END_REASON_DECLINE` | `"decline"` | Call was declined |
-| `END_REASON_ERROR` | `"error"` | An error occurred |
-| `END_REASON_ABANDONED` | `"abandoned"` | Call was abandoned (e.g., caller hung up in queue) |
-| `END_REASON_MAX_DURATION` | `"max_duration"` | Call exceeded maximum allowed duration |
-| `END_REASON_NOT_FOUND` | `"not_found"` | Destination not found |
-
---
## Connect States
@@ -111,9 +54,9 @@ Constants representing the state of a call bridge (connect) operation. Used in
## Event Types
-String constants for all RELAY event types. Use these when registering event
-handlers with [`Call.on()`][call-on] or when
-matching against [`RelayEvent.eventType`][relayevent-eventtype].
+String constants for RELAY event types. Use these when registering event
+handlers with [`Call.on()`][call-on] or when matching against
+[`RelayEvent.eventType`][relayevent-eventtype].
### Calling Events
@@ -148,12 +91,6 @@ matching against [`RelayEvent.eventType`][relayevent-eventtype].
| `EVENT_MESSAGING_RECEIVE` | `"messaging.receive"` |
| `EVENT_MESSAGING_STATE` | `"messaging.state"` |
-### Authorization Event
-
-| Constant | Value |
-|----------|-------|
-| `EVENT_AUTHORIZATION_STATE` | `"signalwire.authorization.state"` |
-
---
## Message States
@@ -172,75 +109,6 @@ messages progress through: `queued` -> `initiated` -> `sent` -> `delivered`
| `MESSAGE_STATE_FAILED` | `"failed"` | Message send failed |
| `MESSAGE_STATE_RECEIVED` | `"received"` | Inbound message received |
-
- Array of terminal states that resolve a [`Message.wait()`][message-wait] call:
- `['delivered', 'undelivered', 'failed']`.
-
-
-## Play States
-
-Constants for audio playback operation states. Used in
-[`PlayEvent.state`][playevent-state].
-
-| Constant | Value | Description |
-|----------|-------|-------------|
-| `PLAY_STATE_PLAYING` | `"playing"` | Audio is playing |
-| `PLAY_STATE_PAUSED` | `"paused"` | Playback is paused |
-| `PLAY_STATE_FINISHED` | `"finished"` | Playback completed |
-| `PLAY_STATE_ERROR` | `"error"` | Playback error occurred |
-
----
-
-## Record States
-
-Constants for recording operation states. Used in
-[`RecordEvent.state`][recordevent-state].
-
-| Constant | Value | Description |
-|----------|-------|-------------|
-| `RECORD_STATE_RECORDING` | `"recording"` | Recording is active |
-| `RECORD_STATE_PAUSED` | `"paused"` | Recording is paused |
-| `RECORD_STATE_FINISHED` | `"finished"` | Recording completed |
-| `RECORD_STATE_NO_INPUT` | `"no_input"` | No audio input detected |
-
----
-
-## Detect Types
-
-Constants for detection operation types. Used in the `type` field of the
-`detect` parameter passed to [`call.detect()`][call-detect].
-
-| Constant | Value | Description |
-|----------|-------|-------------|
-| `DETECT_TYPE_MACHINE` | `"machine"` | Answering machine detection |
-| `DETECT_TYPE_FAX` | `"fax"` | Fax tone detection |
-| `DETECT_TYPE_DIGIT` | `"digit"` | DTMF digit detection |
-
----
-
-## Room States
-
-Constants for audio/video room join/leave states.
-
-| Constant | Value | Description |
-|----------|-------|-------------|
-| `ROOM_STATE_JOINING` | `"joining"` | Joining the room |
-| `ROOM_STATE_JOIN` | `"join"` | Successfully joined |
-| `ROOM_STATE_LEAVING` | `"leaving"` | Leaving the room |
-| `ROOM_STATE_LEAVE` | `"leave"` | Successfully left |
-
----
-
-## Reconnect Settings
-
-Configuration constants for the WebSocket reconnection strategy.
-
-| Constant | Value | Description |
-|----------|-------|-------------|
-| `RECONNECT_MIN_DELAY` | `1.0` | Minimum delay between reconnect attempts (seconds) |
-| `RECONNECT_MAX_DELAY` | `30.0` | Maximum delay between reconnect attempts (seconds) |
-| `RECONNECT_BACKOFF_FACTOR` | `2.0` | Exponential backoff multiplier |
-
## **Example**
```typescript {12}
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/events.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/events.mdx
index 78820d405..1c30d1600 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/events.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/events.mdx
@@ -33,7 +33,7 @@ import { RelayClient, CallStateEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -206,11 +206,11 @@ Handlers for this event receive a `CallStateEvent` with the following properties
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, CallStateEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -296,11 +296,11 @@ Handlers for this event receive a `PlayEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, PlayEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -359,11 +359,11 @@ Handlers for this event receive a `RecordEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, RecordEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -420,11 +420,11 @@ Handlers for this event receive a `CollectEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, CollectEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -470,11 +470,11 @@ Handlers for this event receive a `ConnectEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, ConnectEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -518,11 +518,11 @@ Handlers for this event receive a `DetectEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, DetectEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -562,11 +562,11 @@ Handlers for this event receive a `FaxEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, FaxEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -614,11 +614,11 @@ Handlers for this event receive a `TapEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, TapEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -665,11 +665,11 @@ Handlers for this event receive a `StreamEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, StreamEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -706,11 +706,11 @@ Handlers for this event receive a `SendDigitsEvent` with the following propertie
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, SendDigitsEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -779,11 +779,11 @@ Handlers for this event receive a `ReferEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, ReferEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -818,11 +818,11 @@ Handlers for this event receive a `HoldEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, HoldEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -855,11 +855,11 @@ Handlers for this event receive a `DenoiseEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, DenoiseEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -899,11 +899,11 @@ Handlers for this event receive a `PayEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, PayEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -936,11 +936,11 @@ Handlers for this event receive an `EchoEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, EchoEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -995,11 +995,11 @@ Handlers for this event receive a `QueueEvent` with the following properties:
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, QueueEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -1040,11 +1040,11 @@ Handlers for this event receive a `ConferenceEvent` with the following propertie
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, ConferenceEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -1099,11 +1099,11 @@ Handlers for this event receive a `TranscribeEvent` with the following propertie
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, TranscribeEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -1140,11 +1140,11 @@ Handlers for this event receive a `CallingErrorEvent` with the following propert
#### Example
```typescript {14}
-import { RelayClient } from '@signalwire/sdk';
+import { RelayClient, CallingErrorEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
@@ -1279,7 +1279,7 @@ import { RelayClient, MessageStateEvent } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/message/index.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/message/index.mdx
index af35dc75e..9934cf294 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/message/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/message/index.mdx
@@ -27,20 +27,20 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
await client.connect();
const message = await client.sendMessage({
- to: '+15551234567',
- from: '+15559876543',
+ toNumber: '+15551234567',
+ fromNumber: '+15559876543',
body: 'Hello from SignalWire!',
});
// Wait for delivery confirmation
-const result = await message.wait(30_000);
+const result = await message.wait(30);
console.log(`Final state: ${message.state}`);
await client.disconnect();
@@ -142,15 +142,15 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
await client.connect();
const message = await client.sendMessage({
- to: '+15551234567',
- from: '+15559876543',
+ toNumber: '+15551234567',
+ fromNumber: '+15559876543',
body: 'Order confirmed',
});
@@ -171,20 +171,20 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
await client.connect();
const message = await client.sendMessage({
- to: '+15551234567',
- from: '+15559876543',
+ toNumber: '+15551234567',
+ fromNumber: '+15559876543',
body: 'Your verification code is 123456',
});
try {
- const event = await message.wait(30_000);
+ const event = await message.wait(30);
if (message.state === 'delivered') {
console.log('Message delivered successfully');
} else {
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/message/on.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/message/on.mdx
index 3cc650117..9b044d22c 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/message/on.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/message/on.mdx
@@ -29,15 +29,15 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
await client.connect();
const message = await client.sendMessage({
- to: '+15551234567',
- from: '+15559876543',
+ toNumber: '+15551234567',
+ fromNumber: '+15559876543',
body: 'Order confirmed',
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/message/wait.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/message/wait.mdx
index 12620b8cc..aaeee2be8 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/message/wait.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/message/wait.mdx
@@ -18,7 +18,8 @@ reach a terminal state within the given duration.
## **Parameters**
- Maximum number of milliseconds to wait. `undefined` waits indefinitely.
+ Maximum seconds to wait (matches Python SDK convention). `undefined` waits
+ indefinitely.
## **Returns**
@@ -33,20 +34,20 @@ import { RelayClient } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default']
});
await client.connect();
const message = await client.sendMessage({
- to: '+15551234567',
- from: '+15559876543',
+ toNumber: '+15551234567',
+ fromNumber: '+15559876543',
body: 'Your verification code is 123456',
});
try {
- const event = await message.wait(30_000);
+ const event = await message.wait(30);
if (message.state === 'delivered') {
console.log('Message delivered successfully');
} else {
diff --git a/fern/products/server-sdks/pages/reference/typescript/relay/relay-error.mdx b/fern/products/server-sdks/pages/reference/typescript/relay/relay-error.mdx
index 6db8ebc34..0d66deb98 100644
--- a/fern/products/server-sdks/pages/reference/typescript/relay/relay-error.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/relay/relay-error.mdx
@@ -14,7 +14,7 @@ import { RelayError } from '@signalwire/sdk';
## **Properties**
-
+
Numeric error code returned by the RELAY server.
@@ -35,7 +35,7 @@ import { RelayClient, RelayError } from '@signalwire/sdk';
const client = new RelayClient({
project: process.env.SIGNALWIRE_PROJECT_ID!,
- token: process.env.SIGNALWIRE_TOKEN!,
+ token: process.env.SIGNALWIRE_API_TOKEN!,
contexts: ['default'],
});
diff --git a/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/index.mdx b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/index.mdx
index 6cdc4b270..10b33bf19 100644
--- a/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/index.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/index.mdx
@@ -1,7 +1,7 @@
---
title: "Phone Numbers"
slug: /reference/typescript/rest/phone-numbers
-description: "Search and manage phone numbers."
+description: "Search and manage phone numbers, and bind inbound calls to handlers."
max-toc-depth: 3
---
@@ -12,13 +12,29 @@ max-toc-depth: 3
[update]: /docs/server-sdks/reference/typescript/rest/phone-numbers/update
[delete]: /docs/server-sdks/reference/typescript/rest/phone-numbers/delete
[search]: /docs/server-sdks/reference/typescript/rest/phone-numbers/search
+[setswml]: /docs/server-sdks/reference/typescript/rest/phone-numbers/set-swml-webhook
+[setcxml]: /docs/server-sdks/reference/typescript/rest/phone-numbers/set-cxml-webhook
+[setcxmlapp]: /docs/server-sdks/reference/typescript/rest/phone-numbers/set-cxml-application
+[setai]: /docs/server-sdks/reference/typescript/rest/phone-numbers/set-ai-agent
+[setflow]: /docs/server-sdks/reference/typescript/rest/phone-numbers/set-call-flow
+[setrelayapp]: /docs/server-sdks/reference/typescript/rest/phone-numbers/set-relay-application
+[setrelaytopic]: /docs/server-sdks/reference/typescript/rest/phone-numbers/set-relay-topic
Search for available phone numbers, purchase them, and manage the numbers in your
SignalWire project. This resource extends the standard CRUD pattern with a `search()`
-method for discovering available numbers and uses PUT for updates.
+method for discovering available numbers, uses PUT for updates, and provides typed
+helpers for binding inbound calls to a handler (SWML webhook, cXML webhook, AI agent,
+call flow, RELAY application/topic).
Access via `client.phoneNumbers` on a [`RestClient`][restclient] instance.
+
+**Idiomatic deviation:** `create()` and `update()` accept an untyped body
+object (`Record`) rather than narrow per-field types. This
+mirrors Python's `**kwargs`-style flexibility. Response payloads follow the
+same typing.
+
+
```typescript {9}
import { RestClient } from "@signalwire/sdk";
@@ -36,6 +52,8 @@ for (const number of available.data ?? []) {
## **Methods**
+### Standard CRUD
+
List phone numbers owned by the project.
@@ -56,3 +74,67 @@ for (const number of available.data ?? []) {
Search for available phone numbers to purchase.
+
+### Typed Binding Helpers
+
+Each helper is a one-line wrapper over [`update`][update] that sets `call_handler`
+to the right value and populates the handler-specific companion field for you.
+Pass extra wire-level fields through the `extra` argument (or as additional keys
+on the params object) for fields the helper doesn't name explicitly. Setting a
+binding auto-materializes the matching Fabric resource on the server.
+
+
+
+ Route inbound calls to an SWML webhook URL.
+
+
+ Route inbound calls to a cXML (LAML) webhook.
+
+
+ Route inbound calls to an existing cXML application by ID.
+
+
+ Route inbound calls to an AI Agent Fabric resource by ID.
+
+
+ Route inbound calls to a Call Flow by ID.
+
+
+ Route inbound calls to a named RELAY application.
+
+
+ Route inbound calls to a RELAY topic.
+
+
+
+## **PhoneCallHandler**
+
+For callers passing `call_handler` directly to [`update`][update], the
+`PhoneCallHandler` const provides typed values. It is a `const`-as-enum
+(`as const` object plus a same-named string-union type), so passing a member
+serializes to its wire value with full type-checking on the call site.
+
+```typescript
+import { PhoneCallHandler } from "@signalwire/sdk";
+
+await client.phoneNumbers.update("phone-number-id", {
+ call_handler: PhoneCallHandler.AI_AGENT,
+ call_ai_agent_id: "ai-agent-id",
+});
+```
+
+| Member | Wire value | Companion field | Auto-creates |
+|--------------------|----------------------|----------------------------|---------------------|
+| `RELAY_SCRIPT` | `relay_script` | `call_relay_script_url` | `swml_webhook` |
+| `LAML_WEBHOOKS` | `laml_webhooks` | `call_request_url` | `cxml_webhook` |
+| `LAML_APPLICATION` | `laml_application` | `call_laml_application_id` | `cxml_application` |
+| `AI_AGENT` | `ai_agent` | `call_ai_agent_id` | `ai_agent` |
+| `CALL_FLOW` | `call_flow` | `call_flow_id` | `call_flow` |
+| `RELAY_APPLICATION`| `relay_application` | `call_relay_application` | `relay_application` |
+| `RELAY_TOPIC` | `relay_topic` | `call_relay_topic` | (routes via RELAY) |
+
+
+`LAML_WEBHOOKS` (wire value `laml_webhooks`) produces a **cXML** handler, not a
+generic webhook. For SWML, use `RELAY_SCRIPT` -- or, more conveniently, the
+[`setSwmlWebhook`][setswml] helper.
+
diff --git a/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-ai-agent.mdx b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-ai-agent.mdx
new file mode 100644
index 000000000..04a05fbdb
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-ai-agent.mdx
@@ -0,0 +1,46 @@
+---
+title: "setAiAgent"
+slug: /reference/typescript/rest/phone-numbers/set-ai-agent
+description: Route inbound calls to an AI Agent Fabric resource by ID.
+max-toc-depth: 3
+---
+
+[update]: /docs/server-sdks/reference/typescript/rest/phone-numbers/update
+
+Route inbound calls on this phone number to an existing AI Agent Fabric resource
+by its ID.
+
+This is a typed wrapper over [`update`][update] that sets `call_handler` to
+`ai_agent` and populates `call_ai_agent_id` for you.
+
+## **Parameters**
+
+
+ ID of the phone number to bind.
+
+
+
+ ID of the AI Agent Fabric resource to route calls to.
+
+
+
+ Additional wire-level fields merged into the PUT body.
+
+
+## **Returns**
+
+`Promise` — The updated phone-number resource.
+
+## **Example**
+
+```typescript {9}
+import { RestClient } from "@signalwire/sdk";
+
+const client = new RestClient({
+ project: "your-project-id",
+ token: "your-api-token",
+ host: "your-space.signalwire.com"
+});
+
+await client.phoneNumbers.setAiAgent("phone-number-id", "ai-agent-id");
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-call-flow.mdx b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-call-flow.mdx
new file mode 100644
index 000000000..39b5e7cdd
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-call-flow.mdx
@@ -0,0 +1,54 @@
+---
+title: "setCallFlow"
+slug: /reference/typescript/rest/phone-numbers/set-call-flow
+description: Route inbound calls to a Call Flow by ID.
+max-toc-depth: 3
+---
+
+[update]: /docs/server-sdks/reference/typescript/rest/phone-numbers/update
+
+Route inbound calls on this phone number to an existing Call Flow by its ID.
+
+This is a typed wrapper over [`update`][update] that sets `call_handler` to
+`call_flow` and populates `call_flow_id` for you.
+
+## **Parameters**
+
+
+ ID of the phone number to bind.
+
+
+
+ Flow ID and options.
+
+
+
+ ID of the Call Flow to route calls to. Serialized as `call_flow_id`.
+
+
+
+ Which Call Flow version to invoke. Accepts `"working_copy"` or
+ `"current_deployed"`. Defaults to the server's current deployed version when
+ omitted. Serialized as `call_flow_version`.
+
+
+## **Returns**
+
+`Promise` — The updated phone-number resource.
+
+## **Example**
+
+```typescript {9-12}
+import { RestClient } from "@signalwire/sdk";
+
+const client = new RestClient({
+ project: "your-project-id",
+ token: "your-api-token",
+ host: "your-space.signalwire.com"
+});
+
+await client.phoneNumbers.setCallFlow("phone-number-id", {
+ flowId: "call-flow-id",
+ version: "working_copy",
+});
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-cxml-application.mdx b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-cxml-application.mdx
new file mode 100644
index 000000000..adb1203b7
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-cxml-application.mdx
@@ -0,0 +1,47 @@
+---
+title: "setCxmlApplication"
+slug: /reference/typescript/rest/phone-numbers/set-cxml-application
+description: Route inbound calls to an existing cXML application by ID.
+max-toc-depth: 3
+---
+
+[update]: /docs/server-sdks/reference/typescript/rest/phone-numbers/update
+
+Route inbound calls on this phone number to an existing cXML (LAML) application
+by its ID. The server auto-creates a `cxml_application` Fabric resource
+referencing the application.
+
+This is a typed wrapper over [`update`][update] that sets `call_handler` to
+`laml_application` and populates `call_laml_application_id` for you.
+
+## **Parameters**
+
+
+ ID of the phone number to bind.
+
+
+
+ ID of the cXML application to route calls to.
+
+
+
+ Additional wire-level fields merged into the PUT body.
+
+
+## **Returns**
+
+`Promise` — The updated phone-number resource.
+
+## **Example**
+
+```typescript {9}
+import { RestClient } from "@signalwire/sdk";
+
+const client = new RestClient({
+ project: "your-project-id",
+ token: "your-api-token",
+ host: "your-space.signalwire.com"
+});
+
+await client.phoneNumbers.setCxmlApplication("phone-number-id", "cxml-application-id");
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-cxml-webhook.mdx b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-cxml-webhook.mdx
new file mode 100644
index 000000000..2a7739d39
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-cxml-webhook.mdx
@@ -0,0 +1,67 @@
+---
+title: "setCxmlWebhook"
+slug: /reference/typescript/rest/phone-numbers/set-cxml-webhook
+description: Route inbound calls to a cXML (LAML) webhook.
+max-toc-depth: 3
+---
+
+[update]: /docs/server-sdks/reference/typescript/rest/phone-numbers/update
+
+Route inbound calls on this phone number to a cXML (Twilio-compat / LAML)
+webhook. Despite the wire value `laml_webhooks` being plural, this creates a
+single `cxml_webhook` Fabric resource on the server.
+
+This is a typed wrapper over [`update`][update] that sets `call_handler` to
+`laml_webhooks` and populates the URL fields for you.
+
+
+For SWML webhooks, use
+[`setSwmlWebhook`](/docs/server-sdks/reference/typescript/rest/phone-numbers/set-swml-webhook)
+instead.
+
+
+## **Parameters**
+
+
+ ID of the phone number to bind.
+
+
+
+ Webhook URL and options.
+
+
+
+ Primary cXML document URL. Serialized as `call_request_url`.
+
+
+
+ Fallback URL invoked when the primary URL fails. Serialized as
+ `call_fallback_url`.
+
+
+
+ URL that receives call-status updates. Serialized as
+ `call_status_callback_url`.
+
+
+## **Returns**
+
+`Promise` — The updated phone-number resource.
+
+## **Example**
+
+```typescript {9-12}
+import { RestClient } from "@signalwire/sdk";
+
+const client = new RestClient({
+ project: "your-project-id",
+ token: "your-api-token",
+ host: "your-space.signalwire.com"
+});
+
+await client.phoneNumbers.setCxmlWebhook("phone-number-id", {
+ url: "https://example.com/voice.xml",
+ fallbackUrl: "https://example.com/fallback.xml",
+ statusCallbackUrl: "https://example.com/status",
+});
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-relay-application.mdx b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-relay-application.mdx
new file mode 100644
index 000000000..4b852df0f
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-relay-application.mdx
@@ -0,0 +1,47 @@
+---
+title: "setRelayApplication"
+slug: /reference/typescript/rest/phone-numbers/set-relay-application
+description: Route inbound calls to a named RELAY application.
+max-toc-depth: 3
+---
+
+[update]: /docs/server-sdks/reference/typescript/rest/phone-numbers/update
+
+Route inbound calls on this phone number to a named RELAY application. The
+server auto-creates a `relay_application` Fabric resource referencing the
+application name.
+
+This is a typed wrapper over [`update`][update] that sets `call_handler` to
+`relay_application` and populates `call_relay_application` for you.
+
+## **Parameters**
+
+
+ ID of the phone number to bind.
+
+
+
+ Name of the RELAY application to route calls to.
+
+
+
+ Additional wire-level fields merged into the PUT body.
+
+
+## **Returns**
+
+`Promise` — The updated phone-number resource.
+
+## **Example**
+
+```typescript {9}
+import { RestClient } from "@signalwire/sdk";
+
+const client = new RestClient({
+ project: "your-project-id",
+ token: "your-api-token",
+ host: "your-space.signalwire.com"
+});
+
+await client.phoneNumbers.setRelayApplication("phone-number-id", "my-relay-app");
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-relay-topic.mdx b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-relay-topic.mdx
new file mode 100644
index 000000000..92e8a637c
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-relay-topic.mdx
@@ -0,0 +1,54 @@
+---
+title: "setRelayTopic"
+slug: /reference/typescript/rest/phone-numbers/set-relay-topic
+description: Route inbound calls to a RELAY topic.
+max-toc-depth: 3
+---
+
+[update]: /docs/server-sdks/reference/typescript/rest/phone-numbers/update
+
+Route inbound calls on this phone number to a RELAY topic. RELAY clients
+subscribed to the topic will receive the inbound call event.
+
+This is a typed wrapper over [`update`][update] that sets `call_handler` to
+`relay_topic` and populates `call_relay_topic` for you.
+
+## **Parameters**
+
+
+ ID of the phone number to bind.
+
+
+
+ Topic name and options.
+
+
+
+ RELAY topic name. Serialized as `call_relay_topic`.
+
+
+
+ URL that receives status updates for calls routed via this topic. Serialized
+ as `call_relay_topic_status_callback_url`.
+
+
+## **Returns**
+
+`Promise` — The updated phone-number resource.
+
+## **Example**
+
+```typescript {9-12}
+import { RestClient } from "@signalwire/sdk";
+
+const client = new RestClient({
+ project: "your-project-id",
+ token: "your-api-token",
+ host: "your-space.signalwire.com"
+});
+
+await client.phoneNumbers.setRelayTopic("phone-number-id", {
+ topic: "office",
+ statusCallbackUrl: "https://example.com/status",
+});
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-swml-webhook.mdx b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-swml-webhook.mdx
new file mode 100644
index 000000000..48bc887f7
--- /dev/null
+++ b/fern/products/server-sdks/pages/reference/typescript/rest/phone-numbers/set-swml-webhook.mdx
@@ -0,0 +1,50 @@
+---
+title: "setSwmlWebhook"
+slug: /reference/typescript/rest/phone-numbers/set-swml-webhook
+description: Route inbound calls to an SWML webhook URL.
+max-toc-depth: 3
+---
+
+[update]: /docs/server-sdks/reference/typescript/rest/phone-numbers/update
+
+Route inbound calls on this phone number to an SWML webhook URL. Your backend
+returns an SWML document per call. The server auto-creates a `swml_webhook`
+Fabric resource keyed off this URL — you do **not** need to call
+`fabric.swmlWebhooks.create` or `fabric.resources.assignPhoneRoute`.
+
+This is a typed wrapper over [`update`][update] that sets `call_handler` to
+`relay_script` and populates `call_relay_script_url` for you.
+
+## **Parameters**
+
+
+ ID of the phone number to bind.
+
+
+
+ Webhook URL that returns SWML. The server keys the auto-created Fabric
+ resource off this value.
+
+
+
+ Additional wire-level fields merged into the PUT body (e.g. `name`,
+ `call_fallback_url`).
+
+
+## **Returns**
+
+`Promise` — The updated phone-number resource.
+
+## **Example**
+
+```typescript {9}
+import { RestClient } from "@signalwire/sdk";
+
+const client = new RestClient({
+ project: "your-project-id",
+ token: "your-api-token",
+ host: "your-space.signalwire.com"
+});
+
+await client.phoneNumbers.setSwmlWebhook("phone-number-id", "https://example.com/swml");
+```
diff --git a/fern/products/server-sdks/pages/reference/typescript/rest/rest-error.mdx b/fern/products/server-sdks/pages/reference/typescript/rest/rest-error.mdx
index 15757fa3c..8cd7c7bc0 100644
--- a/fern/products/server-sdks/pages/reference/typescript/rest/rest-error.mdx
+++ b/fern/products/server-sdks/pages/reference/typescript/rest/rest-error.mdx
@@ -9,6 +9,8 @@ Custom error class for REST API errors. Extends JavaScript's built-in `Error`
class. Thrown when an HTTP request to the SignalWire REST API returns a non-success
status code. The `name` property is always `"RestError"`.
+Also exported as `SignalWireRestError` to match the Python SDK class name.
+
```typescript {1}
import { RestError } from '@signalwire/sdk';
```
@@ -19,8 +21,10 @@ import { RestError } from '@signalwire/sdk';
HTTP status code returned by the API (e.g., `404`, `422`, `500`).
-
- Raw response body from the API.
+"} toc={true}>
+ Response body from the API. Parsed as JSON when the response was valid
+ JSON; otherwise the raw text. Matches the Python SDK's
+ `SignalWireRestError.body` behavior.
diff --git a/fern/products/server-sdks/sdk-source-sync.json b/fern/products/server-sdks/sdk-source-sync.json
index c7c922135..880329ef6 100644
--- a/fern/products/server-sdks/sdk-source-sync.json
+++ b/fern/products/server-sdks/sdk-source-sync.json
@@ -12,8 +12,8 @@
"repository": "https://github.com/signalwire/signalwire-typescript.git",
"local_path": "temp/signalwire-typescript",
"status": "active",
- "synced_commit": "f7144ab40505f365e554332e891b38b3a5e2f670",
- "synced_at": "2026-04-08"
+ "synced_commit": "30391ceeb0d5e1e0b409826c99a4a1ac31b1be2b",
+ "synced_at": "2026-04-27"
},
"go": {
"repository": "https://github.com/signalwire/signalwire-go.git",
diff --git a/fern/products/server-sdks/server-sdks.yml b/fern/products/server-sdks/server-sdks.yml
index ffdc5d163..6b802f094 100644
--- a/fern/products/server-sdks/server-sdks.yml
+++ b/fern/products/server-sdks/server-sdks.yml
@@ -21,44 +21,35 @@ navigation:
title: Deploy
- tab: reference
- layout:
- - folder: ./pages/reference/python/core
- title: Core
- - folder: ./pages/reference/python/agents
- title: Agents
- - folder: ./pages/reference/python/relay
- title: RELAY
- - folder: ./pages/reference/python/rest
- title: REST Client
- # variants:
- # - title: Python
- # icon: brands fa-python
- # default: true
- # layout:
- # - folder: ./pages/reference/python/core
- # title: Core
- # collapsed: false
- # - folder: ./pages/reference/python/agents
- # title: Agents
- # collapsed: false
- # - folder: ./pages/reference/python/relay
- # title: RELAY
- # collapsed: false
- # - folder: ./pages/reference/python/rest
- # title: REST Client
- # collapsed: false
- # - title: TypeScript
- # icon: brands fa-typescript
- # layout:
- # - folder: ./pages/reference/typescript/core
- # title: Core
- # collapsed: false
- # - folder: ./pages/reference/typescript/agents
- # title: Agents
- # collapsed: false
- # - folder: ./pages/reference/typescript/relay
- # title: RELAY
- # collapsed: false
- # - folder: ./pages/reference/typescript/rest
- # title: REST Client
- # collapsed: false
+ variants:
+ - title: Python
+ icon: brands fa-python
+ default: true
+ layout:
+ - folder: ./pages/reference/python/core
+ title: Core
+ collapsed: false
+ - folder: ./pages/reference/python/agents
+ title: Agents
+ collapsed: false
+ - folder: ./pages/reference/python/relay
+ title: RELAY
+ collapsed: false
+ - folder: ./pages/reference/python/rest
+ title: REST Client
+ collapsed: false
+ - title: TypeScript
+ icon: brands fa-typescript
+ layout:
+ - folder: ./pages/reference/typescript/core
+ title: Core
+ collapsed: false
+ - folder: ./pages/reference/typescript/agents
+ title: Agents
+ collapsed: false
+ - folder: ./pages/reference/typescript/relay
+ title: RELAY
+ collapsed: false
+ - folder: ./pages/reference/typescript/rest
+ title: REST Client
+ collapsed: false